ROSE / OPD 蒸馏实验的完整实现与训练框架

三个 domain(RLVE 单轮推理、SciWorld 多轮 agent、DAPO-Math)上对比三种蒸馏方式 (teacher-SFT / on-policy distillation / online ROSE)的全部代码。

配套的 checkpoint 与数据在: OPD-dq · ROSE-dq · SciWorld-dq · data-dq

目录

frameworks/
  verl_rose/      ROSE 全部线用的 verl(含 recipe/rose/rose_agent_loop.py)
  verl_opd/       OPD 全部线用的 verl —— 与上游 thunlp/OPD 的计算路径逐字节等价
  verl_sft/       teacher-SFT 用的 verl
  agentgym_rl/    AgentGym-RL —— 本项目里只用于 SciWorld 评测, 未用于训练
  trinity/        Trinity —— SciWorld 的 ROSE/OPD 八条线是它训的
sciworld/
  impl/           自写的多轮 ROSE/OPD 实现(不依赖上面任何框架)
  chains/         编排脚本
  trinity_configs/  Trinity 侧的 workflow 与 yaml
  agentgym_eval/  AgentGym 口径的 200 题评测
launchers/
  rlve/ dapo/ olmo/
eval/             AIME25 / HMMT25 / RLVE 评测
docs/             ENV_NOTES.md —— 跨家族 ROSE 的环境硬约束
tools/            归档上传用的脚本

三种方法

teacher-SFT 教师采轨迹, 学生离线模仿。

OPD(on-policy distillation)教师对学生自己采出来的 token 打分, advantages = teacher_logprobs - student_logprobs, adv_estimator=token_reward_direct, 不做归一化。

ROSE 学生写 K 个 token 的前缀(mask=0), 教师从那里接着写 t 个 token, CE 只打在教师 token 上(mask=1)。学生学的是"我走到这个状态之后, 老师会怎么继续"。 recipe/rose/rose_agent_loop.py 里有完整说明。

SciWorld 有两套并行实现

实现 位置 产物
Trinity frameworks/trinity + sciworld/trinity_configs SCIENCEWORLD_{OPD,ROSE}/ 八条线
自写多轮 sciworld/impl/online_{rose,opd}_sciworld.py 老格式 log.jsonl + step_N/(checkpoint 已清, 脚本保留)

sciworld/impl/ 那套不依赖 verl 也不依赖 Trinity, 是从头写的: 学生走 N 轮 → 按 turn 边界构造 loss mask → 教师接管后续轮次 → 只在教师 turn 上算 CE。 多轮的 mask 构造见 online_rose_sciworld.py; OPD 侧的 forward_kl_topkonline_opd_sciworld.py

AgentGym-RL 只用于评测(sciworld_agentgym_eval.py, 200 题 / ≤20 轮 / greedy / nothink), 本项目没有用它训练过。

结果

RLVE (16k, n=8)

line avg@8 pass@8 解出
基线 未训练 0.0333 0.1111 20
official OPD bf16 (140步) 0.0458 0.1444 26
OPD bf16 mini16 (140步) 0.0556 0.1722 31
OPD fp32 (105步) 0.0694 0.1833 33
OPD fp32 (132步) 0.0667 0.1833 33
official ROSE (140步) 0.0701 0.1778 32
official ROSE seed1 0.0729 0.1889 34
teacher-SFT n4 bs256 0.0556 0.1500 27

fp32 那条与 official bf16 只差 dtype(train/mini/n、lr、resp、更新次数全同)。 上游 on_policy_distillation.sh 默认就是 fp32, bf16 是早期的偏离 —— lr 1e-6 × advantage 10⁻² 的每步相对更新量低于 bf16 的分辨率, 会被舍入吞掉。

SciWorld (AgentGym 口径, 200 题, ≤20 轮, greedy, nothink)

Score Success Pass(>0)
Qwen3-1.7B 基座 0.0479 0.0000 0.1650
OPD lr1e-6 0.0421
OPD lr1e-5 0.1931
teacher-SFT 0.2077 0.0450 0.4100
ROSE 0.3127
Qwen3-32B 教师 0.4346 0.1100 0.9350

ROSE 在 SciWorld 上的优势(+0.105 over SFT, +0.12 over OPD)远大于 RLVE 上的(+0.016 / +0.002)。

DAPO-Math 上的 ROSE 是负结果

AIME25 / HMMT25 avg@16, thinking, temp0.7 / top_p0.95 / max_new 31744:

AIME25 HMMT25
Qwen3-32B 教师 0.7125 0.5042
Qwen3-4B 未训练 0.6521
ROSE←32B 30步 (4B) 0.6125
Olmo-3-7B 基线 0.5917 0.4167
ROSE←32B 30步 (Olmo-7B) 0.5750 0.3854
ROSE←32B 220步 (Olmo-7B) 0.5583 0.3688

四组独立观测同向, 且 Olmo 从 30 步到 220 步(跑满一个 epoch)继续下降 —— 排除欠训。 训练本身也早停滞: ce_loss 从 31 步起斜率 −0.00012, grad_norm 降到 0.18。

诊断: TEACHER_MAX_TOKENS=1024, 而实测 ce_target_tokens960-1016 (占预算 94-99%)—— 教师几乎每条都是写到预算耗尽被截断, 从不自己收尾。 配合学生 16000-18600 token 的推理链, 监督只覆盖 token 1024-2048, 约 6%。 学生学到的是"在思考中段接着往下写", 从没被教过怎么收敛到答案。 表现是输出方差变大而能力边界未动: pass@16 靠多蒙中一题涨(两个 benchmark 各 +1 题, 其中一题是 0/16 → 1/16), 而 avg@16 与 pass@1 都下降, 截断率上升。

要检验这个诊断, 应该把 K 提到 4096-8192、teacher 预算给到 2048-4096, 让切点落到推理链中后段。

跨家族 ROSE(Olmo-3-7B ← Qwen3-32B)

学生 vocab 100278 / 教师 151669, 完全不同的词表。rose_agent_loop 有现成通路 (TEACHER_TOKENIZER 非 null 即启用): 学生前缀 ids → decode 成文本 → 套教师的 chat template → 教师续写 → 取回 text → 用学生的 tokenizer 重新 encode。 实测两边对拼接缝文本的 round-trip 都无损, 教师续写语义连贯且不会重复吐 <think>

环境上的硬约束(vLLM 版本被夹死在 0.11.0、NCCL 只能关 NVLS、verl 序列打包硬依赖 flash_attn 等)见 docs/ENV_NOTES.md —— 每一条都对应一次失败的启动。

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support