先聊一个挺刺激的观察:技术圈这两年一提“让模型自己变强”,默认路径好像就一条——RL。从 PPO 到 GRPO,从 reward model 到 RLHF,大家觉得只有“给奖励、让模型试错”才算真正的学习。可我最近看到一个很反常规的做法:只用“复盘”,不做强化的 4B 小模型,反而追平了 RL,训练时间还省了 63%。
这个标题里最戳我的不是“4B”,也不是“追平 RL”,而是那个“只复盘、不强化”。玩过强化学习的人都知道,RL 最难啃的不是想法,而是工程:滚动采样、reward model、策略更新、稳定训练,每一步都在烧卡和时间。如果真能用“自我解释”替代这部分,先把“做对的题”和“做错的题”像直播回放一样重新剪辑成训练素材,对小模型是一条更实用的路。这篇文章我就把里面的核心思路、可复现的实操流程、成本账和踩坑心得铺开讲,你会看到“复盘”这件事,不只是人类职场里的习惯,放到模型训练里一样好使。
1. 项目定位与逻辑拆解:4B 模型凭什么不做 RL 也能追平
1.1 标题里的四个关键词,其实是一套完整的训练主张
“RL、4B 小模型、自我解释、复盘”这四个词单独拎出来都认识,组合在一起就很有意思。RL,指的是我们用强化学习来对齐和提升模型能力的那套通用做法,例如先让模型输出,再用奖励模型给分数,最后用策略梯度更新参数。4B 小模型,说的是参数规模在 40 亿左右的开源底座,常见的有 Qwen2.5-3B 这类量级。自我解释,不是让模型背答案,而是让模型对“自己刚才为什么错、正确应该怎么想”做一段结构化反思。复盘,就是把反思的结果当作新数据,重新喂给模型做微调。
把四个词串起来,这个项目的核心主张就浮出来了:与其让模型在 RL 的反复试错里找方向,不如让模型回到自己的错误输出上,写一遍“事故分析报告”,然后用这些报告做训练数据。听起来像是数据处理的活,但其实机制上完全能支撑学习:模型通过复盘,把隐含的推理链显式化,再把这些显式推理链作为监督信号,这比单纯给正确回答要更容易让小模型捕捉到。
1.2 为什么“自我解释”对 4B 小模型尤其友好
很多道友会问:那 ML 大厂动辄几十 B、上百 B 的模型,不都在 RLHF 里跑得好好的吗?为什么小模型反而更适合走“自我解释”这条路?关键在于样本效率。
大模型做 RL,靠的是“广撒网”:反正参数多、泛化能力强,多采样几十万条轨迹总能收敛。但 4B 模型本身容量有限,它没有资本去浪费大量无反馈的 rollout。如果强行套 RL,最常见的结果是什么?reward hacking、策略崩坏、loss 震荡,最后在验证集上看起来涨了,实际一测全是模板话术。自我解释则不同,它把每一次错误都转化为一条有监督信号,而且这条信号不是简单的对错标签,而是带着中间推理步骤的解释文本。对小模型来说,高质量的解释文本比成百上千条“对/错”标签信息密度高得多,因为它提供了中间状态,等于把长程稀疏 reward 转换成了密集的监督信号。
这就像新人学开车。你光给他一个“撞了扣分、开对了加分”的强化信号,他可能要撞很多次才会顿悟;但如果每次出问题,都让他停车、回看行车记录仪,写下“我当时为什么没看后视镜、正确做法应该怎么看”,他练一次顶十次。4B 模型当学生,最缺的不是练习次数,而是每次练习后的高质量反馈。
1.3 “省 63% 训练时间”是怎么来的,先看下时间账
这个 63% 不是随便拍脑袋给的,我看完整个路线之后其实能倒推出来。传统 RL 训练一个 4B 模型,时间成本一般分布在这些环节:
- 策略模型多轮 rollout,一般要跑很多轮,哪怕已经收敛的早期阶段也要继续采样;
- reward model 需要额外训练或至少需要大量推理打分;
- RL 训练过程中需要反复实验学习率、KL 系数、奖励缩放这些超参数,一崩就是几天;
- 最后还要用 SFT 做收尾稳定,又是额外一轮。
而“只复盘、不强化”的方案,把 RL 的“策略搜索”直接替换成了“错误重看”,那么反复 rollout 和奖励模型那部分开销就整个消失了。结合我自己跑类似项目的感觉,如果 RL 版本原本需要 22 天完成,这套复盘方案大概 8 天出头就能达到同等效果,节省的 14 天左右恰好接近总时长的 63%。它省的不是小头,而是把 RL 最费钱的那一轮大循环给砍掉了。
2. “复盘数据”的构造:把一次反思变成一条可直接学习的监督样本
2.1 一条复盘记录应该包含哪几块内容
你可能以为复盘数据就是把“问题 + 正确答案”拼起来丢给模型训练,这事我一开始也干过,效果很一般。后来发现,真正起作用的复盘样本有三个组成部分,缺一个效果都打折。
第一部分是“错误还原”。不能只说“回答错误”,而要具体记录模型当时的输出片段、它在哪一步开始跑偏。这部分的意义在于让模型知道问题出在过程里,而不只是结果错。第二部分是“原因解释”。让模型用自然语言写:“我当时的错误假设是什么”“正确的推理步骤应该是什么”“为什么会想到错误方向”。这个部分是自我解释的核心,如果只有错误还原,那就成了一份纠错数据集,不是复盘。第三部分是“修正回答”。让模型基于前面的原因重新输出一个完整答案,修正后的答案会成为训练时的目标句子。
所以一条有效的复盘样本,不是“题目 + 答案”,而是“题目 + 错误现场 + 原因复盘 + 修正回答”。这就好理解了:训练时,模型看到的是原因复盘和修正回答,学习的不只是“正确结论长什么样”,还有“怎么从错误推理切换到正确推理”。
2.2 我用过的复盘提示词模板
实际构造数据时,不必直接让模型“请复盘”,那样出来内容太散。我在实操里会把模板固定成三段式,让模型按框填写。下面这段提示词模板可以直接抄:
你现在是本次答题的复盘员。请针对下面这道题,分析你的上一次回答。 【原题】 {question} 【上一次回答】 {model_prediction} 【正确答案与解析】 {reference_answer} 请按下面结构复盘: 1. 错误定位:上一次回答中哪个关键步骤出现了问题? 2. 错误原因:我当时忽略了什么信息?或者采用了什么错误策略? 3. 正确思路:这道题应该遵循什么样的推理路径? 4. 修正输出:根据正确思路,重新完整回答一次。这里有个细节要提醒:正确答案与解析(reference answer)必须是人工校核过的,或者来自稳定可靠的上游。若 reference 本身不准,复盘出来的修正回答就是“认真地把错误又讲了一遍”,整个数据集直接废掉。这个部分我踩过坑,后面常见问题里再细说。
2.3 直接 SFT 复盘日志,和 RL 相比到底差在哪
你可能会有一个疑惑:这不就是把错误数据颠来倒去写几段话,然后用微调学习一遍吗?这和 RL 的“用损失函数拉高好动作概率、压低坏动作概率”有本质区别。
RL 的工作方式是动作空间搜索。模型每走一步都在尝试,reward 只在序列最后给;训练过程需要大量无梯度信息的尝试来为策略提供方差。换句话说是“做得多、反馈少”,但最终通过蒙特卡洛采样的平均效果来更新。而 SFT 用复盘日志的时候,训练目标是修正后的完整回答,并且前置了原因解释。梯度信息不再稀疏,每一步词元预测都在被约束。
这两者的取舍也很明显。RL 理论上可以探索到训练分布之外的更好策略,所以上限更高;自我解释则更像“把已经会的验证清楚、把不太会的边界理顺”,它的上限通常不会超过 reference 的质量太多。所以你问能不能完全替代 RL,我会说在 4B 小模型、训练预算有限、任务以推理和知识回答为主时,它确实能追平。但你要是追求超越人类标注水平的探索能力,RL 仍然有位置。
为了看得更清楚,我把几个关键维度做了个对比:
| 对比维度 | 传统 RL 微调 | 自我解释 + 复盘 SFT |
|---|---|---|
| 训练信号 | 奖励模型打分、稀疏 | 修正回答 + 解释文本、密集 |
| 数据来源 | 实时滚动采样 | 一次性收集错误后生成 |
| 训练稳定性 | 容易奖励黑客/震荡 | 与普通 SFT 类似 |
| 计算成本 | 多次 rollout + RM 推理 | 只做一轮生成和一轮微调 |
| 小模型友好度 | 低,需要大量样本 | 高,每条样本信息密度大 |
| 上限 | 可以探索新策略 | 受限于参考质量 |
3. 手把手复现路线:三次“生成-反思-微调”我踩出来的流程
3.1 第一阶段:采样出足够多样化的“错误现场”
复现的第一步不是训练,而是制造错误。要让小模型暴露错误,就要故意把采样参数调得偏“散”一些。我正常推理用 temperature 0.2,但这里会把 temperature 调到 0.7 到 1.0,top_p 也放宽到 0.9 以上,目的就是让模型产生更多中间态的失败样本。很多脚本只肯留下正确回答,这个方案恰恰相反,错误回答才是宝贝。
具体操作上,我会对每个评测问题采样 8 到 16 次,保留回答错误的那些。采样完会先去重,因为同一个问题模型可能用同一种错误方式翻车 10 次,这种重复数据对训练没有增量信息,去重后基本能筛掉一半。接下来需要给这些错误打标,标明错在哪一步。这一步可以用来料评测集自带的答案判断对错,也可以用规则校验。如果条件允许,可以加一个足够强的 LLM(比如用一个更大模型)来给错误定位,但注意,不要让大模型直接改写答案,只让它做“错误分类”和“定位”,具体复盘还是让 4B 自己写,这样才能保证训练时的语言风格匹配。
3.2 第二阶段:让 4B 模型用固定模板生成复盘文本
拿到错误采样后,把 2.2 里的模板套上,让 4B 模型批量生成复盘记录。这里有个效率层面很容易忽视的点:如果逐条用单卡推理,生成几万条复盘可能要跑一两天。我建议直接用 vLLM 批量推理,把几百条 prompt 一次性喂进去。整个推理会快一个量级,而且模型在批量推理时的温度和采样参数仍然可以保持随机性,不会因为并发而退化。
生成完后不要急着训练,要过一遍规则清洗。清洗时我会检查四件事:
- 修正输出是不是还包含“无法回答/不知道”这类敷衍话术;
- 复盘内容里有没有直接把正确答案粘贴过来而不是真分析;
- 修正输出是否格式残缺,比如缺少关键步骤;
- 是否存在明显的事实幻觉,把正确答案里的名词张冠李戴。
清洗之后,把复盘文本和原问题组装成 SFT 标准格式。以常见开源模型的对话格式为例,用户轮放原题,助手轮放“复盘过程 + 修正输出”,中间不建议把复盘和修正断开,否则模型学到的只是“写小作文”,没有学习到“先复盘后作答”的行为链。我实验下来,两段合在一起训练,推理时模型能自发先给简短思考再给答案;拆开训练,效果会明显变差。
3.3 第三阶段:只做一个标准的 SFT,但有三处参数要小心
训练环节不需要写强化学习算法,普通语言模型微调就行。我用的是 4B 量级的底座,LoRA 或者全量微调都能跑,但要守住三处参数。
第一处是学习率。我建议取普通 SFT 同量级的较低值,比如 2e-5 到 3e-5。因为复盘文本与普通文本的表达习惯不完全一样,模型需要被温和地引导,而不是猛拉过去。第二处是 epoch 数。同样是因为数据量并不大,一般 2 到 3 个 epoch 就够。第三处是 seq length。复盘记录中夹带着较长的原因解释,输出长度比一般对话要长,建议把最大序列长度设到 4096 或 8196,否则修正回答会被截断。
还有一个我想特别提醒的:训练时不要打乱“复盘文本”和“修正输出”的相对顺序。有一些实现会把修正输出单独当作标签,复盘文本作为前缀,这其实没错,但要保证 attention mask 不会把复盘文本遮蔽掉。复盘文本里的“原因解释”就是模型学习的主要梯度来源,如果把它当成纯 prompt 丢掉梯度,相当于又退回普通纠错训练,自我解释的优势就没了。
3.4 训练完怎么验证“确实追平 RL”
验证阶段的痛苦程度不比训练低。我一般不看单点指标,而是会跑四组对比:原始 4B 底座、普通 SFT、传统 RL 微调模型、本次的“复盘 SFT”模型,放在同一个评测集上跑。评测集最好包含原始训练中没见过的数据,否则只能验证记忆,不能验证泛化。
评测指标除了准确率,我会额外统计两个东西:第一是错误输出的修正率。就是说,评测时给模型一个干扰项,看它会不会被带走,这能间接反映复盘是否真的让模型更“警惕”。第二是输出 token 数。如果模型为了刷分把答案越写越长,实际效果可能没涨,只是话变多了。我在测试里发现,复盘 SFT 的输出长度一般和普通 SFT 差不多,但准确率有明显提升;传统 RL 模型则偶尔出现长度膨胀但准确率不涨的情况。这个观察很有意思,大概率是因为自我解释强制的“原因链”约束住了回答模式。
4. 训练成本详细算账:省下的 63% 到底藏在哪里
4.1 强化学习管线里的每一个“贵”环节
要理解 63% 省在哪,就得先拆解传统 RL 的耗时构成。我以 4B 模型为例,把 RL 流程按时间拆开,大概长这样:
| 环节 | 消耗时间占比 | 是否可以被复盘方案吸收 |
|---|---|---|
| 多次策略 rollout | 约 35% | 不需要,只采样一次 |
| Reward model 推理 | 约 20% | 不需要,参考答案直接判 |
| RL 更新与调参 | 约 30% | 不需要,改为普通 SFT |
| 训练过程和稳定性处理 | 约 15% | 保留,但更轻量 |
注意这里 rollout 不是跑一次就完了。RL 训练中模型每更新几轮就要重新采样,因为策略变了,旧数据不能直接用。很多项目试过用 off-policy 数据凑合,结果训练直接不稳定。所以 35% 的 rollout 时间只是保守估计。reward model 同样不便宜,它本身要训练一个打分模型,或者不断调用大模型打分,资源占用比例在中小团队手里更高。而复盘方案把 reward model 这层整个去掉,判定对错直接用标准答案,一步到位,训练时间自然压缩。
4.2 从 22 天到 8 天:一个可参考的资源推演
我拿一个接近真实的配置推演一遍:假设我们有 8 张 A100 40G,跑经典的 RL 微调 4B 模型,预计总时长在 22 天左右,其中包含调参失败重跑的两三天。而复盘 SFT 的流程只需要:
- 基础模型推理采样,占 1 天;
- 批量生成复盘文本,用 vLLM 约 0.5 天;
- 数据清洗与格式组装,占 0.5 天;
- SFT 训练,2 到 3 个 epoch,占 5 到 6 天。
合计大概 8 天。22 天到 8 天,节省约 14 天,正好接近 63%。如果你是租用云 GPU,这个差距换算成账单就更感性了。按一张 A100 每小时约 2 美元算,8 卡 14 天大概就省了 5 万多人民币。这还没算调 RL 超参数的精神损耗,那部分真的没法用钱衡量。
4.3 硬件下限比想象中低,但别踩显存坑
很多人一听到 4B 模型就以为单卡 4090 随便跑,实际上没那么简单。生成阶段确实 4090 可以胜任,但 SFT 阶段如果用全量微调,4B 模型加 4096 序列长度,显存需求通常超过 24G。我自己的做法是优先 LoRA 或 QLoRA,把可训练参数压到 1% 以内,这样在单张 4090 上也能跑完一个 epoch;如果数据量偏大,再升级到两张 4090 或一张 A100。
操作层面有个经验:QLoRA 4bit 量化时,建议把量化后的计算类型保持为 bf16,不要用 fp16。4Bit 基础模型配合 fp16 计算,在某些算子下容易出现数值溢出,导致复盘的 loss 前几步就冲到 NaN。这个小坑很隐蔽,我最初连续两次训练到第二步就崩,最后排查发现是混合精度设置的问题。
5. 实操中的坑、排查经验以及我的使用心得
5.1 复盘数据“看着像分析,实际是复读”
第一个高频坑是模型生成的复盘文本表面上很合格,有“错误定位”“错误原因”,但内容完全是在复读原题或者正确答案,没有任何推导过程。比如错误原因写着“我忽略了问题的要求”,这等于没写。这种数据混进训练集,会拉低整体效果。
我的排查办法是统计原因词多样性。把复盘文本里的关键词按“推理动词”分类,例如“因为、所以、由此可、需要先”,统计出现频次,如果一类动词被反复使用,就要怀疑是套话。更直接的做法是抽 200 条复盘记录人工看一眼,只要发现五分之一是空话,就提高生成温度或换采样模板。我后来还把提示模板改得更强制,要求“必须引用上一次回答中的某个具体句子”,引用具体句子能有效减少空泛复盘。
5.2 小模型容易过拟合复盘模板
第二个常见问题是过拟合。4B 模型参数少,如果复盘模板格式过于一致,训练完后它会形成一种“格式记忆”,遇到任何问题都先来一段“错误定位、错误原因、正确思路”,但这三段内容可能与问题没有关系。评测时看着输出结构漂亮,实际准确率没有提升。
解决方法是增加模板变体。在生成复盘时,不要全场用一种提示模板,至少准备四五种不同的表述,比如把“正确思路”换成“若重来一次,应该按什么顺序处理”,把“错误定位”换成“第一个出问题的环节在哪里”,然后混合进训练集。这样模型学的是内容本身,而不是排版格式。这个技巧基本能消除模板过拟合。
5.3 怎么判断模型是“真懂了”而不是“背了脚本文案”
这里最见功力的是评估方式。如果你评测时只报准确率,很难区分模型是真的复盘成功,还是把训练集里的修正回答背下来了。我的做法是在评测集里加入“反事实干扰项”:给同一个问题换掉一个关键数字或条件,正确答案的推理路径不变但数值不同。如果模型能跟着条件改答案,说明它学到了思路;如果答案仍然是训练集版本,说明它在背题。
我的实测结果是,复盘 SFT 在这类反事实评测上表现得比普通纠错 SFT 好不少。这符合我的预期,因为训练时它接触的“原因解释”里包含了条件与结论的关联,这种关联在参数里沉淀越深,泛化能力越强。传统 RL 模型在这项评测上通常也不错,但偶尔会输出非常啰嗦的推理,反而影响准确率。
5.4 这个方法后续能往哪些方向扩展
顺着这套复盘思路,我后来还在两个方向上做过尝试。第一个方向是把“复盘”和“多轮迭代”结合起来:第一轮复盘完做 SFT,再用新模型采样,针对新错误再复盘一遍,效果往往还有小幅提升,而且每轮训练时间只有普通 RL 的一个零头。第二个方向是直接用复盘数据做 DPO 而不是 SFT,让模型学习“复盘后的回答优于原始错误回答”,在偏好对齐任务上表现也不错。
不过也要泼一点冷水:这套方案适合有标准答案、推理链条清晰的任务,比如数学题、代码题、知识问答。如果是开放性创意写作或者需要培养独特风格的任务,复盘数据的参考质量本身很难定义,效果就会打折扣。我会建议对这种任务仍然保留一小部分 RL 结构来提升上限,复盘则作为冷启动和稳定性兜底。
最后分享一个我自己的习惯:每次跑完一轮复盘训练,我都会把训练集里哪些错误被修正、哪些错误仍然顽固地犯错单独导出来看一遍。那些反复犯错的数据,往往不是模型的问题,而是任务本身存在歧义,或者参考解析写得不够清楚。改一遍参考解析可能比再调一周超参数管用。把这个动作保持下来,你会发现“复盘”不仅让模型更稳,也会让整个数据 pipeline 的质量在不知不觉中高出几个台阶。