预备概念
这一页只讲读 verl 前必须知道的概念。目标不是把强化学习完整推导一遍,而是让你在源码里看到 actor、ref_log_prob、advantages、response_mask、rollout.n 时知道它们为什么存在。
先把任务说成人话
LLM post-training 的核心问题是:模型已经会说话了,接下来怎样让它更符合某个目标?
- 如果目标来自人类偏好,常见说法是 RLHF。
- 如果目标能被规则、单测、数学 verifier 检查,常见说法是 RLVR。
- 如果目标是“模仿一批标准答案”,常见训练是 SFT。
- 如果目标是“偏好 chosen、远离 rejected”,常见算法是 DPO 一类。
verl 的 PPO/GRPO/RLVR 主线可以先这样理解:
模型生成回答 -> 奖励系统打分 -> 算法把分数变成 advantage -> actor 往更高 advantage 的 token 方向更新RLHF 与 RLVR
RLHF 是 Reinforcement Learning from Human Feedback。典型流程是先 SFT,再训练 reward model,最后用 PPO 等算法让 policy 更偏向高奖励输出。
RLVR 是 Reinforcement Learning from Verifiable Rewards。它更常出现在数学、代码、工具调用等任务中:答案能被规则、单测或 verifier 检查,不一定需要人类偏好 reward model。
在 verl 中,这两类任务都会被统一成一条数据流:模型生成 response,reward 系统给每条 response 打分,训练算法把分数变成更新 actor 的信号。
Policy、Actor、Ref、Critic、Reward
| 名词 | 小白版解释 | verl 里常见位置 |
|---|---|---|
| policy / actor | 正在被训练的模型。它生成 response,也被 loss 更新。 | Role.ActorRollout、actor_rollout_ref.actor |
| reference policy | 通常是冻结的初始模型,用来限制 actor 不要偏离太远。 | Role.RefPolicy、compute_ref_log_prob() |
| critic | 估计“当前状态值不值得期待”的模型,PPO + GAE 常用。 | Role.Critic、_compute_values() |
| reward | 规则函数、reward model 或远端服务给出的分数。 | reward_manager、reward_loop |
| rollout | 用 actor 或近似 actor 的推理服务生成 response。 | workers/rollout、async_rollout_manager |
不是每个算法都需要所有角色。GRPO 常常不需要 critic;规则奖励任务也可以不启用 reward model;OPD 会多出 teacher 信号。
Logprob:为什么训练前还要重算概率
生成 response 时,rollout 引擎会输出 token。但做 PPO/GRPO 更新时,actor 需要知道:
old_log_probs:生成这条 response 时的旧策略概率。log_probs:当前正在更新的 actor 对同一批 token 的概率。ref_log_prob:reference policy 对同一批 token 的概率。
PPO 的比率可以写成:
ratio = exp(log_probs - old_log_probs)如果 ratio 太大,说明 actor 正在把某些 token 的概率推得过猛;clip 就是在控制这件事。
KL:不要让模型为了 reward 跑太远
KL 衡量当前 policy 和 reference policy 的距离。post-training 不希望模型为了追求 reward 走到奇怪分布,所以常用 KL 作为约束。
verl 里有两个位置要分清:
| 位置 | 发生在哪里 | 小白解释 |
|---|---|---|
| reward 侧 KL | ray_trainer.apply_kl_penalty() | 先从 token reward 里扣掉 KL 惩罚,再算 advantage。 |
| loss 侧 KL | actor loss 配置 | actor update 时把 KL 当作额外 loss 项。 |
看到 use_kl_in_reward=False 时,不代表完全没有 KL;它通常表示不在 reward 侧扣 KL,可能交给 loss 侧或 recipe 控制。
Reward、Return、Advantage
reward 只告诉你“这条 response 好不好”。advantage 问的是:“相对某个 baseline,这个 token/response 有多值得加强?”
| 概念 | 直觉 | verl 里的字段 |
|---|---|---|
| reward / score | 答案得分,例如 GSM8K 答对为 1,答错为 0。 | rm_scores、token_level_scores |
| return | 从某个 token 往后累计能得到多少回报。 | returns |
| advantage | 比预期好多少,真正影响 policy gradient 的信号。 | advantages |
PPO + GAE 用 critic 的 values 当 baseline。GRPO 则把同一个 prompt 的多条 response 分成一组,用组内 reward 均值/标准差构造相对 advantage。
Response mask:哪些 token 参与训练
大模型 batch 里有 prompt、response、padding。不是每个 token 都应该被 PPO loss 更新。response_mask 用来标记有效 response token:
prompt tokens: 0 0 0 0
response tokens: 1 1 1 1
padding tokens: 0 0所以你在源码里经常会看到 loss * response_mask 或 masked_mean(...)。这不是细枝末节;如果 mask 错了,模型可能会训练 prompt 或 padding。
Rollout:生成样本不是普通 forward
rollout 是生成训练样本。它和训练 forward/backward 不是同一件事。
在大模型训练里,生成需要高吞吐推理引擎,例如 vLLM 或 SGLang;训练需要 FSDP、Megatron、VeOmni 等训练后端。verl 的难点之一,就是让这两边共享或同步权重,同时节省显存。
因此 rollout.n 也不只是“生成几条”。对 GRPO/RLOO 来说,它决定同一个 prompt 有多少 sibling responses 可以互相比较。
DataProto:训练流水线里的信封
DataProto 可以先理解成一个标准信封:
| 部分 | 放什么 | 例子 |
|---|---|---|
batch | tensor,第一维通常是 batch 维 | input_ids、responses、old_log_probs、advantages |
non_tensor_batch | 字符串、对象、uid、数据源等 | data_source、reward_model、extra_info、uid |
meta_info | 控制信息、计时、采样参数 | temperature、global_steps、timing |
很多小白读源码卡住,不是因为算法太难,而是没分清“这个信息在 DataProto 的哪一层”。
本节参考与延伸阅读
verl/trainer/ppo/ray_trainer.py:apply_kl_penalty()、compute_advantage()、_compute_old_log_prob()、_compute_ref_log_prob()。verl/trainer/ppo/core_algos.py:compute_gae_advantage_return()、compute_grpo_outcome_advantage()、compute_policy_loss_vanilla()。verl/protocol.py:DataProto、DataProtoFuture、BatchData。docs/api/data.rst:官方 DataProto 与 TensorDict 说明。- InstructGPT / RLHF、PPO、GAE、DeepSeekMath/GRPO 论文:读算法页时再按章节深入。