SURVEY · Multi-Turn Tool-Use RL · 5 篇

τ-bench · 多轮工具调用 RL — 5 个坑, 5 篇 paper

1τ-bench 是什么?
Tool-Agent-User Interaction Benchmark (Yao et al. NeurIPS 2024) — agent 一边和 LLM 模拟的真实用户多轮对话, 一边按领域政策调 API 改数据库。
USER
LLM 模拟用户
信息不全、会改主意、问反问题
对话
AGENT (被评测)
读 policy + 调 API
每步要么发消息, 要么 tool_call
API
TOOLS + DB + POLICY
真实业务后端
readwrite + Markdown 政策
τ-RETAIL
115 tasks
15 个 API (8 read + 7 write) · 500 用户 · 50 商品 · 1000 订单
τ-AIRLINE
50 tasks
13 个 API (7 read + 6 write) · 500 用户 · 300 航班 · 2000 预订
评分 r = raction × routput ∈ {0, 1} → DB 终态对齐 回复含 user 要的信息, 才得 1
25 张方 — 各从 τ-bench 的一道难题出发
挑战 A · 失败全丢R=0 的轨迹 30 步全白跑, 0 梯度
Fission-GRPO
从断点 + 错误诊断重新采样, 教模型"调错了要纠错"
挑战 B · 谁背锅?30 步只有终态 0/1, 不知哪步该改
TARL
强模型给每个 turn 打分, 压成一个轨迹标量再喂 GRPO
挑战 C · 奖励越加越偏朴素 dense reward 反而比 sparse 还差
MT-GRPO
先做相关性体检: 跟最终成功同向才留, 反向直接扔
挑战 D · 用户太假训练时若用固定 prompt 假用户, agent 只学死套路
MUA-RL
训练时引入更强/更多样的 user simulator, 逼 agent "先澄清再动手"
挑战 E · 环境太少τ-bench 只有几百 task, 不够烧 RL
CodeGym
代码题改造: 函数=工具, unit_test=verifier, 合 13k 环境

[1] TARL: Process-Supervised RL for Interactive Multimodal Tool-Use Agents ByteDance Seed & JHU 2025.09

"请 LLM 给每个 turn 打分, 再注回 PPO" 听起来很对 — 但直接训练发散。这篇 paper 提出: judge 还是请, 但塌成一个整轨迹标量再喂 GRPO。
τ-bench 30 轮工具调用任务, 终态只给一个 0/1 — 8B agent 跑完 32k token, 最后只知"订单办对没办对", 中间错在哪个 turn 全部埋了。直觉解法: 请 GPT-4.1 给每 turn 打个 PRM 分, 当 dense reward 注回该 turn 喂 PPO。听起来更密、信号更足。论文直接试了一遍:
只给终态 0/1 (sparse baseline)
信号稀薄但至少不污染梯度。8B 学生 GRPO 能从 42.6 慢慢爬。
51.3 τ-Retail pass^1
Per-turn judge 注入 PPO
judge 一次失败级联反复扣分, 后面所有 turn 的 advantage 都被同一个错污染, 梯度方向被一两条 trajectory 拖偏。
训练发散 (curve 直接掉)
问题不在 "judge 不准", 而在 每个 turn 各算 advantage 这套机制本身扛不住 judge 的局部偏差。一条 30 turn trajectory 里 judge 只要在某一个失败 turn 上多扣几分, 这个错就会顺着该 turn 所属的 group 归一化传给整条 trajectory 的下游 turn — 因为 PPO 的 per-turn advantage 是组内 z-score, 一个异常值就会把均值标准差都拽歪。结果是训练对 judge 噪声极度敏感, 一两条带噪 rollout 就能让整 batch 梯度方向反转。
跑完整条 trajectory 后离线请 GPT-4.1 一次, 对每个 turn 输出 ri ∈ {−1, 0, +1}: +1 = 推进任务 / 0 = 中性 / −1 = 重大偏离 (如 policy violation, 工具误用)。**关键**: 不把 ri 挂回 turn token, 而是按 "10 : 5 : cap-5" 三路塌缩成一个 trajectory-level 标量 R̃。整条轨迹只有一个 R̃ 进 GRPO 算 group advantage, 所有 agent token 共享同一个 A — judge 噪声被压在一处, 无法 per-turn 放大。
三档塌缩规则作用
10 · R_term终态 verifier 给的 0/1 ×10✓ 真相压顶, 权重最大
5 · 𝟙[∃ −1] · (−1)整条最多扣一次, 见 −1 就扣✓ 不可饶恕的错
clip(Σr/T, ±5)0/+1 信号先 /T 归一, 再 clip ±5✓ 过程信号, 防长度偏置
per-turn 注入把 ri 直接挂该 turn token 当 dense reward✗ 扔 (训练发散)
5-turn rollout GPT-4.1 judge 打分 塌成一个 R̃ GRPO t=1: search t=2: ask user t=3: policy 违规 t=4: refund t=5: confirm "这 turn 推进了吗?" 每 turn 输出 r∈{−1,0,+1} r = [0, 0, −1, +1, +1] 每条至多 1 个 −1 防失败级联 10 · R_term 终态真相压顶 −5 · 𝟙[∃ −1] 单次重罚 clip(Σr/T, ±5) 过程信号 + 防长度偏 R̃ ∈ [−5, +15] → GRPO
光有 R̃ 还不够 — 纯 τ-bench 训练会让 agent 越训越"省话", "wait" 这种 reflection token 频率快速下降, CoT 缩短退化成 short tool-call。论文在 batch 里按比例混入 DeepScaleR 中等难度数学题 (只用终态 0/1 verifier, 不走 judge), 把"长思考肌肉"绑定住。定量上: TARL 单独贡献 51.3 → 53.9, 再混 MATH 才推到 57.4 — 两者各贡献约一半, 是一个很便宜的正则项。
打个比方: 考试老师不每题判 (太碎, 一处错连带一片), 也不只判最后大题 (太疏, 中间过程一片黑)。而是收完整张卷子一起看 — 每题快划「正确 / 无功无过 / 严重偏离」三档, 但全卷只允许扣一次「严重偏离」红叉, 第二次起不再追加。最后总分 = 大题对错 ×10 − 是否吃过红叉 ×5 + 普通题平均 (上限 ±5)。学生拿到的是一份"对整张卷子的评价", 不是"对第 17 行的评价"。另外: 老师还在期末模考里夹几道纯数学题, 防学生只刷专业题忘了怎么写长推理。
τ-RETAIL PASS^1 (8B)
51.3 → 57.4
+6.1pp · 与 GPT-4.1 teacher (60.9) 仅差 3.5; pass^4 27.0 → 33.9
QWEN2.5-OMNI 语音模态
14.8 → 37.4
+22.6pp · 即便纯文本数据训练也能拉到 32.2 — tool-use 寄存在语言层, 不在模态层
反直觉的核心证据: per-turn 注入直接发散, 轨迹级聚合反而稳。一句 takeaway: bitter lesson 在 agent RL 上的又一次复读 — 信号越聚合, 抗噪能力越强
想看公式细节? 点开 ↓

TARL 塌缩公式 (γ=λ=1, advantage 退化成 trajectory return − group baseline):

$$ \tilde R(\tau)\;=\;10\cdot R(\tau)\;-\;5\cdot \mathbb{1}\!\left[\exists\, r_i=-1\right]\;+\;\mathrm{clip}\!\left(\tfrac{1}{T}\!\sum_{i:\,r_i\in\{0,1\}}\! r_i,\ -5,\ 5\right) $$

怎么读: 第一项 ×10 把终态真相放大压顶 (远高于过程); 第二项 −5 是 major deviation 红叉, 单条轨迹最多扣一次; 第三项把 0/1 turn 信号先 1/T 归一防"30 turn 自然分高", 再 clip ±5 不让过程压过真相。R̃ 落在 [−5, +15], 给 group-relative advantage 留足 spread。

负向消融 (三个"更高级"的方案全被自己 KO, 这是论文最有教育意义的部分):

  • PPO + per-turn assignment — 训练不稳, 效果劣于 trajectory-level
  • Top-20% 高熵 token 选择性 RL — 测试集无收益
  • Real-time intervention (judge 在 rollout 中实时打断) — KL 爆炸, 训练崩盘

关键超参: 单任务最多 30 turn / context 32768; batch 128 task × 4 rollout; APIGEN-MT-5k 下采样 ~3000 条; ~250 step 收敛; user simulator = GPT-4 ReAct; 语音模态用 SeedTTS 把对话翻成语音; 沙盒移植成 SQLite + RESTful + MCP。

顺带提一句成本: 每条 rollout 调一次 GPT-4.1 judge, 单 step ~128 次 API — 对 8B 模型来说 "judge 钱比卡钱贵"。

[2] MT-GRPO + IRC Amity Research 2026.04

"中间过程也给分" 听起来很对 — 但加错了反而比 sparse 还差 6.5pp。这篇 paper 提出: 先体检, 再用
直觉上, 给中间每个 turn 都打分 (dense reward) 应该比只给最后 0/1 (sparse reward) 学得更快。但作者实测发现 — 加得不对, 反而把训练带偏:
只给最后一分 (sparse)
中间 30 步全是空白, 信号稀薄但至少不会带歪方向
64.6 Airline pass rate
朴素 dense (每步都加分)
"读类工具 +0.3 / 写类 +0.1 / 多说话 +0..." 全收。结果方向打架: 11% 的 turn 死信号。
57.3 (−6.5 比 sparse 还差!)
同一条最终成功的轨迹里, 某个中间 turn 的局部分如果比同组其他 rollout 低, GRPO 会判它"不值得学" — 但它明明在成功轨迹里, 最终成败说"学它"。两个信号方向相反, 互相抵消, 形成死信号 (没梯度更新)。作者把这叫 Advantage Misalignment: 看似积极向上的中间步骤奖励, 跟"是否成功"的相关方向其实是反的, 加得越多越糟。
解药很朴素: 每档 reward 进 loss 前先问一句 — "出现这档奖励的轨迹, 是不是更容易最终成功?" 相关性低的当噪声扔掉, 方向反的降权。下表是作者切出的 7 档候选 reward, 体检后 msg 直接被扔, gold/state 留下:
reward 档判定规则体检结论
goldtool call 参数与标准答案完全一致✓ 留 (强正相关)
soft近似标准答案 (参数没完全 match)✓ 留
read读类工具 (查询, 不改 DB)✓ 留 (+0.3)
state写类工具且成功改了状态✓ 留 (+0.1)
msg对 user 回复 (不调工具)✗ 扔 (跟成败无关)
err工具调用报错✓ 留 (−0.1)
dup同一工具用同样参数重复调用✓ 留 (−0.2)
候选 7 档 成功率相关性体检 进训练 read +0.3 state +0.1 msg ? 方向不明 err −0.1 "出现 → 是否成功?" 每档算成功率相关性 ρ (PointBiserial) 成功率差不明显 → 方向反 → 降权 方向对 → GTPO 训练 局部分主导, 最终成败做弱锚点 两路信号 不打架
体检过的 reward 怎么进 loss? 这一步在论文里叫 GTPO — 是 MT-GRPO 框架里"具体怎么更新参数"的那一环。还是两路信号 (每个 turn 的局部分 / 整条轨迹的最终成败), 但调音量: 让局部分主导每个 turn 的更新方向, 让最终成败只在远处当弱指南针锚住大方向 — 两路就不再打架。
打个比方: IRC 像给员工 KPI 校准 ABC 档前, 先抽样看每档 KPI 跟最终业绩的相关性 — "晨会出勤率"这种几乎没相关性的指标, 哪怕看起来再"积极向上", 加进考核也只会把方向带歪。GTPO 像把"季度 KPI"折现到月度, 再留一个弱的年度指南针, 让月度细分指标主导日常但不被年终汇总盖过。
TAU-AIRLINE PASS
58.0 → 69.5
+11.5pp · 30B 模型, 逼近 Claude Sonnet 4.5 (70.0)
DEAD-TURN 比例
11% → 1.4%
死信号几乎清零, 中间步奖励真的开始干活
反直觉的核心证据: 不做体检, 朴素 dense 57.3 比 sparse 64.6 还低 6.5pp。Dense reward 不是免费午餐 — 校准, 是 2026 年 tool-use RL 的新基本动作
想看公式细节? 点开 ↓

GTPO hybrid advantage (γ=0.9 折现 / λ=0.3 outcome 占比, grid 调出):

$$ A^{\text{hybrid}}_{i,k} \;=\; \mathrm{GN}\!\Big(\sum_{l=k}^{K-1}\gamma^{\,l-k} r_{i,l} \;+\; \gamma^{\,K-k} o_i\Big) \;+\; \lambda\, A^O_i $$

怎么读: 把当前 turn 之后所有局部分 r_{i,l} 按 γ 折现累加 (越远的 turn 影响越弱), outcome o_i 也折现放末位, 整段做组内 z-score (GN); 外面再叠一个轻量的 trajectory outcome advantage A^O — λ=0.3 让它"在但不压人"。γ=1 等于不折现, λ=1 等于 outcome 跟 process 同等量级, 都会把音量调回打架状态。

IRC 体检公式:

$$ \rho_c \;=\; \mathrm{PointBiserial}\!\big(\,\mathbb{1}[c\in\tau_i],\ o_i\,\big),\qquad r_c \leftarrow \begin{cases} \alpha\,\rho_c & |\rho_c|>\delta \\ 0 & \text{otherwise} \end{cases} $$

怎么读: 把"轨迹里出没出现这档 reward (0/1)"和"最终成不成功 (0/1)"算 PointBiserial 相关系数 ρ_c — 数学上就是"出现组的平均成功率 − 没出现组的平均成功率"再做标准化。|ρ| 太小直接置 0 (msg 死在这步); 通过的还要查一道"当前梯度方向跟 ρ 同号吗?" — 不同号说明加这档 reward 跟优化方向打架, 降权处理。两步迭代 2–3 轮收敛。

顺带一个工程修复 (deep_equal): golden action 的参数比对用浅层 dict equality 会漏 ("3" vs 3 / None vs 缺字段), 作者写了一个 _deep_equal 规范化, 削掉 23.5% 的假阳性, V8 比 V6 再 +1.3pp。

[3] MUA-RL: Multi-turn User-interacting Agent RL for Agentic Tool Use Meituan + CAS + PKU 2025.08

"训练时把 user 压成 t=0 一段静态 prompt 应该够用" 听起来很对 — 但 Airline 永远卡在 23.5, 因为 agent 从没见过会改主意的真人。这篇 paper 提出: user 也得是 live LLM 进程, 跟 agent 同台采样。
直觉上, 把任务意图一次性塞 t=0 的 system prompt — "用户想退订单号 A123, 金额 $300, 给他办了" — 训练时 agent 拿到完整需求, 直接学怎么调工具完成就好。但 τ-bench 评测时 user 是 GPT-4 演的活进程, 只说半句话还会反问改主意, agent 必须先挖意图再用工具。两边 setup 错位:
SFT 录像 / 静态 prompt
teacher 跑完整 loop 录轨迹, 学生只模仿 agent 那一侧。看起来"看了完整对话",但 user 是固定的录音, 不是 live 进程
23.5 τ-Airline baseline
压平成单轮
意图全塞 t=0 prompt, 训练退化成"已知 A=3、B=5 求 C"。真 user 一开口只说"想退机票", agent 不会反问就崩
train ≠ eval (评测 user 是 GPT-4 live 演)
τ-bench 评测阶段本身就是三方对话: GPT-4 演 user、被测 agent、tool/DB。但过去一年的 agentic RL 训练阶段几乎都把 user 简化掉 — 要么 zero-shot 直接打榜不训, 要么 SFT 一份 teacher 录像, 要么把 user 意图全塞开头一段 prompt。结果是: agent 在训练时从没见过 user 在我策略更新后会改主意这种场景, 学到的只是"模仿录像里 teacher 反问的句式", 不是"在新 user 上学会反问"。换个真实 user 行为分布就崩 — 这就是 train/eval gap: 你的训练分布缺了一整个 axis (live user 的随机性), 模型自然 OOD。
解药很朴素: 把 env 拆成两个独立 LLM 角色 — 一个演 user (会只说半句话、会反问、会改主意), 一个演工具响应 (或直接挂真实 MCP server)。Agent 居中, 每回合面对的是不知道下一句会怎么追问的"活世界", 必须自己反问、调工具、再回话。下表对比 4 种 user 接入方式, 只有"live LLM 进程"能复刻评测分布:
user 接入训练时表现体检结论
Live LLM每回合 GPT-4o 现场生成, 会改主意✓ 留 (复刻评测)
静态 prompt意图压成 t=0 一段, 后续 agent 自言自语✗ 扔 (无反问需求)
SFT 录像固定对话历史, user 那侧不再回话✗ 扔 (off-policy)
固定脚本规则模板出 user 反应, 行为分布窄✗ 扔 (模板可背)
User-LLM (GPT-4o) Agent (训练对象, 8B/32B) Tool / DB "想退一下机票" 意图不全 会反问 / 改主意 "订单号 A123" (被 agent 反问后才给) Agent 居中 ① 反问订单号 ② tool_call ③ 改 DB 边问边调 订单 + 余额 JSON 响应 (SQLite 模拟) hash(DB_final) ==? R ∈ {0, 1}
三角 rollout 解决了"训练 setup"; 接下来"怎么算 reward"这一步, MUA-RL 反其道而行 — 砍掉所有 shaping, 只判 DB 终态对不对, R ∈ {0,1}。τ-bench 原本除了 DB 终态还有第二道关 (agent 回复 user 要包含规定标准串, 比如"退款已提交 $300"), 同时奖励两件事会让 agent 学会先复读模板字符串骗分, 再随便调几个工具的捷径。砍掉文字关后, 必须真把工具用对才有分 — 文字怎么聊不打小算盘。
打个比方: 旧 setup 像"已知 A=3, B=5, 求 C, 同时复读一句标准话术算满分"; MUA-RL 是"客户聊天提需求, 你问出 A、B, 调工具算 C, 老板只看客户账户改对没 — 改对发奖金, 怎么聊、措辞标不标准, 老板不管"。三角 rollout 给的是"客户是活的"这个 setup, 极简 reward 给的是"老板只认结果"这个指挥棒, 两条加一起把训练对齐到真实生产分布。
TAU2 RETAIL (Qwen3)
32B → 反超 235B
67.3 vs 64.9 · 7× 参数被 setup 翻盘
τ-AIRLINE
23.5 → 45.4
+21.9pp · baseline → MUA-RL
反直觉的核心证据: 不动算法 (GRPO 本体没改, KL β=0.001, G=8), 只把 user 接成 live LLM + 砍掉文字 shaping, 32B 就反超 235Bsetup > reward shaping > 参数量 — 把环境改对, 小模型能吃大模型
想看公式 + 超参细节? 点开 ↓

极简 reward 形状 (没 shaping、没 critic、没格式分):

$$ r_i \;=\; \mathbb{1}\!\big[\,\mathrm{hash}(\mathrm{DB}_i^{\text{final}}) = \mathrm{hash}(\mathrm{DB}^{\text{ref}})\big] $$

怎么读: 每条 rollout 跑到 done, 把 agent 改过的 DB 终态 hash 一下跟 reference DB 比, 一致给 1 不一致给 0, 喂回 GRPO 算组内 z-score。没 dense step reward、没 critic、没文字模板分 — 文字关砍掉是因为它跟工具调用并列时, agent 会优先学复读模板的捷径 (文字模板比工具好骗)。

关键超参: G=8 (32K context × 30 turns 显存能塞下); KL β=0.001 (多轮 tool use 需要大量探索, 强 KL 会把 agent 锁回 cold-start 模式); 单任务最多 30 turns, token 上限 32768; rollout 收敛后稳定在 21-23 turns。User-LLM = GPT-4o-2024-11-20; Tool-LLM 演工具或直接挂真实 MCP server; cold-start ~2000 条 (人 + DeepSeek-R1 双重核验) SFT 打底, 再上 GRPO; 165 个训练任务 × 25 epoch ≈ 33k trajectory。

消融对照: RL-only > cold-start-only (Retail 61.6 vs 58.2), 但二者叠加才到 67.3 — SFT 模仿轨迹会以偏概全, RL 探索才是真在挖新行为。14B 模型在 Telecom 拿 33.4 直接压过 GPT-4o 的 24.1, 再次印证 setup > 参数量。

[4] CodeGym — Generalizable End-to-End Tool-Use RL with Synthetic Environments ByteDance Seed × CMU 2025.09

"tool-use RL 卡在算法" 听起来对 — 但同样的合成数据下 SFT 学到 65.6, 但 OOD 一动不动 (42.3 → 42.3)。这篇 paper 提出: 卡的不是算法, 是没足够多可自动打分的环境 — 把代码题改写成 POMDP, 一次合成 13k env。
直觉上, tool-use RL 训得不好就调算法 — 改 GRPO advantage 函数、加 critic、做 reward shaping。但作者实测发现: 同样的合成数据下, SFT 抄答案学格式能把训练集刷到 65.6, OOD 却完全不动 (42.3→42.3); RL 也能把训练集拉到 81, 但同时 OOD 真的 +7.3。差距不在算法, 在 训练 env 数量太少:
直接拿真实 benchmark 训
τ-bench / ALFWorld 一共就几百条。RL 要的"百万次完整轨迹 × 0/1 打分"压根填不满, env 一旦稀缺, 流水线 scale 不动。
几百条 (域单一, 一换工具集就跌)
SFT 一份 ReAct 数据集
学到的是"Action / Observation"格式, 不是"该不该调 / 调哪个 / 调完看啥"的决策。看上去 in-domain 漂亮, OOD 直接退化成抄不到的题。
65.6 / 42.3 (in-domain / OOD, OOD 不动)
人对 RL 失败的本能反应是"loss 是不是写错了" — 加 critic、调 advantage、做 reward shaping。但 CodeGym 的反证很硬: 同样的合成数据、同一个 base model, 抄答案 SFT 把训练集刷到 65.6 但 OOD 完全不动, RL 把训练集刷到 81 同时 OOD +7.3。两条曲线的差异不在 loss, 在数据本身是否能产生有区分度的 rollout。瓶颈不是 GRPO loss 写得不够细, 而是没有足够多样的"可自动打分"环境 — 一个 RL pipeline 要 scale, 真正缺的是百万级 × 多领域 × 可自动 verify 的训练 env, 不是新算法。
反直觉的切入点 — 代码题已经是被人类严格分解过的"原子动作合集": 每个 helper function 是一张工具卡, 每段 main flow 是一份说明书, unit_test 天然是 0/1 verifier。CodeGym 让一个强 LLM 做两件事: Stage A 对每道题做语义抽取 — 函数变 tool 并自动配 docstring, if/for 流程变 state transition, 题里的隐式数据结构作为 agent 看不到的全局 state, observation 只暴露工具返回值, 一道题就成了标准 POMDP。Stage B 让出题人自己解 10 次 (pass@K=10), 至少 1 份能全过才采纳, 全军覆没的直接丢, 同时把这份 solution 留作 oracle trajectory。下表对比哪些能留下:
合成 env 类型判定规则体检结论
函数→toolhelper 函数自带签名 + docstring, 天然 schema✓ 留 (无歧义)
unit_test→R题目自带测试用例, 终态全过 = 1, 否则 0✓ 留 (verifier 免费)
pass@10 ≥1LLM 自解 10 次, 至少 1 次 unit_test 全过✓ 留 (存在可达解)
pass@10 = 010 次全军覆没, 可能题面歧义 / 工具不自洽✗ 扔 (假环境)
tools < 4少于 4 个 distinct tool 的轨迹本质是 RAG✗ 扔 (学不到 orchestration)
leetcode-like Stage A 抽取 Stage B 过滤 13k env → GRPO 代码题 def helper(...) if / for / while unit_tests 函数 → tool + docstring if/for → T(s,a) 隐式 state unit_test → R 终止 0/1 pass@K=10 LLM 自解 10 次 ≥1 份全过 → 全军覆没 → 13k env 80k+ tasks 6.5 tool / env 44 step / 轨迹 → GRPO G=8
合成出来的 env 并不都好用 — 太简单 (全过) / 太难 (全挂) / 太短 (步数不够) / 工具太少 (退化成 RAG) 全都喂不出梯度。作者总结了 4 个 magic number 把 env 卡在"GRPO 组内方差最大"的甜区: T_min=10 (低于 10 步学不到 long-horizon), T_max=256 (再长 reward 信号被稀释), distinct tools ≥ 4 (少于 4 个本质是 RAG), 难度过滤 ≤ 25% (Qwen2.5-32B 4 次尝试解出率 ≤25%, 是组内方差最大的甜区, 太简单全 1 太难全 0 都没对比)。再叠一个工程修复 trial-then-overwrite: 工具执行可能崩 env, fork 一份状态去试跑, 跑成功才覆盖, 跑挂把异常作为 observation 返回 agent — 既保 server 不污染, 又给 agent 一个"调错了要自己纠"的学习信号。
打个比方: 训厨师不必每天去米其林后厨实习; 只要给他切丁 / 焯水 / 爆香 / 收汁这种原子动作卡, 让他在自家厨房反复拼组各种菜谱, 到了真餐厅依然会做。代码题就是这种已经被人类严格分解过的原子动作合集 — 每个 helper function 是一张工具卡, 每段 main flow 是一份说明书。pass@K=10 是收菜前先自己试做一遍 (做不出来的废菜谱不要), 4 个 magic number 是挑题的甜区 (太简单太难都不练手), trial-then-overwrite 是"试做切坏不毁砧板"的安全网。
6 OOD BENCHMARK AVG
42.3 → 49.6
+7.3pp · 干净 OOD; τ-retail +13.0 · ALFWorld +14.0
SFT 同合成数据对照
42.3 → 42.3
in-domain 65.6 漂亮, OOD 一动不动 — 格式不是技能
反直觉的核心证据: 同合成数据下, SFT 把训练集刷到 65.6 但 OOD 42.3→42.3 完全不动, RL 把训练集刷到 81 同时 OOD +7.3。论断: 工具使用是一种可被 RL 训练 + 跨 domain 迁移的技能, 不是格式问题 — 缺的从来不是新算法, 是百万级、可自动 verify 的训练 env。
想看 POMDP 形式化 + magic number 细节? 点开 ↓

env 形式化 (每个保留 env 是一个标准 POMDP, reward 只在终止时给一次):

$$ \mathcal{E} \;=\; \langle S,\,A,\,T,\,R,\,O\rangle,\qquad R(s_T) \;=\; \mathbb{1}\!\left[\,\mathrm{unit\_tests}(s_T) = \text{all pass}\,\right] $$

怎么读: S 是代码题的全部内部变量, agent 看不到 (部分可观测的来源); A 是每步选一个 tool + 参数; O 是 tool 返回值; R 在终止时跑全套 unit_test, 全过给 1 否则 0。GRPO 本体没动, 改的只是 env 接口和 reward 来源 — 用 unit_test 当 verifier, 组内 z-score 当 advantage。

4 个 magic number 卡甜区: T_min=10 (低于 10 步学不到 long-horizon 规划), T_max=256 (再长 context 撑不住, reward 信号被稀释), distinct tools ≥ 4 (少于 4 个工具本质是 RAG), 难度过滤 ≤ 25% (Qwen2.5-32B 在该题 4 次尝试解出率 ≤25%, 卡在 GRPO 组内方差最大的区间; 太简单全 1 没对比, 太难全 0 没对比)。

难度增强 — 主动隐藏部分输入: 为了防止长 CoT 模型 (如 QwQ-32B) 直接靠脑内推导绕过工具, CodeGym 会主动把题目部分输入藏起来, 必须 agent 调相应工具才能查到。这条 trick 把"工具当摆设硬推"这条捷径堵死, 强迫 agent 真的走 tool-use 路径。trial-then-overwrite 则保证 13k 并发 env server 在工具崩溃时不污染 — 这些都是 production 级部署必须解的工程问题, 不是 paper-only 把戏。

[5] Fission-GRPO CUHK + 小红书 2026.01

"调细 reward (F1 / part credit) 能救全错样本" 听起来对 — 但 8 条全错时方差仍然是 0。这篇 paper 提出: 不是 reward 不够细, 是样本本身没信号差, 必须从样本生成那端做手术 — 把失败现场拼上诊断再重采。
1.7B 这类小模型撞到工具 schema 错就陷入幻觉重试死循环 — 参数缺了、值越界了, 它会一遍遍重复几乎一样的失败 call 直到 context 耗尽。结果一组 G=8 rollout 全部 R=0, 组内归一化后 advantage 也是 0, 这条样本对参数完全没贡献。直觉补丁有两条, 但都不彻底:
调细 reward (F1 / part credit)
把奖励改成"半对也给点分"。听起来合理 — 至少有方向感了吧?但 8 条全错时, "0.3 vs 0.3 vs 0.3" 仍然方差为 0
方差仍 = 0 (组内 z-score 全归 0)
预收集错误数据集 SFT
事先攒一批失败轨迹做监督学习。听上去 cheap, 但策略一更新, 它自己犯的错就漂走了, 数据集马上 off-policy。
off-policy (策略改 → 错误分布漂)
GRPO 的核心机制是组内相对优势 — 每条 rollout 跟同组其他 rollout 比, z-score 出 advantage。这套机制的致命软肋: 一旦 G=8 全错, R 全 0, 不管 reward 算得多细 (binary / F1 / part credit), 组内 mean 和 std 都是常数 → z-score 全归 0 → 整组样本零梯度。问题不在 reward 表达力, 问题在样本本身没有信号差。再细的 reward 也救不回方差 0 的样本 — 必须从样本生成那一端做手术, 让"全错"裂变出"有的修对、有的修错"的对照组。
核心动作三步: (a) 把失败轨迹 τ_err 当"案发现场"留住; (b) 让老师补一段诊断反馈 f, 拼成新 prompt x_corr = [原 prompt; τ_err; f], 塞进 LIFO buffer (后进先出, 优先消费最新失败); (c) 触发条件到时, 在 x_corr 上重采 G'=8 条 recovery rollout, advantage 只在这 G' 条 fission group 内部做 z-score, 完全不和 Stage 1 那批原始失败混算。这一刀很关键 — 一旦混算又会被一大堆 0 拖死, 关起门来在"看了诊断之后再生成"的这一小组里互相比, 哪怕绝对分都不高, 只要相互之间有差距, 梯度就回来了:
归一化方式判定规则体检结论
fission groupG'=8 条 recovery 内部独立 z-score✓ 留 (组内有方差)
LIFO buffer失败按"最新优先"出队, 接近当前策略分布✓ 留 (on-policy 近似)
混算 + Stage 1把 G' 条 recovery 跟 G=8 条全错混在一起归一化✗ 扔 (大堆 0 拖死方差)
预收集 SFT事先攒错误轨迹做监督训练✗ 扔 (off-policy 漂移)
Stage 1: G=8 全错 Error Simulator 诊断 Stage 3: G'=8 恢复 τ₁ call(...) R=0 τ₂ call(...) R=0 τ₃ call(...) R=0 ⋮ (×8) τ₈ call(...) R=0 advantage 全 0 → 无梯度 Error Simulator S_φ (Qwen3-32B SFT, 96% 不泄 GT) 输出诊断 f: "param status expects OPEN" x_corr = [x; τ_err; f] τ'₁ 修对 R=1.6 τ'₂ 又错 R=0 τ'₃ 部分对 R=0.9 ⋮ (×8) τ'₈ 修对 R=1.4 组内有方差 → 梯度回来
反馈 f 从哪来? 格式错走确定性模板 ("JSON 缺字段 status"); 语义错走一个独立训出来的诊断模型 S_φ — 用 Claude Sonnet 4 当老师, 在 Qwen3-32B 上 SFT 出来。它的输入是 (system+tools, 历史对话, ground-truth call, 失败 call), 输出贴近运行时报错的诊断串 (如"parameter status expects value OPEN")。硬约束: 不许直接复读 ground truth 的值, 只能给"提示性"信号; 否则训练就退化成抄答案, 完全学不到"挽救"。人评结果: 96% 严格不泄露 (κ=0.71)。Error Simulator 是 Fission 框架"裂变 → 诊断 → 重采"里"诊断"那一环, 跟 fission group 归一化配合 — 没有它, 重采 rollout 没方向; 没有 fission group, 诊断给完也被 Stage 1 一堆 0 拖死。
打个比方: 像围棋复盘 — AI 自己下完输了, 老师把棋谱倒回那一步关键失误, 在旁边写"这里黑棋形势其实领先 3 目, 问题出在你下一步"。然后让 AI 从这一步重新下 8 次, 8 个新下法互相比较, 谁救回来谁就拿正分, 谁继续乱来谁就拿负分。原本"整盘输 = 一个 0 分样本"被裂变成"8 个能互相比较的小样本", 训练信号一下从干涸变密集。而且老师只点哪里错, 不直接告诉这一步该走哪 — 否则就成抄答案了。
BFCL v4 多轮 (Qwen3-8B)
28.75 → 46.75
+18.0pp · 同算力 vanilla GRPO 42.75, Fission 再 +4.0
小模型 (Qwen3-1.7B)
7.80 → 20.38
+12.58pp · long-context 错误恢复率 +11.8, 不是教模型多 retry
反直觉的核心证据: 同尺寸 ToolACE-2-8B (37.0) / BitAgent-8B (37.75) 被 Fission-GRPO 各超 ~10 分。一句 takeaway: RL 视角下的"无信号样本"通过追加 context 转成"有信号样本" — 稀疏的全错信号被裂变成密集的"如何挽救"梯度
想看公式 / 超参 / Error Simulator 细节? 点开 ↓

1. Fission group advantage (GRPO 本体没动, 只是归一化范围变了):

$$ \hat{A}^{\text{fis}}_{i,t} \;=\; \frac{R(\tau_i)\,-\,\mathrm{mean}\big(\{R(\tau_j)\}_{j=1}^{G'}\big)}{\mathrm{std}\big(\{R(\tau_j)\}_{j=1}^{G'}\big)},\quad G'=G=8 $$

怎么读: τ_i 是从 corrective context x_corr 出发的第 i 条 recovery rollout, mean/std 只在这 G'=8 条 fission group 内算, 完全不掺 Stage 1 那批原始失败。哪怕这 8 条绝对分都不高, 只要相互之间有差距, z-score 就出非零 advantage, 模型就学到"哪种修法比哪种修法好"。

2. Reward 形状 (三项加权 + 退火, R ∈ [0,2]):

$$ R(\tau,t) \;=\; \tfrac{1}{3}\big[\,w_{\text{fmt}}(t)\,R_{\text{fmt}} + w_{\text{corr}}(t)\,R_{\text{corr}} + R_{\text{len}}\,\big] $$

怎么读: R_fmt ∈ {0,1} 查 schema 合法性; R_corr = 0.5·𝟙(N=N*) + 0.5·F1(matched args), 一半奖励"调用次数对上 ground truth", 一半奖励"参数集合 F1"; R_len 是 piecewise Gaussian 抑制 retry loop 把 context 写爆。权重退火: w_fmt 沿训练步 3 → 2, w_corr 反向 2 → 3 — 早期管格式, 后期管语义。

3. 关键超参: G' = G = 8 (沿用 GRPO 标配); Trigger interval N ≤ 6 稳定 — 更大 buffer 就 off-policy 了, 在 Miss-Param / Long-Context 上掉点; δ_corr = 1, 即只要不是满分就算"语义错", 全部纳入 fission, 避免"差一点点"被当正例污染。

4. Error Simulator 训练: ~2K 三元组 (system+tools, 历史对话, ground-truth call τ_gt, 失败 call τ_err, Claude Sonnet 4 写的老师诊断), Qwen3-32B 上做 SFT。硬约束"不准复读 τ_gt 的值" — 训练数据本身就只保留满足这条约束的样本; 人评 2 个标注员 κ=0.71, 96% 严格不泄露。跨域质量 (Claude judge 1-5 分): 错误定位 4.21→3.97, 可执行性 4.26→4.12, 不泄露 4.88→4.83 — 跨域略掉但没崩。数据 pipeline: 从 ~2k 候选 query 经"双 LLM 过滤"挑出 630 条高质量训练 query。

横向对照

方法信用粒度user in rollout?合成 env?关键奖励工程主结果
TARLturn-level → 轨迹标量否 (脚本)judge ±1 → 10:5:cap5 聚合τ-Retail Qwen3-8B +6.1, Omni 语音 +22.6
MT-GRPO + IRCturn-level (经校准)PointBiserial 校准 + GTPO 折现Tau airline 30B-A3B +11.5pp 逼近 Claude
MUA-RLoutcome (DB hash)是 (GPT-4o)部分极简 0/1, 砍掉所有 shaping32B 反超 235B; Airline +21.9
CodeGymoutcome (unit-test)是 (13k envs)pass@K 过滤 + trial-then-overwrite6 OOD avg +7.3, ALFWorld +14.0
Fission-GRPO子轨迹 (fission group)Error Simulator 诊断回灌 + 退火Qwen3-8B BFCL +18.0, 1.7B +12.58

开放问题 & 发展趋势

1. 三件事的合体仍未出现。 没有任何一篇兼顾「turn-level reward + user-in-loop + 合成环境」三件事 — 把 TARL 的 judge、MUA-RL 的 user、CodeGym 的 env 拼在一起几乎一定有 paper。

2. 负样本利用还很初级。 只有 Fission-GRPO 系统用了失败轨迹; user-in-loop × fission(让 user simulator 在失败点变换意图)几乎无人做过。

3. Reward 校准还停在线性层。 IRC 用 PointBiserial 是「线性相关性」检查; 非线性 / 条件相关性(某些 reward 只在特定 task family 上才正向)尚未被刻画。

4. Trajectory-level scalar 复辟。 TARL 反证 per-turn advantage 注入不稳; IRC 用 hybrid 把 outcome anchor 留下; Fission 在 fission group 内独立归一化 — 三者隐含同一个原则: outcome reward 永远是地基,dense signal 是装饰、不是承重墙。

5. 「Setup > Algorithm」共识形成。 MUA-RL 的 32B>235B、CodeGym 不动算法只动环境就拿 +7.3 — 五篇里的强 baseline 都不是新算法、而是新 setup。GRPO 已经够好,差在喂给它的数据。

Limitations: (1) 5 篇全部在 τ-bench / BFCL 这一窄 benchmark 上验证,真实生产 agent(长尾意图、跨语种、GUI 操作)效果未知; (2) 合成数据(CodeGym) / 模拟 user(MUA-RL) / Error Simulator(Fission) 各自带「拟真度」债务,但都没系统衡量过这种 sim-to-real gap; (3) 5 篇 reward 设计的可组合性没有 head-to-head 对照 — 把 TARL 的 judge + IRC 的校准 + Fission 的裂变叠起来会不会冲突,仍是空白。