Search Agent RL 的目标不是训练一个新的搜索引擎,而是训练一个 Policy LLM 学会:

  1. 判断当前问题是否需要外部知识
  2. 决定何时搜索、搜索什么
  3. 从带噪的检索结果中提取证据
  4. 根据新证据继续搜索、纠错或停止
  5. 在有限的 token、工具调用次数和时间预算内给出正确答案。

一句话概括:

Search Agent 是一个带外部观察的序列决策过程:

  • 把 Search Engine 当成 RL Environment
  • 把 query / tool call 当成 action
  • 把检索结果当成 observation
  • 再用最终任务奖励优化整条 reasoning–search trajectory

Search-R1、R1-Searcher、ReSearch 等工作的具体标签、奖励和训练阶段不同,但都可以归纳为下面这套闭环。

Notation

符号 含义 典型取值或测量方式
$x=(q,a^*)$ 训练任务,包含问题与可验证答案 QA 数据、multi-hop QA、研究任务
$\pi_\theta$ 待训练的 Search Agent policy LLM actor
$\pi_{\text{old}}$ 生成当前 rollout 的旧策略 当前步更新前的 actor snapshot
$\pi_{\text{ref}}$ 冻结参考策略 RL 起点 checkpoint
$\mathcal{E}$ 搜索环境 本地语料检索器、Search API、网页浏览器
$s_t$ 第 $t$ 步可见状态 原问题、历史 reasoning、tool call 与 observation
$a_t$ Policy 产生的动作 思考 token、search query、browse/open、final answer
$o_t$ 环境返回的观察 搜索结果、snippet、网页正文、错误或超时信息
$\tau$ 一条完整轨迹 $(s_0,a_0,o_0,\ldots,a_T)$
$B$ 交互预算 最大搜索轮数、token、延迟或费用
$R(\tau)$ 轨迹级奖励 EM、F1、规则 verifier、LLM judge、成本惩罚
$m_t$ loss mask Policy token 为 1,环境 observation token 为 0

从 Agent 的视角看,状态并不一定包含真实世界的全部信息,因此更准确地说,这是一个 POMDP:模型只能通过搜索逐步获得 observation。每一步是:

$$ a_t \sim \pi_\theta(\cdot\mid s_t),\qquad o_t \sim \mathcal{E}(\cdot\mid a_t),\qquad s_{t+1}=f(s_t,a_t,o_t). $$

搜索引擎通常不可微,但这并不妨碍 RL:Policy Gradient 不需要对环境求导,只需要记录模型采样动作的 log probability,并在轨迹结束后得到 reward。

Search Agent 典型流程

Search Agent RL 同时存在两个不同时间尺度的闭环:

  • 内层:Agent Loop
  • 外层:Training Loop
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
Agent Loop:一条 rollout 内的 Agent–Environment 交互

 user question
┌───────────────┐   reasoning / search query   ┌─────────────────┐
│ Policy LLM    │ ───────────────────────────► │ Tool Controller │
│  π_old        │                              │ parse / budget  │
└───────▲───────┘                              └────────┬────────┘
        │                                               │ query
        │ observation                                   ▼
        │                                      ┌─────────────────┐
        └──────────────────────────────────────│ Search / Browse │
                                               │ Environment     │
                                               └─────────────────┘
        └── 重复 Thought → Action → Observation,直到 Answer / Timeout / Budget
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Training Loop:跨 rollout 的 RL 参数更新

 任务采样        并行环境交互          轨迹打分          优势估计
┌────────┐      ┌────────────┐      ┌──────────┐      ┌──────────┐
│ q, a*  │ ───► │ G rollouts │ ───► │ R(τ_i)   │ ───► │ A_i      │
└────────┘      └────────────┘      └──────────┘      └────┬─────┘
                                                    ┌──────────────┐
                              新权重同步到 rollout ◄│ PPO / GRPO   │
                                                    │ update π_θ   │
                                                    └──────────────┘
                                                           └──► 下一轮

一条 trajectory 长什么样

以 Search-R1 风格的特殊 token 为例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[system + question]                                              prompt
        ├─ <think>需要先确认人物 A 的出生地</think>                policy token, mask=1
        ├─ <search>person A birthplace</search>                  policy token, mask=1
        ├─ <information>...检索结果...</information>             environment token, mask=0
        ├─ <think>还需找到该城市所属国家</think>                    policy token, mask=1
        ├─ <search>city B country</search>                       policy token, mask=1
        ├─ <information>...检索结果...</information>             environment token, mask=0
        └─ <answer>country C</answer>                            policy token, mask=1
                                                            verifier → reward

这里最关键的工程约束是:

检索结果要进入下一轮 context,但必须从 policy loss、importance ratio 和 KL loss 中 mask 掉。

检索结果由环境产生,模型没有“选择”这些 token。如果把 observation 当作模型 action 计算 loss,就会优化一个模型并未采样的序列,破坏 on-policy 假设并污染梯度。Search-R1 和 R1-Searcher 都显式使用 retrieved-token loss mask。12

典型训练流程

0. 准备任务、环境与初始策略

一条最小训练样本通常只需要 (question, gold_answer),不一定需要人工标注搜索过程。RL 负责探索中间 trajectory,规则 verifier 只判断最终结果。

训练前需要准备:

  • 任务集:答案可自动验证,并且确实需要外部知识;
  • 搜索环境:固定语料库 + 本地 retriever,或真实 Search API + Browse 工具;
  • 交互协议:定义 searchopen_urlanswer 等 action schema;
  • 终止条件:最终答案、最大轮数、最大 token、超时、连续非法调用;
  • 初始策略:可从 base / instruct model 直接 RL,也可先用少量 SFT trajectory 做 cold start。

离线语料环境便宜、稳定、可复现,适合先验证算法;真实 Web 能训练去噪、网页导航与多源核验,但会引入网络波动、页面变化、rate limit 和 prompt injection。两种环境解决的问题并不完全相同。

1. 对每个问题采样一组 rollouts

对同一个问题 $x$,从 $\pi_{\text{old}}$ 独立采样 $G$ 条轨迹:

$$ \tau_i \sim \pi_{\text{old}}(\cdot\mid x;\mathcal{E}), \qquad i=1,\ldots,G. $$

每条 rollout 都有独立的 context / memory,但共享相同的问题、工具定义与预算。采样必须保留:

  • Policy 实际生成的 token IDs 与 old log probabilities;
  • 每个 token 的来源标记:prompt、policy 或 environment;
  • tool call、observation、终止原因、模型版本;
  • 轨迹级 token 数、搜索次数、延迟和错误码。

只保存文本、训练时再 tokenize 容易产生 Retokenize Drift;多轮工具调用越长,这类错位越危险。

2. Tool Controller 驱动环境交互

生成遇到完整的 tool-call 结束标记后暂停,由 Controller:

  1. 解析 query 或 JSON action;
  2. 检查 action schema、权限和剩余预算;
  3. 调用 Search / Browse Environment;
  4. 把结果包装成 observation,追加到当前上下文;
  5. 让 Policy 基于新状态继续生成。

环境本身通常不参与反向传播。它更像代码 RL 里的 sandbox:负责执行 action,并返回可观察结果。

3. 终止并计算轨迹奖励

最简单的 Search QA 使用最终答案奖励:

$$ R_{\text{answer}}(\tau) =\operatorname{EM}(a_{\text{pred}},a^*) \quad\text{或}\quad \operatorname{F1}(a_{\text{pred}},a^*). $$

Search-R1 证明只用 outcome reward 也能学出多轮搜索行为;ReSearch 则组合 answer F1 与格式奖励。13 对更开放的 Deep Research 任务,reward 往往需要扩展为:

$$ R(\tau) =w_aR_{\text{answer}} +w_cR_{\text{citation}} +w_fR_{\text{format}} +w_sR_{\text{safety}} -\lambda_qN_{\text{search}} -\lambda_tN_{\text{token}} -\lambda_lT_{\text{latency}}. $$
奖励项 解决的问题 常见实现
Answer correctness 最终结论是否正确 EM、F1、规则 verifier、LLM judge
Citation / evidence 结论是否被检索证据支持 引文覆盖率、URL 可访问、entailment judge
Format / valid action 工具协议是否可执行 JSON schema、特殊标签检查
Safety 是否访问或输出违规内容 规则过滤、分类器
Search cost 是否无效重复搜索 每次调用扣分、去重 query 比例
Token / latency cost 是否过度思考 长度、wall time、API 成本惩罚

奖励设计应遵循“先保证能探索,再优化成本”:如果模型一开始根本不会调用搜索,可以像 R1-Searcher Stage 1 那样短暂奖励一次合法 retrieval;学会基本协议后,应移除这个奖励并改用答案质量,否则模型最容易学到的是 为了得分而搜索,而不是为了回答问题而搜索。2

4. 计算 group-relative advantage

GRPO 不训练 critic,而是用同一问题的组内奖励作为 baseline。常见的序列级优势为:

$$ \hat A_i= \frac{R_i-\operatorname{mean}(R_1,\ldots,R_G)} {\operatorname{std}(R_1,\ldots,R_G)+\epsilon}. $$

例如同一问题的四条轨迹奖励是:

$$ [1.0,\ 0.0,\ 0.6,\ 0.0], \qquad \mu=0.4,\quad \sigma\approx0.424, $$

则优势近似为:

$$ [+1.41,\ -0.94,\ +0.47,\ -0.94]. $$

这意味着第一条轨迹中的 reasoning、query 和 answer token 都会被整体提高概率,失败轨迹则被整体压低概率。它没有自动知道“第三次 query 是关键动作”还是“第一次 query 是错误根源”——这就是只有 outcome reward 时的 粗粒度 credit assignment

如果一组 rollout 全对或全错,则 $\operatorname{std}(R)\approx0$,有效优势接近 0,几乎没有学习信号。因此数据需要维持在“当前模型有时能解出、有时解不出”的难度带,可用难度过滤、主动采样或课程学习维持非零方差。

5. 对 Policy token 做 PPO / GRPO 更新

定义 token 级 importance ratio:

$$ \rho_{i,t}(\theta)= \frac{\pi_\theta(y_{i,t}\mid s_{i,t})} {\pi_{\text{old}}(y_{i,t}\mid s_{i,t})}. $$

忽略若干实现变体后,带 observation mask 的 GRPO 核心项可写成:

$$ \mathcal J(\theta)= \frac{1}{G}\sum_{i=1}^{G} \frac{1}{\sum_t m_{i,t}} \sum_t m_{i,t} \min\left( \rho_{i,t}\hat A_i, \operatorname{clip}(\rho_{i,t},1-\epsilon,1+\epsilon)\hat A_i \right) -\beta D_{\mathrm{KL}}^{(m)}(\pi_\theta\Vert\pi_{\mathrm{ref}}). $$

其中:

  • $m_{i,t}=1$:reasoning、query、tool-call schema、final answer 等 Policy 生成 token;
  • $m_{i,t}=0$:system prompt、用户问题、搜索结果、网页正文、环境错误信息;
  • clip 防止一次更新把策略推得过远;
  • $D_{\mathrm{KL}}^{(m)}$ 表示只在 $m_{i,t}=1$ 的 token 上计算 KL,约束模型不要过度偏离初始策略。

PPO 的整体交互流程相同,只是额外训练 Value Model,并用 GAE 估计 token / step 级 advantage。对最终奖励稀疏、轨迹很长的任务,PPO 并不自动解决 credit assignment,仍取决于 value estimation 和 reward placement 是否可靠。

6. 同步新权重,进入下一轮

Trainer 更新 $\pi_\theta$ 后,把权重同步给 rollout workers,形成下一轮 $\pi_{\text{old}}$。同步训练容易被最慢的网页或最长轨迹拖住;异步训练能提高吞吐,但长轨迹更可能由旧版本策略生成,必须限制 policy staleness,并保存准确的 behavior log probability。详见 异步 RL Long Horizon RL

Fully async 下,一条 trajectory 属于哪个 policy version?

既然 fully async 会产生 stale rollout,那你们怎么定义一条 trajectory 到底属于哪个 policy version?staleness 到什么程度还能接受?

需要把“轨迹的版本标签”和“轨迹是否严格来自单一版本”分开讨论:

  1. 原子权重更新:只在 episode 边界给 worker 换权重,则整条 $\tau$ 属于启动 rollout 时的 policy_version_start=v;这是最干净的定义。
  2. In-flight 权重更新但保留 KV cache:轨迹前后 token 可能分别由 $v$、$v+1$ 生成,严格说它不属于任何一个单独 policy。必须为每个生成 chunk,最好为每个 action token,记录 behavior_version 和 $\log\pi_{\text{behavior}}(a_t\mid s_t)$。
  3. Trainer 的 current version:训练消费该轨迹时的版本记为 $v_{\text{train}}$,版本差为 $\Delta v=v_{\text{train}}-v_{\text{behavior}}$。它只是易观测 proxy,不能单独代表分布偏移大小。

真正决定“还能不能用”的不是固定的 $\Delta v$,而是 behavior policy 与 current policy 在已采样 action 上的偏移。至少同时监控:

$$ \Delta\ell_{i,t} =\log\pi_{\theta}(a_{i,t}\mid s_{i,t}) -\log\pi_{\text{behavior}}(a_{i,t}\mid s_{i,t}), \qquad \rho_{i,t}=e^{\Delta\ell_{i,t}}. $$
信号 作用 超限后的处理
$\Delta v$ 快速版本闸门 延迟、丢弃或降低样本权重
ratio / log-ratio 分位数 直接度量 action probability 漂移 clip、mask 极端 token、丢弃轨迹
clip fraction 判断大部分梯度是否已被截断 降低 learner / actor 速率差
approximate KL 度量整体策略偏移 收紧最大 staleness 或同步频率
ESS 判断 importance weight 是否被少数样本支配 丢弃 stale batch 或改进调度

因此“最多接受落后几版”没有跨系统通用答案。合理做法是先设一个保守的版本上限(例如只消费最近若干版本),再用 ratio、KL、clip fraction、ESS 和最终质量做 A/B,把阈值校准到自己的更新步长与任务长度。一次很小的参数更新可能让 $\Delta v=3$ 仍接近 on-policy;一次很激进的更新也可能让 $\Delta v=1$ 已经不可用。

还有一条硬约束:不要只拿 $\pi_{\text{old}}$ 的最新 checkpoint 重算旧轨迹的 denominator。importance ratio 的分母必须是实际生成该 token 的 behavior policy probability。否则记录的“旧策略”与真实采样策略不是同一个分布,ratio 在数学上已经失真。

训练系统中的角色

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
                         ┌───────────────────────────┐
                         │ Prompt / Task Scheduler   │
                         └─────────────┬─────────────┘
                                       │ questions
┌─────────────────┐ weights   ┌─────────────────────┐   actions   ┌──────────────┐
│ Actor Trainer   │──────────►│ Rollout Workers     │───────────►│ Search Env   │
│ FSDP/Megatron   │           │ vLLM/SGLang + Agent │◄───────────│ / Web / RAG  │
└────────▲────────┘           └──────────┬──────────┘ observation└──────────────┘
         │ gradients                     │ trajectories
         │                               ▼
         │                    ┌─────────────────────┐
         └────────────────────│ Reward + Ref Logprob│
                              │ Advantage / Mask    │
                              └─────────────────────┘
组件 主要职责 不应该做什么
Actor / Policy 生成 reasoning、query、answer 伪造 environment observation
Tool Controller 解析、执行、预算与状态管理 替模型决定搜索内容
Search Environment 返回检索或网页观察 参与 policy loss
Reward / Verifier 判断任务完成质量 泄露 gold answer 给 rollout
Reference Model 提供 KL 或 ref logprob 跟随 actor 一起更新
Trainer masked loss、反向传播、权重更新 用重建后错位的 token 计算 ratio

最容易出问题的地方

1. Observation mask 错位

这是 Search Agent RL 最基础也最致命的 correctness 问题。需要从真实 token IDs 构造 mask,并做逐 token 单测,不能仅靠字符串查找 <information>;网页正文可能包含相同字符串,截断也可能只保留半个标签。

2. 训练环境与线上环境不一致

本地 Wikipedia retriever 训练出的能力,不等价于真实 Web Agent 能力。线上还有 snippet 噪声、重复网页、动态页面、登录墙、反爬、网络失败和恶意 prompt injection。训练与评估至少要明确区分:

  • Retrieval RL:固定 corpus,重点学习 query formulation 与 evidence use;
  • Web Search RL:真实搜索,重点增加去噪、导航、核验与鲁棒性;
  • Deep Research RL:还要学习多源综合、引用、长报告和成本控制。

DeepResearcher 的实验也强调,真实 Web 环境不是简单替换一个 retriever,而会引入页面异构、网络延迟、rate limit 和浏览代理等系统问题。4

3. Reward hacking

典型表现包括:重复搜索刷 retrieval reward、在答案中堆同义词提高 cover EM、伪造 citation、利用 verifier 偏好写冗长答案。所有 proxy reward 都应配对应的反作弊指标和人工抽检。

4. 长尾与截断偏差

最有价值的 multi-hop 任务往往也是最慢的。如果所有超时轨迹都直接记 0 分,模型可能学会过早回答;如果全部 mask 掉,又会系统性丢失困难样本。至少要分别记录 answered / budget_exhausted / timeout / invalid_action / env_error,避免把策略失败和环境失败混成同一种 reward。

5. 非平稳环境导致不可复现

实时网页会更新,同一 query 的排序也可能变化。建议保存 query、URL、snippet、抓取时间、搜索后端版本和原始响应;需要严格 A/B 时使用快照或 cache,但最终仍要在 live environment 做鲁棒性验证。

6. Search 学会了,答案能力却退化

训练只覆盖 knowledge-intensive QA 时,模型可能对本来不需要搜索的问题也强制调用工具,或损害原有推理、写作和指令遵循能力。训练集应混入 search-neededsearch-not-needed 样本,并持续评估非搜索任务,必要时做 mixed RL 或能力回放。

如何验证训练真的有效

至少需要四组同预算对照,保持 backbone、retriever、语料版本、top-k、最大 token 与工具调用上限一致:

1
2
3
4
A. Direct / CoT,无检索
B. 单轮 RAG
C. Prompted ReAct,多轮搜索但不训练
D. Search Agent RL,多轮搜索并更新 policy

如果还做 SFT cold start,应增加 E. Search Agent SFT,才能区分收益来自轨迹模仿还是在线 RL。

维度 核心指标 要回答的问题
最终质量 EM、F1、task success、rubric score 答案是否真的更好
搜索策略 search-needed 分类准确率、有效 query 比例、重复 query 率 是否知道何时搜、搜什么
证据质量 Recall@k、citation precision / coverage、claim entailment 是否找到并正确使用证据
效率 searches / task、tokens / task、P50/P95 wall time、API cost 是否用合理成本完成
鲁棒性 OOD、时间敏感题、空结果、搜索超时、脏网页 环境变差后是否仍可靠
RL 健康度 reward、entropy、KL、clip fraction、non-zero-advantage group ratio 训练是否稳定且仍有信号
系统吞吐 accepted rollout / s、tokens / s / GPU、straggler 比例 训练资源花在哪里
能力保持 非搜索 QA、reasoning、instruction following 是否出现灾难性遗忘

结果解读也要做拆分:如果 D 相比 C 只增加了搜索次数,却没有提升 answer / citation quality,说明模型学到的是 tool-call format 或 reward shortcut,而不是真正的搜索策略。理想结果应同时满足:

  1. 在 search-needed 与 multi-hop 子集上,D 的正确率显著高于 B / C;
  2. 在 search-not-needed 子集上,不出现无意义搜索激增;
  3. 答案增益不是由更高 token / query budget 单独换来的;
  4. OOD 和 live-search 评估仍保留增益;
  5. observation mask、old logprob、终止原因和环境错误经过 end-to-end 审计。

总结

1
2
3
4
5
6
7
Search Agent RL
    = 普通 LLM RL
    + 多轮 Agent rollout
    + Search / Browse environment
    + observation token masking
    + 可验证的最终任务奖励
    + 工具成本、长尾与环境非平稳治理

最小可行版本其实很简单:问题 + gold answer + 本地 retriever + 多轮 tool loop + outcome reward + GRPO。真正困难的部分不在公式,而在三条边界能否长期保持正确:

  • Action 与 Observation 的 token 边界
  • 策略失败与环境失败的责任边界
  • 答案质量提升与搜索成本增长的收益边界

这三条边界守住后,训练才是在优化“会搜索的 Agent”,而不是在拟合检索结果、奖励工具格式,或单纯堆叠更多 test-time compute。

参考资料