SFR-DeepResearch
Agent RL · arXiv 2025 · 2509.06283v2

SFR-DeepResearch:换个起点、改一行优势,长程 Agent RL 就稳得多

多数 Agent RL 从 base 或 SFT 模型起步,这套配方直接从推理优化模型(QwQ-32B、Qwen3-8B、gpt-oss-20b)做持续 RL。 三件事撑起它:按模型家族改编的交互相导(把多轮压成单轮 + 自管上下文)、全合成训练数据、以及把优势除以轨迹长度 T。 代价是配方逐模型定制,工具也只给三个。

Xuan-Phi Nguyen 等 · Salesforce AI Research arXiv 2509.06283(以 v2 为准)↗
TL;DR · 30 秒抓住核心

推理模型会「想」,但不会「办」。论文要的是让它们在不被人类中途指挥的前提下,自己搜、自己读、自己写代码,把一篇 Deep Research 做出来。难点不在单步推理,而在几十步长程 rollout 上的 RL 训练会塌。

作者观察到两件事:Qwen 系模型在多轮对话里思考质量会在第一轮之后退化;而长轨迹在 batch 里占的 action 步骤更多,即使失败也会被强化,于是变成「反复调同一个工具」。对应两处改动:把历史压进单轮上下文 + clean_memory 自管记忆;把优势改成 A = (r − mean)/std/T。

结果上,gpt-oss-20b 起点最好:SFR-DR-20B 在 HLE 全文集 28.7%(Table 1),比其基座 17.3% 高 11.4 个百分点。Qwen 侧模型则更多靠「推理时改工作流」提分,RL 只再补几个点。

28.7%
SFR-DR-20B 的 HLE 全文集 Pass@1(gpt-oss-20b 基座 17.3)
13.0%
SFR-DR-8B 长度归一化后的 HLE,未归一化对照 7.8
10.0 pt
SFR-DR-32B 单轮工作流(pre-RL)较默认多轮在 FRAMES 的绝对点差
01

Deep Research 要的不是更长的思考,而是自己能「收尾」

读完这节要知道:单智能体 DR 的自由度,恰好是它训练不稳定的根源。

Deep Research(DR)任务要求模型在多来源上大量搜索和推理,最终给出答案。论文把 DR 系统分成两类:多智能体按预定义流程分工(orchestrator、planner、coder、researcher…);单智能体只拿到用户问题,中间步骤没有任何外部指令,自己决定下一步(§2.1)。

论文选单智能体的两个理由写在 §1:“single agents can generalize better to unseen tasks”,以及单智能体可以再嵌进多智能体当子模块。代价是:工具调用顺序完全自由,这“demands advanced reasoning ability to plan and execute correct tool calls”(§1)。

被点名的失败模式

长轨迹在 batch 里「霸占」损失

§3.3 原文:“longer trajectories dominate the training loss, even if said trajectories are not necessarily of higher quality or correct. As a result, failing-but-long trajectories appear more frequently over time”。§4.2.2 补充:模型“degenerates into making repetitive, identical tool calls”。

这不是奖励设计的问题——每一步拿到的 reward 是同一个轨迹奖励 ri,没有任何中间奖励。问题在于同一组里,长度不同的轨迹在 step 级损失里的权重不一样。

论文还专门讨论了一种反直觉的可能性:“More Tool Calls Do Not Equate Better Scores”(§4.2.2)——调用次数多并不等于分数高,只有当调用“diverse and strategically executed”时才成立。第三章的交互就是把这句话变成一个可以亲手调的数。

02

前人要么从头训,要么靠流程分工;它选第三条路

读完这节要知道:对照表里哪些格子其实是「重跑过的数」,哪些没测。

多智能体

角色分工 + 静态流程

OpenDeepSearch、WebThinker、MiroThinker 等把任务拆给多个角色。§2.1 的评价:多智能体“tend to specialize in pre-defined workflows and can achieve greater performance and efficiency”。

盲区:流程是人定的启发式,“not constrained by the predefined, heuristic-based workflows”正是论文认为单智能体能泛化的理由(§1)。

单智能体 + 冷启动

base / SFT 起步再 RL

WebSailor、WebShaper 等从 base 或指令模型出发,先冷启动指令微调再 RL(§2.2 概括为“cold-start instruction-tuning followed by RL with customized objectives and roll-out strategies”)。

盲区:推理能力得在训练里重新获得或保住;论文选择的是“continual RL”而不是从头养。

本文

推理模型 + 持续 RL

起点是已经会长链思考的模型;目标是在保留推理的同时“endowing them with new agentic capabilities”(§2.2)。

论文自己也说这条路的难点是“reliably steering long-horizon chain-of-thought behavior during optimization”——03 节的内容就是怎么 steer。

Table 1 转录:单智能体那一栏

Table 1 的完整版还有专有模型与多智能体分组,这里只转录单智能体分组和两款专有对照,其余未转录。所有数字均为 Pass@1;* 表示作者用开源代码 + 自家 blocklist 重跑,† 表示原文报告值但“do not mention or include leakage prevention efforts”(Table 1 表注)。HLE 列原文写作 “HLE/HLE-500”,这一分组未标注 HLE-500。

Agent基座FRAMESGAIAHLE
Deep Research 专有o3—67.426.6
GPT-5 专有GPT-5——35.2
WebSailor-32B * 重跑Qwen2.5-32B69.7844.010.75
WebShaper-32B * 重跑QwQ-32B69.4248.512.23
AFM-32B † 原报告Qwen2.5-32B55.3——
SFR-DR-8BQwen3-8B63.341.713.2
SFR-DR-32BQwQ-32B72.052.416.2
SFR-DR-20Bgpt-oss-20b82.866.028.7

GAIA 一列,原文对 WebSailor / WebShaper 分别还给了括号里的 † 值 53.2 / 53.3;本表只保留 * 重跑值,† 括号值未转录。HLE-500 子集仅在 MiroThinker-32B(11.8†)、WebThinker-32B(15.8†)、AFM-32B(18.0†)三个多智能体/单智能体基线上出现,不在本表。

03

核心改动只在一行:优势除以轨迹长度

读完这节能亲手推出「调得越多越差」这件事在什么条件下发生。

算法骨架仍是 REINFORCE 系(§3.3 称“a modern variant of the REINFORCE algorithm… which features clipped-surrogate losses”)。对一个输入 q,采样 G 条独立轨迹;每条轨迹所有 step 共享同一个轨迹奖励 ri,无中间奖励。step 级优势为:

Ai,j = Ai = ( ri − mean(R̄) ) / std(R̄) / Ti
Eq. 1 · R̄ 是同一组内全部轨迹级奖励;青色是 GRPO 式组内归一化,陶土红是本文新增的 时间维度归一化(temporal advantage normalization)

原文对它的说明是一句话:“steps of longer rollouts have lower absolute advantage magnitudes than those of shorter rollouts”,并且“The normalization is designed to regulate and stabilize training when the trajectory length varies significantly”(§3.3)。注意它不改变组内谁排第一——只是把长轨迹上的每个 step 权重按 T 压小。

原文自相矛盾(并列)

“moderate” 的用量,与 Figure 2 的曲线

位置一 · §4.2.2 / Figure 2 图注:“with normalization, training is more stable… even though tool usage grows more moderately”;“our length normalization regulates tool usage”。

位置二 · Figure 2 曲线本身:蓝线(长度归一化)的平均轨迹长度全程在约 4–6 之间波动,阶段长度没有单调上升的趋势;红线(未归一化)从约 4.4 一路升到 7 以上,栏内标着 “HLE=7.8”,蓝线标 “HLE=13.0”。

两者怎么对应,原文没有进一步说明。

G = 每组轨迹条数 Ti = 第 i 条轨迹的 agentic 步数 R̄ = 组内轨迹奖励集合 Σ 按 Ti 对 step 权重求和

自己动手:长度归一化下,多调几次工具到底是有用还是浪费

下面按 Eq. 1 在 step 级做一次简化模拟:一组 G 条轨迹,每条 Ti 步、共享奖励 ri。两个读数:①grid 份额——每条轨迹在「优势 × 长度」上的贡献占比,组内归一到 100;②每步平均额度——分到「每一次调工具」上的权重,同样组内归一。切换归一化开关,看长短轨迹的权重怎么重新分配。

T ≤ 阈值的轨迹权重占比
—
—
mean(T) / T*
—
—
grid 份额 |A·T|(组内归一) 每步平均额度 |A|(组内归一)
判读
手算两组:完整算式,与页面逐位一致标准差用总体口径 ÷G

口径:组内 mean / std 用总体标准差(除以 G,不是 G−1);每条轨迹所有 step 共用同一优势 Ai;grid 份额 = |Ai|·Ti,每步平均额度 = |Ai|,两者都按组内最大值归一到 100;轨迹长度 Ti = lo + (hi − lo)·i/(G−1) 在滑块的区间内等距铺开;T* = Σ|r| / Σ|A|,比值 = mean(T)/T*,均保留 1 位小数。

组 A(点「手算组 A」按钮):G=3,奖励 1 / 0 / 1,T 范围 2–8 ⇒ T = [2.0, 5.0, 8.0],阈值 4.0,归一化 ON。

① mean = 2/3 = 0.667;方差 = ((1−0.667)² + (0−0.667)² + (1−0.667)²)/3 = (0.111 + 0.444 + 0.111)/3 = 0.222;std = √0.222 = 0.471。
② A/T = [0.333/0.471/2.0, −0.667/0.471/5.0, 0.333/0.471/8.0] = [0.354, −0.283, 0.088];grid = |A·T| = [0.707, 1.414, 0.707] → 除 1.414 ⇒ 50.0% / 100.0% / 50.0%;每步 = [0.354, 0.283, 0.088] → 除 0.354 ⇒ 100.0% / 80.0% / 25.0%。
③ T* = Σ|r|/Σ|A| = 2.0 / 0.725 = 2.8 步;mean(T) = 5.0 ⇒ 5.0 / 2.8 = 1.8×;T > 4.0 的轨迹有 2 条(T=5.0、8.0);短轨迹占比 = 阈值内的每步额度之和 / 全组 = 0.354 / 0.725 = 48.8%(阈值内只有 T=2.0 这条轨迹)。
④ 切到未归一化(A):A = [0.707, −1.414, 0.707];grid = [1.414, 7.071, 5.657] → 20.0% / 100.0% / 80.0%,失败的 T=5.0 最重;每步 = |A| → 50.0% / 100.0% / 50.0%;T* = 2.0/2.828 = 0.7;比值 7.1×;短轨迹占比 = 阈值内 grid 份额 1.414 / 全组 14.142 = 10.0%。
⑤ 换成样本标准差(÷2)std = 0.577,组 A 的 A/T = [0.289, −0.231, 0.072]:grid 与每步额度的百分比不变(同除一个数);T* = 2.0/0.592 = 3.4,比值 5.0/3.4 = 1.5×。两种口径下「短轨迹每步权重更高、失败长轨迹每步权重更低」的方向一致,只有 T* 的绝对位置变。

组 B(点「手算组 B」按钮):G=2,奖励 1 / 0,T 范围 2–8 ⇒ T = [2.0, 8.0],阈值 4.0。

① mean = 0.5,std = 0.5;A/T = [1/0.5/2, −1/0.5/8] = [0.5, −0.125]。
② grid = |A·T| = [1.0, 1.0] → 100.0% / 100.0%;每步 = [0.5, 0.125] → 100.0% / 25.0%。
③ T* = 1.0 / 0.625 = 1.6;比值 5.0/1.6 = 3.1×;超过阈值的 1 条;短轨迹占比 = 0.5/0.625 = 80.0%(T=2.0 在阈值内)。
④ 未归一化:A = [1.0, −1.0];grid = [2.0, 8.0] → 25.0% / 100.0%——失败的长轨迹独占 100 的 grid,成功短轨迹只有 25;每步 = |A| → 100.0% / 100.0%(两条每步权重相同,长的那条还多了 4 倍步数);T* = 1.0/2.0 = 0.5;短轨迹占比 = 2.0/10.0 = 20.0%。

默认组校验:G=4、1 / 0 / 0 / 1、T 范围 2–8 ⇒ T = [2.0, 4.0, 6.0, 8.0]。mean = 0.5、std = 0.5;A/T = [0.5, −0.25, −0.167, 0.125];grid = |A·T| = [1, 1, 1, 1] ⇒ 全为 100.0%;每步 = [0.5, 0.25, 0.167, 0.125] ⇒ 100.0% / 50.0% / 33.3% / 25.0%;T* = 1.0/1.042 = 1.9,比值 5.0/1.9 = 2.6×;阈值内(T=2、4)的每步额度占比 = 0.75/1.042 = 72.0%。与页面初始读数逐位一致。

交互对账(覆盖与未覆盖):覆盖的是 Eq. 1(§3.3)的组内标准化与分步归一化、|A·T| 与 |A| 的两种份额、T* 与阈值判定。未覆盖:clipped-surrogate 具体损失、episode 过滤 / 部分 rollout / 缓存等训练系统行为、真实长度分布(页面把 T 在所选区间内等距铺开)、多轮 rollout 中优势随 step 变化的细节。这里的「T* 」是页面为了把「多调几次是否值得」变成可调参数而自定的阈值,不是原文概念。

全对组(zero-gradient 边界):奖励形态选「全对」后所有 r 相同 ⇒ 所有 r − mean = 0 ⇒ A = 0,页面显示 0% 与「—」。推断此时 std(R) = 0,Eq. 1 会除零;页面对这一情形直接给出 0,不模拟真实训练框架的 std 截断。这一组只说明一件事:组内没有奖励差,长度归一化无从比较。

04

四条把长程 RL 拽住的工程规矩

读完这节要知道:除了 Eq. 1,还有过滤、部分 rollout、奖励和基础设施四件事在兜底。

轨迹过滤

丢掉截断与格式错乱的轨迹

“filter out invalid trajectories, such as those ending with truncation or incorrectly-formatted responses, from the replay buffer”;同时把组内正负样本比例控制在预设范围内,随机或启发式丢弃过多的一侧(§3.3)。原文:“without such measures, the training process is unstable and prone to model collapse”。

部分 rollout

把半截轨迹当新起点

与 MoonshotAI 的做法不同,这里不「用新策略续写」,而是把部分 rollout 当作独立初始状态,用同一策略重新启动组级 Monte-Carlo——“This allows more exposure to and gradient updates from long-tail intermediate states”(§3.3)。

奖励模型

短答判一致,长报告要排序

用同一个 baseline LLM 当 verifier。短格式:判断是否与标准答案语义一致,ri ∈ {0,1}。长报告:多阶段打分(事实性 / 合规 / 写作 / 引用质量),各类有固定权重,组内再按 verifier 排序产生 ranking score,总奖励是加权和加排序分(§3.3)。

基础设施

同卡共置 + 容错恢复

rollout 异步多进程打满 SGLang 吞吐;工具箱全本地执行并缓存结果;策略推理、verifier、训练模型共置在同一批 GPU,梯度更新时把推理引擎挪开、反之亦然;对 OOM、超时、引擎挂起有恢复流程(§3.3)。

数据:合成到什么程度

训练数据全合成,两类任务:短格式多跳 QA(迭代式逐步加难,另掺数学与代码推理)和长报告写作(LLM 生成指令与评分 rubric)。难度在 §3.2 给了两个锚点:OpenAI Deep Research(o3)在该短格式集上 “less than 65%”,最好的基线智能体 “less than 40%”;一个 o4-mini 智能体单题要“up to 50 tool calls”。这也是为什么 Table 1 里 SFR-DR 的对比对象覆盖了这么强的系统。

Code Interpreter 的边界,写在脚注里

code_interpreter 是无状态的:每次独立运行、不共享变量、5 分钟超时;没有命令行、不能装包。脚注 1 列了黑名单:尝试 import os, sys, subprocess, socket, signal, multiprocessing, threading, ssl, pdb, resource, xmlrpc 等会直接报错。这条限制决定了 §07 的适用边界。

05

一条轨迹从头到尾长什么样

读完这节要知道:Qwen 系和 gpt-oss 走的是两套交互模板,记忆工具也不同。

论文形式化地定义一条 agentic 轨迹为有序集合 T(q) = (q, c₁, o₁, c₂, o₂, …, cₙ, oₙ, a),其中 ci 是含工具调用的模型响应,oi 是环境反馈,a 是最终答案;对推理模型,ci 与 a 还包含 thinking tokens(§3.1.2)。

单轮上下文(Qwen / QwQ)· 始终只有 1 个 user turn q 原始问题 [c₁, o₁] 调用 + 搜索结果 含旧 CoT [c₂, o₂] browse_page 含旧 CoT clean_memory(…) 如第 5 步:重写记忆 此前的 o 被抹掉 [cₙ, oₙ] 最新上下文 旧 CoT 已省略 每步输出 新的 thinking → 只针对最新上下文,不复用旧 CoT → 一个工具调用 cᵢ,或最终答案 a gpt-oss-20b:另一套模板 沿用 harmony 默认多轮;记忆工具改为编辑 / 删除单条历史 理由:§3.1.2 称其多轮能力更强、CoT 更短
按 §3.1.2 与 Figure 1 文字重绘,非原图。原 Figure 1 还画了第 3 步的格式错误修复(返回 syntax-error 提示、要求下一步改正),此处省略。

记忆超限时会发生什么

Qwen / QwQ 的版本:记忆逼近预设上限 Lmem 时,agent 被告知已超过 buffer,此时除 clean_memory 外的任何工具调用都会得到 “memory overflow” 错误,直到成功清理上下文(§3.1.2)。若已清理 K 次,第 K 次之前的工具结果 oj 就被擦掉、不再出现在当前记忆里(脚注 3)。gpt-oss 版本则是「编辑或删除单条过去的结果」。

工具
search_internet:serper.dev 一类基础搜索 API,返回前 10 条自然结果(URL / 标题 / 短描述,不一定齐全)。
工具
browse_page(url, section_id):抓取 HTML 转 Markdown,去掉全部超链接——页面不可点击,新 URL 只能通过搜索发现;长页按 section 切块「滚动」。
工具
code_interpreter:本地执行无状态 Python,5 分钟超时,无 shell、无装包(见 04 节脚注限制)。
容错
格式错误按严重程度修复 / 重试 / 下一步告知模型;调用不存在的工具或参数非法也会收到警告(§3.1.2)。
06

提分最大的一块不是 RL,而是推理时换模板

读完这节要知道:Qwen 系的涨点主要发生在 RL 之前;gpt-oss-20b 才是 RL 真正发力的那个。

Table 2 转录:同一模型,换工作流前后

Table 2 对比默认多轮模板与 SFR-DR 的工作流(pre-RL,即未做 RL)。原文口径:“most notably a 10% absolute increase on FRAMES for the 32B model”(§4.2.1)。下表所有提升均按绝对点差(百分点)与相对幅度两种口径并列给出。

AgentFRAMESHLE
Qwen3-8B multi-turn52.58.8
QwQ-32B multi-turn58.012.3
SFR-DR-8B (pre-RL)58.89.9
SFR-DR-32B (pre-RL)68.013.9

再叠加 RL 后(§4.2.1 与 Table 1 / Figure 2 交叉):8B 的 HLE 从 9.9 到 13.2,+3.3 个百分点(相对 33.3%);32B 从 13.9 到 16.2,+2.3 个百分点(相对 16.5%)。推断(由 Table 2 pre-RL 值与 Table 1 / Figure 2 post-RL 值相减;8B 的 13.2 同时在 Figure 2 的标注里出现)Qwen 系模型的 RL 增益,在 FRAMES 维度上没有对应数据,只能比 HLE——两者都远小于「换模板」在 FRAMES 上带来的 +6.3 / +10.0 个百分点。

SFR-DR-20B 强在哪

HLE 全文集

28.7 vs 基座 17.3(Table 1)

+11.4 个百分点,即 相对提升 65.9%——原文 §4.1 明确写的是 “65% relative improvement over gpt-oss-20b”,与按 (28.7 − 17.3)/17.3 算出的 65.9% 一致。相对 Deep Research(o3)的 26.6 高 +2.1 个百分点(相对 7.9%);比同家族的 SFR-DR-32B(16.2)高 +12.5 个百分点(相对 77.2%)。

GAIA 上 66.0 vs o3 的 67.4,低 1.4 个百分点(相对 −2.1%),不是全面领先。FRAMES 82.8 为本表最高,但同表其他系统在该列多为 * / † 口径,不能直接当成同口径对比。

Figure 2 / Figure 3 的读数(均为图中柱顶标注)

读数数值出处
SFR-DR-8B 未归一化 HLE7.8Figure 2 栏内标注
SFR-DR-8B 长度归一化 HLE13.0Figure 2 栏内标注
两者差(绝对 / 相对)+5.2 / 66.7%13.0 − 7.8;再 /7.8
RL 后工具调用增幅 8B / 32B / 20B+11% / +64% / +28%Figure 3(a) 柱顶标注
RL 后每步响应长度变化 8B / 32B / 20B+10% / +18% / −29%Figure 3(b) 柱顶标注

另有两处值得记的对比:工具越多不等于越好——§4.2.3 指出 Qwen 系在不少样本上只做内部推理、几乎不调工具,而做工具调用的 20B 分数最高;每步响应长度——20B 每步 “less than 2,000 tokens”,比 8B / 32B “4-5 times fewer”(§4.2.4),但 RL 反而让它变短(图中 −29%),Qwen 系则 RL 之后变长(+10% / +18%)。

07

它能证明的比「长程 Agent 训练已解决」窄得多

读完这节要知道:在哪些条件下这套数字不能直接搬到你的场景。

边界一

工作流是逐模型定制的,不是即插即用

§3.1.2 明说 “specific model families have distinct model characteristics that do not allow for a one-size-fit-all training formulation… we tailor our inference setups on a per-model family basis”。Qwen / QwQ 用单轮重构,gpt-oss 用默认 harmony 多轮;记忆工具也不同(clean_memory vs 编辑单条结果)。换基座就得重调。

边界二

基座偏好本身就是变量

同样的 Eq. 1 与数据,20B(gpt-oss-20b)拿到 28.7,32B(QwQ-32B)只有 16.2(Table 1)。§4.2.3 把原因归到 “gpt-oss-20b appears better primed for agentic training, as indicated by its pre-RL number of tool calls”。这说明配方效果和起点强耦合,不能按参数量推断。

边界三

工具与执行环境被刻意收窄

只有三个工具;browse_page 抹掉所有超链接;code_interpreter 无状态、无 shell、不能装包,还得避开一长串 import 黑名单(脚注 1)。需要「点链接浏览」「装依赖跑脚本」「操作 GUI」的任务,本文没有验证。§3.1.1 的理由是 “not render any training tasks trivially easy”——这是训练设计,不保证部署时够用。

边界四

HLE 是单次 Pass@1,没有给方差

Table 1 表注写的是 “Pass@1”,全文未见多次采样的方差或置信区间。推断表内 0.1 级的差距(例如 20B 的 28.7 与 o3 的 26.6,差 2.1 点)需要谨慎解读。

边界五

污染控制有归属不均

Table 1 表注区分了三类数:作者直接引用的 OpenAI 值、作者用自家 blocklist 重跑的 * 值、以及没有泄漏防护信息的 † 值。§4.1 原文:“we are unable to confirm if contamination precautions exist”。开放问题:本文自己的 2100+ 题全文集与 500 子集之间,被 [11] 估计为 “up to 3.4%” 的污染样本分布如何,论文未展开。