Spotter logo

Spotter:让具身模型主导,让视觉语言模型为它反思

如果我们的项目对你有帮助,欢迎在 GitHub 上点一个 star ⭐ 支持我们

English 中文

arXiv Project page License: MIT RoboCasa RoboTwin 2.0

| 📄 论文 | 🏠 项目主页 | 🤖 模型权重 | 🌐 仿真器 | 🚀 上手 | |---|---|---|---|---| | [arXiv](https://arxiv.org/abs/2609.36808) | [zqc3117.github.io/Spotter](https://zqc3117.github.io/Spotter/) | [pi0.5](https://huggingface.co/DAVIAN-Robotics/pi05-robocasa-H50) · [Cosmos Policy](https://huggingface.co/nvidia/Cosmos-Policy-RoboCasa-Predict2-2B)(RoboCasa)· [pi0.5](https://huggingface.co/motus-robotics/pi0.5_robotwin2)(RoboTwin 2.0) | [RoboCasa](https://robocasa.ai) · [RoboTwin 2.0](https://github.com/RoboTwin-Platform/RoboTwin) | [安装](#-环境配置) · [快速开始](#-用发布的权重评测) |

Spotter 总览:具身模型逐段执行,快速 VLM 并行筛查每一段,前沿 VLM 只在确认出错时判断并修复;右侧为成功率和单集耗时。

**Spotter** 在冻结的具身模型(System 1)和 VLM(System 2)之间加入了一个轻量的介入机制。 它不让 VLM 规划每一步,而是让具身模型主导并持续执行;本地筛子并行关注执行进展,只有确认出错时,VLM 才介入确认并纠正。 交给 VLM 的任务因此简单得多,整个框架**用本地部署的开源 Qwen、不借助任何特权信息**就能运行。 ## 📰 最新动态 - [2026/10] 🔥 RoboCasa:发布在 1,200 集测试集上实际评测过的代码版本,加入黑帧 / 噪声帧的重渲染保护,以及基于腕部深度图的 `aim` 抓取步骤。见 [RoboCasa](#robocasa)。 - [2026/10] 🔥 Spotter 支持 **RoboTwin 2.0**(π0.5):一条命令评测(`bash robotwin_eval.sh`),提供 1-shot 示例库([fewshot_bank_robotwin.tar.gz](https://github.com/zqc3117/Spotter/releases/download/v1.0/fewshot_bank_robotwin.tar.gz)),完整日志已上传魔搭(ModelScope),含每一集的画面、判别器提示词和回复([150 集](https://www.modelscope.ai/datasets/seamoke/spotter-robotwin-150):仅策略、Spotter、VLM 主导的智能体,各配 Qwen 和 GPT;[50 个任务 × 10 集](https://www.modelscope.ai/datasets/seamoke/spotter-robotwin-50x10))。真机演示(Franka Research 3)和[项目主页](https://zqc3117.github.io/Spotter/)同步上线。见 [RoboTwin 2.0](#robotwin-20)。 - [2026/09] 🎉 论文发布在 [arXiv](https://arxiv.org/abs/2609.36808),代码同步开源,附 RoboCasa 示例库([fewshot_bank.tar.gz](https://github.com/zqc3117/Spotter/releases/download/v1.0/fewshot_bank.tar.gz))。 ## 🎬 演示

真机演示:把蓝杯叠到粉杯上

真机(Franka Research 3)把蓝杯叠到粉杯上。动图按 2 倍速播放,并缩短了判别器思考的时间;画面里的计时为真实时间。
在项目主页观看完整视频。

## 🔥 核心优势 - **轻量的介入机制。** 就像人做事时分出少量注意力关注进展,发现异常再集中精力处理:执行保持连贯,只在确认出错时才调用 VLM。 - **VLM 的任务更简单。** VLM 不再驱动机器人,只需发现失败、用几个运动原语组成的短计划修复,并检查修复是否奏效。 本地 Qwen 在看不到任务成功条件的情况下也能胜任。 - **执行不中断,开销低。** 常规执行时具身模型不需要等 VLM,成功的 episode 只比策略单独运行多 **13–16 秒**。 ## 💡 为什么需要 Spotter 现有由 VLM 主导的 robot agent 通常是串行的:VLM 先规划一段动作,交给具身模型执行,执行完再由 VLM 判断下一步。这带来一个两难: - **每次安排的动作太少**:需要频繁调用 VLM,任务再简单时延也高; - **每次安排的动作太多**:执行中出现偏差时无法及时纠正,后续动作会持续出错。 Spotter 把串行监督改成并行监督,消除了这个两难。 | | VLM 主导的 agent | Spotter | |---|---|---| | 谁主导执行 | VLM 规划每一步 | 具身模型主导 | | 何时调用 VLM | 每一步之前 | 仅在确认出错时 | | 具身模型是否等待 VLM | 每一步都等 | 仅在修复期间 | | 是否需要特权信息 | 通常需要(如任务成功信号) | 不需要 | | 能否用本地 Qwen | 只有借助特权信息才行 | 可以 | ### 🎯 更弱的模型也能用,不需要特权信息 在 RoboCasa(1200 集)上,用同一个本地 Qwen、不给特权信息时,一种代表性的 VLM 主导 agent 成功率**跌到策略单独运行以下** (Cosmos Policy 67.9 → 65.2,π0.5 64.3 → 60.5);Spotter 仍然能带来提升(分别到 71.7 和 68.4)。 ### ⚡ 不出错时几乎零开销 用 Qwen 时,成功的 episode 平均调用判别器**不到 1 次**,只比策略单独运行多 **13–16 秒**;和用同一个 Qwen 的 VLM 主导方法相比,耗时少约 **70%**。 > **仿真器。** Spotter 同时支持 [RoboCasa](#robocasa) 和 [RoboTwin 2.0](#robotwin-20)。RoboTwin 2.0 可以一条命令 > `bash robotwin_eval.sh` 跑完整个评测(见[用发布的权重评测](#-用发布的权重评测))。 > > **RoboTwin 2.0 的实验结果和完整记录**(每集的画面、提示词和回复): > [50 个任务 × 10 集](https://www.modelscope.ai/datasets/seamoke/spotter-robotwin-50x10)(策略独跑 vs. Spotter-Qwen), > 以及 [150 集](https://www.modelscope.ai/datasets/seamoke/spotter-robotwin-150)(策略独跑、Spotter 和 VLM 主导的智能体, > 后两者各用 Qwen 和 GPT)。 ## 📑 目录 - [文件结构](#-文件结构) - [环境配置](#-环境配置) - [模型准备](#-模型准备) - [仿真资源与评测集](#-仿真资源与评测集) - [用发布的权重评测](#-用发布的权重评测):[RoboCasa](#robocasa) · [RoboTwin 2.0](#robotwin-20) - [复现论文结果](#-复现论文结果) - [重建经验库与示例库](#-重建经验库与示例库) - [接入你自己的具身模型](#-接入你自己的具身模型) - [输出](#-输出) · [配置参考](#-配置参考) - [致谢](#-致谢) · [许可证](#-许可证) · [联系方式](#-联系方式) · [引用](#-引用) ## 📂 文件结构 ```text Spotter/ ├── spotter.sh # 统一入口:部署 Qwen / 策略服务、运行、汇总结果 ├── robotwin_eval.sh # RoboTwin 2.0 一键评测(起服务 + Spotter 组 + 对照组 + 汇总) ├── recovery_explore/ # Spotter 本体 │ ├── judge_driver_v7.sh # 单个 lane 的监督循环:筛查 -> 判别 -> 修复 -> 验证 │ ├── env_service.py # RoboCasa 仿真服务(RPC),由 launch_svc.sh 启动 │ ├── env_service_robotwin.py # RoboTwin 2.0 仿真服务(同一套 RPC 接口,SAPIEN) │ ├── robotwin_intervention.py # RoboTwin 修复原语(双臂);robodojo_intervention.py 是它的基类 │ ├── robotwin_policy_server.py # RoboTwin 的 pi0.5 策略服务(openpi websocket 协议) │ ├── primitives.py # 判别器组合修复计划所用的运动原语 │ ├── grasp_aim.py # RoboCasa 的 `aim` 步骤:在腕部深度图里找到物体并规划抓取 │ ├── render_guard.py # RoboCasa:EGL 上下文泄漏导致黑帧/噪声帧时自动重新渲染 │ ├── JUDGE_BRIEF_V7.md # 判别器提示词;BRIEF_PNP.md / BRIEF_MECH.md / BRIEF_RT.md 是分任务类型的补充 │ ├── cli/ # 筛子、判别通道(Qwen / GPT)、harness、few-shot 工具 │ ├── memory_bank/ # 冻结的 77 条通用经验(RoboCasa) │ ├── memory_bank_robotwin_noreset/ # RoboTwin 2.0 的经验 │ ├── episode_sets/ # sall500.txt(论文,1200 集)· s500q96.txt(96 集,调试用)· rt500.txt / rt150.txt(RoboTwin 2.0) │ ├── fewshot_bank/ # (需下载)1-shot 设置用的示例;robotwin/ 子目录给 RoboTwin 2.0 │ └── runs__<策略>/ # (运行时生成)results.jsonl、各 lane 日志、给判别器看的画面 ├── rpc/ # π0.5 策略服务、RPC 协议、RoboCasa rollout 与采集脚本 ├── cf_bench/ # 纠错能力实验用的快照与重放工具 ├── env/ # env.sh.example、requirements-robocasa.txt、requirements-pi05.txt ├── assets/ # logo └── LICENSE · THIRD_PARTY_NOTICES.md · LICENSES/ ``` ## 🔧 环境配置 **Qwen 筛子和判别器。** vLLM 单独一个环境,再准备本地的 `env/env.sh`: ```bash python3 -m venv .venvs/vllm && .venvs/vllm/bin/pip install vllm cp env/env.sh.example env/env.sh && $EDITOR env/env.sh ``` **RoboCasa。** RoboCasa 用到三个 Python 环境: | 环境 | Python | 运行什么 | 安装 | |---|---|---|---| | `robocasa` | 3.10 | 仿真服务、判别 driver、Cosmos 策略服务 | 按 [Cosmos Policy](https://github.com/NVlabs/cosmos-policy) 的 RoboCasa 说明安装,再装 `env/requirements-robocasa.txt` | | `pi05` | 3.12 | π0.5 策略服务(LeRobot) | `env/requirements-pi05.txt` | | `vllm` | 3.10+ | Qwen 筛子和判别器 | 见上面的 Qwen 步骤 | ```bash # 1) RoboCasa + Cosmos Policy:按 https://github.com/NVlabs/cosmos-policy 的 RoboCasa 说明安装,然后 pip install -r env/requirements-robocasa.txt # 2) π0.5 python3.12 -m venv .venvs/pi05 && .venvs/pi05/bin/pip install -r env/requirements-pi05.txt ``` > **注意**:无显示器的 MuJoCo 渲染需要支持 EGL 的 NVIDIA GPU(`MUJOCO_GL=egl`,已在 `env/env.sh` 中设置)。 **RoboTwin 2.0。** Spotter 可以跑在 [RoboTwin 2.0](https://github.com/RoboTwin-Platform/RoboTwin) (aloha-agilex 双臂,SAPIEN 3,50 个任务,`demo_randomized` 场景)上,族名为 `robotwin`。 RoboTwin 的仿真器和规划器(SAPIEN 3、mplib、cuRobo)在它自己的 Python 3.10 环境里,以"便携运行时"的形式布局, `env/env.sh` 指向它: ```text / ├── .venv/ # python 3.10:sapien 3.0.0b1、mplib 0.2.1、toppra、与显卡匹配的 CUDA 版 torch └── worktree/third_party/RoboTwin/ # RoboTwin 2.0 树 ├── envs/curobo/src/ # cuRobo 源码(其 CUDA 内核需与 torch 匹配) ├── assets/{objects,background_texture,embodiments}/ # RoboTwin 2.0 资源(Hub 上的 TianxingChen/RoboTwin2.0) └── policy/pi0/checkpoints/pi05_robotwin2_clean_randomized/robotwin2/40000/ # pi0.5 权重 ``` 按 RoboTwin 的 README 安装好本体和资源后,在 `env/env.sh` 里设置: ```bash export ROBOTWIN_RUNTIME=/path/to/robotwin-runtime # 或 ROBOTWIN_ROOT + ROBOTWIN_PY export ROBOTWIN_POLICY_PYTHON=/path/to/robotwin-policy-venv/bin/python # 满足 policy/pi05/requirements.txt 的 venv(openpi、lerobot < 0.3) ``` 仿真用 SAPIEN 的光线追踪渲染(Vulkan,RTX 级显卡);RTX 5090 上默认用 `optix` 去噪器,因为官方的 `oidn` 在那上面会报错。 ## 📦 模型准备 **1)Qwen 判别器和筛子。** ```bash huggingface-cli download Qwen/Qwen3.8-27B-FP8 --local-dir checkpoints/Qwen3.8-27B-FP8 ``` 国内用户也可以从 [ModelScope](https://modelscope.cn/models/Qwen/Qwen3.8-27B-FP8) 下载。然后在 `env/env.sh` 中设置: ```bash export QWEN_MODEL=$PWD/checkpoints/Qwen3.8-27B-FP8 export VLLM_VENV=$PWD/.venvs/vllm ``` **2)RoboCasa。** 下载 π0.5 和 Cosmos Policy: ```bash huggingface-cli download DAVIAN-Robotics/pi05-robocasa-H50 --local-dir checkpoints/pi05-robocasa-H50 huggingface-cli download nvidia/Cosmos-Policy-RoboCasa-Predict2-2B --local-dir checkpoints/Cosmos-Policy-RoboCasa-Predict2-2B ``` 下载后的目录: ```text checkpoints/ ├── pi05-robocasa-H50/ # model.safetensors、config.json、policy_*processor*、tokenizer/ ├── Cosmos-Policy-RoboCasa-Predict2-2B/ # Cosmos-Policy-RoboCasa-Predict2-2B.pt、robocasa_t5_embeddings.pkl 等 └── Qwen3.8-27B-FP8/ ``` 然后在 `env/env.sh` 中设置: ```bash export PI05_CHECKPOINT=$PWD/checkpoints/pi05-robocasa-H50 export COSMOS_CHECKPOINT=$PWD/checkpoints/Cosmos-Policy-RoboCasa-Predict2-2B/Cosmos-Policy-RoboCasa-Predict2-2B.pt ``` 1-shot 设置需要 RoboCasa 示例库(151 MB): ```bash curl -L https://github.com/zqc3117/Spotter/releases/download/v1.0/fewshot_bank.tar.gz | tar -xz -C recovery_explore ``` **3)RoboTwin 2.0。** 策略是 pi0.5 权重 [motus-robotics/pi0.5_robotwin2](https://huggingface.co/motus-robotics/pi0.5_robotwin2),放在 RoboTwin 树里的 `policy/pi0/checkpoints/pi05_robotwin2_clean_randomized/robotwin2/40000/`(见[环境配置](#-环境配置))。 1-shot 设置需要把 RoboTwin 示例库(33 MB)下载到 `recovery_explore/fewshot_bank/robotwin/`: ```bash curl -L https://github.com/zqc3117/Spotter/releases/download/v1.0/fewshot_bank_robotwin.tar.gz | tar -xz -C recovery_explore ``` > **GPT 判别器(可选)**:设置 `ENGINE=api`,并配好 `OPENAI_RESPONSES_URL` 和 `OPENAI_API_TOKEN_FILE`; > 判别器换成 GPT-6 Astra,筛子仍然是本地 Qwen。 ## 🧭 仿真资源与评测集 **RoboCasa 资源**随上面 Cosmos Policy 的 RoboCasa 安装步骤一起装好。 **RoboTwin 2.0 资源**随 RoboTwin 本体一起安装(见[环境配置](#-环境配置))。 **评测集**随仓库提供,每行一个 `任务:种子:编号`: | 文件 | 集数 | 用途 | |---|---:|---| | `episode_sets/sall500.txt` | 1,200 | 论文的 RoboCasa 评测:24 个任务 × 编号 0–49,seed 500 | | `episode_sets/s500q96.txt` | 96 | RoboCasa 调试用子集,每个任务 4 集 | | `episode_sets/rt50x10n.txt` | 500 | RoboTwin 2.0:50 个任务 × 10 集 | | `episode_sets/rt500.txt` | 500 | 发布结果所用的 RoboTwin 2.0 评测集:在 `rt50x10n` 基础上,把当前仿真环境里无法开局的集替换为同任务下一个能开局的集 | | `episode_sets/rt150.txt` | 150 | RoboTwin 2.0 上与 VLM 主导智能体的对比:50 个任务 × 3 集,是 `rt500` 的子集 | RoboCasa 的经验和示例都是在 seed 195 上学到的,和测试用的 seed 不重叠。 ## 🚀 用发布的权重评测 每个服务各开一个终端,先执行 `source env/env.sh`。 **1)部署 Qwen 筛子和判别器**(每张卡一个副本,端口 8301、8302……)。 ```bash bash spotter.sh judge --gpus 0,1,2,3 curl -s http://127.0.0.1:8301/v1/models # 检查 ``` 卡少时少写几张(如 `--gpus 0`),并在运行前 `export QWEN_PORTS=8301`。 ### RoboCasa **2)部署具身模型**:π0.5 用 8900 端口,Cosmos Policy 用 8800 端口。 ```bash bash spotter.sh policy pi05 --gpu 4 # 或:bash spotter.sh policy cosmos --gpu 4 curl -s http://127.0.0.1:8900/health # 检查 ``` **3)冒烟测试:跑一集。** 仿真服务由 driver 自动启动。 ```bash bash spotter.sh run pi05 # 跑一集:同一场景下对照组和 Spotter 各跑一次 ``` **4)在 `sall500` 上完整评测。** ```bash bash spotter.sh run pi05 sall500 --lanes 8 bash spotter.sh summary ```
直接调用 driver `spotter.sh run` 会为每个 lane 启动一个 driver。上面跑一集 pi0.5 的命令等价于: ```bash mkdir -p recovery_explore/runs_smoke printf 'PnPCabToCounter:195:0\n' > recovery_explore/runs_smoke/episodes_pi05.txt ON_POD=1 RUN=smoke TARGET=1 NGPU=1 FAMILY_OVERRIDE=pi05 \ SIM_HOST=127.0.0.1 SIM_MANAGED=0 POLICY_URL=http://127.0.0.1:8900 \ ENGINE=qwen MODEL=qwen38 SCREEN=1 QWEN_KEEP_TURNS=20 \ STEP_BUDGET_SCALE=1.8 WINDOW=1 TEL_CHUNKS=10 COMPACT_AT=110000 MAX_INTERVENTIONS=8 \ ALLOW_RESET=0 MAX_RESETS=0 FEWSHOT=0 LEARN=0 CTRL_ONLY=0 SKIP_CONTROL=0 \ bash recovery_explore/judge_driver_v7.sh 0 ``` driver 会自己在 `8450+lane` 端口启动和重启仿真服务。同一个 run 的所有 lane 从同一个队列领取 episode,结果数达到 `TARGET` 后各 lane 自动结束。
### RoboTwin 2.0 **一条命令。** `robotwin_eval.sh` 会在 Qwen 和 pi0.5 策略服务没起来时自动启动它们,然后在同一批 500 集(`rt500`)上 先跑 Spotter 组、再跑纯策略对照组,最后输出汇总。设置和发布结果一致:1.8 倍步数上限、1-shot、Qwen 只在修复回合思考, `QWEN_THINK_BUDGET=5000`。 ```bash bash robotwin_eval.sh --judge-gpus 0,1,2,3 --policy-gpu 4 --lanes 12 ``` 加 `--dry-run` 只打印要执行的命令。每个 RoboTwin 仿真大约占 8 GB 显存,32 GB 的卡建议每张跑 3 条 lane。Spotter 组的耗时 主要在判别器思考上,多给 Qwen 几张卡(`--judge-gpus`)会更快。
分步运行 第 1 步的 Qwen 服务起来后: ```bash bash spotter.sh policy robotwin --gpu 4 # RoboTwin 的 pi0.5,端口 9100(检查:curl http://127.0.0.1:9100/healthz) bash spotter.sh run robotwin # 冒烟:adjust_bottle 第 35 集 bash spotter.sh run robotwin rt500 --lanes 12 --one-shot # 在 500 个评测集上跑 Spotter 组(1-shot) bash spotter.sh run robotwin rt500 --lanes 12 --arm ctrl # 同一批集上的纯策略对照组 bash spotter.sh summary ```
**用这版代码的结果。** 我们用这版代码在 RoboTwin 2.0 上重跑了 Spotter 组,评测集是 `rt500` 的 500 集(1.8 倍步数上限、 1-shot);对照组是同样 500 集上的策略独跑: | 组别 | 成功 | |---|---:| | 策略独跑(pi0.5) | 240 / 500(48.0%) | | Spotter-Qwen,`QWEN_THINK_BUDGET=2000` | 252 / 500(50.4%) | | Spotter-Qwen,`QWEN_THINK_BUDGET=5000`(默认) | 267 / 500(53.4%) | 由于每次运行都有随机因素,这些结果和论文略有差异。我们把逐集结果(每集的画面、判别器提示词和回复)上传到了 ModelScope: [50 个任务 × 10 集](https://www.modelscope.ai/datasets/seamoke/spotter-robotwin-50x10)。 **与 VLM 主导智能体的对比(150 集)。** 在 `rt150`(50 个任务 × 3 集,是 `rt500` 的子集)上,用相同设置(1.8 倍步数上限、 1-shot、Qwen 只在修复轮思考、上限 5000 token),我们还跑了 GPT 版 Spotter,以及分别用两种模型的 VLM 主导智能体; 所有组都在同一批集上运行。VLM 主导的智能体逐轮驱动整个任务、把策略当作工具调用,它的代码不在本次发布中。 | 组 | 模型 | 成功 | |---|---|---:| | 策略独跑(pi0.5) | – | 72 / 150(48.0%) | | Spotter | Qwen3.8-27B-FP8 | 79 / 150(52.7%) | | Spotter | GPT-6-astra | 84 / 150(56.0%) | | VLM 主导的智能体 | Qwen3.8-27B-FP8 | 63 / 150(42.0%) | | VLM 主导的智能体 | GPT-6-astra | 84 / 150(56.0%) | 五个组的完整记录(每集的画面、提示词和回复)都在 ModelScope 上: [150 集](https://www.modelscope.ai/datasets/seamoke/spotter-robotwin-150)。 ### 运行选项 `bash spotter.sh run <策略族> [SET] [选项]`,两个仿真器通用: | 选项 | 含义 | |---|---| | `SET` | `smoke`(1 集,默认);RoboCasa:`s500q96`、`sall500`;RoboTwin 2.0:`rt500`、`rt150`、`rt50x10n`;或每行一个 `任务:种子:编号` 的文件 | | `--lanes N` | 并行跑的集数;lane `N` 在端口 `8450+N` 上运行自己的仿真服务 | | `--sim-gpus N` | 仿真服务共用的卡,即 `0..N-1` 号卡(默认全部) | | `--arm` | `both`(每集对照组和 Spotter 都跑,默认)、`treat`(只跑 Spotter)、`ctrl`(只跑策略) | | `--one-shot` | 给判别器加一个示例(需要示例库) | | `--run NAME` | run 名称(默认 `<策略>_<评测集>`);同名重跑会接着上次继续 | | `--dry-run` | 只打印要执行的命令,不真正运行 | 同一个 episode 的两组使用相同的场景、指令和步数预算: | 组别 | 说明 | |---|---| | **对照组(Control)** | 只有策略,不调用判别器。 | | **实验组(Treatment)** | 策略加判别器,可按需干预。 | `spotter.sh run <策略族>` 使用[配置参考](#-配置参考)里对应那一列的设置,每一项都可以用环境变量覆盖。 ## 📊 复现论文结果 论文 Table 1(RoboCasa,1200 集)中 Spotter 的各行,都是在上面完整评测的基础上加以下设置;环境变量在 `spotter.sh run` 之前 export。 | Table 1 中的行 | 设置 | |---|---| | 具身模型,1.0× / 1.8× 步数上限 | `--arm ctrl`,配合 `STEP_BUDGET_SCALE=1.0` / `1.8` | | Spotter (Qwen),full context | `spotter.sh` 默认值 | | Spotter (Qwen),short context | `TEL_CHUNKS=3 QWEN_KEEP_TURNS=3 COMPACT_AT=22000 MAX_INTERVENTIONS=3 SCREEN_CONFIRM2=0`(π0.5 另加 `WINDOW=2`) | | Spotter (Qwen),1-shot | `--one-shot` | | Spotter (GPT),有 / 无筛子 | `ENGINE=api`,配合 `SCREEN=1` / `SCREEN=0` | | Spotter (GPT),1-shot | `ENGINE=api` 加 `--one-shot` | | Harness VLA | 用其自身代码运行:[RLinf/RPent](https://github.com/RLinf/RPent) | Table 1 中"固定重试"的两行不包含在本次发布中。 **监督模式**:`spotter.sh` 运行的是同步监督循环(`ASYNC_SCREEN=0`)。如需 3.2 节的有界异步模式,设置 `ASYNC_SCREEN=2 ASYNC_K=2`:策略最多领先上一次检查两个监督窗口(Cosmos Policy 为 4 个 chunk,π0.5 为 2 个)。 **耗时**:`results.jsonl` 记录了每组的总耗时,以及判别器和筛子的调用耗时(见[输出](#-输出));本次发布不记录 token 数。 **3.1 节**:`rpc/run_remote_robocasa_cf_branch_collect.py` 采集失败后和正常状态下的候选动作,`cf_bench/` 负责重放这些候选并运行语言反馈实验。测试时打分器(Consistency-Consensus、GeoBoN、RCS)不包含在内。 ## 🧠 重建经验库与示例库 仓库自带的经验库(`recovery_explore/memory_bank/global/` 中的 77 条通用经验)和示例库都是冻结的,论文所有结果都直接使用它们;只有在需要重建或覆盖新任务时才需要这一节。 **1)运行学习用的 episode**:只在 seed 195 上运行,不能用测试 seed。只有这一步允许判别器重置并重试;每集的经验会以草稿形式写到 `memory_bank/inbox//`。 ```bash ENGINE=api LEARN=1 ALLOW_RESET=1 MAX_RESETS=5 bash spotter.sh run cosmos --run learn_cosmos ``` **2)审阅草稿**,把其中通用的经验移到 `memory_bank/global/`,格式见 `recovery_explore/memory_bank/README.md`。去掉所有特权信息和只适用于特定任务的内容。 **3)构建示例库**,从学习 run 中挖掘 1-shot 设置所用的示例: ```bash python3 recovery_explore/cli/fewshot_build.py --family cosmos --seed 195 --out recovery_explore/fewshot_bank ``` ## 🔌 接入你自己的具身模型 Spotter 从不训练策略,所以接入新的具身模型只需要部署服务并注册: 1. **用相同的 RPC 接口提供服务**,参考 `rpc/policy_server_pi05.py`:`GET /health`,以及 `POST /v1/infer`,接收 `InferenceRequest`(任务描述、种子、观测图像和机器人状态),返回包含动作块的 `InferenceResponse`(见 `rpc/protocol.py`)。 2. **注册策略类型**,照着 `cosmos` 和 `pi05` 添加:动作维度和每块步数在 `recovery_explore/cosmos_call.py` 和 `env_service.py`,服务启动在 `launch_svc.sh`,端口和默认值在 `spotter.sh`。 3. **选择监督粒度**:`WINDOW`(每次筛查覆盖的 chunk 数)和 `TEL_CHUNKS`(给判别器看的遥测行数)。 4. **运行** `bash spotter.sh run <你的策略类型> ...`。 ## 📈 输出 ```text recovery_explore/runs__<策略>/ ├── results.jsonl # 每集一行 ├── lane/driver.log # 各 lane 的进度日志 └── lane/jd-.../w/ # 第 k 个窗口给判别器看的画面 ``` | 字段 | 含义 | |---|---| | `task`、`seed`、`episode` | 对应的 episode | | `control_success` / `treatment_success` | 策略单独运行 / 加上 Spotter 是否成功 | | `interventions`、`judge_calls`、`screened_windows` | 执行的修复次数、判别器调用次数、被筛子放行的窗口数 | | `ctrl_s`、`treat_s` | 对照组和 Spotter 组的总耗时(秒;该组被跳过时为 `-1`) | | `model_s`、`screen_s` | 判别器调用和筛子调用的累计耗时(秒) | | `stale_steps`、`stale_ivs` | 仅异步模式:基于过时窗口做出的步数和修复次数 | ```bash bash spotter.sh summary # 所有 run bash spotter.sh summary pi05_sall500 bash spotter.sh summary robotwin_rt500 ``` ## 🧩 配置参考 | 设置 | RoboCasa · Cosmos | RoboCasa · pi0.5 | RoboTwin 2.0 · pi0.5 | |---|---:|---:|---:| | `FAMILY_OVERRIDE` | `cosmos` | `pi05` | `robotwin` | | 每块步数 | 16 | 25 | 16 | | `WINDOW`(判别窗口,单位:块) | 2 | 1 | 2 | | `TEL_CHUNKS` / `RT_TEL_CHUNKS` | 40 | 10 | 10 | | `MAX_INTERVENTIONS` | 8 | 8 | 5 | | `QWEN_KEEP_TURNS` / `COMPACT_AT` | 20 / 110000 | 20 / 110000 | 10 / 40000 | | 策略服务端口 | 8800 | 8900 | 9100 | | 策略服务 | `python -m rpc.server`(上游 Cosmos Policy) | `python -m rpc.policy_server_pi05` | `recovery_explore/robotwin_policy_server.py` | `spotter.sh run <策略族>` 使用对应那一列的取值,`robotwin_eval.sh` 使用 RoboTwin 2.0 那一列并加上 `--one-shot`,与发布结果一致;每一项都可以用环境变量覆盖。下表是共用参数,“论文取值”指 RoboCasa 的设置,上表的分策略族取值优先。 | 参数 | 论文取值 | 作用 | |---|---:|---| | `STEP_BUDGET_SCALE` | `1.8` | 步数预算倍率,对照组和实验组必须相同。 | | `SCREEN` | `1` | 开启筛子;`0` 表示每个窗口都调用判别器。 | | `SCREEN_CONFIRM2` | `1` | 连续两次标记才调用判别器;`0` 表示一次就调用。 | | `MAX_INTERVENTIONS` | `8` | 每集最多干预次数。 | | `ALLOW_RESET` / `MAX_RESETS` | `0` / `0` | 关闭回滚,保证各集可比。 | | `ENGINE` / `MODEL` | `qwen` / `qwen38` | 使用本地 Qwen 判别器;`ENGINE=api` 换成 GPT-6 Astra。 | | `COMPACT_AT` | `110000` | Qwen 对话压缩阈值(token)。 | | `QWEN_KEEP_TURNS` | `20` | 完整保留的最近判别轮数。 | | `FEWSHOT` | `0` | `1` 表示加一个示例(即 `--one-shot`),需要示例库。 | Qwen 只在介入的修复回合里思考,每次最多 `QWEN_THINK_BUDGET`(默认 `5000`)个 token;筛子和窗口判别都不思考,`QWEN_REPAIR_THINK=0` 则全部不思考,与论文设置一致。 **思考预算怎么选。** `QWEN_THINK_BUDGET` 按你的 Qwen 服务能承受的程度来设。预算越大,修复计划想得越充分,但每个修复回合 越慢;预算越小越快,但思考没想完就会被截断。建议取能让修复回合在 `ACT_DEADLINE` 之内完成的最大预算(GPU 较慢、或每个 副本带的 lane 较多时,也把 `ACT_DEADLINE` 调大),跑完后检查一下大多数修复回合**没有**被截断。每次修复回复都存在该集文件夹 的 `act_w*_a*_r*.json` 里,思考撞到预算上限时会记 `think_budget_hit: true`: ```bash python3 - <<'EOF' import glob, json files = glob.glob("recovery_explore/runs__/lane*/jd-*/act_w*.json") hit = sum(bool(json.load(open(f)).get("think_budget_hit")) for f in files) print(f"{hit}/{len(files)} repair turns hit the thinking budget") EOF ``` 如果超过一半被截断,就调大预算(或者加 Qwen 副本,让大预算也能跑得快)。在 RoboTwin 2.0 上,预算 2000 时大约 65% 的修复 回合思考被截断,5000 时大约 44%。 判别器的节奏另有几个开关,默认都是关闭或保守取值: | 变量 | 默认值 | 作用 | |---|---:|---| | `ASYNC_SCREEN` | `0` | `1` 表示判别器思考时策略继续执行,之后从最新完成的窗口接着判。更快,但判别器看到的是已经过去的窗口,这部分代价在 `results.jsonl` 里记为 `stale_steps` 和 `stale_ivs`。`2` 还会把策略限制在上一次检查之后 `ASYNC_K` 个窗口之内。 | | `MISS_GRACE` | `2` | 策略抓空之后,先给它自己重试的窗口数,之后判别器才可以接管。 | | `FIRST_IV_FRAC` | `35` | 第一次干预要等到策略至少抓空过一次,或者已经用掉这个百分比的步数预算。`0` 表示不设这个门槛。 | | `MONITOR_AFTER_BUDGET` | `1` | 干预次数用完后继续调用判别器,只做记录。`0` 表示不再调用。 | | `LATE_IV_FRAC` | `45`(RoboCasa)、`0`(RoboTwin 2.0) | 步数预算用掉这个百分比之后,不再开始*第一次*干预;之后的干预不受影响。`0` 表示关闭。 | | `PLAN_ROUNDS` | `5`(RoboCasa)、`3`(RoboTwin 2.0) | 一次干预里判别器最多可以发几段计划。 | **RoboCasa 的修复步骤。** 除了运动原语,RoboCasa 的判别器还有一个 `aim` 步骤:机器人用腕部深度相机向下看,找到上次抓空位置附近 (或判别器指定位置附近)的物体,沿物体短边抓取,稍微抬起检查是否抓牢,然后报告 `held`、`closed_empty`、`slipped`、`no_object`、 `too_wide`、`blocked` 或 `step_cap`。抓牢后紧接着交还给策略时,夹爪会保持闭合(也可以显式写 `{"op": "policy", "hold": true}`)。 像素目标写成单张相机图像内 0–1000 归一化的 `[行, 列]`(`PIXEL_FRAME=1000`;设为 `512` 则按原始像素),并且每个相机单独作为一张图给 Qwen 用来指点(`QWEN_POINT_TILES=1`)。判别器用到的信息全部来自相机和机器人自身的关节、夹爪读数。 改动 `STEP_BUDGET_SCALE`、`WINDOW` 或策略种类都相当于换了实验。比较不同 run 时只在同一个评测集上比较;由于策略的运行不能逐比特复现,应比较总成功率,而不是单集结果。 ## 🙏 致谢 - [RoboCasa](https://robocasa.ai):我们评测所用的仿真基准和场景资源。 - [Cosmos Policy](https://github.com/NVlabs/cosmos-policy):发布的 RoboCasa 权重及其策略服务。 - [π0.5](https://huggingface.co/DAVIAN-Robotics/pi05-robocasa-H50) 与 [LeRobot](https://github.com/huggingface/lerobot):RoboCasa 上的 π0.5 权重以及加载它的库。 - [RoboTwin 2.0](https://github.com/RoboTwin-Platform/RoboTwin) 与 [RoboTwin 2.0 的 pi0.5 权重](https://huggingface.co/motus-robotics/pi0.5_robotwin2):我们评测所用的双臂仿真基准和策略权重。 - [Qwen](https://huggingface.co/Qwen) 与 [vLLM](https://github.com/vllm-project/vllm):本地部署的筛子和判别器。 - [RPent](https://github.com/RLinf/RPent):`recovery_explore/` 中部分代码改编自它(Apache-2.0,见 `THIRD_PARTY_NOTICES.md`)。 ## 📜 许可证 本项目以 [MIT 许可证](LICENSE) 发布。`recovery_explore/` 中有部分文件改编自 RPent,仍遵循 Apache License 2.0,详见 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。 ## 📬 联系方式 有问题、想分享结果,或者想关注项目进展?欢迎加入交流群:
Spotter 微信交流群二维码
微信交流群
扫码加入
Spotter Discord 二维码
Discord
discord.gg/dcsEJHE4Pk
也可以在 [GitHub Discussions](https://github.com/zqc3117/Spotter/discussions) 提问和交流想法,在 [Issues](https://github.com/zqc3117/Spotter/issues) 反馈 bug,或发邮件联系 Qichao Zhao:[zhaoqc25@mails.tsinghua.edu.cn](mailto:zhaoqc25@mails.tsinghua.edu.cn)。 ## 📖 引用 ```bibtex @article{li2026spotter, title = {Spotter: Let the Embodied Model Lead, and the VLM Reflect for It}, author = {Li, Long and Zhao, Qichao and Yang, Yue and Xu, Fan and Wang, Zhe and Liew, Alan Wee-Chung and Qu, Chao and Shen, Heng Tao and Pan, Shirui}, journal = {arXiv preprint arXiv:2609.36808}, year = {2026} } ```