在大语言模型的强化学习阶段,训推不一致已经不再只是传统意义上的 exposure bias,而是一个更复杂的系统—算法耦合问题。

在预训练中,训推不一致主要来自 teacher forcing:训练时模型总是看到真实前缀,而推理时模型只能看到自己生成的前缀。但在 RL post-training 中,问题进一步复杂化。现代 LLM RL 系统通常会把 rollout generation 和 policy optimization 分离:前者使用高吞吐的推理引擎,例如 vLLM、SGLang;后者使用训练框架,例如 Megatron、FSDP、DeepSpeed 或 veRL。理论上,它们应当代表同一个策略;但在实际系统中,由于数值精度、kernel 实现、并行策略、MoE 路由、采样截断和参数更新延迟等因素,rollout 阶段看到的策略和训练阶段优化的策略并不完全相同。

可以把 RL 阶段的训推不一致统一写成:

\[ y_t \sim \mu_t(\cdot \mid x, y_{<t}) \]

但训练时优化的是:

\[ \pi_\theta^{\mathrm{train}}(\cdot \mid x, y_{<t}) \]

其中 \(\mu_t\) 是实际产生 token 的行为策略。它不一定等于当前训练策略,而是可能同时受到以下因素影响:

\[ \mu_t = \pi_{\theta_{\mathrm{roll}}}^{\mathrm{infer}} (\cdot \mid x, y_{<t}; M_t, Z_t) \]

这里:

  • \(\theta_{\mathrm{roll}}\) 是 rollout 使用的参数版本;
  • \(\pi^{\mathrm{infer}}\) 是推理引擎中的概率分布;
  • \(M_t\) 是 top-p / top-k sampling 形成的候选 token mask;
  • \(Z_t\) 是 MoE 模型中实际激活的 routing path。

而训练阶段计算梯度时,通常使用的是:

\[ \pi_\theta^{\mathrm{train}} (\cdot \mid x, y_{<t}) \]

一旦二者不一致,常见的 policy-gradient 更新就不再是严格 on-policy 的。


1. 基本 policy-gradient 视角

对于一个 prompt \(x\),模型生成完整回复:

\[ y = (y_1, y_2, \ldots, y_T) \]

序列级奖励为:

\[ R(x, y) \]

标准 REINFORCE 形式的目标是:

\[ J(\theta) = \mathbb{E}_{y \sim \pi_\theta} [ R(x,y) ] \]

其梯度可以写为:

\[ \nabla_\theta J(\theta) = \mathbb{E}_{y \sim \pi_\theta} \left[ A(x,y) \nabla_\theta \log \pi_\theta(y \mid x) \right] \]

其中 \(A(x,y)\) 是 advantage,通常为 reward 减去 baseline。由于自回归模型满足:

\[ \log \pi_\theta(y \mid x) = \sum_{t=1}^{T} \log \pi_\theta(y_t \mid x, y_{<t}) \]

因此梯度可以展开为:

\[ \nabla_\theta J(\theta) = \mathbb{E}_{y \sim \pi_\theta} \left[ A(x,y) \sum_{t=1}^{T} \nabla_\theta \log \pi_\theta(y_t \mid x, y_{<t}) \right] \]

这个公式隐含了一个关键前提:

\[ y \sim \pi_\theta \]

也就是说,样本必须来自当前正在优化的策略。

但在 LLM RL 系统中,实际情况通常是:

\[ y \sim \mu \]

而不是:

\[ y \sim \pi_\theta^{\mathrm{train}} \]

此时如果仍然直接使用:

\[ A(x,y) \sum_{t=1}^{T} \nabla_\theta \log \pi_\theta^{\mathrm{train}}(y_t \mid x, y_{<t}) \]

就会得到一个有偏梯度。训推不一致的本质,就是行为策略 \(\mu\) 和训练策略 \(\pi_\theta^{\mathrm{train}}\) 之间存在偏差。


2. 第一类不一致:训练引擎和推理引擎不一致

第一类问题来自训练和推理引擎的实现差异。

在理想情况下,同一个模型参数 \(\theta\)、同一个上下文 \(s_t = (x, y_{<t})\),训练引擎和推理引擎应当给出相同的概率分布:

\[ \pi_\theta^{\mathrm{train}}(\cdot \mid s_t) = \pi_\theta^{\mathrm{infer}}(\cdot \mid s_t) \]

但实际系统中,这个等式常常不成立:

\[ \pi_\theta^{\mathrm{train}}(\cdot \mid s_t) \neq \pi_\theta^{\mathrm{infer}}(\cdot \mid s_t) \]

原因包括:

  • BF16 / FP16 / FP8 等数值精度差异;
  • attention kernel、normalization、softmax 实现差异;
  • tensor parallel / expert parallel / sequence parallel 带来的归约顺序差异;
  • 推理引擎和训练引擎中 MoE top-k expert selection 的数值敏感性;
  • 推理阶段逐 token 自回归计算,而训练阶段通常对完整序列并行计算。

这个问题看似只是数值误差,但在 RL 中会被 importance ratio 放大。因为 policy-gradient 直接依赖 token logprob,一旦 logprob 有系统性偏差,就会改变有效优化目标。

设 rollout 来自推理引擎:

\[ y \sim \pi_{\theta_{\mathrm{old}}}^{\mathrm{infer}} \]

而训练时使用训练引擎计算梯度:

\[ \pi_\theta^{\mathrm{train}} \]

那么自然的重要性采样比率是:

\[ \rho(y) = \frac{ \pi_\theta^{\mathrm{train}}(y \mid x) }{ \pi_{\theta_{\mathrm{old}}}^{\mathrm{infer}}(y \mid x) } \]

展开为 token 乘积:

\[ \rho(y) = \prod_{t=1}^{T} \frac{ \pi_\theta^{\mathrm{train}}(y_t \mid x, y_{<t}) }{ \pi_{\theta_{\mathrm{old}}}^{\mathrm{infer}}(y_t \mid x, y_{<t}) } \]

于是无偏的序列级 IS policy-gradient 可以写为:

\[ \nabla_\theta J(\theta) = \mathbb{E}_{y \sim \pi_{\theta_{\mathrm{old}}}^{\mathrm{infer}}} \left[ \rho(y) A(x,y) \sum_{t=1}^{T} \nabla_\theta \log \pi_\theta^{\mathrm{train}}(y_t \mid x, y_{<t}) \right] \]

但这个序列级比率存在严重方差问题。因为 LLM 输出序列很长,多个 token ratio 连乘后容易爆炸或塌缩:

\[ \rho(y) = \prod_{t=1}^{T} \rho_t \]

其中:

\[ \rho_t = \frac{ \pi_\theta^{\mathrm{train}}(y_t \mid s_t) }{ \pi_{\theta_{\mathrm{old}}}^{\mathrm{infer}}(y_t \mid s_t) } \]

因此一些工作会采用 token-level truncated importance sampling,也就是 TIS:

\[ \bar{\rho}_t = \min(\rho_t, c) \]

或者使用双侧截断:

\[ \bar{\rho}_t = \mathrm{clip}(\rho_t, 1-\epsilon, 1+\epsilon) \]

然后把梯度近似写成:

\[ \hat{g}_{\mathrm{TIS}} = A(x,y) \sum_{t=1}^{T} \bar{\rho}_t \nabla_\theta \log \pi_\theta^{\mathrm{train}}(y_t \mid s_t) \]

这类方法的直觉是:用两个引擎之间的概率比率修正 rollout distribution 和 training distribution 的偏差,同时通过 clipping 控制方差。

但这里需要注意:token-level TIS 并不是严格无偏的完整轨迹修正。它降低了方差,但牺牲了一部分理论精确性。完整序列级 IS 更接近无偏,但方差过高;token-level IS 更稳定,但会忽略 prefix distribution mismatch。因此,TIS 更适合被理解为一种稳定性补丁,而不是完全解决训推不一致的最终答案。


3. 第二类不一致:离线策略导致的参数版本不一致

第二类问题来自 rollout policy 和 training policy 的参数版本不一致。

在理想 on-policy RL 中,数据应当由当前策略产生:

\[ y \sim \pi_{\theta_k} \]

然后用同一个 \(\theta_k\) 做更新。

但在大规模 LLM RL 中,为了提高 GPU 利用率,通常会让 rollout generation 和 policy optimization 并行执行。这样会产生参数滞后:

\[ y \sim \pi_{\theta_{k-d}} \]

但训练时优化的是:

\[ \pi_{\theta_k} \]

其中 \(d\) 表示策略滞后的步数。此时 off-policy ratio 可以写为:

\[ r_t(\theta_k) = \frac{ \pi_{\theta_k}(y_t \mid s_t) }{ \pi_{\theta_{k-d}}(y_t \mid s_t) } \]

如果使用序列级 correction,则为:

\[ r(y) = \prod_{t=1}^{T} r_t(\theta_k) \]

这就是 PPO / GRPO 等方法中 importance ratio 的来源之一。PPO 的 clipped objective 可以写为:

\[ L^{\mathrm{clip}}(\theta) = \mathbb{E} \left[ \min \left( r_t(\theta) A_t, \mathrm{clip}(r_t(\theta), 1-\epsilon, 1+\epsilon) A_t \right) \right] \]

GRPO 在形式上也使用类似的 ratio,只是 advantage 通常来自同一 prompt 下多个 response 的 group normalization,而不是显式 value model:

\[ A_i = \frac{ R_i - \mathrm{mean}(R_1,\ldots,R_G) }{ \mathrm{std}(R_1,\ldots,R_G) } \]

然后对每个 response 的 token 做 policy update。

问题在于,长序列 RL 中 rollout 的生成时间很长。一个 batch 中早生成的 token 可能来自旧参数,而训练引擎已经更新了多轮。这样会使数据变得 stale,导致实际优化越来越偏离 on-policy 假设。

PipelineRL 针对的正是这个问题。它的核心思想可以概括为:不要等整条长序列全部生成完再同步新权重,而是在生成过程中进行 in-flight weight update。一旦训练侧产生了更新后的参数,生成引擎就短暂停顿、接收新权重,并用新参数继续生成后续 token。

这意味着行为策略变成了一个 token 级时间变化的策略:

\[ \mu_t = \pi_{\theta_{\tau(t)}}^{\mathrm{infer}} \]

其中 \(\theta_{\tau(t)}\) 表示第 \(t\) 个 token 生成时实际使用的参数版本。

这样做的优势是可以降低策略滞后:

\[ \mathrm{KL} \left( \pi_{\theta_k} | \pi_{\theta_{\tau(t)}} \right) \]

也就是让训练时的 current policy 和生成时的 behavior policy 更接近。

不过,这并不意味着 off-policy 问题完全消失。因为一条 response 可能由多个不同版本的参数共同生成。因此,更严谨的实现需要记录每个 token 的 behavior logprob,甚至记录其对应的参数版本:

\[ \log \mu_t(y_t \mid s_t) = \log \pi_{\theta_{\tau(t)}}^{\mathrm{infer}} (y_t \mid s_t) \]

训练时再使用:

\[ r_t = \frac{ \pi_{\theta_k}^{\mathrm{train}}(y_t \mid s_t) }{ \mu_t(y_t \mid s_t) } \]

进行 correction 或 clipping。

所以,PipelineRL 的本质不是简单地“同步参数”,而是在系统层面提高数据新鲜度,在硬件利用率和 on-policyness 之间取得更好的折中。


4. 第三类不一致:MoE routing path 不一致

第三类问题在 MoE 模型中尤其重要。

MoE 模型每一层不会激活所有专家,而是通过 router 选择 top-k 个专家。可以简单写为:

\[ z_{l,t} = \mathrm{TopK} ( g_l(h_{l,t}) ) \]

其中:

  • \(h_{l,t}\) 是第 \(l\) 层、第 \(t\) 个 token 的 hidden state;
  • \(g_l\) 是 router;
  • \(z_{l,t}\) 是被选中的 expert indices。

MoE 层的输出可以写成:

\[ h_{l+1,t} = \sum_{e \in z_{l,t}} w_{e,t} E_e(h_{l,t}) \]

其中 \(E_e\) 是第 \(e\) 个 expert,\(w_{e,t}\) 是对应的 routing weight。

问题在于,推理引擎和训练引擎即使使用相同参数,也可能因为数值误差或并行实现差异,得到不同的 routing path:

\[ z_{l,t}^{\mathrm{infer}} \neq z_{l,t}^{\mathrm{train}} \]

这比普通 logprob 偏差更严重。因为一旦 routing path 不一致,训练阶段更新的可能不是 rollout 阶段真正参与生成的 expert。也就是说,模型并不是在更新“产生这个 token 的那部分参数”,而是在更新另一个 active parameter subspace。

这会导致优化目标发生突变:

\[ \pi_\theta(y_t \mid s_t, z_{l,t}^{\mathrm{infer}}) \neq \pi_\theta(y_t \mid s_t, z_{l,t}^{\mathrm{train}}) \]

DeepSeek-V3.2 中的 Keep Routing 就是针对这个问题提出的。其核心做法是:

  1. 在 rollout 时记录每个 token、每个 MoE layer 的 routing path;
  2. 在训练时强制使用相同的 routing path;
  3. 保证训练时优化的 expert 与推理时实际参与生成的 expert 一致。

形式上,可以写为:

\[ z_{l,t}^{\mathrm{train}} \leftarrow z_{l,t}^{\mathrm{infer}} \]

于是训练时优化的条件策略变成:

\[ \pi_\theta^{\mathrm{train}} ( y_t \mid s_t, z_{l,t}^{\mathrm{infer}} ) \]

这样做可以显著降低 MoE RL 中由 expert routing drift 带来的不稳定性。

需要注意的是,Keep Routing 更像一种系统一致性约束,而不是普通的 RL objective 改造。它的目标不是改变 reward,也不是改变 advantage,而是保证 rollout computation path 和 training computation path 对齐。


5. 第四类相关问题:top-p / top-k 改变 action space

除了 MoE routing,sampling 本身也会造成 action space mismatch。

在 RL rollout 中,模型通常不会直接从完整 vocabulary 上采样,而是使用 top-p 或 top-k sampling。设完整词表为 \(V\),top-p / top-k 在第 \(t\) 步得到候选集合:

\[ M_t \subset V \]

那么实际行为策略不是原始模型分布:

\[ \pi(y_t \mid s_t) \]

而是截断并重新归一化后的分布:

\[ \mu_t(y_t \mid s_t) = \frac{ \mathbf{1}[y_t \in M_t] \pi^{\mathrm{infer}}(y_t \mid s_t) }{ \sum_{v \in M_t} \pi^{\mathrm{infer}}(v \mid s_t) } \]

如果训练时仍然在完整 vocabulary 上计算:

\[ \pi_\theta^{\mathrm{train}}(y_t \mid s_t) \]

那么行为策略和目标策略的 support 不一致。对于 \(v \notin M_t\) 的 token:

\[ \mu_t(v \mid s_t) = 0 \]

但训练策略可能有:

\[ \pi_\theta^{\mathrm{train}}(v \mid s_t) > 0 \]

这会违反 importance sampling 的基本 support condition:

\[ \pi_\theta(a \mid s) > 0 \Rightarrow \mu(a \mid s) > 0 \]

也就是说,如果某些 action 在 rollout 中根本不可能被采到,那么训练时却把它们纳入目标分布,会导致 action space 不一致。

DeepSeek-V3.2 的 Keep Sampling Mask 就是为了解决这个问题。它在 rollout 时保存 top-p / top-k 产生的 mask \(M_t\),并在训练时对当前策略应用同一个 mask:

\[ \pi_\theta^{\mathrm{train}, M_t} (y_t \mid s_t) = \frac{ \mathbf{1}[y_t \in M_t] \pi_\theta^{\mathrm{train}}(y_t \mid s_t) }{ \sum_{v \in M_t} \pi_\theta^{\mathrm{train}}(v \mid s_t) } \]

然后训练阶段使用 masked policy:

\[ \pi_\theta^{\mathrm{train}, M_t} \]

而不是完整 vocabulary policy:

\[ \pi_\theta^{\mathrm{train}} \]

这样可以保证 rollout policy 和 training policy 在同一个 action subspace 上比较:

\[ \mathrm{supp} ( \mu_t ) = \mathrm{supp} ( \pi_\theta^{\mathrm{train}, M_t} ) = M_t \]

这本质上是对 action space 的对齐。


6. DeepSeek-V3.2 中的 Off-Policy Sequence Masking

除了 Keep Routing 和 Keep Sampling Mask,DeepSeek-V3.2 还提出了 Off-Policy Sequence Masking。

它针对的是另一种 off-policy 问题:有些 rollout sequence 与当前策略已经偏离太远,继续用它们做负向更新可能会误导模型。

设数据采样策略为 \(\pi_{\mathrm{old}}\),当前训练策略为 \(\pi_\theta\),可以用序列级 KL 衡量二者偏差:

\[ D_{\mathrm{KL}} \left( \pi_{\mathrm{old}}(\cdot \mid x) | \pi_\theta(\cdot \mid x) \right) \]

如果某条样本的 policy divergence 过大,并且 advantage 为负:

\[ A(x,y) < 0 \]

则对该样本进行 mask:

\[ m(x,y) = \mathbf{1} [ D_{\mathrm{KL}}(\pi_{\mathrm{old}} | \pi_\theta) < \tau \ \text{or} A(x,y) \geq 0 ] \]

然后把 GRPO loss 写成:

\[ L_{\mathrm{masked}} = m(x,y) L_{\mathrm{GRPO}} \]

直觉是:模型最应该从“自己犯过但仍接近当前策略的错误”中学习;而高度 off-policy 的负样本可能并不能代表当前模型真实会犯的错误,反而会把优化方向带偏。

这和 Keep Routing / Keep Sampling Mask 的侧重点不同:

  • Keep Routing 对齐 computation path;
  • Keep Sampling Mask 对齐 action space;
  • Off-Policy Sequence Masking 过滤过度偏离当前策略的负样本;
  • TIS / MIS 通过 importance ratio 修正 behavior policy 和 target policy 的概率偏差;
  • PipelineRL 通过系统设计降低参数滞后,从源头减少 off-policyness。

7. 一个统一视角:LLM RL 的真实行为策略是什么?

如果把上述问题统一起来,LLM RL 中真正的 behavior policy 并不是简单的:

\[ \pi_{\theta_{\mathrm{old}}} \]

而是:

\[ \mu_t = \pi_{\theta_{\tau(t)}}^{\mathrm{infer}, M_t, Z_t} \]

其中:

  • \(\theta_{\tau(t)}\):第 \(t\) 个 token 生成时的参数版本;
  • \(\mathrm{infer}\):推理引擎实现;
  • \(M_t\):top-p / top-k sampling mask;
  • \(Z_t\):MoE routing path;
  • \(s_t = (x, y_{<t})\):自回归前缀状态。

而训练时优化的是:

\[ \pi_\theta^{\mathrm{train}} \]

所以真正需要对齐的是:

\[ \mu_t \approx \pi_\theta^{\mathrm{train}} \]

不同方法可以看成在对齐这个等式的不同部分:

问题 不一致来源 典型修正
引擎不一致 \(\pi^{\mathrm{infer}} \neq \pi^{\mathrm{train}}\) TIS / MIS / 统一精度 / 对齐 kernel
参数陈旧 \(\theta_{\tau(t)} \neq \theta_k\) PipelineRL / in-flight weight update / per-token behavior logprob
MoE 路由漂移 \(Z_t^{\mathrm{infer}} \neq Z_t^{\mathrm{train}}\) Keep Routing
采样截断 training action space 与 rollout action space 不一致 Keep Sampling Mask
高度 off-policy 负样本 样本与当前策略 KL 过大 Off-Policy Sequence Masking

因此,RL 阶段的训推不一致并不是单一问题,而是一组分布错配问题:

\[ \text{Training-Inference Mismatch} = \text{Engine Mismatch} + \text{Policy Staleness} + \text{Routing Mismatch} + \text{Action-Space Mismatch} \]

8. 进一步思考:为什么这个问题在 reasoning RL 中尤其严重?

Reasoning RL 通常具有三个特征:

第一,输出序列长。 长 CoT 会让 importance ratio 连乘,导致方差迅速放大:

\[ \rho(y) = \prod_{t=1}^{T} \rho_t \]

当 \(T\) 很大时,即使每个 token 的 ratio 只有很小偏差,序列级 ratio 也可能极端不稳定。

第二,reward 稀疏。 数学、代码、工具调用等任务往往只有最终答案 reward:

\[ R(x,y) \in {0,1} \]

这意味着错误的 off-policy 更新很难被 dense supervision 纠正。

第三,系统异构程度高。 大规模 RL 训练通常混合使用 rollout engine、training engine、reward engine、MoE parallelism、KV cache、quantization、sampling truncation 等组件。每个组件的微小差异都会进入 logprob,并最终影响 policy update。

所以,LLM RL 的稳定性不仅取决于 PPO、GRPO、REINFORCE 或 DAPO 本身,也强依赖底层系统是否能维持严格的概率一致性。


9. 结论

我认为,RL 阶段的训推不一致可以分为三层:

第一层是概率分布不一致。 同一参数下,推理引擎和训练引擎给出的 logprob 不一致,导致 policy-gradient estimator 有偏。

第二层是参数版本不一致。 rollout 生成数据时使用的参数落后于训练时的当前参数,导致样本变成 stale off-policy data。

第三层是执行路径不一致。 MoE routing path、top-p/top-k sampling mask 等系统行为改变了实际参与生成的专家和 action subspace,使训练阶段优化的对象不再严格等同于推理阶段产生样本的对象。

因此,解决 LLM RL 中的训推不一致,不能只从算法角度看,也不能只从系统角度看。真正有效的方案需要同时回答三个问题:

\[ \text{Who generated this token?} \]
\[ \text{Under which probability distribution was it sampled?} \]
\[ \text{Which computation path produced it?} \]

只有当训练阶段能够复现或正确校正这些信息时,RL 更新才是真正可信的。

这也是为什么近年来的 LLM RL 系统越来越重视:

  • rollout logprob 的精确记录;
  • per-token behavior policy 追踪;
  • importance sampling correction;
  • routing path replay;
  • sampling mask replay;
  • training / inference engine 的数值一致性;
  • 更低 policy staleness 的异步训练框架。

从这个角度看,LLM RL 的核心问题正在从单纯的 objective design,转向 policy distribution accounting:我们不仅要知道模型得到了什么 reward,还必须知道这条 trajectory 究竟是由哪个策略、哪个引擎、哪个参数版本、哪个 routing path、哪个 action subspace 生成的。

这才是理解下一代 reasoning RL scaling 的关键。