# TOPReward

TOPRewardは、市販のビジョン・言語モデル（VLM）からトークンの対数尤度を抽出してロボティクスの報酬信号として利用する**ゼロショット報酬モデル**です。動画の軌跡とタスク指示が与えられると、その指示が真であるというVLMの対数尤度を返します。ファインチューニングは不要です。

**論文**: [TOPReward: Token Probabilities as Hidden Zero-Shot Rewards for Robotics](https://arxiv.org/abs/2602.19313) **プロジェクト**: [topreward.github.io](https://topreward.github.io/webpage/) **元のコード**: [github.com/TOPReward/TOPReward](https://github.com/TOPReward/TOPReward) **デフォルトのバックボーン**: [Qwen/Qwen3-VL-8B-Instruct](https://huggingface.co/Qwen/Qwen3-VL-8B-Instruct)

## 概要

TOPRewardでは、ロボットがそのタスクを完了しようとしている**動画**を条件として、汎用のVLMにタスク指示の確率を尋ねます。具体的には、以下が与えられた場合:

- 軌跡の動画（フレームのシーケンス）。
- タスクの指示（例: _「引き出しを開けてください」_）。

この形式のチャットプロンプトを構築します

```text
<video>
"The above video shows a robot manipulation trajectory that completes the
 following task: <instruction> Decide whether the above statement is True
 or not. The answer is: True"
```

VLM へフォワードし、最後のトークン以外のすべてをラベルマスクして、そのトークンの対数尤度を読み戻します。デフォルトでは、サフィックステンプレートを閉じるリテラルの`"True"`です。得られる`log P("True" | video + prompt + instruction)`が報酬となります。

この手法は凍結されたVLMにのみ依存するため、TOPRewardは**ゼロショット**です。ホストするファインチューニング済み重みは存在しません。LeRobotにおける「モデル」とは、`transformers`の`Qwen3VLForConditionalGeneration`とラベルマスキングロジックをラップした小さなラッパーです。プロセッサはトークナイザーを所有し、完全なチャットプロンプトを構築します（EO-1/Robometerパターン）。

## LeRobot統合がカバーする範囲

- LeRobot による標準的な `reward_model.type=topreward` 設定。
- `transformers`の`Qwen3VLForConditionalGeneration` APIを介したVLMの読み込み。
- プロセッサによるプロンプトの組み立てとトークン化（アップストリームの`QwenClient.compute_instruction_reward`と一致）。
- `compute_reward()` は、サンプルごとにスカラーの対数確率を1つ返します。
- LeRobot reward-model の保存/読み込み — `save_pretrained` は `config.json` のみを保存します（VLM は `vlm_name` によって識別されます）。
- RA-BCおよびオーバーレイ用に`topreward_progress.parquet`（SARM互換スキーマ）を書き出すオフラインラベリングスクリプトです。

現在のLeRobotポートは**Qwen3-VLクライアントのみ**をサポートしています。その他のアップストリームクライアント（Gemini、OpenAI、Gemma、Molmo）は、後続の追加機能として追加できます。

## インストール要件

1. [インストールガイド](./installation)に従ってLeRobotをインストールしてください。
2. TOPRewardのオプションエクストラをインストールします:

```bash
pip install -e ".[topreward]"
```

または、ソースチェックアウトから`uv`を使用する場合:

```bash
uv sync --extra topreward
```

これにより`transformers`が導入されます。TOPRewardを初めて実行する際、Hugging FaceはHubからVLMの重みもダウンロードします（Qwen3-VL-8B-Instructの場合、約16 GB）。GPUの使用を強く推奨します。

## モデルの入力と出力

TOPRewardは以下を期待します:

- 軌跡の動画またはフレームのシーケンス。
- 自然言語によるタスクの説明。

LeRobotのデータセットでは、プリプロセッサは以下を読み取ります:

| 設定フィールド              | デフォルト                     | 意味                                       |
| ------------------------- | --------------------------- | --------------------------------------------- |
| `reward_model.image_key`  | `observation.images.top`    | TOPRewardで使用されるカメラ観測          |
| `reward_model.task_key`   | `task`                      | タスク文字列に補完データをキー入力します |
| `reward_model.max_frames` | `16`                        | サンプルごとのフレーム数の上限                      |
| `reward_model.fps`        | `2.0`                       | Qwenのビジュアルプロセッサに渡されるメタデータ   |
| `reward_model.vlm_name`   | `Qwen/Qwen3-VL-8B-Instruct` | 基盤となるVLMのHugging Face Hub ID     |

モデルは以下を返します:

- `compute_reward(batch)`: サンプルごとに1つの対数確率を返します。値が大きいほど、タスクと動画の整合性が高いことを示します。`success_threshold`が有限値の場合、代わりに二値化された閾値処理済みの値を返します。

## 使用方法

### 報酬モデルを直接ロードする

```python
from lerobot.rewards.topreward import TOPRewardConfig, TOPRewardModel

cfg = TOPRewardConfig(
    vlm_name="Qwen/Qwen3-VL-8B-Instruct",
    device="cuda",
)
reward_model = TOPRewardModel(cfg)
```

### リワードファクトリを使用します

```python
from lerobot.rewards import make_reward_model, make_reward_model_config, make_reward_pre_post_processors

cfg = make_reward_model_config(
    "topreward",
    vlm_name="Qwen/Qwen3-VL-8B-Instruct",
    device="cuda",
    image_key="observation.images.top",
)
reward_model = make_reward_model(cfg)
preprocessor, postprocessor = make_reward_pre_post_processors(cfg)
```

プリプロセッサはプロンプト全体（動画 + プレフィックス + 指示サフィックス）をトークン化し、`observation.topreward.*` 配下に Qwen-VL テンソルと `prompt_length` を書き込みます。モデルはこれらのテンソルを読み取り、`prompt_length` に基づいてラベルマスクを適用し、log-prob 報酬を抽出します。

### オフラインデータセットラベリング

RA-BCの学習とオーバーレイ動画用に`topreward_progress.parquet`を作成します:

```bash
# Sparse-dense (15 anchors per episode, matches upstream)
uv run python -m lerobot.rewards.topreward.compute_rabc_weights \
    --dataset-repo-id lerobot/libero_10_image \
    --num-samples 15 \
    --device cuda
```

その後、任意のエピソードの進捗オーバーレイをレンダリングします:

```bash
uv run examples/dataset/create_progress_videos.py \
    --repo-id lerobot/libero_10_image \
    --episode 0 \
    --progress-file topreward_progress.parquet \
    --gif
```

## 設定に関する注意事項

### プロンプトの調整項目

デフォルトのプロンプトは、上流の論文を反映しています:

```text
prompt_prefix = "The above video shows a robot manipulation trajectory that completes the following task: "
prompt_suffix_template = "{instruction} Decide whether the above statement is True or not. The answer is: True"
```

どちらもアブレーションのために`TOPRewardConfig`に公開されています。サフィックスのテンプレートには`{instruction}`を**必ず**含める必要があります。

### チャットテンプレート

`add_chat_template=True` を指定すると、トークナイズの前に、プロンプト全体（指示を含む）がトークナイザーのチャットテンプレートでラップされます。デフォルトは `False` であり、これは上流の論文の主要な実験設定と一致しています。

## 制限事項

- 現在のLeRobotポートは**推論専用かつゼロショット**です。`forward()`はオーバーライドされておらず、`is_trainable`は`False`を返します。
- サポートされているのは**Qwen3-VLファミリー**のみです。その他のアップストリームクライアントは対象外です。
- TOPRewardは、基盤となるVLMのバイアスを継承します。

## 参考文献

- [TOPRewardプロジェクトページ](https://topreward.github.io/webpage/)
- [TOPReward論文](https://arxiv.org/abs/2602.19313)
- [元のTOPRewardコード](https://github.com/TOPReward/TOPReward)
- [Qwen3-VL-8B-Instruct](https://huggingface.co/Qwen/Qwen3-VL-8B-Instruct)

## 引用

```bibtex
@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コードベースはMITライセンスです。LeRobotへの移植版はLeRobotのApache 2.0ライセンスに従います。ラップされたQwen3-VLの重みは、元のQwenライセンスの対象となります。

