指令微调 — 教模型听人话,以及让 LLM 当裁判
这一章做全书的最后一步: 把预训练模型微调成「听得懂指令、给得出回答」的助手。 三件事:数据怎 么包装(Alpaca 模板与 -100 掩码)、为什么这步要换更大的模型、 以及最难的一件——没有标准答案的任务,怎么打分(让另一个 LLM 当裁判)。 读完,第 01 章那张施工图就走完了全程。
1. 这一章讲什么
第 08 章的微调让模型只会答「是/否」。这一章让它会答开放问题:「把这句改成被动语态」 「给 bright 找个同义词」。这是 ChatGPT 那类助手的核心工序,也是这本书的终点1。 训练代码和前两章几乎一字不改——真正的功课全在数据准备和评估上,这一章的篇幅也这么分配。
2. 顶层全景
数据侧(本章 §3.1–3.3,全章的真功夫):
1,100 条「指令+回答」 → 套 Alpaca 模板 → 分词 → 按批内最长补齐
→ 目标 = 输入右移一位 → 补位词元改 -100(不计入损失)
模型侧(§3.4):
加载 GPT-2 medium(355M,不是 124M——小模型容量不够)
→ 同一个 train_model_simple,2 轮
评估侧(§3.5):
110 条测试指令 → 模型生成回答 → 本地 Llama 3(8B)按 0~100 打分 → 平均分
图说:预训练让模型会语言,指令微调让它把语言能力对准「人的要求」。
3. 核心原理
3.1 主走查:一条「Ocassion」的完整旅程
数据集是作者专为本书造的 1,100 条指令-回 答对,存成一个 JSON(一种「键:值」纯文本数据格式,程序之间传数据的通用腔)文件,204 KB。
每条三个字段:instruction、input(可空)、output2。拿第 51 条走完全程:
原始条目:{instruction: "Identify the correct spelling of the following word.",
input: "Ocassion", output: "The correct spelling is 'Occasion.'"}
第一步,套模板。 指令要包装成固定格式,因为模型没见过「三个字段的 JSON」, 它只见过连续文字。书里用 Alpaca 风格——一个早期公开指令微调流程的模型定下的格式, 后来成了惯例3:
Below is an instruction that describes a task. Write a response that
appropriately completes the request.
### Instruction:
Identify the correct spelling of the following word.
### Input:
Ocassion
### Response:
The correct spelling is 'Occasion.'
模板不是唯一答案:微软的 Phi-3 用更简的 <|user|>…<|assistant|>… 结构。
书里选 Alpaca 的理由是「它定义了这套做法的原始形态」3。
要点是「固定」:格式一成不变的重复,模型才能学会「### Response: 后面轮到我写」。
第二步,分词。 整段(含模板文字)编成词元 ID 序列(按先后顺序排成的一串编号)。
第三步,按批内最长补齐。 上一章是整个数据集补到 120;这章升级成每个批只补到该批最长—— 指令长短差异大,按批补能省掉大量无效补位。为此要写自定义的 collate 函数 (DataLoader 默认的拼批逻辑干不了这事)4。
第四步,右移一位造目标。 和预训练完全相同:目标是输入左挪一位,末尾多补一个 502565。
第五步,-100 掩码——全章最值得记住的机关。 补位用的 50256 不该参与损失:
让模型去学「predicting 一个补位符」毫无意义。做法是把目标里的补位位置改成 -100——
PyTorch 的交叉熵默认 ignore_index=-100,遇到这个目标值直接跳过6。
书里用一个三行小实验验证:两个词元的损失是 1.1269;加第三个目标词,损失变成 0.7936;
把第三个目标改成 -100,损失精确回到 1.1269——第三个位置被整个无视了7。
但注意一个反例:每个目标序列保留了一个 50256 没改成 -100。为什么? 要让模型学会「回答完毕时生成结束符」——否则它永远不知道什么时候停8。
还有一个作者选择不做的做法:指令遮蔽——把目标里指令部分的词元也全改成 -100, 只对「回答」部分 算损失,防止模型去背指令模板。做不做,学界当时有分歧: 2024 年有论文发现不遮蔽反而更好;书里选择不遮蔽,留作习题9。
3.2 切分与装载
1,100 条按 85%/10%/5% 切成训练 935 / 测试 110 / 验证 5510。 装载时把「搬到 GPU」这步写进 collate 函数,让数据搬运在后台进行,不阻塞训练主循环11。
3.3 为什么这章要换 355M
前八章用的都是 124M。这章换成 GPT-2 medium(355M),作者给的理由很直接: 124M 容量不够,「学不住指令跟随所需的细密模式」——这不是玄学,是作者试过之后的结论12。 下载量 1.42 GB,是小模型的三倍13。
点火 前的基线:对验证集第一条「把主动句改成被动句」,没微调的 355M 模型只会复读—— 它规规矩矩印出 "### Response:",然后把原句抄了一遍14。 这个「会格式、不会办事」的失败,精确标出了微调要补的那块东西。
训练本身毫无新闻:同一个 train_model_simple,AdamW,lr=5e-5,只训 2 轮——
书上明说,损失曲线显示两轮已收敛,再训只会开始背数据15。
时长参照:355M 模型训两轮,M3 MacBook Air 15.78 分钟,NVIDIA L4 是 1.83 分钟,A100 是 0.86 分钟16。
训完再看那条被动句:模型给出 "The meal is cooked every day by the chef."——会了17。
3.4 评估:没有标准答案,就请另一个 LLM 当裁判
分类任务有准确率一把尺;指令任务没有——同一个指令可以有一万种好回答。 书里先摆三种业界做法18:
| 做法 | 代表 | 量的是什么 |
|---|---|---|
| 选择题基准 | MMLU | 知识面的对错 |
| 人类偏好评比 | LMSYS Chatbot Arena | 真人觉得谁答得好 |
| 让另一个 LLM 打分 | AlpacaEval | 可批量自动跑的「像不像好回答」 |
书里选第三条:本地用 Ollama(一个把开源 llama.cpp 包装成一行命令的推理工具, 只推理不训练)跑 Meta 的 Llama 3 8B(4.7 GB,约需 16 GB 内存)19, 让它拿测试集的标准回答当参照,给我们的模型的回答打 0~100 分。
三条真实判卷,值得逐条读20:
- 明喻题:标准答案「快如闪电」,模型答「快如子弹」——裁判给 85,评语说子弹的比喻成立但没那么生动;
- 雷雨云题:标准答案「积雨云」,模型答「积云」——裁判给 40,指出术语错了但沾边;
- 简·奥斯汀题:模型答对了但把问题复述了一遍——裁判给 95,扣在啰嗦。
110 条测试全跑完(M3 上约 1 分钟),平均 50.32 分21。 这个数怎么看?书里给了两根标尺:同一套卷子,Llama 3 8B 的基座模型(没指令微调过)得 58.51, 官方指令版 得 82.622。我们 355M 的小模型输给 8B 基座——参数差了 23 倍, 数据只有 1,100 条,这个结果不丢人;它是「小模型的诚实天花板」的量尺。
评判方法学上还有两个注脚:Ollama 当时不完全确定(同样输入可能不同分), 要稳妥就多跑几次取平均23;以及这套「LLM 当裁判」的做法,裁判本身也会偏—— 它只能给「像不像好回答」,给不了「对不对」的最终裁决。
3.5 全书的落点
到这里,第 01 章的施工图全部走完。书末给两条「再往下走」的路: 指令微调之后还有一道可选工序——偏好微调(按人的偏好再对齐,书指向配套 GitHub 仓库里的 DPO 补充材料); 以及真要做生产级的微调,作者推荐现成框架 Axolotl 和 LitGPT—— 注意:作者本人参与开发 LitGPT,这是利益相关,读推荐时留意24。
4. 作者的判断与证据
有证据的: -100 的三行实验、复读式基线 、2 轮收敛、三条判卷与 50.32/58.51/82.6 三个平均数—— 全部是书里印的真实记录714162122。
作者的判断:
- 「124M 学不住指令跟随」是作者的实验结论,不是定理12。
- 不做指令遮蔽是权衡后的选择,书里把分歧照实写出并给了反对文献9。
- 选 Alpaca 模板是「历史地位」理由,不是性能比较3。
- 推荐 Axolotl/LitGPT 带利益相关(作者在 Lightning AI 任职并参与 LitGPT)24。
判断(我们的,不是书里的): 这一章最该带走的不是某个分数,而是一个结构: 指令微调的工程内容 90% 在数据(模板、补齐、掩码),训练代码一行没改。 这解释了这个行业里「数据团队比模型团队人多」的现象。 如果错,会错在: 如果读者的场景是训练超大模型,数据工程占比可能下降(架构与系统工程的占比上升)—— 但在本书覆盖的微调尺度上,这个比例是实录。
5. 边界与局限
- 1,100 条数据是教学集;书里给了真实的 Alpaca 数据集(52,002 条)作习题,并提醒要 GPU25。
- 「LLM 当裁判」当时(2024)已是主流但远非完美:裁判有自己的偏好,而且这本书没做裁判信度的检验。
- 偏好微调(RLHF/DPO 这一族)全书只有一段指向——这是 2024 年这本书最大的留白, 今天的「助手感」很大程度是那一道工序给的。想补这一课,我们书架上《The RLHF Book》在。
- 模型规模止于 355M;「什么时候该换多大」没有给系统准则,只有这一次现身说法。
6. 可带走的
- 指令微调 = 同样的训练循环 + 「指令+回答」数据;工作量在数据侧,不在代码侧。
- 模板的意义是「固定」:模型靠一成不变的格式学会「哪里轮到我写」;Alpaca 与 Phi-3 是两种真实风格。
- -100 是 PyTorch 交叉熵的「忽略此目标」暗号;补位词元必须摘掉,但要留一个结束符教模型收工。
- 按批内最长补齐,比全数据集统一补齐省算力;代价是写自定义 collate 函数。
- 容量不够的表现是「会格式不会办事」;这章为此从 124M 换到 355M。
- 指令微调 2 轮就够,再多开始背——损失曲线说了算。
- 评估三件套:选择题基准、人类评比、LLM 当裁判;没有一把尺是完整的。
- 355M/1,100 条的组合平均 50.32 分,8B 基座 58.51、8B 指令版 82.6——规模与数据量的差距就是这么明码标价。
- 读完这本书之后再想深入:偏好微调(DPO)与生产框架是下一步;作者推荐 LitGPT 有利益相关。
7. 原文地图
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| 数据集与三字段 | 7 Fine-tuning to follow instructions | text/15-ch07-7-fine-tuning-to-follow-instructions.txt:117(搜「1,100 instruction–response pairs」) |
| Alpaca 与 Phi-3 模板 | 同上 | text/15-ch07-7-fine-tuning-to-follow-instructions.txt:191(搜「Alpaca prompt style」) |
| 自配 collate 五步 | 同上 | text/15-ch07-7-fine-tuning-to-follow-instructions.txt:376(搜「2.4」) · text/15-ch07-7-fine-tuning-to-follow-instructions.txt:474(搜「different batches to have different lengths」) |
| -100 机 关与实验 | 同上 | text/15-ch07-7-fine-tuning-to-follow-instructions.txt:835(搜「-100」) · text/15-ch07-7-fine-tuning-to-follow-instructions.txt:742(搜「ignore_index=-100」) |
| 留一个结束符 | 同上 | text/15-ch07-7-fine-tuning-to-follow-instructions.txt:675(搜「retain one end-of-text token」) |
| 指令遮蔽之争 | 同上 | text/15-ch07-7-fine-tuning-to-follow-instructions.txt:895(搜「Instruction Tuning With Loss Over Instructions」) |
| 换 355M 的理由与基线复读 | 同上 | text/15-ch07-7-fine-tuning-to-follow-instructions.txt:1050(搜「too limited in capacity」) · text/15-ch07-7-fine-tuning-to-follow-instructions.txt:1192(搜「not yet capable」) |
| 2 轮收敛与时长表 | 同上 | text/15-ch07-7-fine-tuning-to-follow-instructions.txt:1273(搜「15.78 minutes」) · text/15-ch07-7-fine-tuning-to-follow-instructions.txt:1347(搜「counterproductive」) |
| 三种评估与 LLM 裁判 | 同上 | text/15-ch07-7-fine-tuning-to-follow-instructions.txt:1508(搜「MMLU」) · text/15-ch07-7-fine-tuning-to-follow-instructions.txt:1608(搜「Llama 3」) |
| 三条判卷与三个平均数 | 同上 | text/15-ch07-7-fine-tuning-to-follow-instructions.txt:1867(搜「85 out of 100」) · text/15-ch07-7-fine-tuning-to-follow-instructions.txt:1974(搜「50.32」) · text/15-ch07-7-fine-tuning-to-follow-instructions.txt:1999(搜「58.51」) |
| 偏好微调与工具推荐 | 同上 | text/15-ch07-7-fine-tuning-to-follow-instructions.txt:2016(搜「preference fine-tuning」) · text/15-ch07-7-fine-tuning-to-follow-instructions.txt:2073(搜「LitGPT」) |