后训练(post-training)做着做着,经常又回到看数据、改评分规则、查环境。明明已经选了 SFT、DPO 或 GRPO,为什么还要反复试?因为算法只决定了其中一部分:练什么题、用什么反馈、什么时候换数据、花多少生成预算,仍然会影响这次训练是否有效。
不是没有有效的方法,而是还没有一套换个模型、任务和预算就能照搬的通用配方。 SFT、偏好优化和在线 RL 已有明确的方法与实现;还在快速变化的是它们如何组合,以及数据、反馈和系统怎样配合。造数据是在决定让模型练什么,评估是在检查它到底学会了什么。但两者都不能代替探索、优化和系统上要做的工作。
先看公开配方还在改什么,再用同一个问题的三种示范理解数据怎样影响行为。已经在跑实验,可以直接看环境检查和怎样验证数据改动。
公开配方还在改什么?
不是每出一个新缩写,就值得换整套系统。看几份具体记录,更容易分清哪些问题已经有办法处理,哪些选择仍然要试。

| 工作与版本 | 改了什么 | 不能直接推出什么 |
|---|---|---|
| Tülu 3,2024 首发 / 2025 v3 | §5.3 比较新问题、同题增加不同回答对,以及待训练模型自己生成的候选(candidate)回答 | 数据更多不等于有效信息更多;一个模型的数据配比不保证适合另一个 |
| DAPO,2025 v2 | §3.2 动态筛选有组内奖励(reward)差异的采样 | 全错的题不是永远学不会;被筛掉的回答也已经花了生成成本 |
| DR Tulu,2025 首发 / 2026 v3 | §3 随训练更新长篇回答的评分细则(rubric),利用搜索证据与当前回答 | 更细的评分不等于 judge 不会错;附录 A 仍报告训练奖励与外部评估的差异 |
| Rufus-Air,2026-09 v2 | §3.2–3.3 中,reasoning 阶段在线筛题,coding 阶段则预筛容易题并保留预筛时全错的题 | 同一报告也没有处处采用同一规则;§1 明确部分判断来自训练经验,而非完整消融(ablation) |
这些例子说明,训练数据不总是一份事先做完的文件;反馈与任务选择也可能跟着模型改变。这里是对上述工作的归纳,不是说所有项目都需要动态换题或动态换奖励。后两篇作为进一步阅读,不因为更新就自动进入AI 编年史的主干。
用一个小例子看这种变化:同一道可核验题采样四次,奖励 0, 0, 1, 1 时,减去组平均还能分出哪些尝试更值得鼓励;全对或全错时,组内优势全为零。完整算例和零方差(variance)的处理见组内信号什么时候会消失。
模型变强后,一道题可能更经常全对。反过来,一组全错也不能证明它永远学不会。因此题库没变,学习信号也可能变;但“删掉所有全错的题”并不是通用答案。可以比较补示范、增加中间任务或调整采样,同时核对判分,并记录被丢弃的生成成本。这个例子只解释组内信号,不是模型效果实验。
如果固定数据加 SFT 已经解决了一个边界清楚的小任务,就不必为了流程复杂再加 RL。反过来,若卡在探索、信用分配或训练稳定性上,也不能只靠多洗几遍数据。具体见为什么 RL 还是难训。可自动化的格式校验和环境测试应该自动化;真正要反复实验的是那些会改变学习行为的选择。
同一个问题,不一定应该给同一个答案
假设我们在训练一个根据资料回答问题的助手。用户问:“报名最晚到哪天?”
- 资料明确最新通知写着周三截止回答“周三”,并引用这份通知。这里练的是从资料中找到答案。
- 资料冲突两份通知分别写周三和周五如果无法判断哪份有效,就说明冲突并核实。不能挑一个日期装作确定。
- 资料缺失只有报名入口,没有截止日期说明还缺哪项信息,请用户补通知,或在允许时继续检索。不是直接编一个日期。
如果训练集几乎只有第一类,模型练到的主要就是“找到一个日期,然后回答”。我们希望它遇到冲突时会核实,但训练中可能根本没认真教过这件事。
还有一种更隐蔽的情况:teacher 看到了完整通知,student 的输入却只有报名入口。把 teacher 的“周三截止”直接当作标准答案,会奖励 student 给出一个无法从当前资料得到的结论。这个日期可能碰巧是真的,但它不是我们想要的、根据证据回答的习惯。
所以,判断一条示范好不好,不能只读最后一句答案。要把输入、可用工具、答案和依据放在一起看。这里的问题不是“没见过就一定不会”,而是这批训练信号到底在鼓励什么;预训练(pre-training)知识和泛化能力仍然会影响结果。
数据里其实放了四种选择
“数据代表了什么?”可以先理解成:它把我们对任务的设想,变成模型实际能接触到的例子和反馈。
| 我们做的选择 | 落到数据里是什么 | 不检查会怎样 |
|---|---|---|
| 希望模型处理哪些情况 | 问题来源、语言、难度、证据是否完整 | 只练最容易收集的题,重要场景反而很少 |
| 什么行为值得鼓励 | 示范、偏好标签、评分规则、可执行测试 | 把“写得长”误当作“解释得好” |
| 哪些情况更重要 | 采样比例、重复次数、样本权重、有效 target token | 大量重复样本或长答案占据训练 |
| 这个结论是怎么来的 | 来源、时间、资料版本、标注者或生成模型、采样策略 | 新旧资料混用,坏结果无法追查 |
偏好标签尤其不是脱离场景的“正确答案”。谁在标、按什么标准标,都会影响它的含义。InstructGPT 的示范和比较数据来自特定标注流程,论文也讨论了这些偏好不能代表所有人。InstructGPT,2022,§3、§5.2
用户行为也一样:没点某个结果,不一定是不喜欢。这个问题在反馈怎么变成训练目标里展开;这里先记住,观察到的记录和我们想优化的目标,中间需要解释,不能直接画等号。
为什么不改算法,结果也可能差很多
先只看一种明确的 SFT 设置:每条样本内部,对有效答案 token 求平均;样本之间再按权重求和。
$$ \begin{aligned} \ell_i(\theta)&=-\frac{1}{|T_i|}\sum_{t\in T_i}\log p_\theta(y_{i,t}\mid x_i,y_{i,<t})\\ L(\theta)&=\sum_i\alpha_i\ell_i(\theta),\quad \alpha_i\geq 0,\quad \sum_i\alpha_i=1. \end{aligned} $$
这里 $x_i$ 是模型能看到的输入,$y_i$ 是示范答案,$T_i$ 是参与 loss 的位置,$\alpha_i$ 是样本权重。每条样本必须有至少一个有效 target。这只是本节选定的归一化方式,不是所有 trainer 的默认行为。
改输入,会改变模型可以依据什么回答;改答案,会改变它被要求模仿什么;改 mask,会改变哪些 token 受到监督;改采样比例,会改变哪些错误更常推动参数更新。算法名字都可以不变。
例如,两条样本分别有 1 个和 3 个有效 token,平均 loss 是 0.2 和 1.0。样本等权平均是 0.6;按所有有效 token 平均则是 0.8。后者给第二条样本更大权重,不是单纯换了一种显示 loss 的方式。多卡和梯度累积也必须保持你选定的分母,见数据与训练目标。
这也解释了为什么“再加十万条”还不够说明问题:加的是什么,会挤掉哪些样本,在相同训练预算下被看到多少次?这些才决定这次改动的含义。
洗完更整齐了,也可能把重要情况洗没了
沿用报名助手。为了方便手算,假设有 100 条示范,其中 90 条资料完整,10 条资料缺失。你加了一条规则:“太短的答案不要。”
筛完后,完整资料的示范保留了 81 条,缺资料的只保留了 2 条。因为“这里没写截止日期,能补一下通知吗?”恰好比较短。
from fractions import Fraction
before = {"supported": 90, "missing_evidence": 10}
after = {"supported": 81, "missing_evidence": 2}
before_share = Fraction(before["missing_evidence"], sum(before.values()))
after_share = Fraction(after["missing_evidence"], sum(after.values()))
assert before_share == Fraction(1, 10)
assert after_share == Fraction(2, 83)
print(f"Before: {float(before_share):.1%}; after: {float(after_share):.1%}")
输出是 Before: 10.0%; after: 2.4%。如果在剩余样本上均匀采样,模型练习“缺信息时怎么办”的机会就少了。这个算例证明的是数据占比变化,不是模型准确率一定下降多少。
怎么处理?先抽查被删掉的短答案,区分敷衍回答和合理追问;把明显错误的标签修好或移除,再检查每类场景保留了多少。必要时补数据或重采样,但不要为了凑比例留下错误答案,也不要把 50:50 当作普遍最佳配方。过度增加“信息不足”的示范,同样可能让模型在本来能回答时也推脱。
清洗后的总行数、重复率、平均长度值得看,但还得加一张按场景拆开的保留率表。否则你只能知道删了多少,不知道删掉了什么能力所需的练习。
SFT、偏好学习和 RL,要看的数据不完全一样
| 阶段 | 训练接触到什么 | 优先检查什么 |
|---|---|---|
| 自回归预训练 | 文本及其下一个 token | 来源、覆盖、重复、语言比例、污染与使用许可 |
| SFT | 输入和示范输出 | 答案是否被输入支持,模板、mask、截断是否正确 |
| 离线 DPO | 同一个输入下的偏好回答对 | 比较标准是否一致,偏好是否只是长度或格式差异 |
| 在线 RL | 问题、当前策略生成的轨迹、环境反馈和奖励 | 任务是否有学习空间,评分是否可信,失败是什么原因 |
离线 DPO 的 chosen 表示“这一对里更受偏好的回答”,不保证它完全正确。两个答案都错时,相对偏好仍然可以存在;如果任务要求事实准确,构造和审核回答对时就要另查事实。DPO,2023,§3–4
RL 更不能只盯着最初那份题库。模型变了,采样到的回答、工具调用和失败方式也会变。一个训练批次的含义,还取决于当时的策略版本、采样设置、环境和评分规则。
比如,把代码题的成功定义成“通过测试”,测试有没有覆盖边界条件就很重要。程序通过一个不完整的测试集,不等于真正完成了任务。DeepSeek-R1 的规则奖励包括答案核对和代码执行等;“不需要人工写出每条推理示范”并不等于“不需要问题和可靠的反馈”。这里参考的是论文 v2 的奖励设计,不把它当成所有 RL 任务的配方。DeepSeek-R1,v2,§2.2 只奖励答案时回答为什么会越写越长,见长思维链是怎样训练出来的。
低分轨迹也不一定是脏数据。模型给错答案,可能正是 RL 需要纠正的尝试;但工具服务宕机导致失败,是另一回事。把二者混成同一种负奖励,可能会让模型学会回避本来有用的工具。是否重试、跳过还是计入失败,需要根据任务定义,并保留失败原因;不能事后只留下成功尝试。
配环境也有两层含义
一层是让代码能跑:驱动、PyTorch、CUDA、attention 后端、训练框架和依赖版本。另一层是保证“跑出来的东西还是我们要做的实验”:模型看到了同样的输入、算了同样的目标、在同样的任务规则下得到反馈。
| 改动 | 看起来只是配置 | 可能实际改变了什么 |
|---|---|---|
| 换 tokenizer 或 chat template | 数据还是那些对话 | 特殊 token、角色边界、被截掉的内容 |
| 换 packing 或 loss 选项 | 只是想提高吞吐 | 样本间能否互相看见、哪些位置参与监督、分母 |
| 改多卡与梯度累积 | 只是多用几张卡 | 实际 batch、梯度归一化、数据顺序 |
| 换 RL 工具或测试环境 | 接口仍能调用 | 状态是否重置、超时含义、评分和成功条件 |
例如,截至 2026-10 的 TRL v1.16.0,assistant_only_loss=True 仍要求 chat template 用 {% generation %} 和 {% endgeneration %} 标出 assistant 输出;对 Qwen3 等已知模型家族,TRL 会自动换上打过补丁的训练模板。TRL SFT 文档,v1.16.0 换上的训练模板不一定和推理时的模板渲染得一样,例如 Qwen3 的训练模板会在每一轮 assistant 回复里都保留思考块。TRL Chat Templates,v1.16.0 所以不能只看配置项写了 True,就认为标签已经正确。应该拿一条样本解码,检查实际参与 loss 的位置。
固定随机种子也不是跨机器、跨版本结果相同的保证;PyTorch 明确说明了这一限制,2026-10 对照 2.14 文档,这句说明没有变。PyTorch 2.14:Reproducibility
这些工作不必每次从头做。锁定依赖、保存数据与模板版本、留一小组固定样本做 smoke test,可以减少反复修环境的时间。具体要检查哪些输入和梯度,接着看从一条示范到训练 batch。
高质量,不等于只留漂亮答案
一个流畅的长答案可能没有依据;一句短追问可能正好解决问题。难题不一定值得保留:如果题本身有歧义、评分又不可靠,模型学到的可能只是噪声。反过来,把训练集筛成全是容易题,也很难练到需要改善的能力。
实际审核时,可以把“是否正确”和“是否值得训练”分开问:
- 先看能不能用。 来源和使用许可是否清楚,有没有隐私,输入能否支持标签,评估题有没有混进来?
- 再看补了什么。 是新场景、新错误,还是同一个模板换了几十种说法?模型已经会的部分和还不会的部分,各占多少?
- 最后看取舍。 更严格的筛选提高了哪部分可信度,又损失了哪些语言、难度或少见场景?
合成数据也要这样看。Teacher 生成的是待审核样本,不是天然正确的标签。能用计算器、代码测试或原始资料核验的,先核验;主观偏好要有明确标准和抽查。用同一个 judge 筛训练数据、再用它证明效果好,还要警惕模型只是更会迎合这个 judge;验证器的漏洞怎样卡住“生成、验证、再训练”这条回路,见自我改进:为什么卡在验证器。
LIMA 常被用来说明少量精选示范也可能有用。但它的主实验与消融有特定基座、任务和评价方式,不能推出“任何后训练只要 1,000 条”。这里更值得借鉴的是把数据质量、覆盖和数量分开比较,而不是记一个神奇的样本数。LIMA,2023,§2、§5
怎么证明这次改数据真的有用
假设要验证“补充缺资料示范,能减少无依据回答”。先固定一份没有训练集近重复、按问题或资料家族分开的评估集,再比较原始数据和修改后的数据。
| 要控制或记录的量 | 为什么 |
|---|---|
| 基座、训练目标、优化器与主要超参数 | 别把模型或算法改动也算成数据收益 |
| 实际训练 token、有效 target token、训练步数与算力 | 同样行数不代表同样训练量;预算不同要单独报告 |
| 资料完整、冲突、缺失等分组结果 | 少编答案但多拒答,不一定整体更好 |
| 多次运行的波动、人工抽查、错误类型 | 不把随机变化或 judge 偏好当成稳定提升 |
| 数据获取、标注与维护成本 | 离线分数之外,还要知道这套改法能不能持续 |
可以先做同等训练 token 或同等算力预算的对照,并说明采用哪一种;不同长度分布下,二者未必能同时严格相等。如果只想增加某类示范,先只改这一件事。用开发集反复调整,把最终测试集留到最后,别每筛一轮数据都拿它挑配方。
有价值的交付不只是“清洗了几百万条”。更清楚的说法是:发现哪类监督有问题,改了哪条选择规则,保留和删除了什么,在哪些未见场景上变好,哪些代价和问题还在。没有测到改善,也要把这个结果留下。
所以,后训练里忙数据并不奇怪。真正值得追问的是:今天做的这步,是单纯让文件能读,还是让模型更有机会学到我们要的行为?前者尽量自动化,后者需要实验来回答。
接着看哪里
- 反馈怎么变成训练目标:行为、偏好和监督不能直接画等号。
- SFT:一条对话怎样变成训练信号:从条件概率到 mask 和训练更新。
- 后训练工程实践:数据流水线、多卡、checkpoint 与评估怎样接起来。
本页术语 7
- 后训练 post-training
- 预训练之后为特定任务和行为做的所有训练
- 候选 candidate
- 召回阶段捞出来、等待精排挑选的内容
- 奖励 reward
- RL 里指导策略更新的标量信号
- 评分细则 rubric
- 不同分数对应什么可观察的表现
- 消融 ablation
- 去掉一个组件再测一次,用来判断它到底有没有贡献
- 方差 variance
- 估计量的波动幅度;重要性加权最容易在这里爆炸
- 预训练 pre-training
- 先用大量数据学习通用表示和能力,再适配具体任务