# TOPReward

TOPReward adalah **model reward zero-shot** yang mengekstrak log-probabilitas token dari model bahasa-visi (VLM) yang sudah tersedia sebagai sinyal reward robotik. Diberikan sebuah trajektori video dan instruksi tugas, model ini mengembalikan log-likelihood VLM bahwa instruksi tersebut benar — tanpa perlu fine-tuning.

**Makalah**: [TOPReward: Token Probabilities as Hidden Zero-Shot Rewards for Robotics](https://arxiv.org/abs/2602.19313) **Proyek**: [topreward.github.io](https://topreward.github.io/webpage/) **Kode asli**: [github.com/TOPReward/TOPReward](https://github.com/TOPReward/TOPReward) **Backbone default**: [Qwen/Qwen3-VL-8B-Instruct](https://huggingface.co/Qwen/Qwen3-VL-8B-Instruct)

## Ikhtisar

TOPReward menanyakan kepada VLM generik seberapa mungkin sebuah instruksi tugas, **dengan kondisi video** dari robot yang mencoba menyelesaikan tugas tersebut. Secara konkret, diberikan:

- Video lintasan (sekuens bingkai).
- Instruksi tugas (misalnya _"buka laci"_).

membangun prompt chat dengan bentuk

```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"
```

mengirimkannya melalui VLM, melakukan label-mask pada semua token kecuali token terakhir, dan membaca kembali log-probabilitas dari token tersebut — secara default, literal `"True"` yang menutup template suffix. Hasil `log P("True" | video + prompt + instruction)` adalah reward.

Karena metode ini hanya bergantung pada VLM yang dibekukan, TOPReward bersifat **zero-shot**: tidak ada bobot fine-tuned yang perlu dihosting. "Model" di LeRobot adalah wrapper kecil di sekitar `Qwen3VLForConditionalGeneration` dari `transformers` ditambah logika label-masking. Processor memiliki tokeniser dan membangun prompt chat lengkap (pola EO-1/Robometer).

## Cakupan integrasi LeRobot

- Konfigurasi standar `reward_model.type=topreward` melalui LeRobot.
- Memuat VLM melalui API `Qwen3VLForConditionalGeneration` dari `transformers`.
- Perakitan prompt + tokenisasi di dalam prosesor (sesuai dengan `QwenClient.compute_instruction_reward` hulu).
- `compute_reward()` mengembalikan satu log-probabilitas skalar per sampel.
- LeRobot reward-model save/load — `save_pretrained` hanya menulis `config.json` (VLM diidentifikasi oleh `vlm_name`).
- Skrip penandaan offline yang menulis `topreward_progress.parquet` (skema yang kompatibel dengan SARM) untuk RA-BC dan overlay.

Port LeRobot saat ini hanya mendukung **klien Qwen3-VL**. Klien upstream lainnya (Gemini, OpenAI, Gemma, Molmo) dapat ditambahkan sebagai tambahan lanjutan.

## Persyaratan Instalasi

1. Install LeRobot mengikuti [Panduan Instalasi](./installation).
2. Instal ekstra opsional TOPReward:

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

atau, dengan `uv` dari checkout sumber:

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

Ini menarik `transformers`. Saat pertama kali menjalankan TOPReward, Hugging Face juga akan mengunduh bobot VLM dari Hub (~16 GB untuk Qwen3-VL-8B-Instruct). GPU sangat disarankan.

## Input dan Output Model

TOPReward mengharapkan:

- Video lintasan atau rangkaian bingkai.
- Deskripsi tugas dalam bahasa alami.

Dalam dataset LeRobot, preprocessor membaca:

| Bidang konfigurasi              | Default                     | Arti                                       |
| ------------------------- | --------------------------- | --------------------------------------------- |
| `reward_model.image_key`  | `observation.images.top`    | Observasi kamera yang digunakan oleh TOPReward          |
| `reward_model.task_key`   | `task`                      | Masukkan data pelengkap untuk string tugas |
| `reward_model.max_frames` | `16`                        | Batas frame per sampel                      |
| `reward_model.fps`        | `2.0`                       | Metadata yang diteruskan ke pemroses video Qwen   |
| `reward_model.vlm_name`   | `Qwen/Qwen3-VL-8B-Instruct` | ID Hugging Face Hub dari VLM yang mendasarinya     |

Model mengembalikan:

- `compute_reward(batch)`: satu log-probabilitas per sampel. Nilai lebih tinggi = keselarasan tugas-video yang lebih baik. Ketika `success_threshold` bernilai terbatas, mengembalikan nilai biner yang telah di-threshold.

## Penggunaan

### Muat model reward secara langsung

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

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

### Gunakan pabrik reward

```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)
```

Preprocessor melakukan tokenisasi prompt lengkap (video + prefix + instruksi suffix), lalu menulis tensor Qwen-VL + `prompt_length` di bawah `observation.topreward.*`. Model membaca tensor tersebut, melakukan label-masking berdasarkan `prompt_length`, dan mengekstrak log-prob reward.

### Penandaan dataset offline

Tulis `topreward_progress.parquet` untuk pelatihan RA-BC dan video overlay:

```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
```

Lalu, render overlay kemajuan untuk episode apa pun:

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

## Catatan Konfigurasi

### Pengaturan prompt

Prompt default mencerminkan paper upstream:

```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"
```

Keduanya diekspos di `TOPRewardConfig` untuk ablas. Templat sufiks **harus** memuat `{instruction}`.

### Template chat

`add_chat_template=True` membungkus prompt lengkap (termasuk instruksi) dengan template chat tokenizer sebelum tokenisasi. Nilai default adalah `False`, yang sesuai dengan eksperimen utama dari paper upstream.

## Keterbatasan

- Port LeRobot saat ini **hanya untuk inferensi dan zero-shot**; `forward()` tidak dioverride dan `is_trainable` mengembalikan `False`.
- Hanya **keluarga Qwen3-VL** yang didukung; klien upstream lainnya berada di luar cakupan.
- TOPReward mewarisi bias dari VLM yang mendasarinya.

## Referensi

- [Halaman proyek TOPReward](https://topreward.github.io/webpage/)
- [makalah TOPReward](https://arxiv.org/abs/2602.19313)
- [Kode TOPReward asli](https://github.com/TOPReward/TOPReward)
- [Qwen3-VL-8B-Instruct](https://huggingface.co/Qwen/Qwen3-VL-8B-Instruct)

## Sitasi

```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}
}
```

## Lisensi

Kodebase TOPReward asli berlisensi MIT. Port LeRobot mengikuti lisensi Apache 2.0 LeRobot; bobot Qwen3-VL yang dibungkus tunduk pada lisensi Qwen asli.

