ReTool: Reinforcement Learning for Strategic Tool Use in LLMs

Feng, Huang, Qu, Zhang, Qin, Zhong, Jiang, Chi, Zhong · ByteDance Seed · 2025-04-15 · arXiv:2504.11536v2
关键词: tool-integrated reasoning · code interpreter · PPO · outcome reward · cold-start SFT · AIME · neuro-symbolic

速读卡片 (TL;DR)

一句话:ReTool 把 Python code interpreter 当作 deterministic verifier-tool, 用 cold-start SFT 教会基础格式后, 用 outcome-only reward 的 PPO 让 LLM 自己学会什么时候、用什么代码来辅助推理——结果在 AIME 2024 上 Qwen2.5-32B-Instruct 训 400 步就达 67.0%, 比同 backbone 的纯 text RL (40.0%, 1080 步) 又快又强, 并 emergent 出 "Oops, let me fix that" 的 code self-correction 行为。

67.0 vs 40.0
AIME 2024: ReTool vs text-only RL (Qwen2.5-32B)
400 vs 1080
training steps to convergence (~2.7× 更快)
−40 %
最终 response length 比 SFT 前缩短 (10k → 6k tokens)

立场:当 reasoning 任务包含大量算术 / 枚举 / 符号操作时, 长 CoT RL 是 token efficiency 上的死胡同; 让 RL outcome reward 直接信号化"调用 Python interpreter 是不是更好的决策", 就能在不引入 process reward 的前提下涌现出 strategic tool use。这是 Search-R1 把搜索当 tool 的 code-domain 对偶。


1 · 动机: 为什么长 CoT RL 在数学题上撞墙

1.1 历史脉络: 从 PoT 到 long-CoT RL, 再到"长 CoT 不够"

从时间线看, "让 LLM 算数学" 这件事在 2023–2025 之间走了三段:

2022 2023 2024 初 2024 末 2025 春 ① Prompt-only / SFT-only tool PoT · PAL · MathCoder · ToolFormer ② Long-CoT RL (pure text) o1 · DeepSeek-R1 · QwQ · s1 ③ RL + tool (本文 / Search-R1) ReTool · ToRL · Search-R1 CoT prompt PoT / PAL o1 launch DeepSeek-R1 ReTool / Search-R1 "加工具" 的位置从 prompt 一路下沉到 RL training loop
三段进化: ① 2022–2023 时代用 prompt 或 SFT 把 Python 嵌进 reasoning, 模型按教好的固定 pattern 调; ② 2024 long-CoT RL 把推理重心拉回纯文本, 但数学题的算术错误问题没解决; ③ 2025 ReTool/Search-R1 把"是否调工具"这一决策本身丢回 RL outcome reward 让模型自己学。

三段曲线的真正张力在第二段到第三段: long-CoT RL (R1-Zero 风格) 让模型把每一步算术都"用自然语言写"出来——但 LLM 对 9430 mod 7 这种多位数模运算的逐位推理本质上靠的是 token-level 的 implicit table lookup,错误率不为零, 且错一步导致后面整条 trajectory 报废。论文 Figure 6 的对比就是这个症状: 同一道四位数 mod 7 题, text-based reasoning 得出 N=5624 → Q+R=629 (错), CI-powered 得出 N=5694 → Q+R=699 (对)。

1.2 别的方案为什么不够 (对照表)

方案怎么做本质局限
纯 CoT prompting"让我们 step by step"算术误差累积, 没 verifier
PoT / PAL (prompt-only)固定让模型生成完整 Python 程序把 reasoning 全外包给代码, 失去 natural-language 推理的灵活性
ToolFormer / MathCoder (SFT)用 self-curated 含工具调用的轨迹做 SFT只学到训练分布里的固定调用 pattern, 不会自适应判断"该不该调"
DeepSeek-R1-Zero / QwQ (long-CoT RL)outcome reward + GRPO/PPO, 但纯文本超长 CoT (10k+ tokens), 算术 token 多但效率低
ToRL (concurrent, Qwen2.5-Math 1.5B/7B)RL+tool 在小模型上scale 上不去, AIME 表现仍 suboptimal
ReTool (本文)SFT cold-start → outcome-only RL, interpreter-mask, 32B scale填上了 "RL + tool + 大模型 + 大数据" 这格

关键观察是中间两行: SFT-tool 派和 long-CoT RL 派都看到了对方的缺陷, 但都没融合。SFT-tool 没有 outcome 信号, 只能模仿; long-CoT RL 有 outcome 信号, 但没工具。ReTool 的位置就是把这两件事在同一 trajectory内拼起来——模型一边写自然语言推理, 一边在合适的时机 <code>...</code> 出去, sandbox 跑完把 <interpreter>...</interpreter> 塞回上下文。

1.3 为什么这事不平凡

三件事让"RL + code interpreter"在工程上比想象的难:

  1. Mixed-source token 的 loss masking 必须做对。Trajectory 里既有 policy 自己生成的 token (会走梯度), 又有 sandbox 塞回来的 <interpreter> 段 (外部环境产物)。如果 interpreter 输出参与 loss, 等于让模型去"学"它本不该产出的字符——会立刻发散。论文用 Interpreter Feedback Mask 把这段从 loss 里 mask 掉。
  2. Rollout 必须 pause-resume。每次生成到 </code> trigger 都要冻结 KV cache → 把 code 拿去执行 → 把 stdout 塞回 context → 继续 generate。论文做了 KV-cache reuse: code 之前的 KV 不重算, 只增量计算 interpreter feedback 段的 KV, 这才让 32B + multi-turn rollout 可负担。
  3. Sandbox 必须 async + load-balanced。同步等 Python 跑完会让 GPU 闲置; 论文用 pod-pool 的异步 sandbox, 每个 worker 按容量主动 pull 任务。这跟标准 RL infra 不同——environment 不是单 process 而是分布式服务。
  4. Cold-start 不能省。从 Qwen2.5-32B-Instruct 直接做 outcome RL, 模型连 <code> tag 都不会输出, reward 全是 -1, RL 完全无法启动。所以必须先做 SFT on DCI 把"调工具的语法"灌进去。
  5. Reward 只能粗 (outcome-only)。论文显式拒绝加 "code executability" reward——加了反而会 reward hacking (模型只为生成可执行代码而不解题)。单一 sparse 信号反而促成多样行为。

把这五点凑齐, 才能让"模型自己学会该不该调 Python"这件事真的在 RL loop 里收敛。Figure 3 给出的训练动力学就是这五件事都做对了之后的结果: 平均 response length 先降后稳, code ratio 上升到 98%, code lines 升至 5×, code invocation timing 从 ~0.62 (响应中后段) 提前到 ~0.52 (前半段)——所有指标都指向"模型把 Python 当 first-class reasoning primitive"这件事真的发生了。

论文最锋利的一句话:"我们故意 simplify reward design 来 alleviate reward hacking 并 promote more diverse problem-solving behaviors based on mere outcome feedback, 不考虑 code executability reward。"——翻译: 在 RL 里加 process reward 通常是 bad idea, 你以为你在引导, 其实你在挂剥洋葱。

2 · 背景速查

术语含义
Code Interpreter (CI)本文专指 Python sandbox, 接受 print()-based stdout 作为唯一返回通道
Code-integrated reasoning一条 trajectory 里 natural language thought / <code> / <interpreter> 交错的格式
Sandbox受限执行环境, 这里是 ByteDance 的 async pod pool, 每个 worker 拉任务跑 Python
Cold-start SFTRL 前的 SFT 阶段, 让模型先学会输出格式 / 基本工具使用模式
PPOSchulman 2017。clipped importance ratio + value baseline 的 on-policy 算法
Outcome reward只在 trajectory 终点判答案对错, 不给中间步骤打分 (与 process reward 相对)
Interpreter maskRL 训练时, <interpreter>...</interpreter> 内的 token 不参与 loss / advantage 计算
VeRLVolcengine 开源的 RL training framework, 本文实现底座
AIMEAmerican Invitational Mathematics Examination, 30 题, 数学奥赛预选级难度
TIRTool-Integrated Reasoning, Qwen2.5-Math-Instruct-TIR 的命名约定
Pass@1 (avg@32)同一题用 temperature=1.0 重复采样 32 次取平均, 估计单次正确率

PPO 速复习 (本文唯一公式)

JPPO(θ) = 𝔼(q,a)∼D, o≤t∼πθ_old [ min( wt·Ât, clip(wt, 1−ε, 1+ε)·Ât ) ]
wt = πθ(ot | q, o<t; CI) / πθ_old(ot | q, o<t; CI)

注意 ratio 的条件里多了 "; CI"——意思是 rollout 时 context 里穿插了 sandbox 返回的 interpreter feedback。这是说 CI 进了 loss, 只是说生成 wt 时模型看到的上下文包含 interpreter 输出。Loss 仍只在 model-generated token 上算 (见 §5)。Reward 极简:

R(a, â) = +1 if is_equivalent(a, â) else −1

其中 a 是 ground-truth, â 是 model 在 \boxed{...} 里给出的最终答案。没有 step reward, 没有 KL 惩罚 (论文设 KL coef = 0.0), 没有 code-executability bonus。


3 · 方法详解

3.1 Trajectory format: thought / code / interpreter 交错

ReTool 的核心 abstraction 是把一条 rollout 形式化为:

τ = [ t1c1f1t2c2f2 ⊕ … ⊕ o ]

其中 ti 是自然语言 thought (model 生成), ci<code>```python ... ```</code> 段 (model 生成), fi<interpreter>...</interpreter> 段 (sandbox 返回, 外部), o<answer>\boxed{...}</answer>i 的次数由 model 决定——可以一次都不调 (退化到纯 CoT), 也可以调五六次。

Policy LLM (πθ) writes: t / c / o (loss 参与) Code Sandbox (env) returns: f (loss MASKED, KV reused 后再 prefill) trajectory tape → t₁ "先看 1000 mod 7..." <code> c₁ </code> print(1000%7); ... <interp> f₁ </interp> "1000 mod 7 = 6" t₂ "现在构造方程..." <code> c₂ </code> for a in range... <interp> f₂ </interp> N=5694, Q+R=699 o \boxed{699} mask out (no grad) mask out (no grad) outcome reward r = +1 (verifier 判 699 = 699)
一条 ReTool rollout 的展开。蓝色段是 policy 自己写的 token, 都进 loss; 黄色段是 sandbox 塞回的 interpreter feedback, 不进 loss (Interpreter Feedback Mask)。最后一格 \boxed{} 由 rule-based verifier 给 ±1 reward, 没有 step reward。

反向论证 (如果不 mask interpreter 段会怎样?) 假设把 fi 一起算 loss——这相当于在告诉模型 "你应该能输出 1000 mod 7 = 6 这个 stdout"。但这个 stdout 的概率分布完全由 Python 决定, 跟 model 的 reasoning 无关。Loss 会把 model 的输出分布拉向 Python 输出风格, 破坏自然语言段的 coherence。论文一句话称之为 "blocks external tokens from interfering with loss calculations, ensuring training stability"。

3.2 Cold-start SFT pipeline: 从 Dinit 到 DCI

这一步是最容易被忽略但工程上最关键的一步——直接做 RL 模型连 <code> 都不会写。Pipeline 三步:

① 收集 + 过滤 OpenThoughts 等开源 long-CoT 数据 DeepSeek-R1 + 人工双 verify → Dinit (text-only) ② 自动重写 用 Figure 8 prompt 让 LLM 把"手算段" 替换为 <code>+<interp> → DCI (草稿) ③ 双阶段 verify (a) format check 语法 (b) answer check 数值 不匹配的扔掉 → DCI (净化) Cold-start SFT on DCI Qwen2.5-32B-Instruct, 2 epochs → 学会 <code> 语法 / 调用 timing 的 prior AIME2024 = 40.9% (vs base 26.7%, vs text-RL 40.0%)
DCI 构造 pipeline。注意三件事: ① 输入是已有的 long-CoT 数据, 不是从零生成; ② "替换手算段" 由一个 LLM (论文未点名, 但用 Figure 8 的 prompt) 自动完成; ③ 双 verify 必须包括 answer 数值 match——避免 rewriter 把答案改错。

Worked example: DCI 里一条样本长什么样

假设 Dinit 里原始 long-CoT 包含 "1000 mod 7 = 6, 100 mod 7 = 2, 10 mod 7 = 3, 1 mod 7 = 1, 所以方程变为 6+2B+3C+D≡0 (mod 7)" 这一段——这是典型的"模型 in-text 心算"段。Rewriter 拿 Figure 8 prompt 后, 把它改写成:

... 先计算 1000, 100, 10, 1 各自的 mod 7:
<code>
```python
mod_1000 = 1000 % 7
mod_100  = 100 % 7
mod_10   = 10 % 7
mod_1    = 1 % 7
print(f"1000 mod 7 = {mod_1000}")
print(f"100  mod 7 = {mod_100}")
print(f"10   mod 7 = {mod_10}")
print(f"1    mod 7 = {mod_1}")
```
</code>
<interpreter>
1000 mod 7 = 6
100  mod 7 = 2
10   mod 7 = 3
1    mod 7 = 1
</interpreter>

所以方程变为 6 + 2B + 3C + D ≡ 0 (mod 7) ...

关键 design choice (论文 Figure 8 第 6 条): "Execution results should match the model's output exactly, with no extra or missing tokens"——意思是合成数据里的 <interpreter> 段被要求和真实 Python 输出 byte-by-byte 一致。这是为了让 cold-start 模型在真实 RL rollout (届时 interpreter 段来自真 sandbox) 时不会经历 distribution shift。

Cold-start 单独的效果: 只做 SFT (不做 RL) 的 ReTool 在 AIME2024 上 = 40.9%, 已经追平 text-only RL 1080 步训练的 40.0%。这说明 DCI 本身就装得下大部分"调工具该怎么调"的先验; RL 阶段做的事是从这个 prior 里 selection——挑出"哪种调用方式真的更可能答对"的子分布。

3.3 RL stage: PPO + interpreter mask + KV reuse + async sandbox

RL 阶段在 SFT 模型上继续, 用 PPO + outcome reward。核心改动有四:

组件具体做法为什么必要
Rollout loop检测到 </code> 即暂停生成, 把 code 发去 sandbox, 把 stdout/stderr 包成 <interpreter> 拼回 context, 继续 generate让 rollout 时模型看到的轨迹与最终 inference 完全一致 (no train-test mismatch)
Interpreter Feedback Mask<interpreter>...</interpreter> 段 loss-mask = 0不让外部 token 干扰 policy 梯度
KV-cache Reuse每次 </code> 触发后, code 之前的 KV cache 全部冻结, 只 incremental prefill interpreter feedback 部分32B + 16k seq 多轮 rollout 否则 OOM
Async Sandboxpod pool 异步拉任务, 慢 thread 不阻塞快 threadRL throughput 不被 Python 执行时间拖累
Loss / advantage 在 trajectory 上的分布 (示意) t₁ c₁ f₁ (masked) t₂ c₂ f₂ (masked) t₃ o model token (loss ON, Ât 来自 PPO) interpreter token (loss OFF) \boxed{} → outcome reward KV cache reuse 示意: prefill t₁+c₁ pause sandbox runs c₁ incremental prefill f₁ resume gen t₂... 关键: t₁+c₁ 的 KV 不重算, 直接复用——这正是 32B 多轮 rollout 的工程命门。 Async sandbox pool (rollout 并行): rollout #1 pause @ c₁ rollout #2 pause @ c₃ rollout #N pause @ c₂ pod 1 pod 2 pod 3 pod K pods pull task →
三件 RL infra 细节: (上) 每个 token 的 loss 状态——蓝色全计 loss + advantage, 黄色 mask 掉, 红色 o 是 reward 落点; (中) KV cache 复用使每次 </code> trigger 只增量 prefill, 不重算 history; (下) 多个 rollout 异步把 code 扔给共享 pod pool, 慢任务不阻塞快任务。

训练超参 (论文 §2.3.2 直接抄)

反向论证 (KL=0 为什么不爆?) 通常 RLHF/RLVR 训练里 KL coef 不为零是为防 policy 远离 ref model 后 reward hack。ReTool 敢设 0, 我猜的原因有两条: ① outcome reward 是 binary, hack 空间小; ② <code>/<interpreter> 这个 deterministic 通道把"正确答案"锁死, model 无法靠改风格骗到 reward。但这也意味着不能直接拿 ReTool 的 reward+KL setup 套到 reward 不稳的任务上。

3.4 Worked example: 一道 AIME 题完整 rollout

用论文 Figure 4 的真实 AIME 题 (硬币贪心):

From an unlimited supply of 1-cent, 10-cent, and 25-cent coins, ... Find the number of values of N between 1 and 1000 inclusive for which the greedy algorithm succeeds. (答案: 610)

训练好的 ReTool 模型实际产生的 rollout (节选, 真实 token 取自论文):

Alright, let's tackle this problem step by step using code to ensure accuracy.
The goal is to determine for each value of N from 1 to 1000 whether the
greedy algorithm produces the minimum number of coins. If it does, we count
that N. ...

<code>
```python
def test_specific_N(N_values):
    for N in N_values:
        greedy_result = greedy(N)
        ...
test_results = test_specific_N(N_values_to_test)
print(test_results)
```
</code>
<interpreter>
Traceback (most recent call last):
  File "/tmp/tmpbr3uj7zz/tmpdmj39k6o.py", line 11, in <module>
    test_results = test_specific_N(N_values_to_test)
  File "/tmp/tmpbr3uj7zz/tmpdmj39k6o.py", line 5, in test_specific_N
    greedy_result = greedy(N)
NameError: name 'greedy' is not defined
</interpreter>

Oops, the functions need to be defined in the same scope. Let's correct that:

<code>
```python
def greedy(N):
    denominations = [25, 10, 1]
    ...
def test_specific_N(N_values):
    for N in N_values:
        greedy_result = greedy(N)
        ...
test_results = test_specific_N(N_values_to_test)
print(test_results)
```
</code>
<interpreter>
{42: (9, 6), 25: (1, 1), 10: (1, 1), 1: (1, 1), 1000: (40, 40)}
</interpreter>
...
<answer> \boxed{610} </answer>

把这条 rollout 拆开看 (蓝=model token, 黄=interpreter token):

Step谁产生进 loss?关键决策
1"Alright, ...using code to ensure accuracy"policy决定调工具
2第一段 Python (含 bug)policy写代码
3NameError tracebacksandbox✗ (masked)
4"Oops, the functions need to be defined ..."policyself-correction: 不重新解释问题, 直接修代码
5修复后的 Pythonpolicy
6正确 dict 输出sandbox✗ (masked)
...............
N\boxed{610}policyverifier 给 r = +1

整条 trajectory 的 advantage 怎么分配: PPO 用 GAE 把 terminal reward +1 折回到每一个 model-token 上 (黄段 mask 不参与); 因为 KL=0 且 outcome reward 是 sparse +1/-1, 所有 model token 的 advantage 大致同号。这意味着"Oops, let's correct"那一句跟"Alright, let's tackle"那一句拿到几乎相同的 positive advantage——所以下次遇到 NameError 类似情况, 模型生成 "Oops" 风格 self-correction 的概率会上升。这就是 emergent self-correction 的训练机理。

反向论证 (为什么不需要 process reward?) 如果加 "code 跑通 +0.5, 跑不通 -0.5" 的 process reward——第一次 NameError 那条整体答对的轨迹反而会被 process 部分扣分。模型学到的 lesson 可能变成"宁可不调工具也别写出 bug code", 直接抹掉 self-correction 行为。所以论文坚持 outcome-only, 留出 trial-and-error 的空间。


4 · 实验关键结果

4.1 主表 (AIME 2024 / 2025, pass@1 = avg@32)

模型AIME 2024AIME 2025说明
Qwen2.5-Math-72B-Instruct30.0纯 CoT, 大 backbone
Qwen2.5-Math-72B-Instruct-TIR40.0tool-integrated SFT, 72B
OpenAI o1-preview44.637.9闭源 long-CoT
DeepSeek-R1-Zero-Qwen-32B47.0long-CoT RL, 同 scale
QwQ-32B-Preview50.033.5long-CoT, 同 scale
s1-32B56.7test-time scaling
CI-powered RL
ReTool (Qwen2.5-32B-Instruct)67.049.3400 steps
ReTool (DeepSeek-R1-Distill-Qwen-32B)72.554.3更强 backbone
Ablations (Qwen2.5-32B-Instruct)
w/o Training (base)26.7
w/o CI (Text-based RL)40.036.71080 steps
w/o RL (only Cold-start, infer with CI)40.934.5SFT 单独已追平 text-RL

三个最 load-bearing 的读法:

  1. 67.0 vs 40.0 (同 backbone)。同样 Qwen2.5-32B-Instruct + 同样 outcome RL, 加 CI 比不加 CI 在 AIME2024 上多 27 个绝对百分点——这是 tool 的边际贡献, 而不是 backbone / data 的功劳。
  2. 40.9 (SFT only) vs 67.0 (SFT+RL)。SFT 把"会用工具"装好后, RL 再加 26 个百分点——这是RL outcome reward从 SFT prior 里"选出更优 tool-use pattern"的功劳。两步缺一不可。
  3. 72.5 (R1-Distill backbone)。backbone 越强 ReTool 越强, 说明这套框架不是钉死在 Qwen 上, 而是一种 generic 后训练范式。

4.2 训练动力学 (Figure 3)

论文跑 400 steps 在 6 个指标上画曲线, 每个都讲一个有意思的故事:

(a) Response length 10k 2k 0 400 steps 先降 (替换冗长心算) 后稳 最终 −40% (10k → 6k) (b) Code ratio 100 20 含 code 的回答占比 飙到 98%, 几乎每题都调 (c) Code lines 50 10 平均每段 code 的行数 ~5× 增长 (代码更复杂) (f) Code invocation timing: 0.62 → 0.52 (越来越早调 code) 即 code 段 start 在 response 中的相对位置——训得越久, model 越倾向先调工具再聊天
Figure 3 的核心三张子图重绘。读法: response length 先降 (替换冗长心算) 后稳 (代码本身的开销); code ratio 上升到 98% (几乎每题必调); code lines ~5× 上升 (代码也变复杂)。Figure 3(f) 给出一个更微妙的发现: model 学到的不是"等推不动了再调", 而是"越早调越好"。

4.3 涌现行为


5 · 与同类工作对比

工作类型关键差异
DeepSeek-R1-Zero / QwQ / s1long-CoT RL, no tool同 backbone 同算力, ReTool 32B 67.0 / 49.3 vs 47.0 / 33.5。证明 tool 是 token efficiency 的关键
Search-R1 (arXiv:2503.09516)RL+tool, 同 framework同一思想的搜索域对偶: tool = 搜索引擎, observation = 搜索结果片段。ReTool 是代码域实例。架构基本同构 (rollout pause/resume + interpreter mask)
ToolFormer / MathCoderSFT-only tool use只学固定模式, 不会自适应"该不该调"; ReTool 的 cold-start 部分类似这条线, RL 是关键加法
PoT / PAL (arXiv:2211.12588 / arXiv:2211.10435)prompting-only"把整道题翻译成 Python"——失去自然语言推理的灵活, 也不会动态决定调用时机
Qwen2.5-Math-72B-TIRSFT tool-integratedAIME 40.0%——是同思路 SFT-only 的天花板, ReTool 32B 多 27 个点说明 RL 是收益放大器
ToRL (arXiv:2503.23383)concurrent: RL+tool 小模型1.5B/7B Qwen-Math, 性能 suboptimal——ReTool 把这条线 scale 到 32B 并配齐 infra
OpenAI o1 + tools闭源o1-preview 在 AIME 2024 = 44.6%; ReTool-32B 67.0 / R1-Distill-Tool 72.5 都显著高——open-source 32B 在带 tool这条赛道上 cross 了 o1-preview
MathCoder / MAmmoTHcode-aug SFT更早期的 code-augmented math 数据 + SFT, ReTool 的 DCI pipeline 是其精神后继
sibling 05 RethinkingAgenticRLposition paper把 ReTool 列为 "Agentic POMDP" 的实例——本文是具体训出来的 agent, RethinkingAgenticRL 是给它命名的 framework
读法建议:把 ReTool 和 Search-R1 放在一起读最划算——前者是 code interpreter, 后者是 search engine, 两条线在同一 framework 下用同一 PPO + outcome reward + interpreter mask 把"tool decision"丢回 RL。两份 paper 几乎是同一篇文章在不同 tool 上的两个实例, 印证了这条技术路线的通用性

6 · 局限 / 个人 take / 待验证问题

论文的局限

我的疑问 (待验证)

  1. DCI 的 rewriter 如果用比 base model 更强的模型 (例如 R1) 蒸馏, vs 用 base model 自己蒸馏, 哪个 cold-start 效果更好? 论文回避了这个 ablation。
  2. ReTool 的token efficiency 收益(response length −40%) 在 inference cost 上有多大节省? 因为 sandbox 调用本身有 RTT 开销, 单看 token 数不公平。
  3. 如果把 PPO 换成 GRPO/DAPO/GSPO, ReTool 框架是否兼容? interpreter mask 在 group-normalized advantage 上的语义是不是改变?
  4. 错题的 last-code-pass-rate 下降——是 model 在做更难的题 vs 是 model 学到"反正答错了不如赌一把没语法错"? 论文给出前者解读, 但没排除后者。
  5. ReTool 训出来的模型对"该不该调工具" 的判断, 在不需要工具的题 (例如简单算术、文字推理) 上是否会过度调用? Code ratio 98% 看起来可疑——如果训练集全是难题, 那 evaluation 是否会 over-tool simple problems?
  6. 同样 SFT data + 同样 RL setup, 把 Python 换成定理证明器 (Lean) 会怎样? 这是 Search-R1 → ReTool 的下一个自然 sibling。

个人 take

ReTool 的真正贡献不在 67.0 这个数字, 而在于给"RL + 异构 tool"这条技术路线找到了一份能 work 的菜谱: cold-start SFT 装格式 → outcome RL 选 pattern → interpreter mask 防梯度污染 → KV reuse 撑住多轮 → async sandbox 撑住 throughput。这五件事任何一个没做对, 整个流水线都会崩。它和 Search-R1 一起把 "training-time tool use" 从一个 idea 推成一个可复用的 recipe。下一步合理的事是把这个 recipe 复用到 (a) 多工具混合 (Python + 搜索 + 知识库), (b) 非数学任务 (SWE / GUI / formal proof), (c) 更小的 backbone (7B 量级)——这三条都是低悬果。


记忆点

立场 长 CoT RL 在数学题上是 token efficiency 死胡同, 把 Python 当 deterministic verifier-tool 是更好的解
配方 Cold-start SFT (DCI) → outcome PPO + interpreter mask + KV reuse + async sandbox
公式 JPPO 唯一改动: ratio 的 condition 里加 "; CI"; reward = ±1 only
关键数 AIME 2024: 67.0 vs 40.0 (text-RL); 400 steps vs 1080; response length −40%
涌现 code self-correction ("Oops, let me fix that") + adaptive tool selection
对偶 Search-R1 是搜索域的 ReTool; 同 framework 不同 tool
下一步 多工具混合 / 非数学任务 / 小模型复制 — 三条低悬果

精读笔记 v1 · 2026-05-11 · 配套论文 PDF: /tmp/retool_2504.11536.pdf · arXiv:2504.11536