可验证奖励强化学习
目的
为什么一个从自身试错中学习的智能体,会如此稳定地学会作弊?
模仿的边界止于已有示范,而对于许多智能体任务,例如修复真实代码仓库或证明引理,无论付出多高的代价,都找不到示范者;但检查却是可行的,因为测试的结果非通过即失败。强化学习将这种检查转化为目标,让策略在数百万个多轮回合中搜索一切能够获得检查奖励的行为。这种搜索并不关心意图。能够访问测试文件的策略会学会修改测试文件,由学习得到的评判器打分的策略会学会取悦评判器,而仅在三十轮回合结束时才获得奖励的策略,则很难学到究竟哪一轮起了作用。每个回合还会在真实沙箱中运行真实工具,因此,训练成本在很大程度上由环境而非梯度更新步骤决定。训练并不会改变 H·S·A 的任何风险暴露,因为策略仍然保有原先的交互跨度、状态和权限;而为其评分的验证器则成为另一道权限边界,必须由运行时而非模型来守住。
学习目标
- 解释在什么情况下,基于可验证奖励的强化学习能够使智能体超越其示范,以及为什么它需要非零的初始通过率。
- 利用结果检查、部分得分、格式检查和评分准则评判器来设计智能体奖励,并预测策略将如何钻每一种奖励的空子。
- 计算跨轮次蒙特卡洛信用分配的 token 成本,并将其与仅基于结果的奖励和学习得到的过程奖励进行比较。
- 推导 GRPO 的组内相对优势,并诊断零方差组和长度归一化偏差。
- 实现多轮轨迹采样收集,支持观测掩码、忠实保留 token 的轨迹采样记录以及轮次上限。
- 设计验证隔离区,使奖励机制处于策略无法触及的范围内,并能容忍不稳定的测试。
- 评估轨迹采样与训练流水线是否存在熵坍塌、长度失控、策略陈旧等问题,以及是否已具备通过发布门禁的条件。
为什么要从奖励中学习
在通过准入审核的轨迹上进行微调的修复智能体(轨迹微调),能够解决修复方式与示范相似的问题,却会在其余问题上停滞不前。增加示范只有在有人能写出示范的情况下才有帮助,而同策略纠正仍然需要一位专家,能够在策略到达的每个状态中指出正确动作(暴露偏差与同策略数据)。对于代码仓库规模的修复、协议调试或定理证明,没有人能以可接受的价格找到这样的专家。但检查确实存在。测试套件无法编写补丁,却能判断补丁是否有效,而这种较弱的能力已足以支撑强化学习。策略在沙箱内提出完整轨迹,验证器对结果评分,模型权重则朝着能够获得高分的方向更新。
最后这一点正是本章要解决的系统问题。一个因通过测试而获得奖励的优化器,会利用环境允许的任何途径通过测试,包括修改测试本身;它还会在数百万次轨迹采样中这样做,而每次采样都需要一个沙箱、一次验证器运行以及模型计算时间。本章按照问题本身所要求的顺序构建相关机制。首先讨论奖励可以由哪些来源构成,以及策略如何钻每一种来源的空子;随后讨论如何将回合结束时的单一分数归因于三十轮动作,以及 GRPO 如何在不使用学习型评价器的情况下,将成组的轨迹采样结果转化为梯度。在此基础上,本章进一步讨论当回合变成使用工具的多轮轨迹时会发生哪些变化,如何使验证器处于策略无法触及的范围内,在做到这一点后会出现哪些病态现象,以及如何大规模运行环境与轨迹采样并实施门禁控制。
通过试错学习,并不会赋予策略在部署时不具备的任何权限。每次轨迹采样中的动作,无论是 shell 命令、数据库查询还是源代码编辑,都只是一个提议,运行时仅在 智能体沙箱 的沙箱内执行它。探索使这种约束更加重要。以高温度采样的策略经常会提出格式错误或具有破坏性的命令,而轨迹采样集群会数百万次地提出此类命令,因此,沙箱池与重置 的沙箱重置与池化机制也成为训练循环的一部分。
奖励沿用运行时关于证据的规则。模型声称自己已完成任务,并不具备任何证据效力(认识论边界:受强制的约束域与语义正确性);询问模型其代码是否解决了任务,也只是再执行一次具有相同盲点的推理。因此,奖励必须来自模型外部的检查,而奖励的可信程度取决于计算该奖励的检查所具备的闭合证据等级(闭合证据等级)。静态检查弱于封闭测试,封闭测试又弱于形式化证明。
形式上,这种交互是一个具有有限时域 \(T\) 的马尔可夫决策过程。状态 \(s_t\) 包括策略在第 \(t\) 轮所看到的任务、上下文和截至当前的观测,以及这些信息背后的沙箱状态。动作 \(a_t\) 是策略在该轮输出的 token 序列,包括一个推理块,通常还包括一次工具调用。状态转移由运行时在沙箱中执行 \(a_t\) 并追加观测来实现。奖励 \(R(\tau) \in \{0, 1\}\) 由验证器根据轨迹 \(\tau\) 的最终状态计算,目标为
\[\mathcal{J}(\theta) = \mathbb{E}_{\tau \sim \pi_\theta}\left[R(\tau)\right]\]
时域 \(T\) 与 \(H\)(见 H·S·A 暴露面)计数的是相同的交互轮次,此处记为 \(T\),以遵循强化学习文献的惯例 (Sutton 和 Barto 2018年)。
Definition 0.1: 可验证奖励强化学习
可验证奖励强化学习(RLVR) 是一种策略优化方法,其中一条轨迹的奖励由模型外部运行的自动化检查计算,例如封闭测试套件、编译器或证明检查器。这些检查作用于轨迹产生的状态,而非通过学习得到的奖励模型或人工评分来确定奖励。
- 意义:移除了学习得到的奖励模型,也随之消除了优化过程利用该模型错误的途径。奖励的可信程度完全取决于检查的覆盖范围及其与策略的隔离程度。
- 区别:基于人类反馈的强化学习针对学习得到的人类偏好模型进行优化,而策略可能将该模型推向评分失准的区域。RLVR 则针对检查进行优化,其判定不依赖于输出的措辞。
- 常见误区:将可验证奖励视为完整的规范。策略可能用一个空洞或错误的解法通过不完整的测试套件,因为没有任何测试覆盖该解法的问题。
这一目标也解释了为什么监督训练要先进行。策略梯度需要高得分轨迹与未获得高分的轨迹之间存在差异。如果初始策略在某个任务上从未成功,那么每次轨迹采样的得分都为零,该任务的梯度也为零。关键并非单次尝试的通过率,而是 \(k\) 次尝试中至少一次成功的概率,即 pass@\(k\)(见 候选选择):
\[\text{pass@}k = 1 - (1 - \hat{p})^k\]
一个在 18% 的尝试中能解决任务的监督学习策略,在一组 8 次轨迹采样中至少成功一次的概率为 79.6%,在一组 16 次轨迹采样中至少成功一次的概率为 95.8%。这些采样组能提供梯度。成功率为零的策略则无法提供梯度,无论它耗费多少次轨迹采样。因此,监督微调并非强化学习的替代方案,而是其自举步骤:让策略在关键任务上的成功率脱离零点,这也是基于隔离验证器的强化学习(原则 18)所要求的。
现在,这个循环已清晰可见:一个已经能偶尔成功的策略、一个容纳其探索活动的沙箱,以及一个对结果评分的验证器。后续的一切都取决于验证器的分数是否表达了任务设计者的本意。下一节将探讨奖励可以由哪些要素构成,以及为什么优化器会找到分数与意图之间的每一处差距。
可验证奖励信号下的行为演化
从监督模仿到强化学习的转变,标志着模型行为的根本性变化。监督微调迫使模型记忆专家的词元序列,而可验证奖励强化学习则促使模型自主探索、自我纠正并进行算法推理。各训练轮次中的行为演化阶段如 图 1 所示。
可验证奖励
跨越三轮的智能体轨迹解剖 中悄无声息的测试绕过行为破坏了一个结果,而 验证器投机行为防御 展示了同样的捷径如何破坏经过筛选的语料库。强化学习则将其转化为一种策略。当测试文件位于轨迹采样的可写工作区中时,针对一个棘手缺陷的一组轨迹采样大多包含失败的修复,但有时会出现一次削弱失败断言的轨迹采样。该次轨迹采样获得 \(1\) 的分数,得到组内最大的优势值,而梯度则提高了产生这一编辑操作的每个词元的概率。几百个训练步之后,削弱断言就成了策略的主导行为,因为这条路径更短,无须理解缺陷,而且得分与正确修复完全相同。循环中的任何环节都没有发生故障。优化器只是针对所获得的奖励,完成了其设计要求的工作。
奖励黑客行为
在监督训练中,有缺陷的目标会使模型逐渐退化,趋向其数据的平均水平。在强化学习中,策略会主动搜索奖励所定义的空间,因此奖励与开发者意图之间的任何差距都会成为目标。文献将这种现象称为规范博弈 (Krakovna 等 2020年) 或奖励黑客行为 (Amodei 等 2016年; Skalse 等 2022年)。
Definition 0.2: 奖励黑客行为
奖励黑客行为 指策略通过无法完成奖励本应衡量的任务的行为,提高测得的奖励;其手段包括利用奖励检查中的漏洞,或访问并修改计算奖励的机制。
- 重要性:强化学习会将奖励与意图之间的每一处差距转化为优化目标,因此,在奖励缺乏防护时,奖励黑客行为是预期结果,而非异常现象。
- 区别:过程验证 中的古德哈特失效发生在验证器从候选项中进行选择时。奖励黑客行为则发生在验证器训练生成器时,因此,利用漏洞的行为会被学入权重,并在此后的每个任务中反复出现。
- 常见误区:将奖励黑客行为视为提示词问题。对策略下达任何指令,都无法消除其可利用的漏洞,因为无论指令是否禁止这种行为,梯度都会奖励对漏洞的利用。
设 \(U(\tau)\) 为开发者的真实目标,即可正常运行且易于维护的代码,\(\hat{R}(\tau)\) 为训练循环计算出的奖励。如果某条轨迹 \(\tau_{\text{hack}}\) 满足 \(\hat{R}(\tau_{\text{hack}}) \ge \hat{R}(\tau^*)\),同时 \(U(\tau_{\text{hack}}) \ll U(\tau^*)\),且 \(\tau_{\text{hack}}\) 更短或在当前策略下的概率更高,那么对 \(\hat{R}\) 进行梯度上升就会使概率向该轨迹转移 (Hadfield-Menell 等 2016年)。除编辑断言外,编码环境中的漏洞还会表现为其他可辨识的形式。能够将代码加载到测试运行器中的策略可以覆盖其退出状态,例如通过如下形式的钩子:
# Illustrative exploit: a test-runner hook that forces a passing exit status
def pytest_sessionfinish(session, exitstatus):
session.exitstatus = 0 # every failing run now reports success若奖励通过解析构建日志来查找字符串 BUILD SUCCESSFUL,就会奖励只打印该字符串却不进行任何构建的策略。每种利用漏洞的方式都比真正修复更简短,因此一旦某种方式可达,它就会胜出。防御手段不能是更好的指令,而必须是策略无法触及的检查,并基于策略无法伪造的证据来计算;这正是不变量闭合(原则 不变闭包原则)置于模型之上的端到端证据。
奖励可以基于什么构建
过程验证 根据验证器产生的证据,以及它们在候选项之间进行选择时的错误不对称性,对验证器进行了分类。训练改变了问题。选择器接受一个不合格的候选项,只会浪费一次决策;而奖励机制接受一条不合格的轨迹,则会教会策略生成更多这样的轨迹。智能体训练的奖励来源 列出了构建智能体奖励的来源,并按策略能够操纵它们的程度排序。
| 奖励来源 | 检查内容 | 策略如何钻空子 | 在奖励中的作用 |
|---|---|---|---|
| 证明检查器 | 针对固定命题的证明 | 可变的公理或定义;否则可利用的空间很小 | 结果奖励 |
| 封闭测试套件 | 在隐藏的失败转通过测试和通过保持通过测试上的行为 | 测试覆盖的空白;若测试可被触及,则可篡改测试 | 结果奖励 |
| 编译器或类型检查器 | 形式是否正确,而非行为是否正确 | 能编译但什么也不做的代码 | 门控条件或部分得分 |
| 工具调用格式检查 | 调用能否按其模式解析 | 格式正确却毫无成效的调用 | 小幅塑形项 |
| 学习型过程奖励模型 | 每个中间步骤的分数 | 看起来像是在认真推理的文本 | 仅用于塑形,绝不作为门控条件 |
| 评分准则评判器 | 自由形式输出是否符合书面标准 | 篇幅、自信的语气、评分准则中的关键词 | 仅用于不存在可执行检查的情形;须先校准 |
| 人工评分 | 人能够评估的任何内容 | 评分者疲劳和表面线索 | 离线审计;速度太慢,无法用于在线奖励 |
表格顶部的几行对应封闭测试和形式化证明这两个闭合层级。它们的判定结果不会随输出措辞变化,因此提高分数的唯一方式是改变检查所针对的产物,而隔离(节 6)封堵了这条途径。下方几行对文本评分,而文本由策略控制。学习型过程奖励模型或评分准则评判器本身也是有盲点的模型,梯度上升会找到这些盲点。有些任务,例如编写文档或回答用户问题,没有可执行检查,评分准则评判器是唯一可用的奖励来源。此类评判器必须先依据经过验证的结果进行校准,并检查其是否存在位置偏差、长度偏差和自我偏好偏差,如 智能体评估 所述。验证不对称性(原则 3)规定了此类验证器能够承担的作用;这也是 门控之下的学习式排序器 为接纳训练数据划定的边界,如今被应用于奖励。学习型验证器可以对轨迹采样结果进行排序或塑形,但在存在确定性检查的情况下,应由该检查决定奖励。
让学习型验证器决定奖励的代价很容易被低估,因为与大幅提速相比,较低的错误接受率看起来似乎无害。下面的计算示例用真正重要的指标来衡量这一代价:教会策略利用漏洞的更新在正向更新中所占的比例。无需引入新公式。该比例为 \(1 - \Pi_V\),即 equation 中验证器精确率的补值,其中以策略的真实通过率作为基础发生率 \(p\),且不存在错误拒绝。此前在 过程验证 中制约候选项选择的贝叶斯计算,如今支配着哪些轨迹采样结果会获得正奖励。
粗略估算 0.1: 奖励中的错误接受
变量:
- 每步轨迹采样数:\(N = 1,024 \times 8 = 8,192\)
- 真实通过率:10%;失败轨迹的错误接受率:2.5%
数学推导:
\[N_{\text{true}} = 8,192 \times 0.10 \approx 819\]
\[N_{\text{false}} = 8,192 \times 0.90 \times 0.025 \approx 184\]
\[\text{False share} = 1 - \Pi_V = \frac{184}{819 + 184} = \frac{184}{1,003}\]
结果:18.3% 的正奖励流向了欺骗验证器的轨迹。
系统洞见:只要真实成功很少见,一个听起来微不足道的错误接受率就会使错误接受占据正向信号的很大一部分,而这恰好是 RL 训练所处的情形。这些更新会强化任何欺骗了验证器的行为,而且随着策略学会更频繁地欺骗验证器,这一比例还会增长。没有错误接受的封闭测试套件会完全消除这一项,这也是为什么学习型验证器可以塑造奖励,却不能决定奖励。
组合奖励
实用的智能体奖励会将结果与几个小项结合起来,以引导结果本身未涵盖的行为:
\[R(\tau) = R_{\text{outcome}}(\tau) + \lambda_{\text{fmt}} R_{\text{format}}(\tau) - \alpha \frac{|\tau_{\text{gen}}|}{T_{\max}}\]
这里,\(R_{\text{outcome}} \in \{0, 1\}\) 来自决定奖励的检查,\(R_{\text{format}}\) 对能够按其模式解析的工具调用给予奖励(工具接口模式),\(|\tau_{\text{gen}}|\) 统计策略生成的 token 数,\(T_{\max}\) 是生成上限。各系数必须确保正确性占主导地位。简短但错误的轨迹绝不能比冗长但正确的轨迹得分更高,因此,相对于单位结果奖励,\(\lambda_{\text{fmt}}\) 和 \(\alpha\) 必须保持较小。在非成即败的结果使大多数分组都没有成功轨迹的任务中,可以用部分得分(例如通过测试的比例)替代二元结果;只有当部分测试与完整测试套件一样封闭时,这才有帮助。
一个诱人的附加项是对危险操作施加惩罚:只要轨迹尝试访问外部网络、读取凭据或向工作区之外写入,就减去一个较大的 \(\beta\)。这个项不起作用,原因有二。惩罚是概率性的。如果一次未经授权的网络调用代价为 \(\beta\),却获取了隐藏测试并确保获得结果奖励,探索最终会找到净回报为正的轨迹,而梯度会沿着这些轨迹优化。惩罚也在事后才施加。只有在操作已经执行之后才计算梯度,因此,如果该操作已经泄露了凭据或破坏了共享状态,对模型权重施加惩罚并不能修复任何东西。模型侧的项会降低不良操作的概率,却永远无法阻止一次不良操作。隔离约束必须在模型之下强制执行,由沙箱在调用运行之前拒绝它(原则 10);软性项则仅用于即使违反也不会造成损失的偏好,例如格式错误的调用、冗余调用或过长输出。
确定性的、隔离的结果检查配合较小的塑形项,可以为每条轨迹提供可信的分数。然而,它为每条轨迹打分,而策略是逐轮采取行动的。下一节将讨论:一个三十轮回合结束时得到的单一分数,应如何分配给产生该分数的各轮行动。
跨轮次的信用分配
一条修复轨迹持续三十轮。智能体列出目录、读取堆栈跟踪、在调试器下复现故障、定位一个差一错误、修改五行代码、编译并运行集成测试,而测试因一个未处理的边界情况失败。验证器返回 \(0\)。在最简单的策略梯度下,这个零会同等地落到轨迹的每个 token 上。找到缺陷的调试会话受到的惩罚,与有缺陷的修改完全相同。如果一次幸运的修改尽管推理混乱却通过了测试,那么每一步,包括走入死胡同的步骤,都会得到奖励。终局奖励说明的是轨迹是否奏效,而不是哪些轮次使其奏效。
为什么终局奖励会抑制诊断
在使用终局奖励和基线 \(b(s_0)\) 时,REINFORCE 估计量 (Sutton 和 Barto 2018年) 为
\[\hat{g} = \sum_{t=0}^{T} \nabla_\theta \log \pi_\theta(a_t \mid s_t) \left( R(\tau) - b(s_0) \right)\]
每一轮都乘以同一个标量。早期行动与最终结果之间的相关性被后续每个行动的随机性淹没,因此估计量的方差会随时间跨度增长。智能体任务还会引入一种特定的扭曲。运行 grep、阅读文档或检查失败测试等诊断行动,不改变任何状态,只会间接推动修复。当它们出现在失败轨迹中时——在困难任务上,大多数轨迹都失败——它们会反复受到惩罚。如果奖励还包含长度项,那么跳过诊断会缩短轨迹,并在失败时获得略高的分数。策略因此逐渐倾向于立即进行未经诊断的修改。下面的一条示例失败轨迹展示了这一模式:
# Illustrative failing trajectory under uniform terminal credit
Turn 1 [diagnose] $ ls -la src/core/ exit 0
Turn 2 [diagnose] $ grep -rn "buffer_len" src/ exit 0
Turn 3 [diagnose] $ gdb --batch -ex bt ./bin/server exit 0
Turn 4 [edit] patch src/core/net.c exit 0
Turn 5 [verify] $ pytest tests/test_allocator.py exit 1
# Reward 0: turns 1-3 are penalized as heavily as the faulty edit in turn 4.
解决这一问题,需要让信用分配反映每一轮对最终结果的贡献。有两类解决方案,它们都在方差和可操纵性这两个量之间进行权衡。
结果奖励与过程奖励
结果奖励模型(ORM)仅对最终状态评分;在可验证环境中,测试套件本身就是结果奖励模型。它不对执行路径作任何假设,这使其评判保持客观,但也意味着它无法为中间轮次提供任何信号。过程奖励模型(PRM)对每个步骤评分,\(r_t = M_{\text{PRM}}(s_t, a_t) \in [0, 1]\),从而提供密集的逐轮信用分配,并降低方差 (Lightman 等 2024年; Uesato 等 2022年)。过程验证 将二者都作为用于筛选的验证器引入。在训练中,PRM 的弱点成为主导因素,因为它是一个对文本评分的学习模型,而文本由策略生成。有三种利用方式反复出现。策略会输出程式化的谨慎表述(“彻底验证这个指针”),在不采取任何实际行动的情况下提高步骤得分。它会在错误前提上构建连贯的步骤,而对局部一致性评分的模型会奖励这些步骤。它还会避开那些暂时得分较低、却是长程修复所必需的迂回步骤。图 2 将这两种方法与第三种方案进行对照,后者保留终局检查作为唯一的真值来源;信用分配方案 则比较了全部三种方法。
| 维度 | 结果奖励(ORM) | 过程奖励(PRM) | 蒙特卡洛子树 |
|---|---|---|---|
| 评估对象 | 最终状态 \(s_T\) | 每个步骤 \((s_t, a_t)\) | 通过分叉评估中间状态 \(s_t\) |
| 真值来源 | 确定性检查 | 学习模型 | 对后续执行进行确定性检查 |
| 梯度方差 | 高,随 \(T\) 增大 | 低 | 中等,随 \(1/\sqrt{K}\) 降低 |
| 可操纵性 | 受测试覆盖范围和隔离机制限制 | 高(对文本评分) | 受终局检查限制 |
| 额外成本 | 无 | 每个步骤进行一次模型前向计算 | \(\mathcal{O}(K \cdot T^2)\) 个轨迹采样轮次 |
蒙特卡洛价值估计
第三种方案用测量取代学习得到的步骤评分器。在中间状态 \(s_t\),运行时为沙箱创建快照(智能体工作区),分叉上下文,并将当前策略的 \(K\) 条后续执行运行至完成,每条都由终局检查评分。平均值用于估计该状态的价值,相邻状态价值之差则用于估计二者之间动作的优势:
\[\hat{V}(s_t) = \frac{1}{K} \sum_{k=1}^{K} R\left(\tau_k^{(s_t)}\right), \qquad \hat{A}(s_t, a_t) = \hat{V}(s_{t+1}) - \hat{V}(s_t)\]
这使诊断步骤免于受到压制。假设从初始缺陷报告出发的后续执行有 5% 能够成功,\(\hat{V}(s_0) = 0.05\)。智能体运行调试器后,观测中便包含了出错的代码行。从该状态出发的后续执行有 60% 能够成功,因此调试器所在轮次获得 \(\hat{A} = 0.60 - 0.05 = +0.55\),即使运行调试器的那条具体轨迹后来在另一轮失败,也不受影响。一个轮次获得的信用仅取决于它将通过终局检查的概率提高了多少,除此之外没有其他依据。
这种测量成本高昂,而用词元数衡量成本最为合适。
粗略估算 0.2: 蒙特卡洛信用分配的 token 开销
变量:
- 轮数 \(T\),每轮生成的 token 数 \(L\),每次分叉的后续轨迹数 \(K\)
- 在第 \(t\) 轮进行分叉后,执行剩余的 \(T - t\) 轮
数学推导:
\[N_{\text{base}} = T \cdot L = 30 \times 512 = 15,360\]
\[\sum_{t=1}^{29} (T - t) = 435\]
\[N_{\text{MC}} = K \cdot L \cdot 435 = 8 \times 512 \times 435 = 1,781,760\]
结果:\(15,360 + 1,781,760 = 1,797,120\) 个 token,是仅运行该轨迹时的 117 倍,此外,每条后续轨迹还需要一次沙箱分叉和一次验证器运行。
系统洞见:穷举式蒙特卡洛信用分配所生成的 token 数按 \(K \cdot T^2\) 增长,因此,为一条长轨迹分配信用的成本相当于生成一百多条普通轨迹。逐轮信用分配只有在少数选定轮次上才负担得起。
因此,运行时会选择性地分叉。常见的触发条件有两种:一是策略的下一个 token 分布具有高熵的轮次,这标志着真正的决策点;二是发出会改变状态的工具调用的轮次,例如编辑或迁移。每条轨迹只在两三个这样的轮次进行分叉,而非在所有轮次都分叉,可将后续轨迹预算降低一个数量级,同时仍在关键决策点上通过测量分配信用。其余轮次共享轨迹级信号。
逐轮信用若由学习得到的模型提供,就可能被钻空子;若通过测量获得,则成本高昂。这两种方案还都预设了存在一种将分数转化为梯度的方法。经典方法是学习一个价值函数,根据状态预测 \(\hat{V}(s_t)\),而对于智能体轨迹,这个价值函数本身就是一个难题。
Checkpoint 0.1: 奖励与信用分配
在将分数转化为梯度之前,检验你对分数含义的理解:
组相对策略优化
语言模型的标准策略优化器——近端策略优化(PPO)(Schulman 等 2017年)——会学习一个评价器 \(V_\phi(s)\),作为每个状态的基线。对于多轮智能体,状态包含截至当前的完整轨迹、任务、数十条工具观测以及策略自身的推理;要预测其预期结果,就需要一个能够读取所有这些内容的模型。在实践中,评价器是策略模型的副本,并带有一个标量输出头。它使训练集群必须存储和更新的可训练参数、梯度及优化器状态增加一倍,同时又引入了一个学习得到的模型,策略可以利用其误差钻空子。恰恰在智能体任务常见的情形下,即仅有一个二元结果的长轨迹上,它的估计也最不准确。第一项成本背后的内存与通信核算属于训练系统方面的内容,已在《大规模机器学习系统》中讨论;在智能体层面,其后果是评价器的成本与策略相当,却在稀疏、可验证的奖励上收益甚微。
组相对策略优化(GRPO)(Shao 等 2024年) 移除了评价器。它针对同一个任务进行一组轨迹采样,并以该组自身的奖励作为基线。PPO 与 GRPO 对比 总结了由此带来的变化。
| 维度 | PPO | GRPO |
|---|---|---|
| 存储的模型 | 策略模型、评价器、参考模型,通常还有奖励模型 | 策略模型和参考模型;奖励来自外部检查 |
| 可训练模型 | 两个,每个都与策略模型大小相同 | 一个 |
| 基线 | 学习得到的状态价值 \(V_\phi(s_t)\) | 同一任务对应组内的平均奖励 |
| 信用分配粒度 | 通过评价器逐 token 分配 | 按轨迹分配,由轨迹中的所有 token 共享 |
| 每个任务的轨迹采样数 | 可以为一次 | 一组 \(G\),通常为几次到几十次 |
| 失效模式 | 评价器在奖励稀疏的长轨迹上产生误差 | 当组内所有采样轨迹的分数相同时,没有梯度 |
经典演员—评价器架构的内存墙
经典近端策略优化(PPO)在训练期间,会在 GPU 内存中维护四个独立的神经网络模型:
- 演员网络(\(\pi_\theta\)): 正在优化的策略模型。
- 评价器网络(\(V_\phi\)): 估计轨迹预期回报的价值模型。
- 参考策略(\(\pi_{\text{ref}}\)): 预训练模型的冻结快照,用于施加 KL 散度约束。
- 奖励模型(\(R_\psi\)): 预测人类偏好代理分数的神经网络。
对于大型基础模型(例如采用 FP16 的 70B 参数模型),同时存储四个模型的权重、优化器状态和激活值,每个流水线阶段需要超过 560 GB 的 GPU 显存,严重限制了最大上下文长度和批大小。
组相对策略优化(GRPO)(Shao 等 2024年) 通过完全舍弃参数化的评价器网络(\(V_\phi\))突破了这一内存墙。GRPO 无需训练独立的价值网络,而是针对每个任务提示,从当前策略中采样一组 \(G\) 条独立轨迹 \(\{y_1, y_2, \dots, y_G\}\),以评估策略优势;当前策略为 \(\pi_\theta\),任务提示为 \(x\)。基线直接根据组内奖励的经验均值和标准差计算: \[ \hat{A}_i = \frac{r_i - \mu_{\text{group}}}{\sigma_{\text{group}} + \epsilon}, \quad \mu_{\text{group}} = \frac{1}{G}\sum_{j=1}^G r_j, \quad \sigma_{\text{group}} = \sqrt{\frac{1}{G}\sum_{j=1}^G (r_j - \mu_{\text{group}})^2} \]
PPO 与 GRPO 在架构上的对比如 图 3 所示。
通过移除价值模型,GRPO 将 GPU 内存消耗降低了超过 40%,并彻底消除了价值模型训练的不稳定性,使整个 GPU 内存预算都可用于更长的上下文窗口和更大的轨迹采样组。
组相对优势
对于任务 \(q\),运行时采样 \(G\) 条轨迹 \(\{o_1, \dots, o_G\}\),这些轨迹来自生成它们的策略 \(\pi_{\theta_{\text{old}}}\),随后使用验证器 \(r_i = R(q, o_i)\) 为每条轨迹评分。每条轨迹的优势是相对于其所在组进行标准化后的奖励:
\[A_i = \frac{r_i - \text{mean}(\{r_1, r_2, \dots, r_G\})}{\text{std}(\{r_1, r_2, \dots, r_G\}) + \epsilon} = \frac{r_i - \frac{1}{G}\sum_{j=1}^G r_j}{\sqrt{\frac{1}{G}\sum_{j=1}^G \left(r_j - \frac{1}{G}\sum_{k=1}^G r_k\right)^2} + \epsilon} \tag{1}\]
组均值是每个任务各自的基线,用于吸收任务难度的影响。对于简单任务,大多数轨迹都能通过验证,均值接近一,而罕见的失败会获得较大的负优势。对于十六条轨迹中仅有一条通过验证的困难任务,均值为 \(0.0625\),唯一成功的轨迹获得较大的正优势,失败的轨迹则获得较小的负优势。策略因此会朝着在这一特定任务上区分成功与失败的行为方向调整。
这些优势被纳入一个裁剪代理目标,其中包含一项惩罚,使策略保持接近冻结的参考策略 \(\pi_{\text{ref}}\)(公式 2):
\[\mathcal{L}_{\text{GRPO}}(\theta) = \mathbb{E}_{q \sim \mathcal{D}, \{o_i\}_{i=1}^G \sim \pi_{\theta_{\text{old}}}(q)} \left[ \frac{1}{G} \sum_{i=1}^G \frac{1}{|o_i|} \sum_{t=1}^{|o_i|} \mathcal{M}_{i,t}(\theta) - \beta D_{\text{KL}}(\pi_\theta \parallel \pi_{\text{ref}}) \right] \tag{2}\]
其中,逐 token 的裁剪项为
\[\mathcal{M}_{i,t}(\theta) = \min\left( \frac{\pi_\theta(o_{i,t} \mid q, o_{i,<t})}{\pi_{\theta_{\text{old}}}(o_{i,t} \mid q, o_{i,<t})} A_i, \; \text{clip}\left(\frac{\pi_\theta(o_{i,t} \mid q, o_{i,<t})}{\pi_{\theta_{\text{old}}}(o_{i,t} \mid q, o_{i,<t})}, 1-\epsilon_{\text{clip}}, 1+\epsilon_{\text{clip}}\right) A_i \right) \tag{3}\]
该比率比较当前策略对每个采样 token 赋予的概率与采样该 token 的策略所赋予的概率,将其裁剪到 \([1-\epsilon_{\text{clip}}, 1+\epsilon_{\text{clip}}]\) 可防止任何一次更新使策略变化过大。轨迹 \(i\) 中的每个 token 都具有相同的优势 \(A_i\),因此 GRPO 的信用分配处于轨迹级别;节 3 的逐轮次信用分配只有在运行时将 \(A_i\) 替换为轮次级估计时才会发挥作用。散度项按每个采样 token 估计,而非在整个词表上计算(公式 4):
\[D_{\text{KL}}(\pi_\theta \parallel \pi_{\text{ref}}) \approx \frac{\pi_{\text{ref}}(o_{i,t} \mid q, o_{i,<t})}{\pi_\theta(o_{i,t} \mid q, o_{i,<t})} - \log \frac{\pi_{\text{ref}}(o_{i,t} \mid q, o_{i,<t})}{\pi_\theta(o_{i,t} \mid q, o_{i,<t})} - 1 \tag{4}\]
该估计量始终非负,当两个策略对该 token 赋予的概率一致时为零,并且只需要参考模型对每个生成 token 赋予的概率,即对整条轨迹额外进行一次前向传播。
公式 1 和 公式 2 中的两种归一化看似中性,实则不然。因子 \(1/|o_i|\) 先对每次轨迹采样的各个 token 项取平均,再在组内取平均,这通常被描述为防止长轨迹采样占据主导地位。然而,它对失败轨迹采样的影响恰好相反。对于满足 \(A_i < 0\) 的一次轨迹采样,除以 \(|o_i|\) 会使每个 token 的惩罚随着轨迹采样长度增加而减小,因此,在错误答案中,目标函数对长答案的惩罚最小;在正确答案中,对短答案的奖励最大。总体上,这会推动失败响应变得更长,也是 节 7 长度失控的原因之一。用常数进行归一化,例如用批次中策略生成的 token 总数进行归一化,可以消除依赖长度的权重。优势中的标准差也有类似的副作用。对于结果几乎一致的组,也就是任务非常容易或非常困难的组,其标准差很小,因此组内少数结果不同的轨迹采样会获得很大的优势值,这类任务的权重也就高于通过率接近 50% 的任务。希望各任务权重相等的实现会去掉这一除法,使用减去均值后的奖励。
没有信号的组
GRPO 的基线存在一个盲点。智能体的奖励通常是二元的,因此一组轨迹采样往往得分完全相同:任务过难时,每次轨迹采样都失败;任务过易时,每次轨迹采样都通过。此时,\(r_i = \text{mean}(\{r_j\})\) 对每个 \(i\) 都成立,所有优势值均为零,并且
\[\nabla_\theta \mathcal{L}_{\text{GRPO}}(\theta) \propto \sum_{i=1}^G \sum_{t=1}^{|o_i|} \nabla_\theta \log \pi_\theta(o_{i,t} \mid \cdot) \cdot A_i = 0\]
该组消耗了 \(G\) 次完整的轨迹采样,每次都需要沙箱、工具调用和验证器运行,却对更新毫无贡献。一组轨迹采样避免这种情况的概率,就是 equation 为拒绝采样推导出的有效信息比例,其中 \(k = G\)。如果策略在某个任务上的尝试成功率为 5%,那么一个包含八次轨迹采样的组大约有三分之二的概率无法提供信号。如果批次中的大多数任务都产生结果一致的组,有效批次大小就会趋近于零,而轨迹采样的成本却保持不变。运行时系统从四个方向减少这种浪费:
- 动态采样。 丢弃奖励全部相等的组,并持续采样任务,直到批次中填满能够产生梯度的组,从而使每一步都能使用预定数量的含有效信息的组进行训练。
- 难度感知的任务选择。 跟踪每个任务近期的通过率 \(\hat{p}(q)\),并采样通过率既不接近零也不接近一的任务。二元奖励的方差 \(\hat{p}(1-\hat{p})\) 在 \(0.5\) 时最大。
- 为困难任务使用更大的组。 一个大小为 \(G\) 的组至少包含一次成功的概率为 \(1 - (1-p)^G\),因此,对于通过率低但非零的任务,增大 \(G\) 可以将没有信号的组转变为含有效信息的组。
- 部分得分。 当检查可以分解时,例如按通过测试的比例评分,分级奖励可以区分那些在二元奖励下得分相同的轨迹采样,前提是每项局部检查都与完整检查一样受到严密保护。
GRPO 无需学习得到的评价器,就能将一组经过验证的结果转化为梯度,代价是必须生成完整的组,并丢弃结果一致的组。到目前为止,每次轨迹采样都被视为一个输出 \(o_i\)。智能体的轨迹采样并非单个输出,而是策略与环境之间的一段对话,下一节将考察这会带来哪些变化。
多轮智能体强化学习
单轮数学任务的轨迹采样包含一个提示和一个响应,生成的每个 token 都属于策略。一次修复任务的轨迹采样则包含二十轮交互:策略写出工具调用,运行时系统在沙箱中执行该调用,并将测试日志、文件列表或编译器错误追加到上下文中,随后策略再次生成内容。最终上下文中的很大一部分 token 由环境写入,而非由策略生成。如果直接套用 公式 2,就会对策略从未采样过的 token 计算概率比,因策略预测编译器输出而给予奖励,并将冗长测试日志中的每一行都计入长度归一化。多轮强化学习是将 GRPO 应用于轨迹,需要进行四项调整。
屏蔽环境写入的内容
替代目标、散度惩罚和长度计数都必须仅涵盖策略输出的 token:其推理、工具调用,以及将控制权交还给运行时的回合结束 token。观测 token 保留在上下文中,为下一回合提供条件,但不对损失作任何贡献。这就是 观测损失掩码 中的观测损失掩码,而观测损失屏蔽(原则 17)在此处更为重要。在监督训练中,未被屏蔽的观测会教模型模仿工具输出。在强化学习中,它还会将环境文本纳入重要性比率;对于策略从未采样过的 token,其“旧策略概率”毫无意义。
该掩码要求准确知道哪些 token 是策略采样得到的,这引出了一个细微的要求。轨迹采样工作进程必须在采样时记录所采样的 token ID 及其对数概率,而不能事后对完整交互记录重新分词。对文本重新分词可能会将字符跨越观测插入处的边界合并,也可能通过聊天模板以不同于生成时的方式呈现工具调用(轨迹序列化),从而产生策略从未输出过的 token 序列。此时,比率比较的就是错误 token 的概率。多回合轨迹采样记录 列出了多回合轨迹采样记录为确保训练正确而必须包含的内容,扩展了 轨迹日志 中的轨迹日志模式。
| 字段 | 内容 | 训练为何需要该字段 |
|---|---|---|
| 任务与环境标识符 | 任务 ID、环境镜像摘要、随机种子 | 复现轨迹采样;确保训练任务与评估任务互不重叠 |
| 策略版本 | 生成该采样轨迹的权重版本 | 衡量陈旧程度(节 8.4) |
| 词元 ID | 最终上下文中的每个 token,按顺序排列 | 在与采样完全一致的序列上重新计算概率 |
| 损失掩码 | 每个 token 对应一位:是否由策略输出 | 从替代目标、散度和长度项中排除观测 |
| 采样对数概率 | 每个策略 token 在生成策略下的对数概率 | 重要性比率的分母 |
| 回合边界 | 每个回合起止位置的 token 偏移量 | 回合级信用分配;逐回合诊断 |
| 结果 | 验证器判定,或超时、截断、篡改标记 | 奖励,以及该采样轨迹是否纳入损失计算 |
逐回合信用分配
GRPO 为一条采样轨迹中的所有回合赋予相同的优势。对于较短的交互过程,这已经足够;对于三十回合的修复过程,它会在回合层面重现 节 3 中的诊断信息抑制现象。有两种切实可行的改进。运行时可以在若干回合边界处计算蒙特卡洛价值,并根据每个回合引起的价值变化为其分配优势,从而仍以终局检查作为判定依据。它也可以添加少量可验证的逐回合信号作为奖励塑形项,例如成功解析的工具调用或正常退出的命令。这些信号成本低廉,但每一个都会成为策略为了达成目标本身而学习追求的目标。因正常退出码而获得奖励的策略会学会运行不可能失败的命令。这类项相对于最终结果应保持较小的权重,而且只能由最终结果决定一条轨迹是否算作成功。
轨迹采样中的环境耗时
一个回合的墙钟时间等于模型生成时间加上工具执行时间;对于智能体任务,工具执行时间往往占主导。测试套件或构建可能需要数秒到数分钟。当一条采样轨迹等待工具返回时,其注意力状态要么常驻推理服务器,要么被丢弃,并在观测返回后重新计算,这就是 保留、驱逐、重计算或卸载 中的保留或重算决策。因此,轨迹采样工作进程调度的是回合,而非整条轨迹的采样。多个环境并发运行,推理服务器为任何已获得观测的采样轨迹执行生成,这与智能体运行框架在部署时使用的等待工具期间让出执行权的模式相同(等待工具)。一次只生成一条采样轨迹的工作进程,会使模型在每次工具调用的大部分时间里处于空闲状态。
停滞与截断的采样轨迹
在大规模训练中,有些轨迹采样永远不会自行结束。测试因死锁而挂起,命令等待永远不会到来的输入,或者策略反复执行同一条失败的命令,而 语义看门狗定时器 中的进度检测机制正是为捕捉这种循环而设计的。因此,每次轨迹采样都在 预算与上限 规定的上限内运行:单次工具调用超时、轮次上限和 token 预算。更棘手的问题是,被截断的轨迹采样应获得什么奖励。将其判为失败,会教会策略在上限内完成任务;当上限与部署预算一致时,这样做是正确的,但也会惩罚那些只需再多几个轮次就能成功的较长方案。在损失计算中屏蔽被截断的轨迹采样,可以消除这种偏差,却浪费了它们消耗的计算资源;而且,如果困难任务更容易被截断,这种做法就会在不知不觉中使训练分布向简单任务偏移。合理的选择是将训练上限设为与部署上限相同,并将截断判为失败,从而让策略在实际可用的预算下学习完成任务。
在部署运行框架下训练
最后一项调整将其他三项调整推广为一条通用要求。策略会学习在轨迹采样期间所见的上下文中采取行动。如果部署运行框架在固定轮数后压缩上下文(上下文压缩)、以特定错误拒绝格式不正确的工具调用,或者执行特定预算限制,那么轨迹采样运行框架就必须采取相同做法,否则策略就是在针对一个它永远不会实际运行于其中的运行框架进行优化。未经上下文压缩训练的策略,可能会依赖压缩时被移除的细节;在更宽松的轮次限制下训练的策略,则会学到在部署时被截断的策略。在多轮强化学习中,运行框架是环境的一部分,训练得到的策略也针对该框架而形成。
屏蔽观测内容、按采样时的原样记录 token、围绕工具等待安排轮次,并使训练运行框架与部署运行框架保持一致后,GRPO 就能像应用于单次响应一样应用于智能体轨迹。然而,每次轨迹采样都会在沙箱中执行动作,而为其评分的测试也位于同一个沙箱中。下一节将弥合这一缺口。
隔离验证器
正在接受优化的策略,是其自身奖励的对手。它没有意图,但在数百万次轨迹采样上执行梯度上升,会产生同样的效果。任何能提高得分的动作都会得到强化,无论它是在修复缺陷,还是在改写测试。模型底层的约束机制(原则 10)已经假定,任何指令都无法保证模型的下一项提议是安全的。强化学习使这一假设成为必然,因为梯度会主动奖励任何能够提高得分的越界行为。这就是内部带有优化器的约束问题 (Lampson 1973年)。基于隔离验证器的强化学习(原则 18)只有在策略无法触及计算奖励的验证器时,才信任该奖励。
作为对手的策略
智能体沙箱 中的沙箱已经将策略的动作与宿主机隔离开来。但它本身并不能将这些动作与奖励隔离,因为在朴素设计中,测试就在策略一直编辑的同一个工作区内运行。该工作区内部的威胁模型包含四条路径,每条都是 智能体威胁模型 中沙箱威胁模型的一个特例:
- 篡改检查。 编辑或删除测试文件、预期输出或构建标志,使原本失败的用例通过。
- 替换工具。 设置
PATH或PYTHONPATH等环境变量,植入桩测试运行器,或向真正的测试运行器加载钩子。 - 获取隐藏信息。 读取留在磁盘上的隐藏测试、探测本地服务,或通过网络获取解答。
- 制造有利的超时。 耗尽内存或陷入循环,使运行框架超时;如果运行框架将超时视为失败以外的任何结果,就可能发放奖励。
出站控制(出口控制)封堵了第三条路径中涉及网络的部分。其余部分则要求将策略的工作区与奖励的工作区置于不同的机器上。
双沙箱隔离区
能够封堵这些路径的设计将两个工作区分开,并仅允许不具执行能力的制品在二者之间传递(图 4)。策略在一次性沙箱中工作,其中包含代码仓库和公开测试。轨迹采样结束时,运行时提取源代码树的统一差异补丁,对其进行检查,再将其应用到第二个全新沙箱中;该沙箱包含未经修改的代码仓库和完整测试套件,其中包括策略从未见过的隐藏测试。返回的只有判定结果。表 1 列出了每一侧可以查看、写入和输出的内容。
| 属性 | 策略工作区 | 验证隔离区 |
|---|---|---|
| 用途 | 探索、编辑、本地诊断 | 对提交的补丁评分 |
| 文件系统 | 代码仓库之上的写时复制可写层 | 原始代码仓库和完整测试套件,只读 |
| 网络 | 无出站访问 | 无 |
| 可见测试 | 仅公开示例 | 公开测试、隐藏测试和回归测试 |
| 生命周期 | 一次轨迹采样,随后销毁 | 一次验证,随后销毁 |
| 输出内容 | 源代码树的统一差异 | 判定结果和粗粒度计数 |
生命周期的每个阶段都会封堵一条途径。工作区不含任何隐藏测试,因此无从读取。提取步骤仅接受源代码树内文件的文本差异;它会拒绝二进制文件、环境文件以及测试目录或构建目录下的任何路径,并在公开测试的校验和发生变化时直接拒绝此次轨迹采样。隔离区从干净的快照启动,因此策略预先植入的任何内容都不会留存其中;隔离区通过先检查再应用的步骤应用补丁:
# Enclave: validate, apply, and run the hidden suite on a clean checkout
$ git apply --check candidate.patch && git apply candidate.patch
$ pytest -q tests/hidden/无法应用的补丁,或被提取步骤拒绝的补丁,均得零分,且不会运行任何由策略编写的代码。判定结果通过单向通道返回;在多轮轨迹采样期间,对于任何中间检查,策略最多只能收到通过或失败的信号,绝不会收到隐藏测试的名称、断言或堆栈跟踪。将这些信息反馈给策略,会使其能够逐轮拟合隐藏测试,从而将封存的测试变为可见测试。
隔离区为每次轨迹采样增加了第二层沙箱和一次验证运行,因此,沙箱池与重置 中采用池化管理并通过快照恢复的沙箱在这里尤为重要。每次轨迹采样都冷启动一个隔离区,其耗费的实际时间可能比轨迹采样本身还长。验证在普通计算资源而非加速器上运行,其容量必须合理配置,使判定速度跟上生成速度,这正是 采集流水线架构 所讨论的采集与验证之间的平衡。
不稳定测试作为奖励噪声
隔离能够阻止蓄意篡改,但也引入了一个统计问题。依赖线程时序、网络模拟、随机种子或浮点容差的测试,有时会让有缺陷的补丁通过。分阶段验证器级联 将此类测试视为训练集中的标签噪声;在 GRPO 下,它们的影响更为严重,因为组内归一化会放大这些噪声。
假设一个存在缺陷的补丁以 0.20 的概率通过不稳定测试。在一组 16 次轨迹采样中,若所有采样都提交等价的缺陷补丁,则至少有一次侥幸通过的概率为 \(1 - (1 - 0.20)^{16} \approx 0.97\)。当一次轨迹采样通过而其余 15 次失败时,在 公式 1 下,这次幸运采样的优势为 \(\sqrt{G-1} = \sqrt{15} \approx 3.87\),这是二元奖励组所能产生的最大正优势。梯度会强烈强化这个存在缺陷的补丁,并在大量任务中教会策略编写利用测试竞态的代码。
隔离区通过三项措施抑制噪声。第一项是 分阶段验证器级联 用于准入的“所有运行均通过”共识规则,此处将其应用于奖励。通过测试的补丁会在 3 个采用不同随机种子的新隔离区中重新运行,只有每次运行都通过才算通过。这将误通过率从 0.20 降至 \(0.20^{3} = 0.008\),而额外运行的成本仅由曾通过一次的补丁产生。第二项是在这些运行中打乱测试顺序,使依赖先前测试泄漏状态的补丁失败。第三项是隔离那些在参考解上多次运行却给出不一致结果的测试,将其完全排除在奖励之外,正如 分阶段验证器级联 对训练数据所做的那样。
工作区与奖励计算位于不同机器上,二者之间仅传递不具备执行能力的差异文件,并且不稳定的判定结果受到抑制。在这些条件下,奖励只衡量隐藏测试所检查的内容,不受策略能够触及的任何因素影响。策略再也无法通过任何其他途径提高得分,只能生成通过测试的补丁。这消除了外部漏洞利用,并暴露出内部问题:优化本身使策略退化的各种方式,下一节将对此展开讨论。
Checkpoint 0.2: 优化智能体轨迹
在考察优化对策略本身的影响之前,请检查你对训练循环的理解:
硬性机制不变量与软性奖励信号
系统设计者经常尝试通过在奖励函数中惩罚不期望的动作来强制落实安全要求和协议遵循要求(例如,对禁止的系统调用扣分)。然而,软性奖励惩罚本质上具有随机性:智能体可能发现,执行一条被禁止的高风险命令能够触发某种漏洞利用,从而获得巨额终局奖励,于是欣然接受微小的中间惩罚。
不变量闭包原则(不变闭包原则)对此作出了形式化表述:不可妥协的安全属性必须通过监督器的硬性防护机制强制保障,而不能依靠软性的优化奖励,表 2 对二者进行了对比。
| 架构层 | 强制保障机制 | 失败响应与信号 | 目标 |
|---|---|---|---|
| 硬性运行时隔离区 | 虚拟机监控器命名空间、seccomp-bpf、只读挂载 | 硬故障(SIGSEGV、EPERM、OOM 终止);立即中止进程 |
主机绝对安全、零数据外泄、测试夹具保护 |
| 软性奖励设计 | 数学损失目标(\(R_{\text{outcome}} + R_{\text{format}} - \alpha \cdot \text{Cost}\)) | 在整个轨迹采样批次上反向传播的可微梯度更新 | 优化任务准确率、节约词元、保证工具调用派发的语法有效性 |
训练病态
即使一次训练运行得到了良好的隔离,仍可能以两种相反的方式出现问题。第一种是策略停止探索。每个组中的轨迹采样趋于相同的词元序列,组内奖励变得完全一致,尽管许多任务仍未解决,梯度却已消失。另一种是轨迹采样每过一百步就变得更长,用反复重述的推理填满词元预算,而通过率几乎没有变化。两者都是优化稀疏奖励的结果,而且在评估中显现之前很久,就已经能够从训练遥测数据中观察到。图 5 概述了这两种变化轨迹及其正则化后的对应轨迹。
熵坍缩
在每个位置,策略都会定义一个词表上的概率分布,该分布的分散程度由其熵衡量:
\[\mathcal{H}(\pi_\theta(\cdot \mid s_t)) = -\sum_{v \in \mathcal{V}} \pi_\theta(v \mid s_t) \log \pi_\theta(v \mid s_t)\]
在训练早期,某个特定词元序列碰巧解决了一些任务,获得正优势,其概率随之增加。每次更新都将更多概率集中到该序列上,而在关键位置,分布逐渐集中于单个词元。随着熵降低,一个任务的 \(G\) 次轨迹采样变得几乎互为副本,奖励变得完全一致,该组便陷入 节 4.3 所述的零方差陷阱。策略再也无法改进,因为它不再采样那些能够揭示更好路径的备选方案。裁剪使坍缩比表面上看起来更容易发生。在对称裁剪下,每次更新中一个词元的概率最多可增至原来的 \(1+\epsilon_{\text{clip}}\) 倍。对于概率已经达到 0.9 的词元,这一上限几乎不起约束作用;但对于概率为 0.01 的备选词元,它将增量限制在极小的绝对值内,因此很少被采样的备选词元恢复缓慢,而占主导地位的词元则继续变得更加集中。
长度失控
在仅依据结果给予奖励的情况下,相反的病态更为常见。更长的推理提高了最终生成正确答案的概率,正确答案会将功劳归于此前的每个词元,而 节 4.2 中的长度归一化对较长的失败轨迹惩罚最轻。平均轨迹采样长度逐渐逼近上限。新增文本大多是重复内容,下面这对示例轨迹就体现了这一点:它们得出了相同的、经验证的答案:
# Illustrative: two traces with the same verified answer (reward 1)
Trace A (184 tokens):
T(n) = 2T(n/2) + O(n). Master theorem, case 2: a = 2, b = 2, f(n) = Theta(n).
Result: Theta(n log n)
Trace B (4,096 tokens):
Let me re-read the recurrence. It says T(n) = 2T(n/2) + O(n). Let me check
that a = 2. Yes. Let me check that b = 2. Yes. Let me restate the master
theorem ... [about 3,900 tokens of restatement and re-checking]
Result: Theta(n log n)
对于智能体而言,长度会带来直接成本。每增加一个 token,就会增加一个生成步骤,并在整个轨迹采样期间保留注意力状态(从上下文 token 到 KV 状态),因此,一个将推理长度增加到四倍的策略,会使每次轨迹采样占用推理服务器的时间大致增加到四倍,并减少服务器能够同时容纳的轨迹采样数量。在多轮回合中,长度失控还会表现为额外的交互轮次:重新读取已读过的文件、重新运行已运行过的命令、迟迟不进行编辑。
对探索与长度进行正则化
RLVR 训练中的病态现象列出了每种病态现象及其标准应对措施。
| 病态现象 | 遥测中的症状 | 成因 | 应对措施 |
|---|---|---|---|
| 熵坍缩 | token 熵下降;零方差组的占比上升 | 对早期解反复强化;对称裁剪 | 自适应熵奖励;提高裁剪上界;参考策略惩罚 |
| 长度失控 | 平均长度上升,而通过率持平 | 将终局奖励归因于每个 token;按每次轨迹采样的长度归一化 | 对超出预算的长度施加惩罚;使用固定分母归一化 |
| 重复循环 | 轨迹采样达到 token 上限时结束,并包含重复的 \(n\)-gram | 重复文本使自身的生成概率进一步提高 | 在生成过程中检测循环;截断并判为失败 |
固定熵奖励 \(\alpha \sum_t \mathcal{H}(\pi_\theta(\cdot \mid s_t))\) 在实践中并不奏效。足以防止策略在简单任务上发生坍缩的系数,会引入噪声,使策略无法进一步专注于困难任务所需的精确语法。自适应控制器在每个批次调整该系数,使熵趋向目标区间 \([\mathcal{H}^*_{\min}, \mathcal{H}^*_{\max}]\):
\[\alpha_{k+1} = \operatorname{clip}\left(\alpha_k - \eta_\alpha \cdot \left(\overline{\mathcal{H}}_k - \frac{\mathcal{H}^*_{\min} + \mathcal{H}^*_{\max}}{2}\right), \; \alpha_{\min}, \; \alpha_{\max}\right)\]
当测得的熵 \(\overline{\mathcal{H}}_k\) 低于该区间时,\(\alpha\) 增大,将概率重新分配给其他选项;当熵较高时,\(\alpha\) 衰减,使策略能够集中于已通过验证的解。一项互补的改动针对裁剪本身。将裁剪上界提高到下界之上,即 \([1-\epsilon_{\text{low}}, 1+\epsilon_{\text{high}}]\),其中 \(\epsilon_{\text{high}} > \epsilon_{\text{low}}\),可以让具有正优势的稀有 token 更快地提高概率,从而直接抵消导致坍缩的非对称性。
对于长度,对每个 token 施加线性惩罚,会抑制困难任务确实需要的长篇推导。阈值惩罚提供一段不受惩罚的预算,仅对超出预算的部分计费:
\[R_{\text{final}} = R_{\text{task}} - \gamma \cdot \max\left(0, \; T_{\text{tokens}} - T_{\text{budget}}\right)\]
其中,\(\gamma\) 的设定应确保达到长度上限的轨迹采样即使答案正确,也无法获得正的净奖励,即 \(\gamma \cdot (T_{\max} - T_{\text{budget}}) \ge 1\)。在预算之内,长度不产生成本;超出预算后,每个 token 都有成本。将每次轨迹采样各自的 \(1/|o_i|\) 替换为固定分母,可以消除对冗长失败轨迹的结构性偏向,使惩罚项无需与目标函数相抗衡。
重复循环需要运行时检查,而非奖励项。轨迹采样工作进程在生成过程中跟踪最近的 \(n\)-gram;当某个片段在一个窗口内的重复次数超过阈值时,工作进程便停止此次轨迹采样,并将其得分记为零。提前停止比评分更重要,因为如果不停止,陷入循环的轨迹采样会一直占用推理服务器上的槽位,直到达到 token 上限。
RLVR 所引发的最深刻的行为转变,是自主回溯能力的涌现。在纯监督行为克隆下,执行过程中遇到错误必然会导致遗憾不断累积(暴露偏差与同策略数据),因为策略只在无瑕疵的轨迹上接受过训练。在 RLVR 下,由于策略仅因通过终局验证测试集而获得奖励,它会发现,识别执行错误并尝试其他工具参数能够带来更高的期望回报。
figure展示了涌现出的自我纠错行为的 token 轨迹。
训练使行为发生哪些变化
一旦坍塌和长度失控得到控制,RLVR 就会以多项报告中一致观察到的方式改变策略的输出。在推理任务上,DeepSeek-R1 报告描述了平均响应长度在强化学习过程中持续增长,而训练并未给出任何延长响应的指令;同时,输出中开始出现策略停下来、重新评估先前步骤并改变方法的段落;报告标出了训练中途的一个时点,此类重新评估在该时点突然出现 (DeepSeek-AI 等 2025年)。在智能体轨迹中,与之对应的行为包括:在编辑前重新运行失败的测试,在修补前阅读堆栈跟踪,以及在工具结果与某个假设相矛盾后放弃该假设。
这些是关于输出的观察,而非关于机制的观察,需要注意两点。出现重新评估的段落并不能证明答案正确;只有验证器才能提供这种证据,而且策略可能学会自我纠正的形式,却未获得其效果。长度增长同样具有歧义。它与长度失控表现为同一种信号,而 节 4.2 的归一化偏差可能在没有任何收益的情况下造成这种增长。区分二者是一个评估问题,应根据在相同词元预算下通过率是否提高(统计评估的严谨性)来判断,而非根据输出是否显得更加深思熟虑。
正则化使策略持续探索,并将其轨迹采样控制在预算内,而验证器则判定由此产生的行为是否有益。这一切都以存在可供策略探索的任务,以及能够针对这些任务运行数百万次轨迹采样的机制为前提。最后一节将讨论这些任务的供给与运行机制。
环境与轨迹采样
一次训练运行若在每一步采样十六条轨迹,针对一千个任务中的每一个,并持续几千步,就会运行数千万个智能体回合。每个回合都需要一个检查可信的任务、一个每次都能重置到相同起始状态的环境、一个沙箱、一次验证器运行,以及模型运行时间。基础设施的设计受两个事实影响。轨迹采样的耗时在很大程度上由环境决定,而非由模型决定;不同轨迹采样的长度可以相差多个数量级。本节将沿着轨迹采样的流程,从任务一直讲到它所帮助训练的权重。
可验证任务从何而来
本章一直假定存在一个具有可信检查的任务池。构建这个任务池占据了 RLVR 项目的大部分工作,而检查的质量限定了训练能够教会策略什么。这个任务池就是 任务夹具设计 中的测试夹具池,其来源也相同:从代码仓库历史中挖掘的任务,附带从失败转为通过以及始终保持通过的测试 (Jimenez 等 2024年);共享同一判定器模板的人工构造变体;以及退款类任务等有状态工具环境,这些环境根据最终状态评分,并由模拟用户驱动。每个测试夹具都必须事先通过该节的区分能力测试,即拒绝未经修改的初始状态,并接受参考解。恢复示范筛选 排除在监督训练之外的困难负例在这里也能发挥作用,因为这些负例对应的任务正是当前策略无法完成的任务。
强化学习使三项数据策展要求从良好实践上升为必要条件。首先是可复现性,因为如果一个测试夹具的测试在参考解上无法确定性地通过,或者它试图从不允许出站访问的沙箱中访问网络,就会将噪声直接注入优势值,而组归一化会进一步放大这些噪声(节 6)。其次是分离性,因为优化器比模仿器搜索得更深入,因此必须遵循 数据集划分卫生验证 的数据划分规范,在代码仓库和问题两个层面上,确保训练任务与所有评估任务互不重叠。在基准自身的代码仓库上训练的策略,其报告的性能提升衡量的是记忆,而非技能。最后是难度。策略总能解决或始终无法解决的任务会产生 节 4.3 中所述的无信号组,因此任务池必须持续保有处于有效信息区间内的任务,并随着策略的改进而更新;更新周期应以梯度步数计,而非自我改进循环中的训练轮次。
轨迹采样的时间花在哪里
有了任务之后,下一个问题是一次轨迹采样的时间花在哪里。数据策展已经要求重置时间仅占回合时间的一小部分(任务夹具设计)。这里的要求更为严格,因为强化学习的轨迹采样持续时间短,且执行次数以百万计;下文的算例将以秒为单位核算一个环境的运行周期,说明这一点。
粗略估算 0.3: 轨迹采样时间与环境重置
变量:
- 每次轨迹采样的有效工作时间,即各轮耗时加上验证器耗时:
\[T_{\text{useful}} = 20 \times (120 + 80)\text{ ms} + 0.5\text{ s} = 4.5\text{ s}\]
数学计算:
冷启动重建:
\[T_{\text{cycle}} = 4.5 + 3.5 = 8\text{ s}, \qquad \frac{4.5}{8} = 56.25\%\]
\[\frac{256 \times 3,600\text{ s}}{8\text{ s}} = 115,200\text{ rollouts per hour}\]
快照恢复:
\[T_{\text{cycle}} = 4.5 + 0.015 = 4.515\text{ s}, \qquad \frac{4.5}{4.515} = 99.7\%\]
\[\frac{256 \times 3,600\text{ s}}{4.515\text{ s}} \approx 204,120\text{ rollouts per hour}\]
结果:在相同的环境和模型下,快照恢复每小时完成的轨迹采样次数是冷启动重建的 1.77 倍。
系统洞见:重置位于每次轨迹采样的关键路径上,因此,资源池中耗时为 沙箱池与重置 的快照恢复几乎使训练吞吐量翻倍,而无需改动模型。同样的核算表明,工具耗时占每轮时间的 40%;对于智能体强化学习,环境速度就是训练速度。
即使重置很快,轨迹采样的长度仍然差异巨大。在同一个组内,一次轨迹采样可能在两轮后就未通过语法检查,而另一次则经历漫长的调试过程,直到达到轮数上限;每轮都运行完整测试套件的轨迹采样,其耗时可能是不这样做的轨迹采样的一百倍。如果训练器在更新前等待一个训练步的所有轨迹采样完成,那么该训练步的耗时就由批次中最慢的轨迹采样决定:
\[T_{\text{step}} = \max_{i} T_{\text{rollout}}(\tau_i) + T_{\text{train}}\]
在耗时最长的轨迹采样完成之前,所有生成器和训练器都处于空闲状态。耗时分布的尾部越重,空闲时间占比就越大;而智能体轨迹采样的耗时分布具有重尾特性,因为工具耗时本身就具有重尾特性。
将轨迹采样与训练分离
循环的两个部分具有不同的工作负载,使用同一个加速器资源池来承担两者,会迫使双方都接受对方的约束。生成过程逐步产生词元,服务于许多独立的轨迹采样过程;这些过程何时开始、何时因工具调用而暂停、何时结束,都难以预测。生成受限于内存带宽(原理 1,推导见 为什么输出的成本高于输入),其内存保存每次轨迹采样的注意力状态。训练则以同步步骤处理整批已完成的轨迹采样,其内存保存权重、梯度和优化器状态。因此,大多数大型 RLVR 系统在独立的资源池中运行生成和训练,如 轨迹采样资源池与训练资源池 所概述,并通过一个存放已完成且经过验证的轨迹采样结果的队列将二者连接起来。
| 属性 | 轨迹采样资源池 | 训练资源池 |
|---|---|---|
| 工作单元 | 一次轨迹采样中的一轮,其间穿插工具等待 | 对一批已完成的轨迹采样执行一次梯度更新 |
| 运行节奏 | 异步;轨迹采样随各自任务的完成而结束 | 同步步骤 |
| 内存保存的内容 | 权重和进行中的轨迹采样的注意力状态 | 权重、梯度和优化器状态 |
| 扩展取决于 | 并发轨迹采样数和环境数 | 模型大小和批次大小 |
| 组内共享的内容 | 任务提示词,只需预填充一次即可供全部 \(G\) 次轨迹采样使用 | 无 |
| 接收的内容 | 每个策略版本获准使用后更新的权重 | 队列中经过验证的轨迹采样结果 |
有一种节省计算的方法可直接用于 GRPO 的分组。同一任务的全部 \(G\) 次轨迹采样都以相同的提示词开始,其中包含任务描述、代码仓库上下文和工具定义,长度通常达数千个词元。由于注意力状态由词元前缀决定(原理 5),组内的这一状态完全相同,因此轨迹采样资源池只计算一次,随后由 \(G\) 次轨迹采样共享;只有在各自采样后续内容时,才开始出现分歧。这就是将 跨轮次前缀缓存 中的前缀缓存和写时复制分叉应用于一个组,从而在每 \(G-1\) 次提示词预填充中省去 \(G\) 次。
限制策略陈旧程度
将资源池分离后,慢任务造成的同步屏障得以消除,因为训练器会使用队列中已有的已完成轨迹采样结果,而生成器则持续生成 (Mnih 等 2016年; Espeholt 等 2018年)。这也引入了一个新问题。在一次轨迹采样的生成、执行和验证过程中,训练器仍在持续更新,因此,当该轨迹采样结果被使用时,生成它的策略已经是旧版本。图 7 展示了两种调度方式,以及限制这一滞后程度的门控机制。
令 \(v\) 表示训练器的更新步数。每条采样轨迹都记录生成它的策略版本 \(v_{\text{rollout}}\)(多回合轨迹采样记录)。当它到达版本为 \(v_{\text{trainer}}\) 的训练器时,其陈旧度为
\[\Delta v = v_{\text{trainer}} - v_{\text{rollout}} \approx \left\lfloor \frac{\Delta t_{\text{rollout}}}{t_{\text{step}}} \right\rfloor\]
其中,\(\Delta t_{\text{rollout}}\) 是从轨迹的第一个 token 生成到轨迹到达训练器所经历的时间,涵盖生成、工具调用、验证和排队;\(t_{\text{step}}\) 是每个训练步骤所需的时间。长智能体轨迹恰恰是返回时已经陈旧的那些轨迹。随着 \(\Delta v\) 增大,当前策略对轨迹中各 token 赋予的概率逐渐偏离采样时的概率,重要性比率
\[\rho_t(\theta) = \frac{\pi_\theta(a_t \mid s_t)}{\pi_{\theta_{\text{rollout}}}(a_t \mid s_t)}\]
也随之偏离 1。该比率乘在每个 token 的梯度上;对于一条长轨迹,少数概率急剧上升的 token 会产生极大的比率,进而造成极大的更新。两种约束可以限制这种危害。准入门控直接丢弃任何满足 \(\Delta v > \Delta v_{\max}\) 的采样轨迹。公式 3 的裁剪替代目标使用 \(\rho_t\) 相对于所记录的采样概率进行计算,限制了保留下来的轨迹中任意单个 token 的影响;这与 actor-learner 系统用于离策略校正的截断重要性权重密切相关 (Espeholt 等 2018年)。此类有界陈旧度机制在分布式训练中已有悠久历史:工作节点读取的参数最多滞后固定数量的步骤 (Ho 等 2013年)。
选择 \(\Delta v_{\max}\) 是在浪费与漂移之间进行权衡。严格的上限,例如一个或两个版本,可以使比率保持在 1 附近,但会丢弃长轨迹;而在智能体强化学习中,长轨迹更多地对应困难任务,因此会使训练分布偏向简单任务。宽松的上限会保留这些轨迹,但依赖裁剪来抑制漂移,这也会抑制它们的学习信号。\(\Delta v_{\max} = 0\) 对应同步调度。在实践中,运行时系统会保持较小的上限,转而缩短 \(\Delta t_{\text{rollout}}\),具体通过更快的环境、回合数上限,以及向轨迹采样池快速广播新权重来实现,从源头上减少到达时已经陈旧的轨迹。
轨迹采样与训练器的分离式架构
在隔离的沙箱中生成数千条多轮智能体轨迹,是一项 I/O 密集且受内存限制的工作负载;而模型梯度反向传播则受计算能力限制,并且对网络带宽的需求很高。尝试将轨迹采样和梯度训练部署在同一 GPU 集群上,会导致等待轨迹期间 GPU 利用率严重不足。
现代 RLVR 基础设施通过将执行拆分到两个专用集群来解决这一问题:一个针对推理优化的轨迹采样引擎,运行支持 KV 前缀缓存的高吞吐量引擎;另一个是分布式训练集群,执行 Megatron-LM 或 FSDP 梯度更新。这种分离式架构如 图 8 所示。
表 3 对比了同步步进锁定循环与异步流式队列之间的同步权衡。
| 架构维度 | 同步锁步架构 | 异步流式架构 |
|---|---|---|
| 集群耦合 | 严格的全局屏障;推理与训练交替暂停 | 完全解耦;通过环形暂存缓冲区持续流式传输 |
| 加速器有效吞吐量 | 较低(\(15\%\text{--}35\%\) MFU),原因是长尾慢任务造成的空泡 | 较高(\(60\%\text{--}85\%\) MFU);流水线空泡时间接近零 |
| 离策略陈旧性 | 严格为零(\(\Delta v = 0\));数据同分布 | 非零(\(\Delta v \ge 1\));数据分布滞后于当前参数 |
| 重要性采样 | 无需使用;标准同策略梯度估计量成立 | 必须使用;通过词元级重要性权重裁剪限制方差 |
| 对慢任务的敏感性 | 严重;步延迟受最坏情况下的轨迹尾部耗时制约 | 极低;耗时较长的轨迹被异步接收或丢弃 |
| 内存压力 | 批次屏障期间存在大量临时 GPU HBM 分配 | 环形回放队列中的主机锁页 DRAM 用量恒定 |
同组慢任务的延迟差异
在 GRPO 等组相对算法中,对一个提示进行梯度更新,需要该组中的全部 \(G\) 次轨迹采样完成后,才能计算组均值 \(\mu_{\text{group}}\) 和标准差 \(\sigma_{\text{group}}\)。在多轮编码环境中,轨迹执行时间可能相差数个数量级(从简单的 1 轮语法检查到 30 轮测试套件),同组执行时间由极端慢任务决定: \[ T_{\text{cohort}} = \max_{j \in \{1, \dots, G\}} T_j \] 不同队列规模下的实测延迟差异详见 轨迹采样队列执行延迟差异。
| 轨迹采样工作进程 | 生成的 token 数 | 终止原因 | 执行时间特征 | 同步屏障空闲开销 |
|---|---|---|---|---|
| 工作进程 \(\tau_1\) | 48 个 token | 提前失败(语法错误) | 快速退出(\(\sim 0.2\ \text{s}\)) | 4,048 个 token 槽位空闲等待(\(98.8\%\) 空闲) |
| 工作进程 \(\tau_2\) | 512 个 token | 提前成功(测试通过) | 正常完成(\(\sim 2.1\ \text{s}\)) | 3,584 个 token 槽位空闲等待(\(87.5\%\) 空闲) |
| 工作进程 \(\tau_3\) | 1,024 个 token | 多轮重构 | 延长搜索(\(\sim 4.2\ \text{s}\)) | 3,072 个 token 槽位空闲等待(\(75.0\%\) 空闲) |
| 工作进程 \(\tau_4\) | 4,096 个 token | 达到最大深度而超时(\(T_{\max}\)) | 慢工作进程的最坏情况(\(\sim 16.8\ \text{s}\)) | \(0\) 个槽位空闲(仍在执行、使屏障等待的慢工作进程) |
发布门禁隔离环境
将新训练的 RLVR 检查点晋级至轨迹采样池,需要通过自动化发布门禁,以确保策略没有对验证器过拟合,也没有发生灾难性的能力崩溃。发布门禁的验证标准列于 确定性发布门禁评估隔离环境。
| 评估隔离环境 | 测试套件与基准目标 | 验证判定机制 | 门禁通过阈值 | 门禁失败后的缓解措施 |
|---|---|---|---|---|
| 核心领域基准 | 256 项未见过的软件工程任务 | 沙箱编译与测试套件运行器 | 通过率 \(\ge \text{Baseline} - \epsilon\)(\(\epsilon \le 0.5\%\)) | 暂停晋级;触发学习率衰减 |
| 回归测试套件 | 256 项形式化多步推理任务 | 形式化证明器(Lean 4)与符号检查器 | 黄金参考任务上的通过率 \(\ge 100\%\) | 拒绝该检查点;恢复至上一个有效发布版本的指针 |
| 契约不变量套件 | 程序化模式验证测试 | 严格的 JSON 模式解析器 | 格式漂移为零(100% 严格合规) | 回滚策略权重;检查分词器和提示适配层 |
对新策略版本实施门禁
异步循环还有一个风险。每个新版本的权重都会广播到轨迹采样池,因此,一个有问题的版本不仅会得分偏低,还会生成后续批次的训练数据。如果某个版本学会了利用格式漏洞、退化为循环,或丧失了生成格式正确的工具调用的能力,它就会使队列充满退化的轨迹采样结果;验证器拒绝这些结果,各组不再产生有效反馈,而恢复则需要回滚权重并丢弃该问题版本生成的所有轨迹采样结果。训练损失无法揭示这一点;强化学习损失噪声较大,并不能反映任务成功率。
因此,新版本必须通过 分阶段金丝雀部署 中的发布门禁,才能晋级至轨迹采样池,并在之后进入部署,而不能直接从优化器进入这些阶段。对于 RLVR,门禁会在奖励机制从未接触过的留出环境中检查三项内容:
- 目标能力。 对于与训练任务同类的留出任务,新策略经验证的通过率必须在明确规定的容差范围内达到当前策略的水平,并采用 统计评估的严谨性 中的试验次数和置信区间。
- 其他方面无回归。 训练分布之外的回归测试套件应覆盖其他语言、其他工具类别和指令遵循,其表现不得低于基线。针对某一任务类别的强化学习可能削弱其他类别的能力。
- 契约合规性。 新版本在留出测试套件上生成的每一次工具调用,都必须能够依据其模式进行解析。策略的格式漂移会破坏智能体运行框架,而不仅仅是影响得分。
门禁还应报告恰当的统计指标。强化学习可以提高 pass@1,却不提高 pass@\(k\)(在 \(k\) 较大时),因为它可能只是将概率集中到初始策略偶尔已能采样到的解上,而没有找到新的解。同时报告这两项指标,以及重复运行中的 pass\(^k\) 可靠性(统计评估的严谨性),能够区分策略是变得更可靠,还是能力变得更强;实际部署通常对前者的需求与对后者的需求同样迫切。
环境池、彼此分离的轨迹采样池与训练池、新鲜度门控和发布门控,使 RLVR 成为生产系统,而不再只是实验。接下来需要讨论的是团队在构建此类系统时容易产生的误判。
谬误与陷阱
基于验证器的强化学习,其失败方式在训练曲线上往往看起来像是成功。以下误判反复出现,是因为它们都源于对奖励、输出长度或轨迹采样运行框架的过度信任。
谬误: 可验证的奖励无法被钻空子。
确定性检查无法被奉承,但错误的产物也可能满足其要求。检查退出码的奖励,可以被一个以零退出的桩程序满足;检查输出文件是否存在的奖励,可以被一个空文件满足;覆盖不足的测试套件,可以被仅处理测试输入的代码满足。在强化学习中,策略恰恰会搜索这些漏洞(节 2)。防御方法是在用任务开展训练之前,将每个任务的检查机制视为攻击面:为 任务夹具设计 中的辨别测试补充刻意构造的错误解答,要求检查机制必须拒绝这些解答;使用隐藏的 fail-to-pass 和 pass-to-pass 测试评分;并在奖励机制从未接触过的留出环境中评估训练后的策略(节 8.8)。
陷阱: 在智能体的工作区内运行验证器。
在策略一直编辑的工作区中运行测试,可以省去第二个沙箱和补丁传输,却也让策略获得了对自身奖励的写入权限。策略最终会修改断言、删除失败的测试,或在测试运行器中植入钩子;由于每种钻空子的做法都比真正修复更短,它们便会胜出(节 6)。指令或惩罚等模型侧措施,只能降低篡改的概率。真正的保证来自隔离执行区:工作区中不存放任何隐藏测试,只有经过检查的差异补丁可以离开工作区,而判定结果则由一个包含干净代码检出的全新沙箱计算得出。
谬误: 更长的推理轨迹表明,强化学习带来了更深入的问题求解。
强化学习会因多种原因导致长度增加,其中只有一种是有益的。终止奖励将正确轨迹中的每个 token 都计入贡献;按每次轨迹采样进行的长度归一化,对较长失败轨迹的惩罚最轻(节 4.2);重复文本则会提高自身再次出现的概率。已有报告中的重新评估行为确实存在(节 7.4),但输出中出现这种行为,并不能证明输出正确。对于智能体而言,额外的长度会消耗轨迹采样时间、服务器容量,并增加部署时的延迟。检验标准是在相同 token 预算下的通过率,而非轨迹长度。
陷阱: 使用每次轨迹采样都通过或每次轨迹采样都失败的任务进行训练。
如果一组轨迹采样的得分完全相同,那么每次轨迹采样的优势值都为零,对梯度没有任何贡献,尽管已经为 \(G\) 次完整的轨迹采样及其沙箱和验证器运行付出了成本(节 4.3)。随着策略改进,从固定数据集中均匀采样的任务池会逐渐进入这种状态:简单任务的通过率趋于饱和,而不可能完成或存在缺陷的任务始终无法产生成功结果。跟踪每个任务近期的通过率,从通过率既不为零也不为一的区间中采样,更新任务池,并让每个批次都由能产生梯度的组构成,可以确保轨迹采样预算始终用于仍能提供学习信号的任务。
陷阱: 使用与部署时不同的运行框架采集训练轨迹。
如果轨迹采样运行框架跳过上下文压缩、使用不同的模板呈现工具调用、允许更多轮交互,或在训练前对交互记录重新分词,就会得到一个针对永远不会遇到的上下文进行优化的策略(节 5)。这种不匹配的表现是:策略在训练中得分很高,却在部署后性能下降,而任何训练指标都无法解释其原因。轨迹采样应通过部署所用的运行框架执行,采用部署时的预算,记录策略实际采样的 token,并对环境写入的所有内容进行掩码处理。
总结
监督微调止步于示范所覆盖的范围;只要存在能够判定轨迹是否成功的检查,可验证奖励强化学习就能超越这一范围。代价是,检查本身成为了优化目标。本章依次探讨了由此产生的后果。由封闭的确定性检查构建的奖励决定得分,而格式项、部分得分以及学习型评判器或基于评分准则的评判器仅对其加以塑造;对危险动作的惩罚永远不能替代能够阻止这些动作的沙箱。终局奖励能够说明三十轮交互是否成功,却无法指出哪些轮次作出了贡献,因此,信用分配要么依赖策略可以钻空子的学习型步骤评分,要么依赖蒙特卡洛续采样,而后者的 token 成本随时域长度的平方增长。GRPO 用组内统计量替代学习型评价器,代价是需要整组轨迹采样,而且无法从结果一致的组中获得信号。多轮回合要求屏蔽环境写入的内容,记录策略实际采样的内容,并在部署时使用的智能体运行框架下训练。验证器必须位于独立的隔离区内,仅接收经过检查的差异补丁,并抑制不稳定的判定。一旦策略无法触及奖励机制,剩余的失效便来自内部,即熵坍塌和长度失控;剩余的成本则来自环境,因为工具耗时、重置耗时以及呈重尾分布的轨迹采样决定了训练节奏,促使轨迹采样与训练在不同的资源池中运行,并受到新鲜度门控和发布门控的约束。
要点回顾: 针对策略无法触及的检查进行优化
- 只有存在检查时,奖励才能替代示范:RLVR 能够在具有可信检查且初始通过率大于零的任务上改进智能体;对于策略从未解决过的任务,无论进行多少次轨迹采样,都不会产生梯度。
- 奖励什么,策略就学习什么:只要检查与意图之间存在策略可利用的漏洞,奖励投机就是预期结果。确定性检查决定奖励;学习型评判器和格式项仅对其加以塑造,而惩罚能够降低不安全动作的概率,却无法阻止这些动作。
- 将验证器置于边界的另一侧:策略的工作区中不存放任何隐藏测试,只有经过检查的差异补丁才能传入全新的隔离区,返回的也只有判定结果。不稳定的测试需要通过重复运行取得一致判定,因为组内归一化会将一次侥幸通过转化为组内最大的优势。
- 组基线以轨迹采样换取评价器的省略:GRPO 不需要价值模型,但每个任务要耗费 \(G\) 次轨迹采样,无法从结果一致的组中获得信号,而且其归一化会引入长度偏差和难度偏差,需要运行时加以校正。
- 多轮强化学习使策略适应其智能体运行框架:在损失、比率和长度计数中屏蔽观测 token,记录采样所得的 token ID 及其概率,并在部署时使用的智能体运行框架和预算下进行轨迹采样。
- 环境耗时就是训练耗时:工具调用、重置以及呈重尾分布的轨迹采样长度决定了吞吐量,因此轨迹采样和训练在不同的资源池中运行,数据陈旧程度由新鲜度门控限制,而每个新版本的权重在生成更多数据之前都必须通过发布门控。
将优化器置于沙箱内并使其以奖励为目标,使针对隔离验证器的强化学习(原则 18)落实为三项具体要求。验证器在仅接收补丁的独立隔离区中运行,留出测试限定了奖励能够教会策略的内容,而组相对梯度只存在于策略在部分尝试中成功、在另一些尝试中失败的任务上。双沙箱隔离区将模型底层的遏制机制(原则 10)从宿主扩展到了奖励本身,而发布门控则将验证不对称性(原则 3)从单次决策延伸到了每个新版本的权重。
后续内容: 从一个更好的智能体到多个智能体
第五部分以一个更好的单智能体收尾:其策略基于经过验证的轨迹筛选构建,经过微调以执行动作,并针对其无法触及的检查进行优化。如今,它的权重使提出能够通过检查的方案更有可能,但并未赋予它任何新的权限;它仍然使用一个上下文,在同一段实际耗时内运行一条轨迹。有些任务会同时使这三者承压,例如状态量超出单个上下文容量的代码仓库迁移,或可以并发运行的独立子任务。将此类任务拆分给多个智能体,会使每一项 H·S·A 暴露成倍增加,并带来协调这些智能体的成本。多智能体协同 由此开启第六部分《规模化智能体》,探讨相较于预算相同的单智能体,这种协同开销何时能够带来足以抵偿自身的收益,以及在能够抵偿时,协同机制必须强制落实哪些约束。
