vLLM V0 到 V1:在 RL 中先保正确性,再谈修正

Hugging Face Blog 工具

摘要

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 引擎的大幅重写。因此,我们的迁移目标刻意保持狭窄:

  1. 验证 V1 返回的 rollout logprob 格式是否符合训练器预期
  2. 针对 V0 参考运行相同的工作负载
  3. 仅在恢复后端一致性后,再评估目标层面的变更

首批可见症状出现在:

  • clamp_log_ratio_new_old_indicator
  • kl_new_old
  • entropy
  • reward

这些指标来自 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)

我们将可能的原因分为三个层次:

  1. 语义不匹配:后端返回的 logprob 含义与训练器预期不同。
  2. 推理路径不匹配:后端对缓存、调度或请求处理使用不同的运行时默认值,因此相同 prompt 遵循不同的执行路径。
  3. 目标不匹配: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"waitabort 更接近旧的飞行中更新模型
  • 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

GitHub Releases Watchlist

vLLM v0.20.1 是一个小版本更新,针对这款流行的开源大语言模型推理和服务库,继续保持其高吞吐量和高效内存管理的核心优势。

vllm-project/vllm v0.21.0rc1

GitHub Releases Watchlist

vLLM v0.21.0rc1 是高性能大语言模型推理和服务库的预发布更新,主要功能包括针对吞吐量、量化以及硬件支持的优化。