核心概念

ServiceNow AI 在 Hugging Face 部落格發表這篇遷移實錄,記錄將 RL 訓練框架 PipelineRL 的推論後端從 vLLM V0 升級至 V1 時,遭遇訓練指標偏移問題及其系統性診斷過程。

文章的核心主張:先修復後端正確性,再考慮目標函數的修正(Correctness Before Corrections)

遷移目標的刻意限縮

vLLM V1 是 V0 的全面重寫。PipelineRL 遷移設定了三個驗證目標:

  1. 確認 V1 返回的 rollout logprobs 與訓練器預期格式相符
  2. 在相同工作負載下與 V0 參照跑比對
  3. 只有後端達到同等效果後,才評估目標函數的優化空間

早期症狀出現在 clamp_log_ratio_new_old_indicatorkl_new_oldentropyreward 四個指標,在採用 GSPO 目標函數的 RL 訓練跑中出現明顯偏移。相同的問題也可能出現在 PPO、GRPO 或任何以 rollout 端 logprobs 作為優化目標的線上 RL 系統。

三層故障模型

團隊將可能原因分為三個層次:

  1. 語意不符:後端返回的 logprobs 含義與訓練器預期不同
  2. 推論路徑不符:後端採用不同的快取、排程或請求處理方式,相同提示走不同執行路徑
  3. 目標函數不符:RL 目標函數需要針對 staleness 或後端差異進行修正

診斷關鍵:先排除前兩層後端行為問題,不要急著跳到第三層增加目標函數修正

四個具體修復

1. Logprob 語意修復

vLLM V1 預設返回原始模型輸出的 logprobs——temperature scaling、penalties、top-k/top-p 過濾前的分佈。但 PipelineRL 需要的是採樣器實際使用的處理後分佈。

修復設定:logprobs-mode=processed_logprobs

此修復移除了 rollout logprobs 的均值偏移,讓 policy ratio 均值在所有跑中穩定維持在 1.0 附近。然而訓練曲線仍與 V0 參照存在差距,表示還有下一層問題。

2. 執行時預設值對齊

早期 V1 遷移跑混用了 vLLM 0.18.1 的新預設值。需明確設定:

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

Prefix caching 在線上 RL 中尤其危險:cache 命中可能重用 weight update 前的舊狀態,因為快取策略不識別 weight update 邊界。停用 prefix caching 移除了 V1 特有的差異自由度。

3. Inflight Weight Update 行為對齊

V0 的 weight 更新行為接近:暫停引擎 → 載入新 weights → 繼續執行,不做明確 cache 失效。V1 對應實作:

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

mode="keep"waitabort 更接近 V0 行為;clear_cache=False 對應 V0 保留快取狀態的語意。

4. fp32 lm_head 精度對齊

最後的修復是數值路徑:訓練器採用 fp32 的 lm_head 做最終投影,rollout 後端必須匹配。小幅 logit 差異在 policy ratio、KL 與 clipping 指標中會被放大,最終投影精度是線上 RL 正確性面的一部分。MiniMax-M1 技術報告與 ScaleRL 論文都獨立發現並修復了相同的問題。

為什麼要先修後端

目標函數修正(importance ratio 重加權、truncated importance sampling 等)在 rollout 刻意 stale 或後端等效性無法保證時是合理工具。但若在後端本身存在 bug 的狀態下加入修正,會混淆兩個獨立問題:後端是否返回正確 logprobs?在正確 logprobs 前提下,目標函數是否需要 off-policy 修正?兩個問題混在一起,訓練曲線就失去可解釋性。

這與 GPT 小妖精事件:強化學習人格訓練的行為外洩 呈現的反例形成對比——在行為異常的前期診斷中,若過早加入「修正」而非先確認訓練管線是否正確,問題只會被掩蓋而非解決。

關鍵要點

  • 三層診斷框架:語意不符 → 路徑不符 → 目標不符,按序排除,不跳層
  • logprobs-mode=processed_logprobs:vLLM V1 遷移必要設定,返回採樣器實際使用的分佈
  • prefix caching 在線上 RL 是正確性風險:可能跨越 weight update 邊界重用舊狀態
  • fp32 lm_head 是 RL 訓練細節,不是最佳化:多個獨立研究均驗證了這一點
  • 消融實驗揭示偽相關:processed_logprobs 單獨修復不足夠;首次 V1 跑有多個預設值同時改變,是被污染的比較基準
  • 訓練指標可解釋性要求純淨環境:混雜多個差異時加修正,指標失去診斷意義

實務應用

線上 RL 系統(PPO、GRPO、GSPO 等)將 vLLM 升級至 V1 的遷移檢查清單:

  1. 確認 logprobs 返回處理後分佈(logprobs-mode=processed_logprobs
  2. 明確停用 prefix caching 與 async scheduling,直到行為與 V0 完全比對
  3. 確認 inflight weight update API 呼叫語意等效(mode="keep", clear_cache=False
  4. 確認訓練器與 rollout 後端使用相同的 lm_head 精度(fp32)
  5. 每次只引入一個變數,分步驗證,不做全量切換

延伸觀點

這篇文章提出的「後端正確性優先」原則,在近期其他研究中獲得獨立驗證,但各自從不同角度深化了問題的理解。

精度格式是 mismatch 的根本原因之一。arXiv 2510.26788(Defeating the Training-Inference Mismatch via FP16)指出,BF16 只有 7 個 mantissa bits,而 FP16 有 10 個。在 online RL 中,訓練引擎(FSDP/Megatron)與推論引擎(vLLM/SGLang)的 CUDA kernel 實作不同,BF16 的 rounding error 隨序列長度指數級累積,導致相同權重在訓練與推論端計算出不同的 logprob。量化結果是 FP16 的 mismatch 約小 24 倍,GRPO + FP16 訓練準確率可達 99%,而 BF16 在 73-84% 後崩潰。這與本文 fp32 lm_head 的結論高度一致:精度差異是 RL 訓練穩定性的核心變數,而不是細節。

Backend 修復之後仍需要 objective 層面的補丁。arXiv 2602.01826(Beyond Precision)揭示了更深層的問題:即使使用 FP16,浮點加法的非交換性(autoregressive inference 的計算順序與 parallel training 不同)也意味著 mismatch 無法被完全消除。這篇研究提出以 LR scheduling 處理殘餘 mismatch:偵測 response length 突然上升(約在 110-160 訓練步時出現),觸發 LR 衰減。這與本文構成互補的兩層方案——先修 backend(ServiceNow 的四項修復),再以 LR scheduling 處理殘餘誤差(Beyond Precision 的做法)。

三篇文章合起來描述的是一個分層治理框架:語意層(processed_logprobs)→ 快取層(prefix caching 停用)→ 精度層(fp32 lm_head / FP16)→ 優化層(LR scheduling)。每一層都有獨立的故障模式與診斷指標,混層治理會讓訓練曲線失去可解釋性,這正是文章標題「Correctness Before Corrections」想表達的根本工程原則。

反向連結

以下頁面引用了本頁: