Do What You Say: Steering VLA Models via Runtime Reasoning-Action Alignment Verification · NVIDIA / CMU / U. Utah / U. Sydney · arXiv 2510.16281v2 (2026)
推理 VLA 模型虽然能生成正确的文本计划,但其动作执行常常"言行不一"——尤其在 OOD 场景。SEAL 提出一种无需重训练的运行时策略引导方法:同时采样多条动作序列,在仿真中前向预测结果,用预训练 VLM (GPT-4o) 验证哪条动作最忠实于模型自身的文本计划,再选择该动作执行。把策略的"动作多样性"从错误来源变为优势来源。
arXiv:2510.16281v2);运行时流程与 VLM Verifier prompt 核对自仓库 examples/libero/eval_libero_reason_sample.py。解读为学习者视角。~/projects/dwys(基于 openpi)| 项 | 内容 |
|---|---|
| 标题 | Do What You Say: Steering VLA Models via Runtime Reasoning-Action Alignment Verification |
| 单位 | NVIDIA / Carnegie Mellon University / University of Utah / University of Sydney |
| 核心问题 | Embodied CoT Faithfulness Gap:推理 VLA 文本推理正确,但动作执行偏离计划 |
| 核心方法 | Best-of-N 运行时策略引导 + VLM Verifier (SEAL = Steering for Embodied reasoning-Action aLignment) |
| Base Model | 基于 pi0 架构的推理 VLA (pi0-reason),使用 <think>/<act> token 自适应切换 |
| 三阶段 | Hypothesize (采样 K 条动作) → Predict (并行仿真预测结果) → Verify (VLM 评分对齐) |
| 关键结果 | 行为组合任务 +15%;ID 任务 94-97%;Visual-Viewpoint OOD +17%;推理时延 347ms (K=10) |
| 训练开销 | pi0-reason 微调 20h/8xA100;SEAL 推理阶段无需任何额外训练 |
| 特性 | Training-free · Model-agnostic · 与 Best-of-N / test-time compute scaling 兼容 |
大型 VLA 模型(如 pi0)通过视觉-语言骨干 + 动作头实现通用机器人控制。为解决长时序任务中的累积误差和复杂指令跟随问题,推理 VLA(Reasoning VLA)在动作生成前先产生中间文本计划——这是 LLM 中 Chain-of-Thought 的具身版本。
然而,即使文本计划完全正确,生成的动作序列仍可能偏离计划目标:
作者将此类比 LLM 中的 "CoT Faithfulness" 问题:
| 方法 | 验证信号 | 粒度 | OOD 泛化 |
|---|---|---|---|
| V-GPS [16] | 离线 Q-function | 固定长度 action chunk | 弱 (MUSE encoder 泛化差) |
| RoboMonkey [6] | 微调 VLM + 合成偏好标签 | action chunk | 中 (verifier 未开源) |
| SEAL (本文) | 预训练 VLM (GPT-4o) | 变长 plan-level 动作序列 | 强 (利用 VLM 常识) |
SEAL 的关键区别:不是验证单个短 chunk,而是验证整条从当前计划开始到下次 think 的完整动作序列。这自然对应"一个子任务"的粒度。
SEAL = Steering for Embodied reasoning-Action aLignment。一个三阶段的运行时策略引导框架,无需任何额外训练。
在每个推理步(文本计划更新后),SEAL 最小化对齐损失:
其中 Ralign 衡量未来观察 ot:t+H 是否满足文本计划 l̂r 描述的子目标。
从 pi0-reason 模型并行采样 K=10 条候选动作序列:
关键特性:
维护 K=10 个向量化仿真环境,与 Hypothesize 阶段交错执行:
利用预训练 VLM (GPT-4o) 作为对齐 reward 的 proxy Rψ:
基于 pi0 架构(PaliGemma VLM + flow-matching action expert),增加推理能力:
λreason = λact = 0.5
无需人工标注子任务边界(不同于 OneTwoVLA [8] 需要手动标注):
标注格式(用于训练数据):
Plans: 1. Pick the alphabet soup 2. Place it in the basket 3. Pick the butter 4. Place it in the basket
What I have done: Pick the alphabet soup, Place it in the basket
Now I need to do: Pick the butter
每段标注包含 (l̂jr, t'j):子计划文本 + 该子任务结束的时间步。一个子任务的结束即下一个的开始。
GPT-4o 作为 verifier,使用结构化 prompt 引导逐步推理:
Verification: Success 或 Verification: Failure传统 VLA 的训练目标:
推理 VLA 将此分解为文本生成 + 条件动作生成,但两者并未显式优化对齐:
增加候选样本数 K 可以直接提升性能(类似 LLM 中 test-time compute scaling):
| K | ID 成功率 | Compose 成功率 | 推理延迟 (ms) |
|---|---|---|---|
| 1 | 89% | 38% | 147 |
| 2 | 92% | 44% | 167 |
| 5 | 96% | 48% | 246 |
| 10 | 97% | 53% | 347 |
延迟分解:Batch Action Sampling 86→184ms (亚线性);VLM Verification 61→163ms (线性)。瓶颈在 VLM 查询时间 (每次 7-10s,但异步执行)。
| 参数 | 值 |
|---|---|
| Training Batch Size | 128 |
| Training Steps | 30000 |
| Max Token Length | 415 |
| λreason / λact | 0.5 / 0.5 |
| Image Size | 224 × 224 × 3 |
| GPU | 8× A100 (~20h) 或 8× H100 (~10h) |
| 数据集 | 任务数 | Episode数 | 用途 |
|---|---|---|---|
| LIBERO-10-R | 10 | 379 | 最小集,基线对比 |
| LIBERO-100-Basket-R | 16 | 761 | 中等集,技能组合测试 |
| LIBERO-100-R | 82 (full LIBERO-100) | 4338 | 最大集,全面评估 |
所有数据集都通过 Gemini 2.5 Pro 自动标注推理信息。
| 组件 | 开销 | 说明 |
|---|---|---|
| pi0 vanilla 微调 | ~6h / 8xA100 | 无推理标注 |
| pi0-reason 微调 | ~20h / 8xA100 | 含推理标注的 SFT |
| SEAL 推理 | +0 训练 | 纯运行时,无额外训练 |
| VLM Verifier | GPT-4o API | 每个推理步 K 次 API 调用(异步) |
所有实验在 LIBERO 仿真基准上进行,每个任务 50 trials。三类评测:
| 评测块 | Benchmark / 任务 | 具体设置 | 为什么这样测 | 复现状态 |
|---|---|---|---|---|
| ID 基准 | LIBERO-10 | 训练集分别为 LIBERO-10-R、LIBERO-100-Basket-R、LIBERO-100-R;每任务 50 trials。 | 确认 SEAL 的 runtime verification 不会牺牲常规分布内成功率。 | 未本地复现;页面基于论文结果。 |
| 行为组合 | LIBERO-10-Compose / Basket-Compose / LIBERO-100-Compose | 组合已学对象、容器、动作阶段,构造训练中未见的行为组合。 | 检验“说的推理”和“做的动作”是否能在组合泛化时保持一致。 | 未复现。 |
| 语言 OOD | Lang-Rephrase / Lang-Object-Property | 改写指令、增加物体属性约束。 | 测 reasoning VLA 是否理解语言变化,以及 verifier 是否能过滤语言误解导致的错误动作。 | 未复现。 |
| 视觉 OOD | Visual-Scene / Visual-Viewpoint | 改变场景外观和视角;Viewpoint 是最难 setting。 | 测 runtime VLM verifier 在视觉分布变化下是否仍能判断“动作后果是否符合推理”。 | 未复现。 |
| Verifier 对比 | pi0-V-GPS vs SEAL | Q-function verifier 与 VLM verifier 对比。 | 证明离线 Q-function 在 OOD 组合上会过估计错误动作,VLM verifier 更适合语义一致性检查。 | 未复现。 |
| 方法 | 描述 |
|---|---|
| pi0 | Vanilla VLA,无推理,无验证 |
| pi0-V-GPS | 离线 Q-function + best-of-K action chunk |
| pi0-reason | 推理 VLA(SEAL 的 base model),无验证 |
| SEAL | pi0-reason + 运行时 VLM 验证 |
| 训练集 | 评测 | pi0 | pi0-V-GPS | pi0-reason | SEAL |
|---|---|---|---|---|---|
| LIBERO-10-R | ID (LIBERO-10) | 85 | 90 | 92 | 96 |
| LIBERO-10-Compose | 14 | 17 | 18 | 16 | |
| LIBERO-100-Basket-R | ID (LIBERO-10) | 85 | 89 | 86 | 94 |
| Basket-Compose | 11 | 13 | 23 | 26 | |
| LIBERO-100-R | ID (LIBERO-10) | 85 | 87 | 89 | 97 |
| LIBERO-100-Compose | 16 | 16 | 38 | 53 |
训练集 = LIBERO-100-R,评测 4 种 OOD 变体:
| 评测 | pi0 | pi0-V-GPS | pi0-reason | SEAL |
|---|---|---|---|---|
| ID (LIBERO-10) | 85 | 87 | 89 | 97 |
| Lang-Rephrase | 73 | 71 | 86 | 95 |
| Lang-Object-Property | 72 | 81 | 81 | 91 |
| Visual-Scene | 84 | 83 | 91 | 98 |
| Visual-Viewpoint | 28 | 23 | 25 | 45 |
对比实验展示了 Q-function verifier vs VLM verifier 的核心差异:
仓库基于 openpi 框架改造,核心改动集中在推理 VLA 数据集 + 运行时 SEAL 评测脚本。
| 路径 | 功能 |
|---|---|
src/openpi/models/pi0.py | pi0 模型定义 (PaliGemma + action expert) |
src/openpi/policies/libero_reason_dataset.py | 推理标注数据集的加载与处理 |
examples/libero/eval_libero_reason_sample.py | SEAL 核心实现:Hypothesize-Predict-Verify 循环 |
examples/libero/prompt_template_verifier.txt | VLM verifier 的完整 prompt 模板 |
examples/libero/vec_env.py | K 个并行环境 (Predict 阶段) |
examples/libero/utils.py | 工具函数:图像编码、API key、环境构建 |
eval_scripts/launch_libero_vla_reason_sample.sh | SEAL 评测启动脚本 |
scripts/train.py | pi0-reason 训练入口 |
eval_libero_reason_sample.py 中的核心循环:
# 并行推理 K 条动作序列 (batch_size = K)
obs_dict_np, previous_obs = get_pi_obs_dict_batch(all_obs, previous_obs, task_description, args)
policy_return_dict = client.infer(obs_dict_np) # WebSocket batch inference
# 模型返回 isthinking=True → 该序列完成(生成了<think> token)
policy_is_thinking = policy_return_dict.get('isthinking', [False]*args.batch_size)
# 当某序列完成时,提取其子目标文本
plan_string = policy_return_dict['thought'][i].split('Now I need to do:')[-1]
# 并行环境步进 (Predict)
vec_obs, vec_reward, vec_done, vec_info = vec_env.step(actions, np.arange(args.batch_size))
关键实现细节:模型服务使用 WebSocket 通信,batch 中每个元素独立 autoregressive 生成。当 <think> 出现时标记该序列完成。
test_reset_flags() 函数实现异步 VLM 验证:
# 异步验证 - 后台线程并行调用 GPT-4o
def test_reset_flags(reset_indices, initial_image, agent_images, wrist_images, instruction_text, args):
# 为每个候选序列启动独立线程
for idx in current_indices:
thread = threading.Thread(target=test_single_index, args=(int(idx),), daemon=True)
threads.append(thread)
thread.start()
# 单序列验证: 发送 3 张图 + subtask 文本给 GPT-4o
def test_single_index(idx):
b64_initial_image = optimize_image_for_api(initial_image, max_size=512)
b64_image = optimize_image_for_api(agent_images[idx][-1], max_size=512)
b64_wrist_image = optimize_image_for_api(wrist_images[idx][-1], max_size=512)
prompt = get_prompt(subtask_goal, "verifier")
response = session.post("https://api.openai.com/v1/responses", json={
"model": "gpt-4o-2024-08-06",
"input": [{"role": "user", "content": [
{"type": "input_text", "text": prompt},
{"type": "input_image", "image_url": f"data:image/jpeg;base64,{b64_initial_image}"},
{"type": "input_image", "image_url": f"data:image/jpeg;base64,{b64_image}"},
{"type": "input_image", "image_url": f"data:image/jpeg;base64,{b64_wrist_image}"},
]}]
})
# 解析 "Verification: Success" / "Verification: Failure"
verification_result = result_text.split("\n")[-1].strip()
if "SUCCESS" in verification_result: results[idx] = True
# 检查后台验证结果 (非阻塞)
def check_background_verification() -> int | None:
return _background_verification_result.get_nowait() # 返回通过验证的 index
# 主循环中: 一旦有结果立即执行
verified_idx = check_background_verification()
if verified_idx is not None:
# 用选中序列的动作在执行环境中前进
for selected_action in batch_action_plan[reset_index]:
exec_obs, exec_reward, exec_done, exec_info = env_exec.step(selected_action)
# 同步所有并行环境到选中状态
env_reset_sim_state = vec_env.get_sim_state(reset_index)[0]
vec_env.set_init_state(np.repeat(env_reset_sim_state, K, axis=0), np.arange(K))
libero_reason_dataset.py 中推理标注数据的加载逻辑:
class LiberoReasonDataset(LeRobotDataset):
# 关键参数
self.use_reasoning = data_config.use_reasoning # 是否使用推理标注
self.pred_reasoning_prob = 0.7 # 70% 概率预测推理内容
def _get_thought(thoughts: list[dict], step: int) -> dict:
"""根据当前时间步获取对应的推理标注"""
for thought in thoughts:
if thought['start_step'] <= step < thought['end_step']:
return thought # 返回包含 text plan 的 dict
训练时以 70% 概率让模型预测推理文本(对应 <think> 段),30% 跳过(增强鲁棒性)。
| 局限 | 具体表现 | 可能方向 |
|---|---|---|
| 依赖 Base VLA 质量 | 如果 K 条采样中没有任何好的动作序列,验证无用 | 更好的 base model / 更大 K |
| VLM 可靠性 | GPT-4o 对细粒度 gripper-object 接触/遮挡判断不准 | 针对具身场景微调 verifier |
| 延迟开销 | 每个 reasoning step 需额外 VLM API 调用 (7-10s per query) | 蒸馏 verifier / 量化 |
| 仿真依赖 | Predict 阶段需要环境模型(当前用 LIBERO sim) | learned world model / digital twin |
| 仅限 sim 验证 | 论文只在 LIBERO 仿真中验证,无真实机器人实验 | world model 支撑的真实部署 |
Q1. SEAL 的 "Embodied CoT Faithfulness Gap" 指的是什么?
Q2. SEAL 为什么不直接通过反向传播优化对齐 loss?
Q3. SEAL 的 Verify 阶段使用什么作为 alignment reward 的 proxy?
Q4. 为什么 V-GPS (Q-function) 在行为组合 OOD 场景下失败?
Q5. SEAL 的 Runtime Scaling Law 中,增加 K 的主要瓶颈是什么?
Q6. 为什么 SEAL 在大数据集上增益更大?