跳转到正文
YK Liu
返回

深入浅出讲解 Agentic RL Infra 八大问题

Agentic RL Infra 这个词,第一次看上去,很容易让人觉得只是把几个熟悉的词拼在了一起:Agent、强化学习、基础设施。

仔细看下去,却会发现每个词都在增加难度。模型要生成很长的内容,要调用工具,要等环境反馈,还要从这些经历里学到东西。等你把生成速度提上来,数据又过期了;把过期数据过滤掉,昂贵的轨迹又白跑了;好不容易看到奖励上涨,模型可能只是学会了绕过测试。

问题就这样一层层长出来。

Agentic RL Infra,是支撑智能体在环境中采样、执行、验证和学习的一整套系统。 它既要把算力用起来,也要保证送进优化器的经历值得学习。GPU 上的训练只是其中一段,队列、工具、沙箱、评分器和上下文管理,同样会改变最后学出来的策略。

理解它,不妨从一个具体任务开始:让一个代码 Agent 修复 bug,同时保证原本正常的功能不被破坏。 它需要读仓库、定位问题、修改文件、运行测试、分析报错,可能再来几轮。我们沿着这件事,把八个问题依次拆开。

目录

从 RL 到 Agentic RL,究竟变了什么

RL 学的是行为,不只是答案

强化学习(Reinforcement Learning,RL)的基本过程并不复杂:智能体看到当前情况,采取行动,环境发生变化,再返回反馈。如此反复,形成一条轨迹,trajectory,通常记作 τ\tau。

把单步奖励记作 rtr_t,一条轨迹的折扣回报记作 G(τ)G(\tau):

G(τ)=∑t=0T−1γtrt,J(θ)=Eτ∼πθ[G(τ)].G(\tau)=\sum_{t=0}^{T-1}\gamma^t r_t, \qquad J(\theta)=\mathbb E_{\tau\sim\pi_\theta}[G(\tau)].

πθ\pi_\theta 是参数为 θ\theta 的策略,γ\gamma 是折扣因子,TT 是轨迹长度。训练希望提高期望回报 JJ。这里要分清两个词:reward 是某一步得到的奖励,return 是把后续奖励累计起来的回报。 有些论文也用大写 RR 表示回报,读公式时先看定义,不能只看字母大小。

如果只在任务结束时给分,中间的 rtr_t 可以全是零。一个修改代码的动作没有立刻得到奖励,不代表它没有价值;它的价值可能要到几分钟之后,测试真正跑完才体现出来。

传统 RL 早就在处理延迟奖励、探索和信用分配。Agentic RL 没有重新发明这些问题,而是把它们带进了一个特别昂贵、特别长、特别难控制的环境。

RLHF、RLVR 与 Agent,并不是一条简单的替代链

语言模型的预训练和监督微调,主要从已有文本里学习“下一步应该写什么”。RLHF(基于人类反馈的强化学习)进一步把人的偏好变成奖励,让模型更倾向于产出被认可的回答。

RLVR(基于可验证奖励的强化学习)则尽量使用能自动检查的结果:数学答案是否正确、程序能否通过测试、形式化证明能否通过检查。DeepSeekMath 提出的 GRPO,是这一发展过程中的重要方法之一。DeepSeekMath 原论文

但“答案能检查”不等于“过程容易训练”。一段几万 token 的推理,即使没有外部工具,也已经会带来长序列和稀疏奖励问题。

另一边,Agent 把模型接进了一个循环:生成行动,执行工具,读取观察,再决定下一步。ReAct 是把推理与行动交替组织起来的代表性工作,但这样的 Agent 可以仅靠提示和已有模型运行,并不要求重新训练权重。ReAct 原论文

当我们用整段交互经历来更新策略,训练模型怎样行动、怎样使用工具、怎样从失败中恢复时,就进入了本文讨论的 Agentic RL。 它可以使用可验证奖励,也可以使用偏好和生成式评判;并不是 RLHF 或 RLVR 的简单下一代。

一次回答,变成了一条会改变世界的轨迹

对代码 Agent 来说,模型看到的只是仓库和执行状态的一部分。完整历史记作 hth_t,真正送给模型的上下文可能经过压缩,记作 ctc_t:

at∼πθ(⋅∣ct),ot+1∼Penv(⋅∣ht,at),ct+1=fctx(ht,at,ot+1).a_t\sim\pi_\theta(\cdot\mid c_t),\qquad o_{t+1}\sim P_{\mathrm{env}}(\cdot\mid h_t,a_t),\qquad c_{t+1}=f_{\mathrm{ctx}}(h_t,a_t,o_{t+1}).

ata_t 是模型动作,ot+1o_{t+1} 是工具返回的观察,fctxf_{\mathrm{ctx}} 是上下文管理逻辑。环境的完整状态往往不可见,因此把它看成部分可观测决策过程更合适。

这里有两个时间尺度。Agent 层面的一步可能是“运行测试”;模型层面,这个调用又是逐个 token 生成出来的。后面讨论 token 级概率比值时,我们是在更细的尺度上分析同一个行为过程。

代码 Agent 的推理、环境执行、奖励验证、轨迹队列与训练更新闭环

图 1:生成与环境交互产生经历,验证与训练决定哪些经历会改变策略。实线是主要数据流,虚线表示权重更新。

从系统角度看,变化尤其明显:生成不再连续占着 GPU,工具执行会插进来;每条轨迹时长不同;上下文可能被改写;环境也可能坏掉。于是,下面八个问题就不再是八个可以分别处理的小问题。

问题最直接的矛盾常见处理方法仍然留下什么
架构选型资源共享与独立扩缩共卡、训推分离、环境外置动态负载与同步成本
同步与异步等待成本与分布偏移partial rollout、流式队列、窗口 FIFO长任务公平性与截断偏差
策略陈旧新鲜度与样本复用版本窗口、背压、重要性采样版本差不能代表实际漂移
训推不一致吞吐与数值一致性算子对齐、QAT、掩码、路由回放校正有偏、对齐昂贵
策略算法稳定性与有效梯度GRPO、GSPO、CISPO、分层过滤不同任务缺少统一最优解
奖励与信用分配结果可信与归因精细outcome、rubric、critic、GAE局部贡献难观测
Reward Hacking代理分数与真实目标独立验证、权限隔离、对抗审计新漏洞与语义投机
环境噪声可复现与真实复杂性故障归因、重试、mask、课程训练噪声分布与部署分布不一致

一、架构选型:训练、推理和环境怎样摆放

代码 Agent 运行一次测试,可能要等几十秒。此时模型并不需要一直计算。如果把“Agent 任务还没有结束”理解成“GPU 还得专门留给它”,利用率很快就会变得难看。

因此,首先要分清三种工作:训练负责更新参数,推理负责生成动作,环境负责执行动作。 它们对资源的需求并不一样。

训练需要保存梯度、优化器状态和激活,通常偏重高吞吐的矩阵计算与通信。推理需要权重和 KV cache,prefill 与 decode 的瓶颈又有差别。环境可能主要消耗 CPU、内存、磁盘和网络;浏览器、编译器、测试进程也各有脾气。某些环境还需要 GPU,所以“环境外置到 CPU”是一种常见布局,不是定义。

共卡与分离,各有一笔账

共卡,colocated,指训练与推理共享 GPU 资源。 常见做法是分时:生成阶段跑推理引擎,训练阶段切换到训练引擎,必要时 offload 暂时不用的数据。资源不被固定切成两池,较小集群里往往更容易安排。

代价是切换、搬运和显存协调。如果希望在同一设备上交叠执行,还要处理计算与内存带宽竞争。共卡不等于“两个引擎随时可以同时满速运行”。

训推分离,disaggregated,指为训练和推理配置独立资源池。 训练池更新权重,推理池持续生成,两边通过权重同步和轨迹传输连接。推理侧可以选择不同硬件和并行方式,环境等待也更容易由大量并发请求摊平。

不过,分离会产生副本、网络传输、独立资源池闲置等成本。模型更新得越频繁,权重同步的代价越难忽略。AReaL 是解耦生成与训练、让两者交叠运行的代表系统。AReaL 原论文

共卡与训推分离都可以连接独立的 CPU、容器或 microVM 环境池

图 2:共卡与分离回答 GPU 怎样分配;环境外置回答工具在哪运行。这是两层选择,不是三个互斥选项。

做一个理想化的容量估算。假设每批 rollout 需要 TrT_r 秒,训练需要 TlT_l 秒,权重更新与切换等未被隐藏的开销是 TwT_w:

Tserial≈Tr+Tl+Tw,Toverlap≳max⁡(Tr,Tl)+Tw.T_{\mathrm{serial}}\approx T_r+T_l+T_w, \qquad T_{\mathrm{overlap}}\gtrsim\max(T_r,T_l)+T_w.

第二个式子描述资源足够、流水线进入稳态后的每批间隔下界。假设 Tr=80T_r=80 秒、Tl=40T_l=40 秒、Tw=5T_w=5 秒,两者是 125 秒和至少 85 秒。但这不能直接当成相同预算下的 1.47 倍加速:如果交叠需要额外 GPU,GPU 小时可能反而增加。必须在相同总资源或相同费用下重新比较。

环境侧也有自己的容量约束。按照 Little 定律,在稳定系统里,平均在途任务数约为到达率乘以平均停留时间。假设每秒启动 4 个环境任务,平均停留 90 秒,就需要容纳约 360 个在途任务;内存、进程数和网络连接也要按这个规模准备。再加 GPU,并不能解决环境池已经排满的问题。

还没有解决的是动态平衡

训练前期,模型可能很快失败;训练后期,它开始多试几次、调用更多工具,轨迹自然变长。即使模型规模没变,最合适的资源比例也会变。

因此,值得继续做的方向是按实际队列和负载动态分配资源:推理积压时增加 rollout 容量,环境等待增加时扩容沙箱,训练吃不完时限制新任务。共享前缀复用、KV cache 分层存储、增量权重传输也能降低开销,但都要检查是否保留了真实上下文和训练语义。

架构好不好,最终应看达到同一验证集水平用了多少时间和 GPU 小时,以及环境资源花了多少钱。单看 GPU 利用率,很容易把“机器忙着”误认为“学习有效”。

二、同步与异步:为什么大家开始不等最慢的任务

假设同一批启动了三个代码任务,分别需要 10 秒、20 秒和 100 秒。同步训练必须等到第 100 秒,再统一更新参数。前两个任务早就完成了,却还不能进入下一轮。

如果把它们想成三个固定工作槽,这一轮的时间利用率只有:

Uslot=10+20+1003×100≈43.3%.U_{\mathrm{slot}}=\frac{10+20+100}{3\times100}\approx43.3\%.

这是调度示意,不是 GPU 利用率实测。真实推理引擎会动态拼 batch,但同步屏障仍然会让最慢的轨迹决定批次什么时候结束。

异步解决了等待,又改变了数据抵达的顺序

异步把两个循环拆开:rollout 不断生产经历,learner 凑够一批就训练。AReaL 还支持 partial rollout,让一条长轨迹跨多个策略版本继续生成。AReaL 异步训练文档

partial rollout 的关键是“这次暂停,后面继续”,不是把所有超时轨迹都判成失败。它可能需要保存生成状态,也可能需要保存环境快照。未完成轨迹如果要提前参与训练,还得解决末端价值估计;没有终局奖励,不能随手填一个零。

恢复时还有一个细节:旧权重算出的 KV cache,不能直接当作新权重下重新计算的结果。系统需要选择重算、继续使用旧版本,或明确记录混合版本的生成语义;否则连“这段内容由哪个策略生成”都说不清。

全异步 streaming 则进一步弱化整批屏障,让完成的轨迹持续流入队列,训练与生成交叠。这里的 streaming 指训练流水线的数据流,不是聊天界面逐字显示答案。

但“谁先完成就先训练”会带来另一个问题:简单任务往往更快,复杂任务往往更慢。训练早期看到的经验,可能被简单任务占满。若系统又有超时、取消和有限队列,这种差异还会影响最终被接纳的比例。

反过来,如果每个任务只执行一次、没有丢弃,并且最后全部消费,完成顺序不一定改变最终计数;它仍然会改变训练过程中的分布,以及任务抵达时对应的策略版本。讨论偏差时,需要分清这两层。

Windowed FIFO 保留一部分秩序

MiniMax 的 Forge 使用 Windowed FIFO:给提交队列设置一个滑动窗口,只允许消费窗口内已经完成的任务。窗口内可以先取快的,窗口外即使完成也先等着;窗口随着队首任务被消费而前进。MiniMax-M2 技术报告,第 6.2.4 节

同步批次等待最慢任务,窗口 FIFO 在局部窗口内允许完成顺序不同

图 3:窗口大小决定调度自由度。它减轻阻塞,也限制纯粹按完成速度取样;窗口内最老的任务仍可能拖住整体前进。

窗口太小,接近严格 FIFO,容易等长尾;窗口太大,接近全局贪心,局部批次的分布更容易变化。这不是一个只影响速度的参数,它还会影响 learner 看到什么。

长尾 token 预算,也是一种选择

一种直接办法是给每轮规定 token 预算,剩下的长轨迹暂停,留到下一轮;另一种是给每个任务设最大生成长度和工具调用次数。两者分别管理批次推进与任务资源上限,不能混在一起。

尤其要问清:模型已经做错了,还是预算先用完了? 如果预算就是产品要求的一部分,超预算属于失败;如果只是训练系统暂时切断采样,则应考虑续跑或 bootstrap。二者的训练目标不同。

这一类问题还没有统一答案。更合理的方向,是让调度器同时看到任务类型、耗时分布、难度、样本年龄和训练配比,而不只看到“完成了没有”。验证时除了吞吐,还应观察各类任务进入训练的比例、P95/P99 时长、取消率,以及长任务是否被系统性遗漏。

三、策略陈旧:数据还没用,模型已经往前走了

训练与生成交叠以后,一条轨迹可能由第 100 版模型开始生成,等它运行完测试、进入队列、凑齐训练批次时,learner 已经到了第 106 版。

这条经历不是坏数据,但它来自旧的行为策略。当前模型未必还会以同样概率采取那些行动。这就是 policy staleness,策略陈旧。

最简单的记录是版本差:

Δv=vlearner−vbehavior.\Delta v=v_{\mathrm{learner}}-v_{\mathrm{behavior}}.

staleness manager 可以限制最大版本差、在途请求数和队列容量。生产过快时施加背压,过旧样本则拒绝、降权或作进一步检查。AReaL 的实现就是把并发容量与 off-policy 约束放在一起管理。StalenessManager 源码

不过,版本号只是一个便宜的代理指标。两次大更新可能比十次小更新改变得更多;同一批参数变化,也可能对简单题影响很小,对某类工具调用影响很大。

重要性采样为什么有用,又为什么难用

假设数据来自行为分布 μ\mu,希望估计目标分布 π\pi 下的期望,可以使用重要性采样,Importance Sampling,简称 IS:

Ea∼π[f(a)]=Ea∼μ[π(a)μ(a)f(a)].\mathbb E_{a\sim\pi}[f(a)] =\mathbb E_{a\sim\mu}\left[ \frac{\pi(a)}{\mu(a)}f(a)\right].

成立的前提包括:目标分布有概率的动作,行为分布也必须能采到。放到多步决策里,还要处理历史或状态分布的变化;只乘当前 token 的局部比值,不会自动完成整条轨迹的无偏校正。

一条完整轨迹的概率比,包含每一步动作概率比的乘积。假设为了说明累积效应,某条已采样轨迹上 100 步的比值恰好都是 1.02,那么:

1.02100≈7.24,1.02500≈19956.1.02^{100}\approx7.24,\qquad 1.02^{500}\approx19956.

这不是说所有轨迹都会单向增长;真实比值有大有小。它说明,长程乘积可能让少数轨迹拿到极大的权重,梯度估计的方差很难控制。

因此,系统常用截断或掩码来牺牲一部分无偏性,换取稳定性。但代价不能藏起来:删掉的样本也许正是昂贵的长任务;留下的样本可能越来越集中在容易生成、变化较小的区域。

可以用有效样本量粗看权重是否被少数样本垄断:

ESS=(∑i=1Nwi)2∑i=1Nwi2.\mathrm{ESS}=\frac{(\sum_{i=1}^{N}w_i)^2}{\sum_{i=1}^{N}w_i^2}.

当权重相近时 ESS 接近 NN;当极少数权重占主导时,ESS 会显著下降。它只是权重退化的诊断量,不代表最终学习收益,也不能反映所有过滤偏差。

接下来要管理的,是整段经历的年龄

partial rollout 会让同一条轨迹的不同片段来自不同版本。用一个版本号标记整条轨迹,信息已经不够。至少应保留片段或 token 对应的行为版本、采样 log-probability,以及暂停和恢复位置。

陈旧也不只发生在排队阶段。轨迹生成了很久,本身已经老了;生成完又在池里等了一段时间,则进一步变老。PACE 正是把生成期陈旧与等待期陈旧分开分析的近期研究。PACE 原论文

我认为更有价值的方向,是把版本年龄、实际概率漂移、任务类别和队列压力结合起来,决定一条经历还能否使用。固定“最多落后四步”很容易实施,却很难成为所有模型和任务通用的答案。

四、训推不一致:同一份权重,为什么不是同一个策略

假设把异步关掉,也不更新参数。推理引擎生成了一段内容,训练引擎拿同一份权重计算它的概率。按直觉,两边应该一致。

实际却未必。

推理与训练可能使用不同的矩阵乘法 kernel、精度、归约顺序、attention 实现和并行切分。MoE 还有一个敏感环节:top-k 专家选择。路由分数接近边界时,很小的数值变化就可能换掉专家,后续计算路径随之改变。

所以需要区分:陈旧是参数版本变了;训推不一致是执行路径变了。即使参数没变,后者也可能存在。

把两个比值拆开看

用 πtrain,v\pi_{\mathrm{train},v} 表示训练引擎上的第 vv 版策略,μinfer,v\mu_{\mathrm{infer},v} 表示真正生成数据的推理策略。learner 已更新到 v+kv+k 时,有:

πtrain,v+k(at∣ct)μinfer,v(at∣ct)=πtrain,v+k(at∣ct)πtrain,v(at∣ct)⏟参数更新带来的变化⋅πtrain,v(at∣ct)μinfer,v(at∣ct)⏟相同版本下的训推差异.\frac{\pi_{\mathrm{train},v+k}(a_t\mid c_t)} {\mu_{\mathrm{infer},v}(a_t\mid c_t)} = \underbrace{\frac{\pi_{\mathrm{train},v+k}(a_t\mid c_t)} {\pi_{\mathrm{train},v}(a_t\mid c_t)}}_{\text{参数更新带来的变化}} \cdot \underbrace{\frac{\pi_{\mathrm{train},v}(a_t\mid c_t)} {\mu_{\mathrm{infer},v}(a_t\mid c_t)}}_{\text{相同版本下的训推差异}}.

这是 LongCat-Flash-Prover 分析 HisPO 时采用的分解思路:两类偏移应该分别处理。LongCat-Flash-Prover,第 3.3 节

分母必须与真实采样行为对应。temperature、top-p、top-k 和受限解码都会影响行为分布;保存的是原始 softmax 概率,还是经过采样变换后的概率,必须说清楚。top-p 等截断还会改变支持集,标准 IS 的前提可能不再满足,不能靠一个比值就宣称完全校正。

先检查更基础的东西:token ID 是否一致、chat template 是否一致、工具返回是否被重新截断、训练时是否重建了模型当时真正看见的上下文。对着不同输入算出的两个概率,谈不上单纯的数值对齐。

三条常见路线

第一条,在系统层减少差异。 对齐敏感算子、数据类型、量化尺度和采样语义。MiniMax 在 M1 的实践中发现 LM head 精度对训练与推理概率的一致性十分关键,恢复这一层的 FP32 计算后训练才明显改善。这说明,有时问题不在 loss 公式,而在下面的数值路径。MiniMax 官方后训练经验

低精度进一步放大了这个问题。FP8、MXFP4 等可以降低部分存储和计算成本,但“推理量化、训练不量化”可能增加分布差异。量化感知训练(QAT)让训练过程也接触量化误差,不过两端都写着 FP8 或 FP4,仍不代表尺度、舍入和 kernel 一致。NVIDIA 端到端 FP8 RL 实践

第二条,在算法层过滤或校正。 IcePop 用训推概率比的上下界筛掉偏差较大的 token。KPop 则改用采样 token 与“其他所有 token”形成的二元分布,检查两个方向的 binary KL,把固定比值窗口改成随概率位置变化的接受区域。KPop 团队技术说明

对二元概率 p,qp,q,它所使用的基本量是:

DB(p∥q)=plog⁡pq+(1−p)log⁡1−p1−q.D_{\mathrm{B}}(p\Vert q) =p\log\frac pq+(1-p)\log\frac{1-p}{1-q}.

这种检查比固定比值多考虑了概率所在区域,但它不是整个词表的完整 KL;通过检查,也不等于两种策略完全相同。无论如何筛选,都需要观察被删掉的是哪些 token 和任务。

第三条,回放 MoE 路由。 Rollout Routing Replay,R3,记录采样时的专家选择,并在训练时复用,直接减少路由路径差异。R3 原论文

R3 需要保存和传输路由元数据,也会改变训练时自由选择专家的行为。它解决的是一类不一致,不能顺便消除模板、attention 或量化路径的所有差异。近期的 Router Drift Control 进一步讨论了回放可能引入的梯度偏差,并研究按路由漂移过滤的替代方法。这仍是具体实验下的研究结果,不能据此认定回放已经过时。Router Drift Control 原论文

真正需要的是可重复的一致性验收

一个简单的诊断,是在固定权重、固定 token 与上下文下,计算两端采样 token 的 log-probability 差:

δt=log⁡πtrain,v(at∣ct)−log⁡μinfer,v(at∣ct).\delta_t=\log\pi_{\mathrm{train},v}(a_t\mid c_t) -\log\mu_{\mathrm{infer},v}(a_t\mid c_t).

观察 ∣δt∣|\delta_t| 的均值、尾部分位数和最大值,再按长度、任务类型、专家和概率区间切分。平均值小不代表没有极端 token;采样 token 的差值,也不等于完整分布 KL。

未来的突破,可能更多来自训练与服务的共同设计。TRACE 已开始用 rollout 侧量化信息指导训练侧舍入,而不只是分别提高两端的量化精度。TRACE 原论文

从这些工作可以推断,系统对齐与算法容错会长期并存:前者减少误差来源,后者吸收剩余差异。只靠掩码,可能把有效经历一起丢掉;追求所有路径逐位一致,也可能付出过高成本。

五、策略算法:GRPO、GSPO、CISPO 各自在改什么

到了这里,再看这些算法名就容易得多。它们大多围绕几个具体选择展开:怎样估计优势,按 token 还是序列控制更新,裁剪之后还保留多少梯度,以及偏得太远的数据究竟要不要用。

先把 advantage,优势,理解成:这个动作或结果,比当前预期好多少。 正优势倾向于提高相关动作的概率,负优势倾向于降低。它和奖励不是同一个量。

PPO:同一批经历可以学几次,但别改得太猛

PPO 的典型 clipped surrogate 是:

LPPO=E[min⁡(rtAt,clip⁡(rt,1−ϵ,1+ϵ)At)],rt=πθ(at∣ct)πold(at∣ct).L_{\mathrm{PPO}} =\mathbb E\left[ \min\left(r_t A_t, \operatorname{clip}(r_t,1-\epsilon,1+\epsilon)A_t\right) \right], \qquad r_t=\frac{\pi_\theta(a_t\mid c_t)}{\pi_{\mathrm{old}}(a_t\mid c_t)}.

这里使用最大化目标的写法。它希望重复利用采样数据,同时抑制某些方向上过大的更新。PPO 原论文

一个常见误解是,比值超出区间,token 就必然没梯度。实际要看优势的正负和 min 选择了哪个分支。例如,At>0A_t>0 且 rt>1+ϵr_t>1+\epsilon 时,继续提高概率的收益被截住;At<0A_t<0 时,分支选择不同。不能把所有区间外 token 一概说成被删除。

GRPO:用同题多条回答替代独立 critic

GRPO 对同一道题采样一组回答,用组内奖励比较构造优势。常见的结果奖励形式是:

A^i=Ri−R‾std⁡(R1,…,RG)+ε.\widehat A_i =\frac{R_i-\overline R}{\operatorname{std}(R_1,\ldots,R_G)+\varepsilon}.

这里 RiR_i 是第 ii 条回答的结果分数,GG 是组大小。它省去了独立价值模型,减少相关显存与计算开销。但同题多次生成仍然要付钱;如果采用序列级结果优势,整条回答的许多 token 会共享一个信号。DeepSeekMath 中的 GRPO

还可以做一个小推导。假设每条回答独立、成功概率都是 pp,奖励只有 0 和 1,那么一组 GG 条回答全同分的概率为:

Psame=pG+(1−p)G.P_{\mathrm{same}}=p^G+(1-p)^G.

若 G=8G=8,p=0.5p=0.5 时约为 0.78%;p=0.01p=0.01 时约为 92.3%。后者意味着绝大多数组都没有组内奖励差异。这个推导依赖独立、同成功率的假设,但足以说明:任务过难或过易,都会削弱组相对学习信号。 更大的组不总比更合适的题目有用。

GSPO:把约束粒度移到序列

GSPO 采用基于序列似然、经过长度归一化的比值:

si(θ)=exp⁡[1Li∑t=1Lilog⁡πθ(yi,t∣x,yi,<t)πold(yi,t∣x,yi,<t)].s_i(\theta) =\exp\left[\frac{1}{L_i}\sum_{t=1}^{L_i} \log\frac{\pi_\theta(y_{i,t}\mid x,y_{i,<t})} {\pi_{\mathrm{old}}(y_{i,t}\mid x,y_{i,<t})}\right].

然后在序列级进行 clipping。它把许多局部波动合在一起处理,Qwen 在其报告的 MoE 实验中获得了更稳定的训练,并不再依赖原有的路由回放策略。GSPO 原论文与公式

要留意,这个几何平均比值不是未经归一化的完整轨迹 IS 权重,不能当作后者的无偏替代。把粒度变粗,也可能淡化少数关键步骤的异常;多轮、上下文被改写的轨迹,还需要按真实输入边界处理。

所以,GSPO 的结果说明有些任务可以通过目标函数设计减少对底层对齐的敏感性,不能外推成“所有 MoE Agent 都不需要路由回放”。

CISPO:裁剪权重,不把策略梯度一起截掉

CISPO 改变的是 clipping 的位置。它把重要性权重裁剪并停止梯度,再用这个系数乘策略 log-probability。忽略其他项,可以用下面的简化形式理解:

LCISPO=E[sg⁡(clip⁡(rt,l,u))A^tlog⁡πθ(at∣ct)].L_{\mathrm{CISPO}} =\mathbb E\left[ \operatorname{sg}\big(\operatorname{clip}(r_t,l,u)\big) \widehat A_t\log\pi_\theta(a_t\mid c_t) \right].

sg⁡\operatorname{sg} 表示 stop-gradient,l,ul,u 是权重边界,具体设置以实现为准。与 PPO 的平坦 clipping 分支不同,只要该项没有被其他 mask 排除、优势非零,仍可通过 log⁡πθ\log\pi_\theta 提供梯度。MiniMax-M1 原论文

这也是 CISPO 有时被概括为“全梯度”的原因。但它不保证所有 token 都被训练:padding、工具观察、非法轨迹、环境故障仍可能被 mask。保留梯度也不是免费的,离目标分布很远的动作仍有影响,偏差和稳定性需要另外控制。

MIS-PO 与 HisPO:先判断这条经历还能不能学

Step 3.5 Flash 的 MIS-PO 受 Metropolis Independence Sampling 启发,在 token 与轨迹两个层次使用二元过滤,把保留的样本近似当作 on-policy 数据。这里的 MIS 不是 MiniMax 实践中提到的 multiple importance sampling,缩写相同,含义不同。Step 3.5 Flash,第 5.2.1 节

LongCat-Flash-Prover 的 HisPO 则把训推差异与策略陈旧分解开,使用序列级、token 级掩码,并结合 clipping 控制更新。本文的 HisPO 特指这份报告中的方法。LongCat-Flash-Prover

二者都在回答一个工程上非常实际的问题:与其给一条严重偏离的经历乘上剧烈波动的权重,是否应该直接不学它?

代价是拒绝率和选择偏差。训练曲线变平稳,也可能是因为难样本被大量丢掉。比较方法时,需要同时看独立验证集、有效样本量、拒绝样本分布、生成成本和多次运行的波动。

这一类算法还没有公认的统一赢家。后续值得研究的是按 token、工具调用、子任务分层决定更新粒度,并让信任区域随真实漂移变化。但粒度更精细以后,额外计算是否值得,仍要由同预算实验回答。

六、奖励与信用分配:事情做成了,功劳应该算给谁

一个 Agent 用了 30 轮交互修好 bug。第 2 轮定位到了关键文件,第 7 轮走错了方向,第 16 轮修正了判断,第 29 轮补上回归测试。

最后给它 1 分,当然合理。但如果把 1 分平均传播给整段行为,就很难区分哪些动作值得保留,哪些只是碰巧出现在成功轨迹里。

奖励设计回答“什么算好”,信用分配回答“好坏应该归到哪里”。 这两个问题相关,却不能靠同一个分数自动解决。

结果奖励最可靠的地方,也是最稀疏的地方

代码任务的 outcome reward,可以来自修复测试是否通过、已有功能是否回归、产物是否符合约束。相比“看起来写得不错”,真实执行证据更有说服力。

但一次成功仍可能包含大量无效动作,一次失败也可能只差最后一步。只用终局结果,方差大,学习慢;加过程奖励,又可能鼓励表面进度。例如按工具调用次数加分,Agent 可能不停调用;按通过测试的数量加分,可能优先讨好容易的测试。

GRM 和 rubric 让评价有理由,但不会自动变成真相

开放任务往往没有唯一答案。生成式奖励模型(Generative Reward Model,GRM)会生成分析或比较,再给出判断;rubric 则把“好”拆成具体标准,例如要求是否满足、证据是否支持结论、产物是否可用。

两者可以组合,也可以独立使用。固定 rubric 不一定由模型生成,生成式评判也不一定包含明确 rubric。Rubrics as Rewards 就研究了把结构化评价标准变成训练奖励的方法。Rubrics as Rewards 原论文

如果评分标准包含“引用准确”,最好让评判器实际打开引用;如果包含“功能可用”,就应该运行和操作产物。MiniMax 的 Agent-as-a-Verifier 也沿着这个方向,把评判从读文本推进到真实环境中的操作与验证。MiniMax 官方实践

遗留问题是,评判器也可能偏爱冗长、自信和熟悉的表达,被候选内容里的提示影响,或者根本无法判断专业正确性。让评判器写一长段理由,并不会天然增加可靠性。需要保留证据、评分器版本和分项结果,用独立样本及人工抽查持续校准。

Critic 与 GAE,为中间状态提供一个预期

critic 学习状态的期望后续回报 Vϕ(ct)V_\phi(c_t)。GAE 用一串时序差分残差估计优势:

δt=rt+γVϕ(ct+1)−Vϕ(ct),A^tGAE=∑l=0T−t−1(γλ)lδt+l.\delta_t=r_t+\gamma V_\phi(c_{t+1})-V_\phi(c_t), \qquad \widehat A_t^{\mathrm{GAE}} =\sum_{l=0}^{T-t-1}(\gamma\lambda)^l\delta_{t+l}.

真实终止时末端价值通常设为零;因采样预算截断时,如果任务仍可继续,就需要考虑保留末端 bootstrap。λ\lambda 调节估计的偏差与方差。GAE 原论文

直觉上,定位到正确文件后,成功的预期应该上升;删掉关键实现后,预期应该下降。critic 试图把这种变化变成较细的学习信号。

但 critic 不是因果裁判。它可能学到“上下文更长就更像快成功了”等捷径。长轨迹、状态压缩、不同任务混合以及策略不断变化,都会让价值拟合变难;模型、激活和额外训练也需要资源。因此,去掉 critic 与保留 critic 都有合理场景。

压缩上下文,也是在做决策

Agent 跑久以后,需要决定哪些历史保留、哪些摘要、哪些删除。如果摘要漏掉“这个测试失败是因为依赖没装好”,后续 Agent 可能反复修改正确代码。

可以让压缩器与任务执行策略共享终局奖励,使它学习“哪些信息对后续成功有用”。AutoCompact 已经尝试联合优化编码与上下文压缩决策。AutoCompact 原论文

但共享奖励没有解决归因:到底是摘要丢了证据,还是执行策略后来犯错?更严格的评估可以固定环境快照,对不同摘要做后续 rollout 比较;代价是要多跑很多次。并且,训练必须使用压缩后真实出现过的上下文,不能把完整历史重新拼回来,假装模型当时看得到。

这一问题的突破方向,我更看好有执行证据支持的局部反馈,加上能跨越工具与上下文边界的价值估计。进程里打印了“完成”,远不如测试真正通过;摘要很流畅,也远不如它能保住决定下一步行动的事实。

七、Reward Hacking:得高分和把事情做好之间的缝隙

如果奖励来自“测试全部通过”,Agent 有两种提高得分的办法:修好代码,或者让失败的测试不再运行。

后者就是 Reward Hacking,奖励投机。更一般地说,是优化了可见的代理指标,却偏离了真实目标。它不必以模型有明确的“作弊意识”为前提,只要这条行为路径能持续得到高分,就可能被强化。

传统 RL 就已经观察到,能力更强的策略可能更善于利用错误奖励。Agent 能读文件、改代码、联网和调用命令,能触碰的评分漏洞也随之增加。奖励错设的系统研究

验证器应该处在 Agent 改不到的地方

对代码任务,固定测试、奖励脚本、参考答案和评测配置,应由独立验证服务管理。Agent 可以提交候选 patch,不能修改决定它拿几分的程序。验证时还要检查实际执行了多少测试、是否发生 skip、测试输入来自哪里,而不只是看 exit code 是否为零。

对工具型任务,同样需要防止伪造工具返回、污染日志和把指令混入待评判文本。LLM judge 可以发现一部分语义问题,规则可以检查一部分结构约束,二者互补,但也可能同时被同一份伪造证据骗过。

Agent 操作区与独立验证区分离,并分别处理任务失败、基础设施故障和奖励投机

图 4:训练要区分真实失败、基础设施故障和评分投机。同一个“未成功”状态,可能对应完全不同的更新方式。

在沙箱加固中,AppArmor、eBPF 等可以参与限制文件访问、约束网络或观测运行行为,但具体能力取决于策略和挂载方式。eBPF 本身不是一道自动生效的沙箱边界;隔离也需要最小权限、宿主机保护和验证服务分离共同完成。

形式化证明则有另一种典型漏洞:证明器接受了一个证明,不等于模型证明了原问题。它可能修改命题、加入不允许的公理,或者绕开预定约束。LongCat-Flash-Prover 因此增加了命题一致性和基于 AST 的合法性检查,并对识别到的投机结果调整奖励。LongCat-Flash-Prover 的合法性检测,附录 E

AST 可以检查某些结构与语法模式,却不能包办全部语义正确性。把奖励置零也只是处理这次结果,环境中的漏洞还需要修掉。

不能只统计训练奖励

可以设计两层评价:训练时使用效率较高的代理评分,独立审计时用隐藏测试、不同验证器和人工检查估计真实成功率。一个值得观察的量是:

H=P(独立审计失败∣训练评分通过).H=P(\text{独立审计失败}\mid\text{训练评分通过}).

它描述“评分通过的样本里,有多少没有通过独立审计”。其中可能包含奖励漏洞,也可能包含测试覆盖不足或评判误差;不能全部解释为模型主动作弊。审计样本若有选择偏差,这个比例也不能直接代表总体。

还需要估计检测漏掉了什么。若所有检测器都只认识过去出现过的方式,报告的投机率下降,可能只是新方式没被识别。Hack-Verifiable Environments 尝试在环境中植入可检测的投机机会,使这类测量更可重复。Hack-Verifiable Environments

长期方向是把评分器也当成需要持续维护的系统:对抗测试、漏洞回归、版本化审计、权限最小化。尤其要防止一种自我强化:训练模型和评判模型共享相近盲点,双方都越来越相信一个漂亮但错误的结果。

八、环境噪声:模型犯错,还是世界出了问题

现在把作弊问题暂时拿开。Agent 认真修了代码,代码也正确,但测试执行时网络断了,或者宿主机把进程杀掉了。如果系统直接给零分,优化器收到的就是:刚才那些动作不好,以后少做。

这已经不是“奖励有一点噪声”那么简单,它可能把正确行为往反方向推。

先区分两种噪声

第一种是训练设施产生的污染:镜像损坏、随机端口冲突、验证器异常、与任务无关的超时,以及重复运行结果不一致的 flaky test。应尽量减少,并保留故障类型、日志和重试结果。

第二种是 Agent 本来就应该应对的不确定性:接口偶尔限流、用户指令不完整、工具返回部分信息、网页结构变化。把这些全部清理掉,模型可能只会在理想环境里工作。

同样是 timeout,宿主机异常造成的超时,和 Agent 自己写了死循环造成的超时,就不该用同一种 mask。归因错了,过滤本身也会变成另一种奖励漏洞。

噪声怎样改变学习信号

用一个非常简化的二元奖励模型说明。假设真实成功率是 pp,标签以与动作无关的概率 η\eta 对称翻转,观测成功率就是:

p~=η+(1−2η)p.\widetilde p=\eta+(1-2\eta)p.

当 η=0.2\eta=0.2 时,两个策略真实成功率的差距,在观测中只剩原来的 60%。如果真实环境的错误并不对称,或更容易发生在长任务上,偏差还会更复杂。

重跑有帮助,但不是保证。若同一错误以概率 qq 独立出现在每次执行中,那么连续 kk 次都遇到该错误的概率是 qkq^k;可一旦根因是同一个损坏镜像、同一个依赖版本,错误高度相关,重跑再多次也无法得到这个下降幅度。

因此,应优先使用环境指纹、固定依赖、参考解回归、已知失败解检查和故障日志定位原因,再决定重跑、剔除还是标记为奖励缺失。MiMo-V2.6 的技术报告也把环境稳定性与无效惩罚处理纳入了训练系统。MiMo-V2.6 技术报告

microVM 提供边界,不提供正确答案

microVM 为任务提供独立 guest kernel 和较小的虚拟设备模型。Firecracker 是代表性实现,结合 KVM、进程约束和权限管理建立隔离。Firecracker 官方设计

它有助于隔离任务副作用,快照与恢复也可以减少重复初始化的成本,但不会自动修好 flaky test、锁住远端 API 的行为或判断测试是否充分。快照里如果已经有坏状态,恢复只是把坏状态更快地恢复出来。

环境自动合成同样如此。生成一个仓库、一组依赖和几个测试,并不代表得到了一道可靠训练题。至少要验证可构建、可求解、参考解通过、明显错误解失败,以及任务之间没有泄漏。只让同一模型同时出题、写答案、写测试和判分,容易把共同盲点当成闭环成功。

把该排除的故障排除,把该学习的噪声加回来

LongCat-Flash-Thinking-2601 对真实噪声作了拆解,并设计训练过程显式纳入这些不完美条件,这是噪声鲁棒训练的一条路线。LongCat-Flash-Thinking-2601 技术报告

课程式噪声注入可以从低频、可恢复的工具失败开始,再逐步提高强度,同时确保任务仍有解。否则模型学到的可能只是更早放弃。

但人工生成的噪声,也可能与部署环境相差很远。未来更需要的是可重放的真实故障集、分层故障标签,以及同时衡量干净环境与噪声环境的评估。我们既要知道模型是否更能恢复,也要知道这种恢复能力有没有以正常任务性能下降为代价。

把八个问题放回同一套系统

再回头看最初那个修代码任务:

选择训推分离,希望 GPU 少等一会儿,这是架构问题。把生成和训练交叠起来,进入异步问题。轨迹还没跑完,模型已经更新,是陈旧问题。同一份旧权重在两个引擎上算得不一样,是训推一致性问题。

接着,需要选择怎样使用这些经历,是算法问题。任务最后成功了,怎样把信号传给中间动作,是信用分配问题。测试绿了却没修好代码,是 Reward Hacking。代码修好了却被坏掉的环境判失败,是环境噪声。

这条链条说明,许多看起来属于算法的波动,根因可能在采样器;许多看起来属于基础设施的调度决定,实际上又在改变学习目标。

我更愿意用一个完整任务的成本来评价这套系统:

Ctask=Cgeneration+Cenvironment+Cverification+Ctraining+Cretry and waste.C_{\mathrm{task}} =C_{\mathrm{generation}}+C_{\mathrm{environment}} +C_{\mathrm{verification}}+C_{\mathrm{training}} +C_{\mathrm{retry\ and\ waste}}.

各项需要统一成同一种计价单位。再结合独立验证集上的能力提升,才知道钱花得是否有效。只报告 tokens/s,既看不到验证器越来越贵,也看不到被丢弃的长轨迹和训练后退的代价。

实际推进时,可以先建立一个小规模同步基线:固定输入、可重放环境、可信终局奖励,先确认模型确实在学。然后引入异步,观察新鲜度和任务配比;再做低精度、路由或算法改动;最后扩展到更复杂的过程奖励和长程上下文。每次都保留独立评估,才知道问题从哪里开始。

对未来方向,我有三个判断。

其一,调度器会越来越懂学习。 它不仅要知道任务要用多少资源,还要知道这条经历有多旧、属于哪个任务分布、是否还有学习价值。难点在于,价值估计本身也会犯错,不能又把调度偏差藏进一个新模型里。

其二,训练引擎与推理引擎会共享更多语义。 token、上下文、采样变换、量化和专家选择,需要有明确的记录与一致性契约。相比在出问题后继续叠掩码,这会让定位和比较更可靠。

其三,环境和验证器会成为与模型同样重要的资产。 它们需要版本、回归集、故障记录和独立审计,也需要衡量单位成本能产生多少可信学习信号。环境多,不等于经验好;奖励密,不等于方向对。

Agentic RL 真正有吸引力的地方,是模型能够从做事的结果里继续学习。而 Infra 要守住的,正是这件事最朴素的前提:它确实做过这件事,我们知道当时发生了什么,也有足够理由相信,这次结果值得影响下一次行动。

几个容易混淆的问题

Agentic RL 与普通 LLM RL 有什么区别

两者使用相同的强化学习基本框架。Agentic RL 更强调与外部环境的多轮交互:模型动作会改变环境,工具观察会改变后续上下文,最终回报可能经过很长时间才能得到。它因此对环境服务、轨迹记录、调度和长程信用分配提出更高要求。

异步训练一定比同步更好吗

不一定。异步有机会隐藏生成与环境等待,但增加策略陈旧、队列管理和分布控制成本。应在相同资源或费用下,比较达到同一独立验证水平所需的时间;短任务、小集群、数值问题尚未排清时,同步基线仍然很有价值。

GRPO、GSPO、CISPO 和 R3 是互相替代的吗

GRPO、GSPO、CISPO 主要改变优势估计或策略优化目标;R3 主要处理 MoE 的 rollout 与训练路由差异。它们作用层次不同,有时可以组合,但组合是否有益仍需实验。一个方法在特定模型上不需要路由回放,不能推出所有模型都不需要。

环境故障为什么不能全部给零分

因为无关故障造成的零分会惩罚本来正确的行为。但也不能把所有失败都 mask:死循环、错误工具参数、任务定义内的预算耗尽,可能正是策略应当承担的后果。关键是故障归因,而不是选择一个统一的分数。

参考资料

文中的方法可以沿下面几条线继续读;具体机制的链接也已放在相关段落附近。



上一篇
当你输入 prompt 并且按下回车到大模型完整输出,发生了什么?

评论与讨论

使用 GitHub 登录留言。评论公开保存在 GitHub Discussions;加载较慢时也可直接前往讨论区。