TOPReward: Token Probabilities as Hidden Zero-Shot Rewards for Robotics
Shirui Chen, Cole Harrison, Ying-Chun Lee, Angela Jin Yang, Zhongzheng Ren, Lillian J. Ratliff, Jiafei Duan*, Dieter Fox*, Ranjay Krishna*
*Equal advising
TOPReward is a reward modeling method that uses token probabilities from vision-language models (VLMs) as zero-shot reward signals for robotics. By computing the log-likelihood that a model assigns to a task instruction given a video trajectory, TOPReward provides scalable, annotation-free reward estimation for robot learning and data curation.
The codebase supports two prediction methods:
- TOPReward: Computes log-likelihood rewards for instruction matching on video trajectories (the TOPReward method)
- GVL: Generative Value Learning - predicts task completion percentages (0-100%) from shuffled video frames
- 02-22-2026: TOPReward is available on arXiv.
After setup (see Getting Started), run either prediction mode:
HYDRA_FULL_ERROR=1 PYTHONPATH=. uv run python3 -m topreward.scripts.predict \
--config-dir configs/experiments \
--config-name predict_gvlHYDRA_FULL_ERROR=1 PYTHONPATH=. uv run python3 -m topreward.scripts.predict \
--config-dir configs/experiments \
--config-name predict_topreward \
model=qwenIf you prefer one shell entrypoint, use:
topreward/scripts/run_predict.sh --config-name predict_gvl dataset=nyudoor model=gemini
topreward/scripts/run_predict.sh --config-name predict_topreward dataset=austin_sirius_dataset model=qwen prediction.add_chat_template=trueThe script selects an experiment config by name and forwards all remaining arguments as Hydra overrides.
Common override types:
- Group selection:
dataset=... model=... data_loader=... mapper=... prompts=... - Scalar values:
prediction.num_examples=20 prediction.output_dir=./results model.model_name=... - Booleans:
prediction.add_chat_template=true prediction.use_video_description=false
Results are saved under outputs/DATE_TIME/ with predictions, raw outputs, and metrics.
Tip: you can override any config at the CLI, e.g. model.temperature=0.5.
- Python 3.11+
- uv for environment and dependency management
ffmpegavailable on your system PATH
-
Clone the repository:
git clone https://github.com/TOPReward/TOPReward.git cd TOPReward -
Install
ffmpeg(if not already installed):# macOS (Homebrew) brew install ffmpeg # Ubuntu / Debian sudo apt-get update && sudo apt-get install -y ffmpeg
-
Set up a
uvvirtual environment and install dependencies:uv venv source .venv/bin/activate uv sync
Create a .env file in the project root:
cp .env.example .envThen edit .env with your credentials:
OPENAI_API_KEY="your-openai-api-key"
GOOGLE_API_KEY="your-google-api-key"
HUGGING_FACE_HUB_TOKEN="your-hugging-face-token"
Configuration lives in configs/:
configs/model/: model configs (e.g.,gemini.yaml,gemma.yaml,openai.yaml)configs/dataset/: dataset configsconfigs/data_loader/: data loader configs (e.g.,huggingface.yaml,local.yaml)configs/prompts/: prompt stylesconfigs/experiments/: complete experiment presets (e.g.,predict_gvl.yaml)
Override parameters from the command line. Examples:
# Run with explicit experiment config
PYTHONPATH=. uv run python3 -m topreward.scripts.predict --config-dir configs/experiments --config-name predict_gvl
# Override individual fields
PYTHONPATH=. uv run python3 -m topreward.scripts.predict --config-dir configs/experiments --config-name predict_gvl \
model=gemini dataset=berkeleymvp data_loader=huggingface model.temperature=0.5Run TOPReward on a single local video directly (no frame extraction step):
topreward/scripts/run_predict.sh --config-name predict_topreward \
data_loader=local \
dataset=local_video \
dataset.video_path=/absolute/path/to/video.mp4 \
dataset.instruction="open the drawer" \
prediction.num_examples=1 \
prediction.output_dir=./results/local_video_toprewardTOPReward clients inherit from topreward.clients.base.BaseModelClient. You only need to implement _generate_from_events(self, events: list[Event]) -> str, which receives a provider-agnostic sequence of text/image events already assembled by the framework. See topreward/clients/gemini.py for a complete reference implementation.
- Implement a client in
topreward/clients/my_model.py:
# topreward/clients/my_model.py (concise example)
import os
from typing import cast, List
from loguru import logger
from topreward.clients.base import BaseModelClient
from topreward.utils.aliases import Event, ImageEvent, ImageT, TextEvent
from topreward.utils.images import encode_image
class MyModelClient(BaseModelClient):
def __init__(self, *, rpm: float = 0.0, model_name: str):
super().__init__(rpm=rpm)
if not os.getenv("MY_MODEL_API_KEY"):
raise OSError("Missing MY_MODEL_API_KEY")
self.model_name = model_name
logger.info(f"Using MyModel '{self.model_name}'")
def _generate_from_events(self, events: List[Event]) -> str:
parts: List[bytes | str] = []
for ev in events:
if isinstance(ev, TextEvent):
parts.append(ev.text)
elif isinstance(ev, ImageEvent):
parts.append(encode_image(cast(ImageT, ev.image)))
# Call your provider with `parts` and return the provider's text response.
# Placeholder response for docs/tests:
return "Frame 1: Task Completion: 50%\nFrame 2: Task Completion: 100%"- Add a Hydra config at
configs/model/my_model.yaml:
_target_: topreward.clients.my_model.MyModelClient
model_name: my-model-name
rpm: 15 # requests per minute (rate limiter)- Use your model via CLI or experiment config:
PYTHONPATH=. uv run python3 -m topreward.scripts.predict \
--config-dir configs/experiments \
--config-name predict_gvl \
model=my_modelCreate a dataset config that matches the keys used by our HuggingFace loader (configs/data_loader/huggingface.yaml). Example:
# configs/dataset/my_dataset.yaml
name: my_dataset
dataset_name: "org-or-user/my_dataset_on_hub"
camera_index: 0
max_episodes: 100
num_frames: 15
num_context_episodes: 2Then choose a loader (e.g., Hugging Face) in your experiment or via CLI:
PYTHONPATH=. uv run python3 -m topreward.scripts.predict \
--config-dir configs/experiments \
--config-name predict_gvl \
dataset=my_dataset data_loader=huggingface- macOS library path:
export DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/lib - GPU OOM (CUDA): reduce
batch_sizeor image resolution in the model config (e.g.,configs/model/gemini.yaml). - Hugging Face authentication: ensure
HUGGING_FACE_HUB_TOKENis set in.envfor gated models/private datasets. - API rate limits: consider lowering concurrency or increasing
TQDM_MININTERVALwhen applicable.
If you use TOPReward in your research, please cite:
@article{chen2026topreward,
title={TOPReward: Token Probabilities as Hidden Zero-Shot Rewards for Robotics},
author={Chen, Shirui and Harrison, Cole and Lee, Ying-Chun and Yang, Angela Jin and Ren, Zhongzheng and Ratliff, Lillian J and Duan, Jiafei and Fox, Dieter and Krishna, Ranjay},
journal={arXiv preprint arXiv:2602.19313},
year={2026}
}TOPReward builds on OpenGVL / GVL (Generative Value Learning). We reuse and adapt substantial portions of that implementation throughout this repository, and thank the OpenGVL authors: Paweł Budzianowski, Emilia Wiśnios, Gracjan Góral, Michał Tyrolski, Igor Kulakov, Viktor Petrenko, and Krzysztof Walas.
Video processing utilities in topreward/utils/video_utils.py are adapted from
LeRobot (HuggingFace), licensed under Apache 2.0.
This project is licensed under the MIT License. See LICENSE for details.