上一篇《教会模型「哪个更好」》收在一道题上:整句的分,怎么摊给每个 token。PPO 雇 critic 分功,GRPO 让同学互比,GSPO 干脆整句结算。今天讲一篇换了思路的论文,它的答案是:不摊了,每个 token 自己领一个分,而且打分的老师不用另请,就是模型自己。
论文叫《Self-Distilled Reasoner: On-Policy Self-Distillation for Large Language Models》,方法简称 OPSD(在线自蒸馏),UCLA、港大和 Meta Superintelligence Labs 合作,2026 年 1 月挂出,3 月更新到第三版(修了聊天模板的 bug,加了裁剪)。代码开源,Qwen3-1.7B 上 4 张 H100 跑 15 分钟就能复现主结果。
先用一个场景把它的直觉说透。学生做错一道题,最有效的复盘不是再做十遍试错,而是翻开答案册,对着正确解法看一遍:哦,原来第三步该用整除,我在这里拐错了。看过答案再回头理解,比从零想出答案容易得多,这就是 OPSD 的全部赌注。它让同一个模型分饰两角:看过参考解的当老师,没看过的当学生,老师在学生自己写的每一个 token 上逐字批注。
一、三条老路,各有一根刺
先看它想替代什么。要让模型学会做数学题,手头有一份数据集:每道题配一份人写或验证过的解答(论文用 OpenThoughts 的数学子集,约 3 万对)。已有三条路:
- SFT:照着参考解逐 token 抄。信号稠密(每个位置都有正确答案),但离线:训练时接的永远是别人写的前缀,推理时却要接自己写的前缀,一步走偏后面全没见过(暴露偏差)。而且抄的是「别人的解法」,学不到「我自己错在哪」。论文里 SFT 在三个尺寸上平均分全线低于不训;
- GRPO 这类 RL:在线,学生自己采样,可信号稀疏,整句只有一个 0/1(答案对不对),中间几千个 token 谁的功劳靠猜;又贵,一道题采 8 条、每条最长 16k;还有个隐患,上一篇提过:一组全对或全错,标准差为 0,这道题这一轮没梯度。论文数了数,训练 100 步内,GRPO 超过一半的 batch 落入这种「奖励多样性坍塌」;
- 在线蒸馏(GKD、Thinking Machines 的 on-policy distillation):在线又稠密,学生采样,老师逐 token 给整个分布,但要另请一个通常更大的老师模型,而且参考解就摆在数据集里没人用。
OPSD 把三格同时占住:学生在线采样,老师逐 token 给全词表分布,老师就是自己,只不过多看了一份参考解。
二、一个模型,两个上下文
核心设定只有一句话:同一套参数 θ,喂不同的上下文,就是两个策略。
学生 p_S(· | x) 只看到题目 x
老师 p_T(· | x, y*) 看到题目 x + 参考解 y*
老师不是另一个模型,甚至不是另一份权重,它和学生逐参数相同,唯一的区别是提示词里多贴了一份答案。论文管这份答案叫特权信息(privileged information):训练时能看、考试时看不到的东西。
一步训练走三拍:
- 学生采样:给学生看题目,让它自己写一遍解答 ŷ(论文只让它写 1024 个 token);
- 两次前向:把这段 ŷ 分别接到学生上下文和老师上下文后面,各做一次前向,得到每个位置上的全词表分布 p_S 和 p_T;
- 逐 token 对齐:在每个位置上算两个分布的散度,沿整段回答取平均当损失,梯度只回传给学生那一路。
注意第二拍:老师不生成任何 token。它不是先写一份自己的标准解再让学生模仿,而是拿着答案册,在学生的草稿纸上逐字批注:「写到这儿,知道答案的我,下一个词会怎么写?」这份「合理化」是隐式的,一次前向就完成。
提示词长什么样,直接看仓库的 data_collator.py:
学生(user 消息):
Problem: {problem}
Please reason step by step, and put your final answer within \boxed{}.
老师(user 消息):
Problem: {problem}
Here is a reference solution to this problem:
=== Reference Solution Begin ===
{solution}
=== Reference Solution End ===
After reading the reference solution above, make sure you truly understand
the reasoning behind each step — do not copy or paraphrase it. Now, using your
own words and independent reasoning, derive the same final answer to the
problem above. Think step by step, explore different approaches, and don't be
afraid to backtrack or reconsider if something doesn't work out:
Please reason step by step, and put your final answer within \boxed{}.
两段提示词都过 Qwen3 的聊天模板,再把学生采样出的 ŷ 原样接在各自后面。老师那段的措辞值得玩味:「别抄、别复述,用你自己的话推出同一个答案」。它在把老师的注意力从「复读参考解」引向「理解之后重写」,这样老师在学生的稿子上给出的分布才是「懂了答案的我会怎么写」,而不是「参考解第 37 个词是什么」。(仓库还留了一个可选的 --reason_first 模式:老师先显式写一段对参考解的分析,再拼进自己的上下文;主结果没用它。)
三、目标函数:逐 token 拉近两个分布
写成公式,一行:
L_OPSD(θ) = E_(x, y*) E_ŷ~p_S(·|x) [ (1/|ŷ|) Σₙ D( p_T(·|x, y*, ŷ<n) ‖ p_S(·|x, ŷ<n) ) ]
└── 每个位置一个散度,沿学生自己的回答取平均 ──┘
D 是两个分布之间的散度,论文试了三种:正向 KL、反向 KL 和广义 JS 散度(用 β 在两者之间插值;代码里 --beta 0 就是正向 KL,1 是反向 KL)。三种里正向 KL 明显最好,Qwen3-1.7B 在 AIME25 上:
| 散度 | 训练前 | 50 步 | 100 步 |
|---|---|---|---|
| 正向 KL(β=0) | 36.7 | 43.9 | 41.1 |
| 反向 KL(β=1) | 36.7 | 37.5 | 35.0 |
| JSD(β=0.5) | 36.7 | 36.9 | 39.0 |
正向 KL 是「老师加权」:Σ_v p_T(v)·log(p_T(v)/p_S(v)),老师觉得该有概率的词,学生必须给够,否则重罚,等于要求学生覆盖老师的每一种可能。反向 KL 相反,是「学生加权」,只要求学生认的词老师也认,容易缩到老师的一个众数上。Thinking Machines 那篇在线蒸馏选的是反向 KL,OPSD 反过来,一个直觉的解释是:这里老师和学生本是同一个模型,分布形状本就相近,正向 KL 把老师因为看过答案而多出的那点「确信」整份搬给学生,效果最好。
带数字走一遍。 题目:「1 到 30 之间有几个质数?」参考解列出 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,答 10。学生(不开思考模式)写道:
Let me list the primes up to 30: 2, 3, 5, 7, 11, 13, 17, 19, 23, 27, 29.
So there are 11. ← 把 27 当成了质数
挑两个位置看两边的分布(数字是我编的,形态是论文的):
- 位置 A,写完「23, 」之后。学生犹豫:29 给 0.55,27 给 0.35;老师看过答案,29 给 0.92,27 只给 0.02;
- 位置 B,整段开头第一个词。学生直接答题,「Let」0.60;老师开着思考模式、又刚读完一份解答,张口更想说「Okay」,给 0.70。
正向 KL 逐项算(每一项是 p_T · log(p_T/p_S)):
位置 A(数学):29: 0.92·log(0.92/0.55) = +0.473 27: 0.02·log(0.02/0.35) = −0.057 其余 ≈ −0.03
KL_A ≈ 0.39
位置 B(风格):Okay: 0.70·log(0.70/0.10) = +1.362 Let: 0.15·log(0.15/0.60) = −0.208 其余 ≈ −0.10
KL_B ≈ 1.05
正向 KL 对学生 logits 的梯度正好是 p_S − p_T:位置 A 把「29」推高 0.37、把「27」压低 0.33,这正是我们想要的批注:「这里该写 29」。可位置 B 的口头禅之争,把「Okay」推高 0.60、「Let」压低 0.45,力度比数学位还大。风格 token 的 KL 系统性地压过数学 token,这是 OPSD 训练不稳的根源,下一节专门治它。
四、两个稳定器
4.1 老师定格在第 0 步。 老师和学生同一套参数,那学生学着学着,老师不也跟着变?论文的做法是把老师固定为初始模型,理由是稳定,并且隐式地起到正则作用:标尺不动,学生就跑不远。实现上一行都不多写:学生用 LoRA 训,老师就是「把 LoRA 关掉」的同一个模型。
# opsd_trainer.py · compute_loss(节选、简化)
outputs_student = model(input_ids=student_ids, attention_mask=student_mask) # LoRA 开:学生
student_logits = outputs_student.logits[:, student_prompt_len - 1 : -1, :] # 只取回答部分
with torch.no_grad(), model.disable_adapter(): # LoRA 关:老师 = 第 0 步的自己
outputs_teacher = model(input_ids=teacher_ids, attention_mask=teacher_mask)
teacher_logits = outputs_teacher.logits[:, teacher_prompt_len - 1 : -1, :]
loss = generalized_jsd_loss(student_logits, teacher_logits, labels, beta=0, token_clip=0.05)
README 里特意标了个感叹号:不用 PEFT,老师就会每步跟着更新,训练可能不稳。这个设计还有个副作用:它天然限制了 OPSD 能走多远。老师永远是第 0 步的模型,学生最多学到「看过答案的初始模型」那个水平。这一点第七节还会回来。
4.2 逐点裁剪:别在口头禅上较劲。 论文统计了训练中每类 token 的 KL(词表见附录:「maybe / okay / wait / so / therefore」算风格词,「prime / factor / integer / equation」算数学词)。以 Qwen3-1.7B 为例:
| 学生 / 老师的思考模式 | 风格词 KL | 数学词 KL | 其他 |
|---|---|---|---|
| 关 / 关 | 0.68 | 0.12 | 0.11 |
| 开 / 关 | 0.51 | 0.10 | 0.17 |
| 开 / 开 | 0.51 | 0.09 | 0.08 |
| 关 / 开(采用) | 0.85 | 0.14 | 0.25 |
风格词的 KL 是数学词的 6 到 15 倍。梯度按 KL 分配,就意味着学生大部分力气花在学老师的口头禅上:「wait」「Okay」这些词学得再像,题也不会更对。(按 Qwen3 的模板推断,最极端的一处在整段第一个位置:老师开着思考模式,张口就想写 <think>,学生却直接写正文,这一处的分歧和数学毫无关系。)
解法很朴素:逐点裁剪。正向 KL 在每个位置是对全词表求和,Σ_v ℓ_{n,v},其中 ℓ_{n,v} = p_T(v)·log(p_T(v)/p_S(v))。裁剪不是裁这个和,而是裁求和之前的每一项:
D_clip = (1/|ŷ|) Σₙ Σ_v min( ℓ_{n,v} , τ ) τ = 0.05(论文说没调过)
代码就是一句 clamp,加在对词表求和之前:
# opsd_trainer.py · generalized_jsd_loss(节选,beta=0 即正向 KL)
student_log_probs = F.log_softmax(student_logits / temperature, dim=-1)
teacher_log_probs = F.log_softmax(teacher_logits / temperature, dim=-1)
# 逐项:p_T · (log p_T − log p_S),形状 [batch, seq, vocab]
jsd = F.kl_div(student_log_probs, teacher_log_probs, reduction="none", log_target=True)
if token_clip is not None:
jsd = jsd.clamp(max=token_clip) # 逐点封顶,而不是先对词表求和再封顶
jsd = jsd[labels != -100] # 只算学生回答部分
loss = jsd.sum() / (labels != -100).sum() # 对 token 取平均
回到刚才两个位置:位置 B 那项 +1.362 被削到 0.05;位置 A 的 +0.473 也被削到 0.05。裁完之后,两个位置的损失变成 −0.03 和 −0.26,是负的。README 专门提醒过这一点:正项被封顶,负项原样保留,和就可能小于零。
裁剪之后,梯度从哪来? 我把位置 A 在裁剪前后的梯度算了一遍。下面的脚本不依赖任何库,可以直接跑:
import math
def summands(pT, pS): # 正向 KL 的逐项 p_T (log p_T − log p_S)
return [t * (math.log(t) - math.log(s)) for t, s in zip(pT, pS)]
def clipped_loss(pT, pS, tau):
return sum(min(l, tau) for l in summands(pT, pS))
def softmax(z):
m = max(z); e = [math.exp(v - m) for v in z]; return [v / sum(e) for v in e]
def grad(pT, pS, tau, eps=1e-6): # 有限差分:loss 对学生 logits 的梯度
z = [math.log(p) for p in pS]; g = []
for i in range(len(z)):
zp, zm = list(z), list(z); zp[i] += eps; zm[i] -= eps
g.append((clipped_loss(pT, softmax(zp), tau) - clipped_loss(pT, softmax(zm), tau)) / (2 * eps))
return g
toks = ["29", "27", "wait", "so", "其他"]
pT = [0.92, 0.02, 0.01, 0.01, 0.04] # 老师:看过答案
pS = [0.55, 0.35, 0.02, 0.03, 0.05] # 学生
for tau in (1e9, 0.05): # 1e9 相当于不裁剪
print(tau, f"loss={clipped_loss(pT, pS, tau):+.3f}",
{t: f"{-g:+.3f}" for t, g in zip(toks, grad(pT, pS, tau))}) # 取负号:正 = 该 logit 被推高
不裁剪:loss=+0.389 29:+0.370 27:−0.330 wait:−0.010 so:−0.020 其他:−0.010
τ=0.05:loss=−0.034 29:−0.044 27:−0.008 wait:+0.008 so:+0.008 其他:+0.036
把位置 B 的数组换进去跑一遍,不裁剪时「Okay」+0.600、「Let」−0.450;裁剪后「Okay」−0.030、「Let」−0.030、「We」+0.040。两点观察:
- 力度被拉平了。 不裁剪时,风格位 B 的最大推力 0.60 压过数学位 A 的 0.37;裁剪后两处都只剩 0.04 上下,谁也压不过谁,这正是论文要的效果:风格词不再霸占梯度;
- 方向也变了。 被封顶的那一项梯度归零,老师最想要的「29」不再被拉高,反而随剩余项的归一化被轻微压低;被压下去的还有学生过于自信的「27」,让出的概率质量流向长尾。也就是说,在分歧大的位置,裁剪不是「温和地学老师」,而是「基本不学,顺手降一点学生的置信度」。τ 越小越如此:README 里 8B 非思考模式用的 τ 是 1e-7,等于把所有正项都封掉,只剩「老师不会这么写的,你少写点」这一种信号。
这段推演是我从代码算出来的,论文只说裁剪「稳定训练、防止崩溃」:1.7B 在 AIME24 上的消融里,不裁剪的曲线几十步内掉回基线以下,裁剪后一路涨到 100 步。用「信任域」理解或许最顺:分歧太大的地方先不学(多半是风格差异),整体信号主要来自师生本就接近的大多数位置,在那里裁剪什么都不改,正向 KL 原样生效。
五、换个角度:它是带稠密奖励的策略梯度
论文附录 D 给了另一副面孔。把每个位置的散度换成只看采样出的那个 token,目标就变成策略梯度,每个 token 领一个自己的分:
rₙ = log p_T(ŷₙ | x, y*, ŷ<n) − log p_S(ŷₙ | x, ŷ<n) ← 看过答案的我,比现在的我更愿意写这个词吗?
∇L = −E[ (1/|ŷ|) Σₙ rₙ · ∇ log p_S(ŷₙ | x, ŷ<n) ] ← 标准 REINFORCE,rₙ 当常数
rₙ 为正,说明这个词老师比学生更认可,推高;为负,老师觉得不该这么写,压低。回到位置 A:学生若采样了「27」,rₙ = log 0.02 − log 0.35 = −2.86,狠狠压下去;若采样了「29」,rₙ = log 0.92 − log 0.55 = +0.51,温和推高。
拿它和两位前辈对照,OPSD 的位置就清楚了:
- STaR(2022)的「合理化」和 OPSD 是同一个念头:做错了,把答案当提示喂给模型,让它倒推一份能得出答案的推理,再拿去 SFT。但 STaR 是硬蒸馏:生成、过滤、整句 0/1 地学,一批全错就一个样本都留不下。OPSD 是软蒸馏、在线的:老师不生成,直接在学生的稿子上给逐 token 的分布,答案错了也有批注;
- Thinking Machines 的在线蒸馏(2025)用的正是上面这个 rₙ(他们叫逐 token 反向 KL),只是老师是另一个更大的模型。OPSD 把老师换成「看过答案的自己」,并把采样 token 版升级为全词表版。
代码里两个版本都在,--use_tinker_loss 切到采样 token 版:
# opsd_trainer.py · 采样 token 版(Thinking Machines 风格)
advantage = (teacher_log_probs_sampled - student_log_probs_sampled).detach() # rₙ,必须 detach
loss = -(advantage * student_log_probs_sampled).mean()
论文表 4 比了两版:全词表版在 AIME25 和 HMMT25 上各高 2 到 3 个点,代价是显存。全词表要存形状为 [batch, 1024, 15 万] 的 logits,学生老师各一份;采样版每个位置只留一个数。
上一篇的那道题到这里有了第五种答案:不摊了。整句一个分要靠 critic 或同学来摊,OPSD 让每个 token 直接从「看过答案的自己」那儿领分。
六、数字说话
设定。 Qwen3-1.7B / 4B / 8B,OpenThoughts 数学子集约 3 万道题;LoRA(秩 64,α 128,挂在全部七个投影上),学习率 5e-6,有效 batch 32,学生采样长度 1024、温度 1.1,正向 KL,固定老师,τ=0.05,只训 100 步。GRPO 基线:每题 8 条采样、最长 16k、训 500 步、不加 KL 项;SFT 基线同样 100 步。评测统一开思考模式,最长 38912 个 token,温度 1.0,每题采 12 次取平均(Avg@12)。
有个细节值得停一下:学生训练时不开思考模式,只写 1024 个 token;评测时开思考模式,允许写近 4 万个 token。1024 token 的短采样上学到的东西,迁移到了长思维链上。至于为什么学生关、老师开,就是第四节那张表:这个搭配下数学词的 KL 最大,论文据此选它。
主结果(Avg@12,AIME24 / AIME25 / HMMT25 / 平均):
| AIME24 | AIME25 | HMMT25 | 平均 | |
|---|---|---|---|---|
| Qwen3-8B | 75.8 | 65.6 | 43.9 | 61.8 |
| +SFT | 72.3 | 64.2 | 42.9 | 59.8 |
| +GRPO | 76.4 | 68.9 | 46.7 | 64.0 |
| +OPSD | 77.8 | 70.8 | 45.8 | 64.8 |
| Qwen3-4B | 74.9 | 66.4 | 42.2 | 61.2 |
| +SFT | 70.2 | 62.3 | 43.4 | 58.6 |
| +GRPO | 75.6 | 68.1 | 44.4 | 62.7 |
| +OPSD | 76.4 | 68.3 | 46.1 | 63.6 |
| Qwen3-1.7B | 51.5 | 36.7 | 23.1 | 37.1 |
| +SFT | 48.4 | 36.3 | 22.7 | 35.8 |
| +GRPO | 51.1 | 38.3 | 23.7 | 37.7 |
| +OPSD | 57.2 | 43.9 | 29.2 | 43.4 |
三个尺寸上 OPSD 都追平或超过 GRPO,SFT 全线负增长。最亮眼的是 1.7B:平均 +6.3 分,GRPO 只挪了 0.6。小模型上 GRPO 更容易一组全错,奖励多样性坍塌更严重;而 OPSD 的老师即便学生答错也能批注,差距就拉开了。
账单。 一步里每道题要生成多少 token:
GRPO 上限 8 × 16k ≈ 128k,OPSD 1 × 1024,相差两个数量级,步数还只是 GRPO 的五分之一(100 对 500)。OPSD 额外的开销是两次前向(学生一次带梯度、老师一次不带)和全词表 logits 的显存。仓库给的数:Qwen3-1.7B 在 4 张 H100 上训 15 分钟;评测反倒更久,每个 checkpoint 要 30 到 50 分钟。
训练曲线(1.7B,README 给的逐步数字):
| 步数 | AIME24 | AIME25 | HMMT25 |
|---|---|---|---|
| 0 | 51.5 | 36.7 | 23.1 |
| 25 | 51.4 | 42.5 | 24.7 |
| 50 | 52.8 | 43.9 | 27.8 |
| 75 | 54.4 | 40.6 | 26.9 |
| 100 | 57.2 | 41.1 | 29.2 |
AIME25 在第 50 步见顶后回落,主表里报的 43.9 正是那个峰值;AIME24 和 HMMT25 则一路涨到 100 步。README 坦率地写了:单 seed,波动难免。
其他消融。 学生采样长度从 1024 加到 4096,成绩没有稳定提升。论文的解释是前面的 token 更要紧:前缀越长,后面的词对老师越可预测,批注也就越稀。也就是说,OPSD 在意的是「开头怎么起手、在哪个岔路口拐弯」,而不是把整条长链写完。
七、边界,以及后来者的追问
论文自己划的边界。
- 没有用上「答案对不对」这个信号。老师批注不看学生最终答案,正确性验证完全缺席,把两者合起来是显然的下一步;
- 有难度阈值。题目超出模型的理解力时,就算把答案摆在面前,老师也「合理化」不出来:看不懂答案的学生,抄答案也没用。论文建议配课程学习,让题目难度贴着模型能力的前沿走;
- 老师定格在第 0 步,天花板就是「看过答案的初始模型」;只做到 8B,再大是否成立是开放问题;
- 非思考模式下曲线不单调:8B 在 AIME24 上第 50 步冲到 49.7(基线 26.4),到 100 步又跌回 38.3。需要早停,且不同尺寸用的 τ 不同(1e-6、1e-7)。
后来者的追问更有意思。 2026 年 8 月,Ichihara 等人的 OP²SD 做了一个釜底抽薪的对照:把老师看的参考解,换成另一道无关题目的解,其余一切不动,学生采样、固定老师、LoRA、逐 token 目标全一样。结果在 9 组设定里 8 组追平甚至超过 OPSD(他们复现的一组 8B 数字:基线 28.5,OPSD 45.0,OP²SD 55.8)。这说明 OPSD 的涨幅不能全归功于「看过这道题的答案」:老师的上下文里多了一份像样的解答,本身就改变了它的行为,比如更像一个正在讲题的人,比如对数学词更笃定。这份「上下文诱导的老师行为」可能才是主力。论文还标着 working progress,但它提醒我们:「特权信息」到底特权在哪,还没完全说清。
同期还有一串近亲,2026 年上半年「在线自蒸馏」几乎成了一个小流派:
- SDFT(Shenfeld 等,和 OPSD 前后脚):老师看的不是参考解而是示范样例,用同样的自蒸馏做持续学习。学新技能的同时大幅减少遗忘,因为在线蒸馏天然不会把模型拽离自己的分布;
- SDPO(Hübotter 等,《Reinforcement Learning via Self-Distillation》):把特权信息换成环境反馈,运行时报错、单测结果,或干脆是同一批采样里做对的那条,让「看过反馈的自己」批注「没看过的自己」。这正是 OPSD 论文结尾畅想的「组自蒸馏」:不要数据集里的参考解,用自己做对的那次当答案;
- 再往后还有一批分析:老师到底该不该固定、正向反向 KL 的几何、「更稠密未必更好」的反例,热闹得很。
八、写在最后
三句话收束:
- OPSD 是一台「对答案复盘」机:同一个模型,看过答案的当老师、没看过的当学生,老师不生成,只在学生自己写的每个 token 上逐字批注;
- 它同时占住在线、稠密、无外部老师三格,用 1024 token 的短采样追平 8 × 16k 的 GRPO,小模型上甩开一截。代价是需要一份参考解,和一个定格在第 0 步的天花板;
- 真正让它跑起来的是两处工程:老师固定为「关掉 LoRA 的自己」,以及逐点裁剪把口头禅上的分歧封顶。后者从代码看,实际是在分歧大的位置「基本不学、顺手降置信度」。
而「看过答案」到底贡献了几分,OP²SD 已经举手提问。下一篇如果有人把验证信号、课程学习和自蒸馏缝到一起,我不会意外。
参考
- Self-Distilled Reasoner: On-Policy Self-Distillation for Large Language Models(arXiv:2601.18734,本文主角;作者博客、代码仓库)
- STaR: Bootstrapping Reasoning With Reasoning(arXiv:2203.14465,「合理化」的出处)
- On-Policy Distillation of Language Models: Learning from Self-Generated Mistakes(GKD)(arXiv:2306.13649,广义 JSD 与在线蒸馏)
- On-Policy Distillation(Thinking Machines 博客)(逐 token 反向 KL 当优势,采样 token 版的原型)
- Learning by Distilling Context(arXiv:2209.15189,把上下文蒸进参数的早期工作)
- Self-Distillation Enables Continual Learning(SDFT)(arXiv:2601.19897)
- Reinforcement Learning via Self-Distillation(SDPO)(arXiv:2601.20802)
- Privileged Solutions or Context-Induced Teacher Behavior? Dissecting On-Policy Self-Distillation(OP²SD)(arXiv:2608.09228,代码)
- DeepSeekMath(arXiv:2402.03300,GRPO 出处);TRL 的 GOLD trainer(OPSD 代码的底座)