Skip to content

必读论文路线

论文不是收藏链接。对 verl 新手来说,每篇都要带着五个问题读:它解决什么问题,核心公式或思想是什么,小白怎么理解,verl 哪段源码在实现它,读完应该回到本站哪一节继续动手。

先验地图

层次要学会的问题必读材料
Policy gradient 基础为什么要有 ratio、advantage、clipPPO、GAE
RLHF 范式SFT、RM、PPO、KL 是什么关系InstructGPT
RLVR / reasoning没有人类偏好模型时怎样用可验证奖励DeepSeekMath、DeepSeek-R1
无 critic baseline没 value model 时怎样降方差GRPO、RLOO、ReMax、REINFORCE++
recipe 稳定性长 CoT、动态采样、clip、overlong 怎么配DAPO、Dr.GRPO
偏好优化侧翼不 rollout 也能做偏好对齐吗DPO
工程执行为什么 verl 要这样拆 trainer、worker、rollout engineHybridFlow / verl
训练-推理不一致rollout policy 和 train policy 不一致怎么办Rollout correction

PPO:让 policy 更新不要一脚踩太远

解决什么问题。 普通 policy gradient 更新太猛时,模型可能为了短期 reward 大幅偏离旧策略。PPO 用 clipped surrogate objective 限制每次 policy update 的幅度。

核心公式。

text
r_t(theta) = pi_theta(a_t|s_t) / pi_old(a_t|s_t)
L_clip = E_t[min(r_t A_t, clip(r_t, 1-eps, 1+eps) A_t)]

LLM 里 a_t 就是第 t 个 response token。r_t 大于 1 表示新模型比旧模型更想生成这个 token;A_t 大于 0 表示这条轨迹值得鼓励。

小白版解释。 PPO 像是在说:答得好的输出可以提高概率,但一次别提高太多;答得差的输出可以降低概率,也别一刀切太狠。clip_ratio 就是这根安全绳。

verl 对应源码。

  • verl/trainer/ppo/ray_trainer.py::fit():先 rollout,再重算 old_log_probs,再 update actor。
  • verl/trainer/ppo/core_algos.py::compute_policy_loss_vanilla():计算 ratio = exp(log_prob - old_log_prob)actor/pg_clipfracactor/ppo_kl
  • verl/trainer/ppo/core_algos.py::agg_loss():把 token 或 sequence 级 loss 聚合成标量。
  • examples/ppo_trainer/run_qwen3_8b_fsdp.shalgorithm.adv_estimator=gaeROLLOUT_N=1、actor/critic 都启用。

建议先读章节。 GSM8K PPO,再看 调试指标 里的 actor/pg_clipfracactor/ppo_kl

GAE:把最终 reward 分摊到 token

解决什么问题。 PPO 需要 advantage。只有最终 reward 时,直接把 reward 当每个 token 的学习信号方差很大;critic/value baseline 可以降方差,但会引入一点偏差。GAE 用 gammalam 控制这个取舍。

核心公式。

text
delta_t = r_t + gamma V(s_{t+1}) - V(s_t)
A_t^GAE = delta_t + gamma * lam * delta_{t+1} + ...
return_t = A_t + V(s_t)

小白版解释。 critic 像一个“预期分数估计器”。如果实际结果比它预期更好,advantage 为正;比预期更差,advantage 为负。

verl 对应源码。

  • verl/trainer/ppo/core_algos.py::compute_gae_advantage_return():倒序扫 response token,计算 deltalastgaelamreturns,最后对 advantage 做 masked whiten。
  • verl/trainer/ppo/ray_trainer.py::compute_advantage()algorithm.adv_estimator=gae 时调用 GAE。
  • examples/ppo_trainer/run_qwen3_8b_fsdp.sh:PPO 示例有 critic.model.pathcritic.optim.lr,GRPO 示例没有 critic。

建议先读章节。 GSM8K PPO 的 advantage/update 部分。

InstructGPT / RLHF:SFT、奖励模型、PPO、KL 的经典三段式

解决什么问题。 预训练模型会续写文本,但不一定听用户指令。InstructGPT 把人工示范、偏好奖励模型、PPO 优化串成一条 RLHF pipeline,并用 KL 约束避免模型偏离 reference 太远。

核心思想。

text
SFT policy -> collect comparisons -> train reward model
PPO reward = reward_model_score - beta * KL(policy || reference)

小白版解释。 先教模型“人类喜欢什么样的回答”,再让模型自己生成回答,用奖励模型打分,同时用 KL 拉住它别为了刷分变怪。

verl 对应源码。

  • verl/trainer/ppo/ray_trainer.py::apply_kl_penalty()token_level_rewards = token_level_scores - beta * kld
  • verl/trainer/ppo/core_algos.py::kl_penalty():支持 klabsmselow_var_klfull
  • docs/examples/config.rst:解释 algorithm.use_kl_in_rewardactor_rollout_ref.actor.use_kl_loss

建议先读章节。 如何写奖励函数调试指标 的 KL 部分。

DeepSeekMath / GRPO:用组内相对分数替代 critic

解决什么问题。 PPO 的 critic 显存和训练成本都高。GRPO 对同一个 prompt 采样多条 response,用组内 reward 均值和标准差构造 advantage,不训练 value model。

核心公式。

text
G = rollout.n
A_i = (R_i - mean(R_1...R_G)) / (std(R_1...R_G) + eps)

小白版解释。 同一道题让模型答 5 次。答得比自己这组平均好,就加概率;比平均差,就降概率。

verl 对应源码。

  • examples/grpo_trainer/run_qwen3_8b_fsdp.shalgorithm.adv_estimator=grpoactor_rollout_ref.rollout.n=${ROLLOUT_N:-5}algorithm.use_kl_in_reward=Falseactor_rollout_ref.actor.use_kl_loss=True
  • verl/trainer/ppo/ray_trainer.py::fit():先给每个原始 prompt 写 uid,再 repeat(repeat_times=rollout.n)
  • verl/trainer/ppo/core_algos.py::compute_grpo_outcome_advantage():按 uid 聚合 reward,得到组内相对 advantage。

建议先读章节。 GRPO 配置解读

DAPO / Dr.GRPO:把 reasoning RL 从算法推到 recipe

解决什么问题。 纯 GRPO 还会遇到全对/全错组没有学习信号、长输出偏置、clip 不够灵活、过长回答刷 reward 等问题。DAPO 把动态采样、decoupled clip、token-level loss、overlong penalty 组合成可复现实验 recipe。

核心思想。

text
只训练“组内有差异”的 prompt
clip_ratio_low 和 clip_ratio_high 可分开
loss_agg_mode 控制 token/sequence 如何归一化
overlong_buffer 对接近最大长度的输出给线性惩罚

小白版解释。 DAPO 不是只换一个公式,而是在训练现场加了很多“别浪费 batch、别奖励废话、别被长度骗”的规则。

verl 对应源码。

  • docs/algo/dapo.md:给出动态采样、clip-higher、token-level loss、overlong reward shaping 的配置形态。
  • verl/trainer/ppo/core_algos.py::agg_loss()token-meanseq-mean-token-sumseq-mean-token-sum-normseq-mean-token-mean
  • verl/workers/reward_manager/dapo.pyoverlong_buffer 根据 response 长度扣分。
  • verl/trainer/ppo/core_algos.py::compute_grpo_outcome_advantage()norm_adv_by_std_in_grpo=False 对应 Dr.GRPO 风格。

建议先读章节。 GRPO 配置解读loss_agg_modenorm_adv_by_std_in_grpo

DPO:不用 rollout 的偏好优化侧翼

解决什么问题。 RLHF 的 PPO 需要采样、reward model、KL、critic 或 advantage,训练链路复杂。DPO 从偏好数据直接优化 policy/reference 的 log-prob 差,不在训练中 rollout。

核心公式。

text
L_DPO = -log sigmoid(beta * [
  log pi_theta(y_w|x) - log pi_ref(y_w|x)
  - log pi_theta(y_l|x) + log pi_ref(y_l|x)
])

小白版解释。 DPO 直接告诉模型:在同一个 prompt 下,chosen 的概率相对 rejected 应该更高;同时别偏离 reference 太远。

verl 对应源码。 DPO 不走 RayPPOTrainer.fit() 这条 rollout/reward/advantage 主线。读它的价值是帮你区分:RLVR 是在线采样后用可验证 reward;DPO 是离线偏好对。

建议先读章节。 学完 PPO/GRPO 后再读,不要一开始就混在一起。

RLOO / ReMax / REINFORCE++:无 critic 时怎样做 baseline

解决什么问题。 无 critic 的方法省资源,但 reward 方差会大。RLOO 用 leave-one-out 组内 baseline,ReMax 用 greedy rollout baseline,REINFORCE++ 系列改造 advantage 和 loss 来降低噪声。

核心思想。

text
REINFORCE: A_i = R_i
RLOO:      A_i = R_i - mean(R_j, j != i)
ReMax:     A_i = R_sampled - R_greedy_baseline

小白版解释。 baseline 不是奖励本身,而是“本来预计能拿多少分”。减掉 baseline 后,训练信号变成“比预期好多少”。

verl 对应源码。

  • verl/trainer/ppo/ray_trainer.py::compute_advantage():非 GAE/GRPO 的 estimator 通过 core_algos.get_adv_estimator_fn() 分派。
  • verl/trainer/ppo/ray_trainer.py::fit()AdvantageEstimator.REMAX 会额外生成 greedy baseline,并写入 reward_baselines
  • verl/trainer/ppo/core_algos.py:注册了 GRPO、RLOO、REINFORCE++ 等 advantage estimator。

建议先读章节。 先读 GRPO 配置解读,再回头比较这些 estimator。

DeepSeek-R1:为什么 RLVR 成为 reasoning 模型关键路径

解决什么问题。 DeepSeek-R1 展示了可验证任务上的大规模 RL 可以激发 self-reflection、verification、long CoT 等推理行为,也说明 reasoning post-training 不一定依赖人类标注的完整推理轨迹。

核心思想。 对数学、代码、STEM 这类可验证任务,用 reward 约束最终正确性和格式,让模型在 trial-and-error 中学会更强的推理策略。

小白版解释。 你不给模型“标准解题过程”,只给它“最后答案对不对”和一些格式规则;模型为了拿分,自己探索出更长、更会检查的思考过程。

verl 对应源码。

  • examples/data_preprocess/gsm8k.pyexamples/data_preprocess/math_dataset.py:把可验证任务做成 parquet。
  • verl/utils/reward_score/gsm8k.pymath_reward.pymath_dapo.pymath_verify.py:规则验证入口。
  • examples/grpo_trainer/run_qwen3_8b_fsdp.sh:reasoning RLVR 的最小 GRPO 入口。

建议先读章节。 GSM8K PPO如何写奖励函数

Rollout Correction:rollout policy 和 train policy 不一致怎么办

解决什么问题。 rollout 可能由 vLLM/SGLang 用低精度、异步或旧权重生成;actor update 时又用训练后端重算 logprob。两者概率不一致会让 on-policy 假设变弱。

核心思想。

text
log_ratio = old_log_probs - rollout_log_probs
IS weight = exp(log_ratio) 之后做截断
RS mask = 丢掉偏离过大的 token/sequence

小白版解释。 训练时你以为“这是当前模型生成的回答”,但真实 rollout 可能来自另一个近似模型。correction 就是在估计“这条样本到底离训练 policy 有多远”。

verl 对应源码。

  • verl/trainer/ppo/rollout_corr_helper.py::compute_rollout_correction_and_add_to_batch():计算 IS weights、rejection mask、off-policy metrics。
  • verl/trainer/ppo/ray_trainer.py::fit():在 token_level_rewards 之后、advantage 之前应用 rollout correction。
  • verl/utils/debug/metrics.py::calculate_debug_metrics():记录 rollout 与 actor 概率差。

建议先读章节。 调试指标 的 rollout correction 部分。

HybridFlow / verl:为什么工程架构长这样

解决什么问题。 RLHF/RLVR 不是单模型训练:actor、critic、reference、reward、rollout engine 都要协作,且训练和推理需要不同并行策略。HybridFlow 用 single-controller + multi-controller 混合方式组织复杂 dataflow。

核心思想。 上层 trainer 用单控制器描述算法流程;底层 worker 负责分布式模型计算;rollout engine 和 training backend 通过 checkpoint/weight sync 连接。

小白版解释。 RayPPOTrainer.fit() 像导演,worker group 像各部门,vLLM/SGLang 像外景拍摄组。导演不亲自拍每一帧,但要决定什么时候生成、什么时候打分、什么时候更新权重。

verl 对应源码。

  • verl/trainer/ppo/ray_trainer.py::fit():PPO/GRPO dataflow 主线。
  • verl/workers/reward_manager/*:rule reward / reward model 管理。
  • verl/workers/engine_workers.py:actor update、logprob、reward/value 等 worker 入口。
  • examples/ppo_trainer/run_qwen3_8b_fsdp.shrun_qwen3_8b_megatron.sh:同一算法切换 FSDP/Megatron backend。

建议先读章节。 读完 examples 三页后再回来看 HybridFlow,不然架构词会显得很抽象。

本节参考与延伸阅读

面向源码阅读的 verl 学习文档。