大模型算法总结
从 next-token 条件分布出发,统一理解 SFT、RL/GRPO、OPD 三种训练范式的梯度机制,并以 slime 源码为例解析 On-Policy Distillation 的 advantage shaping 实现。
SFT / OPD / RL 的第一性原理#
SFT、RL、OPD 最底层都在改模型的 next-token 条件分布 ,但它们区别在于:训练 prefix 从哪里来、target token 是谁生成的、每个 token 的权重/方向由什么决定。
在 slime 里,OPD 不是单独写成一个“纯 KL loss”替代 RL,而是把 teacher 对 student rollout token 的 logprob 差异转成一个 dense token-level advantage shaping 信号,再走和 PPO/GRPO 类似的 policy loss 更新路径。slime README 也把它定位成一个 Megatron training + SGLang rollout + Data Buffer 的统一 RL/dataflow 框架,rollout 侧生成数据和 verifier/reward,training 侧从 Data Buffer 读数据并更新模型。(GitHub ↗)
1. 先从大模型 next-token 建模说起#
大模型本质上学的是一个条件分布:
其中:
也就是当前 prompt + 已经生成的前缀。
整条 response 的概率是:
所以 logprob 是加和:
所有 SFT、RL、OPD 最后都会落到这件事:
在某些 prefix 下,让某些 token 的 上升或下降。
区别只是:
- SFT:prefix 来自 expert trajectory,target 是 expert token,永远正向提升;
- RL:prefix 来自 student rollout,target 是 student 自己采样的 token,advantage 正则提升、负则压低;
- OPD:prefix 来自 student rollout,target 也是 student 采样 token,但 teacher 会评价这个 token 在该 prefix 下是否合理。
2. SFT 到底在更新什么?#
SFT loss 是:
其中 是 expert/human/teacher 数据里的 gold token。
slime 里的 sft_loss_function 也是这个逻辑:先用当前模型 logits 计算 response tokens 的 log probabilities,然后 loss 是负的 mean logprob:
源码里 sft_loss_function 明确写了它是 response tokens 上的 negative log-likelihood,并且 loss = -sum_of_sample_mean(log_probs)。(GitHub ↗)
从 logit 梯度看 SFT#
模型在某个位置输出 logits:
经过 softmax:
如果 gold token 是 ,cross entropy 是:
它对 logit 的梯度是经典结果:
所以:
- 对 gold token :梯度是 ,梯度下降会让 变大;
- 对其他 token :梯度是 ,梯度下降会让 变小。
因此你说的“加大目标 token 在当前条件下的 logit/概率”对 SFT 是完全准确的。
但注意:SFT 只在 expert prefix 上这样做。
它学的是:
而不是:
这就是 exposure bias 的根源。
3. RL / GRPO 到底在更新什么?#
RL 不是给 gold token,而是让模型自己 rollout:
然后 verifier/reward 给一个分数:
最原始 policy gradient 是:
这里 是 student 自己采样出来的 token, 是 advantage。
如果:
说明这个 token/action 所在轨迹比预期好,那么 loss 会推动:
如果:
说明这个 token/action 所在轨迹比预期差,那么 loss 会推动:
所以你说“RL 本质上是不是也像 SFT 一样增加目标 token 概率”——答案是:
形式上类似,都是在 selected token 的 logprob 上反传;但 RL 的 token 不一定是正确 token,而且方向由 advantage 决定:好 token 增强,坏 token 压低。
在 slime 里,policy loss 会先计算当前模型在 response tokens 上的 log_probs,然后根据 old log_probs 和 current log_probs 得到 PPO-style ratio,再用 advantage 计算 clipped policy loss。源码中 policy_loss_function 里会计算当前 log_probs、旧 old_log_probs、ppo_kl = old_log_probs - log_probs,再调用 compute_policy_loss。(GitHub ↗)
compute_policy_loss 里核心就是:
然后:
并带 PPO clip。源码里对应 ratio = (-ppo_kl).exp(),因为 ppo_kl = old_log_probs - log_probs,所以 -ppo_kl = log_probs - old_log_probs。(GitHub ↗)
4. OPD 到底在做什么?#
OPD 的基本思想是:
让 student 先走自己的轨迹,然后 teacher 在 student 自己产生的 prefix 上给监督。
普通 off-policy distillation / SFT 是:
OPD 是:
这就是“on-policy”的含义。
已有 OPD 文献也基本这样定义:student 在自己生成的 rollouts 上接受 token-level teacher supervision。近期一些工作也指出,OPD 在长程任务中会遇到 student prefix drift、teacher signal 失效等问题。(arXiv ↗)
5. 经典 KL distillation 是怎么工作的?#
先说最标准的“全分布 KL”。
在某个 student prefix 下:
- student 分布:
- teacher 分布:
5.1 Forward KL#
对 student 来说,第一项 是常数,所以优化等价于 soft-label cross entropy:
它的梯度会把 student 的整个 vocab 分布往 teacher 靠:
所以:
- 如果 teacher 在某 token 上概率比 student 高:
梯度下降会提高这个 token 的 logit。
- 如果 teacher 在某 token 上概率比 student 低:
梯度下降会降低这个 token 的 logit。
这是真正意义上的“让学生 logits 分布靠近 teacher logits 分布”。
5.2 Reverse KL#
它更像:
student 当前认为可能的 token,如果 teacher 不认可,就压下去;teacher 认可,就保留。
Reverse KL 通常更 mode-seeking,也就是更倾向于让 student 集中到 teacher 支持的高概率模式上。
6. slime 里的 OPD 更像哪一种?#
slime 当前源码里实现的 OPD 更接近 sampled-token reverse-KL shaping,不是完整 full-vocab KL。
关键数据字段是:
teacher_log_probs
rollout_log_probs
tokens
loss_maskspythonslime 的 rollout 侧会把 teacher_log_probs 作为 rollout_data 的一部分传到训练侧;_ROLLOUT_DATA_TENSOR_DTYPES 里也明确包含 teacher_log_probs 和 rollout_log_probs。(GitHub ↗)
参数上,slime 支持:
--use-opd--opd-type sglang--opd-type megatron--opd-kl-coef
源码说明 sglang 模式是在 rollout 时从外部 SGLang teacher server 获取 teacher log-probs;megatron 模式是在训练时加载 teacher checkpoint 做 forward,并且 teacher 要和 policy/ref model 架构一致。(GitHub ↗)
6.1 slime OPD 的核心代码#
核心函数是:
apply_opd_kl_to_advantages(...)python它做的是:
然后修改 advantage:
源码 docstring 也直接写了:计算 reverse KL,即 student_logp - teacher_logp,并把加权 penalty 加到 advantages 里。(GitHub ↗)
所以,在 slime 里,OPD 不是一个单独的:
而是:
然后继续走 policy loss。
源码里也明确说 OPD 是 orthogonal to advantage estimators,可以叠加在 GRPO、PPO 等 estimator 上,通过给 advantage 加 KL penalty 来实现。(GitHub ↗)
7. slime OPD 中,学生到底学到了什么信号?#
假设某个 prefix 是:
h_t = "Task ... previous commands ... stderr ..."textstudent 采样了一个 token/action:
a_t = "rm"textstudent 自己给这个 token 的 logprob 是:
teacher 给这个 token 的 logprob 是:
那么:
如果 OPD 系数 ,基础 advantage ,则:
于是 policy loss 会压低这个 token 的概率。
直觉是:
student 很想输出这个 token,但 teacher 很不认可,所以这个 token 应该被压下去。
反过来,如果:
那么:
于是 policy loss 会提高这个 token 概率。
直觉是:
student 采样到了一个 token,但自己信心不高;teacher 很认可,所以应该加强。
这就是 slime OPD 最核心的学习信号:
teacher 不直接告诉学生“应该输出哪个替代 token”,而是评价 student 已经采样出来的 token 是否合理。
如果 teacher_logprob 高,就强化。 如果 teacher_logprob 低,就抑制。
8. 这和“靠近 teacher logits 分布”有什么区别?#
你问得非常准。
完整 KL distillation 是:
student 的整个 vocab 分布靠近 teacher 的整个 vocab 分布。
也就是你真的拿到了:
对所有 vocab token 的概率。
但 slime 这个实现更像:
对 student rollout 中实际出现的 token ,拿 teacher 对这个 token 的 logprob,然后做 sampled reverse-KL / advantage shaping。
也就是说它只知道:
而不一定知道 teacher 对其他 token 的完整分布。
所以它不能直接说:
teacher 更想让你输出 pytest,而不是 rmtext它只能说:
你刚才输出 rm,teacher 给 rm 的概率很低,所以降低 rm。text当然,降低 rm 的概率后,softmax 概率质量会重新分配给其他 token;如果模型本来知道 pytest、ls、cat 等替代 token,那么这些替代 token 的相对概率可能上升。
但这是间接的。
所以我们要区分两种 OPD:
Full-distribution OPD#
优点:teacher 明确告诉 student 整个分布应该长什么样。 缺点:需要 full logits,成本高。
Sampled-token OPD#
优点:便宜,只需要 teacher 给 student 采样 token 的 logprob。 缺点:teacher 没有显式给出替代 token,长程 drift 后信号可能变弱。
近期 OPD 论文也在讨论 sampled-token OPD 的不稳定性:比如 student 走到坏 prefix 后,teacher 可能局部也给不出有效纠错信号,出现 low-KL agreement trap;或者 sampled-token signal 太局部,不足以表达 teacher 真正的替代分布。(arXiv ↗)
9. slime 里 RL 和 OPD 是怎么合在一起的?#
在 slime 的 compute_advantages_and_returns 中,先根据 advantage_estimator 算出基础 advantage/returns。支持的 estimator 包括 GRPO、GSPO、CISPO、PPO、REINFORCE++ 等。然后如果 args.use_opd,就调用 apply_opd_kl_to_advantages 修改 advantages。(GitHub ↗)
所以整体逻辑是:
然后 policy loss 用:
其中:
再带 PPO clip。
所以 slime OPD 的本质不是“另开一个 OPD loss 分支”,而是:
把 teacher 对 token 的认可度变成 dense advantage correction。
10. 从第一性原理看:update 后模型会变成什么样?#
我们考虑某个 token 。
训练时 policy loss 近似是:
为了直觉先忽略 PPO ratio 和 clip。
对 logits 的梯度是:
如果 :
- 的 logit 上升;
- 其他 token 的 logit 下降。
如果 :
- 的 logit 下降;
- 其他 token 的概率质量相对上升。
因此,RL/OPD 的统一理解是:
advantage 决定了 student 自己生成的 token 是被强化还是被惩罚。
OPD 只是把 teacher logprob 引入 advantage:
于是:
- teacher 比 student 更认可该 token:
则:
这个 token 更可能被强化。
- teacher 比 student 更不认可该 token:
则:
这个 token 更可能被抑制。
这就是从参数反传角度看的 OPD。
11. 长序列里,为什么 OPD 比 SFT 更接近推理?#
SFT 的问题是:
训练时看到的是 expert prefix。
但部署时:
student 可能早就犯错了。
例如 terminal agent:
cd wrong_dir
pytest -q
sed -i ...bash这时候后续 context 已经变了。SFT 可能从来没有在这种 prefix 上训练过。
OPD 改变的是 prefix 分布:
也就是 student 自己生成的 prefix。
所以 OPD 学的是:
在我自己真实会走到的状态下,teacher 如何评价我当前 token。
这就是它相比 SFT 的核心优势。
但长程 agent 里也有问题:如果 student 走到非常坏的 prefix,teacher 对 sampled token 的 logprob 可能只能告诉你“这个 token 不好”,但不能构造一个可恢复路径。这也是为什么我们前面讨论 terminal agent 时更倾向于 Anchor-Replay SFT / recovery suffix:
不只是让 teacher 给坏 prefix 上的 token 打 logprob,而是让 teacher 从可 replay 的失败状态继续修复,给出正向 repair trajectory。
这比 sampled-token OPD 更强,因为它提供了替代动作序列。
12. 为什么说 RL、SFT、OPD 底层是同一个 logprob 机械?#
可以把三者统一成:
区别在于 。
| 方法 | prefix 来自哪里 | token/action 来自哪里 | 权重 是什么 |
|---|---|---|---|
| SFT | expert trajectory | expert token | 恒为正,通常 1 |
| RL/GRPO | student rollout | student sampled token | reward/advantage,可正可负 |
| OPD | student rollout | student sampled token | teacher-student logprob gap + RL advantage |
| Full KL distillation | teacher/student prefix | full vocab distribution | teacher probability |
| Anchor-Replay SFT | student failed state | teacher repair token | 恒为正,但 context 是失败状态 |
所以:
是的,它们都在通过反向传播改变 next-token logits;但“加大哪个 token、压低哪个 token、在哪个 prefix 上做”完全不同。
这三个维度决定了训练范式的本质。
13. 和我们 terminal-agent idea 的关系#
现在看,我们的 Anchor-Replay SFT 不是 full OPD,但它抓住了 OPD 最关键的点:
训练 context 应该来自 student 自己会进入的状态,而不是只来自 clean expert trajectories。
区别是:
- OPD:student prefix 上 teacher 给 token logprob;
- 我们:student failed executable state 上 teacher 给 repair continuation。
也就是:
而我们想要的是:
这个更适合 terminal,因为 terminal 的错误不是纯文本 prefix 的错误,而是 workspace/environment state 的错误。
所以我们的 publication-ready 说法可以是:
Standard OPD provides dense token-level feedback on student-generated prefixes. For terminal agents, however, student mistakes change the executable environment state. We therefore move from token scoring to state recovery: we replay student-induced failure states and distill verifier-validated teacher repairs as SFT data.
这就把 OPD 和我们的 idea 关系讲清楚了。
14. 最后用一个极简图式总结#
SFT:
expert prefix + expert token
loss = -log p_student(expert token)
RL:
student prefix + student token + reward/advantage
loss = -A * log p_student(student token)
OPD in slime:
student prefix + student token + teacher logprob
reverse_kl = log p_student(token) - log p_teacher(token)
A' = A - beta * reverse_kl
loss = PPO/GRPO policy loss with A'
Our Anchor-Replay SFT:
student failed executable state + teacher repair suffix
loss = -log p_student(teacher repair token | failed-state context)text所以你可以这样理解:
SFT 是“模仿正确答案”;RL 是“强化带来好结果的自己动作”;OPD 是“让老师评价自己动作是否像老师会做的动作”;Anchor-Replay SFT 是“在自己犯错后的状态里,学习老师怎么修回来”。