8GB 显卡能学到什么:用最小实验拆开 SFT、DPO 与 GRPO 的后训练边界
大模型后训练常被描述成只有实验室才做得起的工作:数据、GPU 集群、复杂的分布式训练脚本,缺一不可。但如果目标不是训练一个可上线的通用模型,而是理解一次训练究竟改变了什么,实验规模可以小得多。
pochenai/nano-llm-posttraining 是一个 MIT 许可的实验仓库。它把重点放在可阅读、可重复的最小后训练流程:以 1.35 亿参数模型为起点,在单张 8GB 显卡上运行 SFT、DPO 和部分 GRPO 实验,并观察指令遵循、分布漂移和遗忘。它不是生产训练平台,也不承诺用小模型复刻前沿模型能力;恰恰因为边界清楚,适合作为理解后训练取舍的工作台。
先把问题从“训练得更聪明”改成“改动了什么”
后训练通常有两个相互拉扯的目标:一方面,希望模型更稳定地按指定格式回答、拒绝不合规请求,或偏好某类输出;另一方面,不希望它为了新行为丢失原有的语言能力和泛化能力。
只看某一组提示词是否答对,很容易得出过度乐观的结论。一个模型也许学会了新模板,却在未参与训练的问题上变得僵硬。这个仓库把这种变化显式放到实验设计中:除了任务表现,也关注训练后模型相对于初始模型的 KL 散度,以及不同随机种子下的变化。KL 在这里不是“质量分数”,而是一个信号:输出分布离原模型越远,越需要追问这种偏移是否带来了不想要的遗忘。
这也解释了为什么不应把“RL 比 SFT 好”当成结论。不同数据、奖励函数、模型大小和训练步数都会改变结果。较小的分布漂移可能是好事,也可能意味着策略没有真正学到任务;更高的任务分数也可能只是对狭窄评测集过拟合。最小实验的价值,是让开发者能把这些指标和具体训练配置放在一起看。
三种方法,三种约束来源
SFT(监督微调)最直接:给定提示词和目标回答,训练模型提高目标回答的概率。它适合把明确的格式、身份设定或示范性行为写进模型。代价是训练目标并不天然约束“不要离原模型太远”;当示例质量不稳定,或示例分布和底座模型差异很大时,模型可能把局部模式学得过重。
DPO(直接偏好优化)不只给一个“标准答案”,而是使用偏好对:同一提示下,哪些回答更好、哪些更差。它把偏好信号直接写进优化目标,避免了先单独训练奖励模型再做强化学习的完整链路。需要注意的是,偏好数据仍然是数据:如果 chosen/rejected 对的标准含混,DPO 只会稳定地学到这种含混。
GRPO(组相对策略优化)属于基于采样结果和奖励的强化学习路径。直观地说,模型先为同一问题生成一组候选,再根据组内相对表现更新策略。仓库用它讨论一个很重要的限制:强化学习可以放大模型已经能偶尔采样到的自检、搜索或推理行为,但不能凭空注入它没有的事实知识或能力。把“偶尔做到”变成“更稳定做到”,和从零创造能力,是两回事。
用 8GB 显卡跑起第一个对照实验
仓库的快速开始使用 uv 固定依赖,并从身份/指令遵循的 SFT 实验开始:
git clone https://github.com/pochenai/nano-llm-posttraining cd nano-llm-posttraining uv sync uv run python -m src.identity_sft
这段命令的价值不在于立刻得到一个有用助手,而在于建立可比较的基线。运行前先记录模型对一组未见提示词的输出;运行后除检查身份或格式是否遵循外,还应保留同一批提示词、随机种子、训练步数和显存日志。否则下一次修改数据或超参数时,很难知道改善来自算法还是偶然波动。
建议把实验目录保持为三个层次:data/ 放训练和评测样本,runs/ 放每次配置与指标,prompts/ 放固定的人工检查题。后训练尤其不适合只保存最终 checkpoint:没有数据版本和评测提示词,就无法解释一个模型为什么“看起来变好了”。
3B GRPO 不是 8GB 实验的延伸线
README 对硬件边界有明确区分:小模型的 SFT、DPO 与主要 GRPO 路径面向 8GB 显卡;其中 3B 模型的 GRPO rollout 实验则需要约 48GB 显存,并需安装 vLLM 额外依赖:
uv sync --extra vllm
这不是无关紧要的安装细节。rollout 要同时处理生成、候选、奖励和训练状态,显存压力与小模型微调并不在同一量级。把 48GB 实验写成“消费级显卡也能跑”,会掩盖后训练工程中最常见的失败模式:配置看似正确,却因上下文长度、批大小或生成阶段显存峰值而 OOM。
因此,个人开发者更实际的路线是先在 135M 量级验证因果关系:改变数据质量、偏好对或奖励规则时,指标与输出怎样变;确认评测设计可信后,再决定是否值得租用更大 GPU 验证 3B 级别的现象。README 以“低于 5 美元、约 5 小时”的云端 48GB 训练作为其特定实验条件,而不是普遍成本承诺;实际费用会随平台、区域与可用实例变化。
先设计评测,再决定该不该训练
后训练项目最容易犯的错误,是先花时间调学习率、batch size 和 epoch,最后才发现没有一个能反驳自己的评测。对最小实验而言,评测不必大,但必须分层。可以先准备三组固定提示词:第一组与训练目标直接相关,例如要求特定身份、JSON 格式或拒答规则;第二组是同领域但换说法的未见问题,用来检查模型是否只记住了原句;第三组完全脱离训练主题,用来观察通用问答、续写或多轮指令是否明显退化。
每次运行都把模型版本、数据提交号、随机种子、最大生成长度和解码参数写入一份机器可读配置。若比较 SFT、DPO 和 GRPO,三者还应尽量共享底座模型、评测集和计算预算。否则“某方法更好”实际上可能是在比较更长训练、更干净数据或更宽松采样。对输出做人工阅读仍然重要:自动分数能报告趋势,却难以发现模型用看似正确的格式逃避了问题,或为了拿奖励而重复关键词。
对于业务数据,先用合成或已脱敏样本验证流水线。把用户对话、内部文档直接塞进小规模实验,既可能造成训练—评测泄漏,也会让日志、checkpoint 和共享目录成为新的数据暴露面。真正进入训练前,应明确数据保留期限、可删除性和谁有权访问产物。后训练是模型行为的变更流程,理应像代码发布一样留下可审计的输入与评测记录。
不要把最小实验当成生产配方
这个仓库适合三类工作:理解 SFT、DPO、GRPO 的优化对象;为自己的小数据集建立训练前后对照;以及在投入大规模算力前排查数据和评测设计。它不适合直接证明某算法会在任何业务上“更安全”“更会推理”或“不会遗忘”。
实践时至少增加三道防线。第一,训练集与评测集严格分离,避免用训练样本的复述掩盖过拟合。第二,用多个随机种子复跑,单次成功不足以说明策略稳定。第三,保留任务外的通用提示词,检查格式提升是否以通用表达、事实准确性或拒答行为退化为代价。
后训练并不神秘,但它也不是运行一条命令后的魔法。能在 8GB 显卡上复现的最小实验,最有价值的产出不是一个 checkpoint,而是一套可质疑、可复跑的判断过程:模型变好了哪些地方,又为此牺牲了什么。