vLLM V0 到 V1:在 RL 中先保正确性,再谈修正
摘要
ServiceNow 工程师详细介绍了他们从 vLLM V0 迁移到 V1 的过程,重点解决了后端正确性问题,包括 logprob 语义和运行时默认值,以确保强化学习训练动态的稳定。
查看缓存全文
缓存时间: 2026/05/08 08:57
vLLM V0 到 V1:强化学习中先保证正确性,再谈修正
来源:https://huggingface.co/blog/ServiceNow-AI/correctness-before-corrections 返回文章列表 (https://huggingface.co/blog)
Rafael Pardinas 的头像 (https://huggingface.co/rafapi-snow)
Ehsan Kamalloo 的头像 (https://huggingface.co/ehsk)
- 迁移目标 (https://huggingface.co/blog/ServiceNow-AI/correctness-before-corrections#migration-objective)
- 失效模式 (https://huggingface.co/blog/ServiceNow-AI/correctness-before-corrections#failure-modes)
- V1 后端修复 (https://huggingface.co/blog/ServiceNow-AI/correctness-before-corrections#v1-backend-fixes)- Logprob 语义 (https://huggingface.co/blog/ServiceNow-AI/correctness-before-corrections#logprob-semantics) - 运行时默认值 (https://huggingface.co/blog/ServiceNow-AI/correctness-before-corrections#runtime-defaults) - 飞行中权重更新 (https://huggingface.co/blog/ServiceNow-AI/correctness-before-corrections#inflight-weight-updates)
- 剩余差距:fp32 lm_head (https://huggingface.co/blog/ServiceNow-AI/correctness-before-corrections#the-remaining-gap-fp32-lm_head)
- 消融实验 (https://huggingface.co/blog/ServiceNow-AI/correctness-before-corrections#ablations)
- 为何我们先修复后端正确性 (https://huggingface.co/blog/ServiceNow-AI/correctness-before-corrections#why-we-fixed-backend-correctness-first)
PipelineRL (https://huggingface.co/blog/ServiceNow-AI/github.com/ServiceNow/PipelineRL/) 使用 vLLM 作为推理引擎来生成 rollout。推理引擎采样 token 并返回 token 的 logprob;训练器使用这些 logprob 计算策略比率、KL 散度、裁剪率、熵和奖励。这些 logprob 的计算方式如有任何差异,都会改变训练动态。这就是我们在 vLLM V0 到 V1 迁移过程中需要消除的训练-推理不匹配问题。
TL;DR。 在修复了四项内容后,vLLM V1 与我们的 vLLM V0 参考结果一致:处理后的 rollout logprob、V1 特定的运行时默认值、飞行中权重更新路径,以及用于最终投影的 fp32 lm_head。我们在修改 RL 目标之前先修复了后端行为。
参考运行使用 vLLM 0.8.5;V1 运行使用 vLLM 0.18.1。图 1 展示了最终结果。红色曲线是最初的 V1 尝试,绿色曲线是下文所述修复后的最终 V1 运行。
图 1. vLLM V0 参考(蓝色)、初始 vLLM V1 尝试(红色)以及修复后的最终 vLLM V1 运行(绿色,包含 fp32 lm_head)的训练器端指标。最终 V1 运行在裁剪率、KL 散度、熵和奖励方面均接近 V0 的轨迹。
迁移目标 (https://huggingface.co/blog/ServiceNow-AI/correctness-before-corrections#migration-objective)
vLLM V1 是对 V0 引擎的大幅重写。因此,我们的迁移目标刻意保持狭窄:
- 验证 V1 返回的 rollout logprob 格式是否符合训练器预期
- 针对 V0 参考运行相同的工作负载
- 仅在恢复后端一致性后,再评估目标层面的变更
首批可见症状出现在:
clamp_log_ratio_new_old_indicatorkl_new_oldentropyreward
这些指标来自 GSPO 训练运行,即本实验使用的目标。同样的不匹配问题也可能出现在 PPO、GRPO 或任何将 rollout 端 logprob 作为优化目标的在线 RL 系统中。
初始 V1 运行清楚地显示了问题。训练器端的 logprob 和奖励在训练早期就偏离了 V0 参考。
图 2. 更新过程中训练器计算的当前策略 logprob(左)和奖励(右)。初始 vLLM V1 运行(红色)与 vLLM V0 参考(蓝色)分离。同样的模式也出现在训练器指标中。在初始对比中,裁剪率是最容易读取的信号。
图 3. vLLM V0 参考(蓝色)和初始 vLLM V1 尝试(红色)的训练器端指标。裁剪率跟踪 rollout/训练器策略差距;熵和奖励展示了该差距如何传播到训练中。
失效模式 (https://huggingface.co/blog/ServiceNow-AI/correctness-before-corrections#failure-modes)
我们将可能的原因分为三个层次:
- 语义不匹配:后端返回的 logprob 含义与训练器预期不同。
- 推理路径不匹配:后端对缓存、调度或请求处理使用不同的运行时默认值,因此相同 prompt 遵循不同的执行路径。
- 目标不匹配:RL 目标需要针对剩余的滞后量或后端不匹配进行修正。
我们过早地怀疑了第三类问题。有效的诊断方法是将前两类视为后端行为问题,并首先排除它们。
V1 后端修复 (https://huggingface.co/blog/ServiceNow-AI/correctness-before-corrections#v1-backend-fixes)
Logprob 语义 (https://huggingface.co/blog/ServiceNow-AI/correctness-before-corrections#logprob-semantics)
第一个问题是语义层面的。vLLM V1 默认从原始模型输出返回 logprob,即在 temperature 缩放、惩罚项和 top-k/top-p 过滤等 logits 后处理之前。PipelineRL 期望的是采样器使用的处理后分布的 logprob。
所需设置为:
logprobs-mode=processed_logprobs
这消除了 rollout logprob 中明显的均值偏移。但训练曲线与已知良好参考之间仍存在差距,因此下一个问题必然出在推理路径中。
策略比率图直接展示了这一点。一旦 V1 开启 processed_logprobs,三个运行的平均策略比率都极其接近 1.0。这确立了均值偏差的修复。剩余的不匹配体现在裁剪率、KL 散度、熵和下游训练行为中。
图 4. vLLM V0 参考(蓝色)、初始 vLLM V1 运行(红色)和修正后的 vLLM V1 运行(绿色)的 rollout/训练器策略比率每步偏离 1.0 的程度,放大了 10,000 倍。
运行时默认值 (https://huggingface.co/blog/ServiceNow-AI/correctness-before-corrections#runtime-defaults)
早期 V1 运行将引擎版本与 V1 运行时默认值混合在一起:
- 前缀缓存,在早期运行中未设置,因此应用了 vLLM
0.18.1的默认值 - 异步调度,在早期运行中未设置,因此应用了 vLLM
0.18.1的默认值 - 一个通过启动时 kwarg 透传设置的临时
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 独有的自由度。
飞行中权重更新 (https://huggingface.co/blog/ServiceNow-AI/correctness-before-corrections#inflight-weight-updates)
权重同步也必须匹配在线 RL 的更新模型。一种选择是让 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 包装器行为,即在更新时保持缓存状态不变
滞后是一个有用的运行时诊断指标。初始 V1 路径在训练后期比修正后的 V1 运行携带更多持久性滞后。
图 5. vLLM V0 参考(蓝色)、初始 vLLM V1 运行(红色)和修正后的 vLLM V1 运行(绿色)中,rollout 服务器权重落后于训练器策略的步数。
剩余差距:fp32 lm_head (https://huggingface.co/blog/ServiceNow-AI/correctness-before-corrections#the-remaining-gap-fp32-lm_head)
上述 V1 后端修复消除了明显的迁移问题,但最终一致性仍需匹配计算 logits 所用的数值路径。训练器使用 fp32 lm_head 进行最终投影。Rollout 后端必须匹配该行为。
MiniMax-M1 技术报告 (https://arxiv.org/abs/2506.13585) 中出现了一个密切相关的问题:他们的 RL 运行显示了训练/推理 token 概率不匹配,追溯原因是 LM 输出头,并通过在 fp32 中计算该头修复了问题。
这很重要,因为 RL 更新直接消费 token logprob。Logits 的微小变化可能在策略比率、KL 散度和裁剪中变得可见。因此,最终投影精度是在线 RL 正确性表面的一部分。ScaleRL 论文 (https://arxiv.org/abs/2510.13786) 后来将 fp32 logits/头计算作为其 RL 方案的一部分,并将其消融为大规模 RL 的有用设计选择。
包含 fp32 lm_head 路径后,奖励给出了最终一致性结果的紧凑视图。在图 6 中,最终 V1 运行跟踪 V0 参考;初始 V1 尝试产生了明显不同的奖励曲线。
图 6. vLLM V0 参考(蓝色)、初始 vLLM V1 尝试(红色)以及包含 fp32 lm_head 路径的最终 vLLM V1 运行(绿色)的奖励。包含 fp32 头后,最终 V1 运行跟踪 V0 参考。
消融实验 (https://huggingface.co/blog/ServiceNow-AI/correctness-before-corrections#ablations)
负面结果很重要,因为它们排除了常见解释。
- 仅
processed_logprobs:修复了语义 logprob bug;训练不匹配仍然存在。 - 批次不变性:在单独测试中,不匹配仍然存在,伴随更高滞后、更高裁剪率和 NCCL 并发症。
- 将首次 V1 运行作为公平基线:首次 V1 运行启用了多个 V1 独有的默认值,因此是一个混杂的迁移比较。
为何我们先修复后端正确性 (https://huggingface.co/blog/ServiceNow-AI/correctness-before-corrections#why-we-fixed-backend-correctness-first)
目标层面的修正,如截断重要性采样、重要性比率重加权及相关方法,都是有用的工具。如果 rollout 是故意滞后的、异步生成的,或由与训练器端策略等效性不可用的后端产生,那么添加某种形式的修正通常是正确的做法。
这里的首要问题是推理正确性。迁移到 V1 后,rollout 后端返回的 logprob 和运行时行为破坏了训练器假设。此时添加目标层面的修正会混合两个问题:
- 推理后端是否产生了正确的 logprob?
- 给定正确的 logprob,目标是否仍需要离策略或异步修正?
这些问题需要分开。否则,目标层面的修正可能补偿损坏的推理后端行为,使训练曲线更难解释。
当前目标仍可改进。恢复推理一致性后,下一步改进是常规的异步/离策略清理:
- 保留 rollout 时刻的显式行为策略 logprob
- 在优化时刻重新计算训练器端的旧策略 logprob
- 将后端不匹配修正与策略更新比率分离
- 在聚合训练器指标旁跟踪修正项的 ESS 等诊断指标
此次迁移的主要教训更狭窄:先修复后端正确性,再为剩余的不匹配添加修正。
相似文章
vllm-project/vllm v0.20.1
vLLM v0.20.1 是一个小版本更新,针对这款流行的开源大语言模型推理和服务库,继续保持其高吞吐量和高效内存管理的核心优势。
异步智能体强化学习中丢失旧 logits:非策略修正中的语义不匹配及修复方法
本文探讨了大型语言模型(LLM)异步强化学习中的旧 logits 缺失问题,提出了精确与近似的修正方法,以提升训练稳定性和性能。
vllm-project/vllm v0.21.0rc1
vLLM v0.21.0rc1 是高性能大语言模型推理和服务库的预发布更新,主要功能包括针对吞吐量、量化以及硬件支持的优化。
@vllm_project: 今天我们很高兴推出vime——一个在vLLM生态系统中用于LLM后训练的简单、稳定且高效的RL框架……
vime是一个用于LLM后训练的新开源RL框架,基于slime的训练设计和vLLM的推理引擎构建,在vLLM生态系统中提供简单、稳定且高效的流水线。
LLMZero:通过LLM智能体发现强化学习后训练的自适应训练策略
LLMZero利用LLM智能体通过树搜索在训练轨迹中进行搜索,发现用于强化学习后训练的自适应多参数过渡策略,该策略在多种任务中优于固定调度和网格搜索。