从 vLLM V0 迁到 V1:强化学习中,先保证正确,再考虑修正

原作者:Rafael Pardinas、Ehsan Kamalloo(ServiceNow-AI)· 原载 Hugging Face Blog · 2026 年 5 月 6 日

PipelineRL 使用 vLLM 作为生成 rollout 的推理引擎。推理引擎采样 token,并返回每个 token 的对数概率(logprob);训练器据此计算策略比率、KL、裁剪率、熵和奖励等训练相关量。只要这些 logprob 的计算方式出现差异,就可能改变训练动态。这正是我们从 vLLM V0 迁移到 V1 时需要消除的训练与推理不一致。

先给出结论:修复四项问题后,vLLM V1 才与我们的 V0 参考结果接近。这四项分别是返回经过采样处理的 rollout logprob、明确 V1 专有的运行时默认值、对齐在途权重更新路径,以及在最终投影中使用 fp32 的 lm_head。我们的顺序是先修复后端行为,再考虑改变强化学习目标函数。

参考运行使用 vLLM 0.8.5,V1 运行使用 0.18.1。原文图 1 展示最终结果:蓝色是 V0 参考运行,红色是最初的 V1 尝试,绿色是完成下述修复、包括 fp32 lm_head 后的最终 V1 运行。

修复前后三次运行的当前策略对数概率、裁剪率、熵和奖励曲线

查看原文图 1:修复前后的训练器指标

原文图 1。V0 参考(蓝)、初次 V1(红)和修复后的 V1(绿)的训练器指标;图中依次展示当前策略 logprob、裁剪率、熵及奖励;修复后 V1 的轨迹较初次尝试更接近 V0。图及实验归属 Rafael Pardinas、Ehsan Kamalloo / ServiceNow-AI。

迁移目标:先恢复后端的一致性

V1 对 V0 引擎进行了大幅重写,因此我们刻意将迁移目标收窄为三件事:

  1. 确认 V1 返回的 rollout logprob 符合训练器所期望的语义。
  2. 使用同一个工作负载重新运行,并与 V0 参考结果比较。
  3. 只有在后端行为恢复一致之后,才评估目标函数层面的改动。

最先暴露异常的是以下指标:

  • clamp_log_ratio_new_old_indicator
  • kl_new_old
  • entropy
  • reward

这些指标来自采用 GSPO 目标函数的训练运行。同一类问题也可能出现在 PPO、GRPO,或者任何把 rollout 侧 logprob 作为优化目标组成部分的在线强化学习系统中。

最初的 V1 运行很快就显出了问题:训练早期,训练器侧的 logprob 和奖励便开始偏离 V0 参考。

V0和初次V1的当前策略对数概率及奖励曲线

查看原文图 2:当前策略 logprob 与奖励

原文图 2。左图是训练器在更新过程中计算的当前策略 logprob,右图是奖励。初次 V1(红)与 V0 参考(蓝)逐渐分离。图及实验归属原作者 / ServiceNow-AI。

训练器的其他指标也呈现同样的趋势。在最初的对比中,裁剪率是最直观的信号。

V0和初次V1的训练器指标曲线

查看原文图 3:V0 与初次 V1 的训练器指标

原文图 3。V0 参考(蓝)与初次 V1(红)的训练器指标。裁剪率反映 rollout 与训练器之间的策略差距,熵和奖励则显示差距如何传导到训练过程。图及实验归属原作者 / ServiceNow-AI。

把可能的故障分成三层

我们把原因划分为三个层次:

  1. 语义不一致:后端返回的 logprob 与训练器期望的 logprob,含义不同。
  2. 推理路径不一致:缓存、调度或请求处理的默认设置发生变化,使相同提示词经过不同执行路径。
  3. 目标函数不一致:对于剩余的策略陈旧程度或后端差异,需要在 RL 目标函数中加入修正。

我们一开始过早怀疑了第三层。真正有效的诊断来自先把前两层视为后端行为问题,并逐一排除。

vLLM迁移排查示意:rollout原始logits经温度、惩罚与top-k/top-p处理后返回processed_logprobs,与训练器fp32输出头的概率计算比较;依次对齐运行默认值、在途权重更新和数值精度,最后评估目标函数修正。
编者原创技术示意图:区分概率语义、执行路径和目标函数修正的排查次序。它不是实验曲线,不表示所有 RL 系统都应采用同一组开关。

修复 V1 后端

第一项:logprob 的语义

首先是语义问题。按原文所用的 V1 版本,默认返回的是原始模型输出对应的 logprob,位置在 logits 后处理之前;后处理包括温度缩放、惩罚,以及 top-k、top-p 过滤。而 PipelineRL 需要的是采样器实际使用的、经过这些处理之后的概率分布的 logprob。

所需设置为 logprobs-mode=processed_logprobs。

这消除了 rollout logprob 明显的均值偏移,但训练曲线仍然与已知正常的参考运行存在差距。因此,下一个问题需要沿推理执行路径排查。

策略比率图直接反映了这一点。对 V1 启用 processed_logprobs 后,三个运行的平均策略比率都极接近 1.0。这证明均值偏差已经修复;剩余差异则仍体现在裁剪率、KL、熵及后续训练行为中。

三次运行的新旧策略比率相对1的偏离,纵轴放大10000倍

查看原文图 4:策略比率对 1.0 的偏离

原文图 4。每一步 rollout/训练器策略比率相对 1.0 的偏离,放大 10,000 倍显示。蓝色为 V0 参考,红色为初次 V1,绿色为修正后的 V1。均值接近 1.0 并不意味着其他分布差异已经消失。图及实验归属原作者 / ServiceNow-AI。

第二项:运行时默认值

早期 V1 运行把“更换引擎版本”和“采用 V1 运行默认值”混在了一起:

  • 没有显式设置前缀缓存,因而使用了 vLLM 0.18.1 的默认行为。
  • 没有显式设置异步调度,同样落入 0.18.1 的默认行为。
  • 还通过启动时透传关键字参数,临时添加了 disable-cascade-attn 覆盖项;它不属于已提交配置中的一致性对照方案。

在对照运行中,我们把选择明确写进配置:

vllm_config:
  use_v1: true
  vllm_kwargs:
    logprobs-mode: processed_logprobs
    enable-prefix-caching: false
    async-scheduling: false

前缀缓存需要单独解释。对于固定模型状态,它通常是一项保持正确性的推理优化。但在这套在线 RL 系统中,相对 V0 参考路径,缓存的生命周期和复用方式构成了 V1 特有的差异。与此同时,actor 还在处理重复前缀、并发请求、异步调度与在途权重更新。

如果缓存策略不考虑权重更新边界,一次前缀缓存命中就可能复用更新之前计算出的状态。关闭前缀缓存,是为了在一致性对照中移除一个只有 V1 才有的变量。

第三项:在途权重更新

权重同步也必须匹配在线强化学习的更新模式。可以选择让 V1 比 V0 更严格:每次更新前等请求全部完成,再清空缓存。但这回答的是另一个问题。我们首先要验证的是,V1 能否复现现有 V0 的行为。

V0 的实际做法更接近以下过程:

  • 在引擎边界处阻塞执行。
  • 载入新权重。
  • 恢复执行,不显式使缓存状态失效。

在 V1 中,最接近的写法是:

await engine.pause_generation(mode="keep", clear_cache=False)
await engine_client.collective_rpc_async(
    "receive_weight_update",
    args=(request.model_dump_json(),),
)
await engine.resume_generation()

这里有两个关键细节。第一,mode="keep" 比 wait 或 abort 更接近旧的在途更新模型。第二,clear_cache=False 与 V0 包装层更新时保留缓存状态的行为一致。

滞后程度(lag)是一个有用的运行时诊断指标。训练后期,最初 V1 路径的滞后比修正后的 V1 更持久。

三次运行的rollout服务权重相对训练器的滞后曲线

查看原文图 5:rollout 服务权重滞后

原文图 5。rollout 服务中的权重,相对训练器策略落后多少步。蓝色为 V0 参考,红色为初次 V1,绿色为修正后的 V1。图及实验归属原作者 / ServiceNow-AI。

最后的差距:fp32 的 lm_head

上述修复消除了明显的迁移问题,但最终要恢复一致性,还必须对齐计算 logits 的数值路径。训练器在最后的投影中使用 fp32 的 lm_head,rollout 后端也必须与之匹配。

作者指出,MiniMax-M1 技术报告中出现过很接近的问题:RL 训练与推理的 token 概率不一致,最终定位到语言模型输出头,并通过以 fp32 计算输出头解决。

这之所以重要,是因为 RL 更新直接使用 token logprob。logits 的微小变化可能反映到策略比率、KL 和裁剪行为中。因此,最终投影的计算精度属于在线 RL 正确性的一部分。作者还引用后来的 ScaleRL 论文:其中将 fp32 logits/输出头计算纳入 RL 配方,并通过消融实验讨论其在大规模 RL 中的作用。

加入 fp32 lm_head 路径之后,奖励曲线可以简洁展示最终对齐结果。图 6 中,最终 V1 运行跟随 V0 参考轨迹,而最初 V1 尝试的奖励曲线明显不同。

V0、初次V1和加入fp32输出头后的V1奖励曲线

查看原文图 6:加入 fp32 输出头后的奖励

原文图 6。V0 参考(蓝)、初次 V1(红)与包含 fp32 lm_head 的最终 V1(绿)的奖励。采用 fp32 输出头后,最终 V1 跟随 V0 参考运行。图及实验归属原作者 / ServiceNow-AI。

消融:哪些解释没有成立

负面结果同样重要,因为它们能排除常见解释:

  • 只开启 processed_logprobs:修复了 logprob 的语义错误,但训练不一致仍然存在。
  • 批次不变性(batch invariance):另一次独立测试中,差异仍未消失,并伴随更高的滞后、更高的裁剪率和 NCCL 相关问题。
  • 把第一次 V1 运行当成公平基线:最初运行启用了多个 V1 专有默认行为,因此这是一组存在混杂因素的迁移比较。

为什么先修后端正确性

截断重要性采样、重要性比率重加权,以及其他目标函数侧修正,都是有用的工具。如果 rollout 本来就有意允许陈旧、以异步方式生成,或者所用后端无法做到与训练器策略等价,那么加入某种修正通常是合理的。

但这里的第一问题是推理正确性。迁到 V1 后,rollout 后端返回的 logprob 及其运行行为破坏了训练器原有假设。此时立即加入目标函数修正,就会把两个问题混在一起:

  • 推理后端是否产生了正确的 logprob?
  • 在 logprob 正确的前提下,目标函数是否仍然需要离策略或异步修正?

这两个问题必须分开。否则,目标函数修正可能恰好补偿了有问题的后端行为,反而让训练曲线难以解释。

现有目标函数当然还有改进空间。恢复推理一致性之后,下一步才是通常的异步/离策略整理工作:

  • 明确保留 rollout 生成时的行为策略 logprob。
  • 在优化时重新计算训练器侧的旧策略 logprob。
  • 把后端不一致修正与策略更新比率分离。
  • 除了汇总训练器指标,还跟踪修正项的有效样本量 ESS 等诊断信息。

这次迁移的核心经验更具体:先修复后端正确性,再针对仍然存在的不一致加入修正。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容