2B模型从5.5%到34.4%,500条agent轨迹就够?先看数据怎么切
Hugging Face TRL发布一个post-training示例:Qwen3.5-397B在OpenCode里当老师跑数据分析任务,留下正确轨迹,再SFT Qwen3.5-2B。2B在未见任务上从5.5%升到34.4%,接近老师一半。但held-out怎么切,直接决定这个数字有多可信。
Hugging Face TRL 放出一个 post-training 示例:让 Qwen3.5-397B-A17B 当老师,在 OpenCode 里跑数据分析任务,把正确轨迹留下来,再对 Qwen3.5-2B 做 SFT。
结果先摆出来:在 held-out 任务上,2B 从 5.5% 升到 34.4%,老师是 74.2%。流程视频在下面。
任务来自 SmolDataEnvs。它们是真实 Kaggle 数据集上的数据分析题,比如“多少比例的比赛以平局结束”。每题是一个 Harbor task:问题、数据集文件、标准答案,以及一个确定性 grader,给 agent 写出的 answer.txt 打 1 或 0。训练集 5000 题,eval 144 题。
Agent 是 OpenCode,一个开源 coding agent,带 bash、read 等文件工具。OpenEnv 把它放进 Hugging Face Sandbox 跑任务,并记录每次模型调用:发出去的消息、提供的工具、模型的回复。训练数据就是这些记录。
整套流程分 5 步:
- 准备任务。
- 老师模型跑训练任务,保留每条 rollout。
- 只留下做对的 rollout,构建 SFT 数据集。
- 用 TRL 的
SFTTrainer微调学生模型。 - 用 vLLM 服务学生模型,在 eval/test 上跑分。
老师模型走 Inference Providers,生成轨迹的 Job 不需要 GPU。它在干净训练任务上解出 78%,中位 6 轮,每题约 2 分钟。每条轨迹约 10k token,大头是 OpenCode 的 system prompt 和工具 schema,真正参与训练的只有 4% 到 8%。约 500 条轨迹,单张 H200 上训练 3 个 epoch,大约 16 分钟。assistant_only_loss=True 把 loss 放在 assistant 轮次上,学生学老师的工具调用和回答,不学工具输出。超过 16k token 的轨迹直接丢掉,不做截断,因为截断会切掉最终答案。

| 模型 | Eval 144 | Test 163 |
|---|---|---|
| Qwen3.5-2B | 7.6% | 5.5% |
| Qwen3.5-2B-SmolDataEnvs-SFT-500 | 33.3% | 34.4% |
| Qwen3.5-397B-A17B 老师 | 71.5% | 74.2% |
关键细节在数据切分。原文说,train/eval/test 是按任务抽的,不是按 Kaggle 数据集抽的。144 个 eval 任务里有 122 个、250 个 test 任务里有 185 个,用了某个训练任务也用过的 Kaggle 数据集。学生可能已经见过这些文件、列名和结构。
有网友 Sagar Tanur 在回复里追问:held-out 任务怎么切?如果它们和 solved 轨迹来自同一批 repo,涨幅里可能有一部分是模型学会了 repo 布局,不是 agent 能力变强。Deep 也提醒,检查 held-out 任务是否来自不同 repo。
这套示例的处理方式是加 --exclude-datasets-of 过滤,跳过那些和 eval split 共享 Kaggle 数据集的训练任务,5000 题留下 2879 题。最终评估只用 307 个任务,它们的 Kaggle 数据集没被任何训练轨迹用过,包括 144 个 eval 任务和 163 个 test 任务。
不做这个过滤会怎样?原文给了对照:学生模型在无共享数据集的 eval 任务上 17.3%,在共享数据集的任务上 42.4%。差距很直白,模型先认文件,再谈解题。
轨迹数量也有边际效应。473 条轨迹时 eval 33.3%、test 34.4%;963 条时 32.6%、38.7%;2238 条时 36.8%、38.7%。大部分收益来自前几百条,后面多加几倍数据,只多 3 到 4 分。144 和 163 个任务上,几个点的差异在噪声范围内。
这套 SFT 的定位是 RL 的起点。2B 在十题里能得分的不到一题,三分之二的任务它根本不写答案。老师先教会它用工具、什么时候该回答,RL 再从一个能答大多数任务、能解三分之一任务的模型开始。这里的 SFT 是 sequence-level distillation,学生只模仿老师的文本,拿不到老师 logits。TRL 的 on-policy distillation 训练器,比如 AsyncDistillationTrainer,会基于学生自己的样本、用老师的逐 token 分布来训练,需要把老师服务在学生旁边。
想直接复现,可以跳到第 4 步,用已发布的轨迹:--dataset sergiopaniego/smoldataenvs-opencode-traces --dataset-config 500,也可以选 1k 或 full。完整脚本和命令在 Hugging Face TRL 的示例里:https://github.com/huggingface/trl/tree/main/examples/sft_agent_traces 。
发布时间: 2026-11-11 01:28