全书导航
大模型之路:从图灵、感知机到 ChatGPT · 卷 4

第 29 章:指令微调:让模型听懂「人话」

本章问题:为什么裸模型什么都会,但什么都不听你的?


29.1 能续写《哈姆雷特》,但听不懂"给我写一段摘要"

2019-2020 年,GPT-2 和 GPT-3 的研究者不断发现令人惊讶的事情:这些纯粹为了"猜下一个词"而训练的模型,客观上拥有了大量的知识和能力。它们能写出结构优雅的代码,解释复杂的科学概念,从英文翻译到斯瓦希里语——而且这些能力可以在不给任何专门标注训练数据的情况下(zero-shot)显现。

但这里有一个奇怪的断层。

GPT-3 作为一个裸的续写模型,可以在零样本下完成很多任务——但它也经常在简单的指令面前输出莫名其妙的内容。你问"总结一下这段话",它可能给你的输出是"下一段话的内容……"而不是总结。你问"这个产品的优点和缺点各列出三点",它可能输出半篇维基百科。

问题不是它不能总结或分析——它的参数里确实存储了这些能力。问题是它不知道你想让它做什么。它学会的唯一目标是"续写"——如果你给它一段文本,它从概率上最可能续写出的内容取决于训练数据中类似模式的统计分布,而不是你的意图。

训练数据中,一段文本后面跟着"总结"的场景远比跟着"下一段"的场景少。裸模型会自然地倾向最常见的续写模式——而不是你心里想要的那一种。

这个时候,一个朴素的想法出现了:

既然模型学会了续写——那能不能教它一件事:看到指令格式的文本时,应该生成符合指令的答案

这就是指令微调(Instruction Tuning)的起点。


29.2 教模型"理解任务描述"

指令微调的核心思想极其直接:

  1. 收集大量 NLP 任务(翻译、摘要、分类、问答、推理……)。
  2. 把每个任务重新格式化成一个统一的自然语言模板——"指令 + 输入 → 输出"。
  3. 用这些格式化的数据去微调(fine-tune)一个预训练好的语言模型。

训练完成后,模型不再是"看到一段文本续写下去"——而是"看到一段指令,生成符合指令的回答"。

公式化来看,指令微调把训练从:

P(next_token | prefix)          ← 语言建模(裸模型)

变成了:

P(response | instruction, input) ← 指令跟随

在预训练阶段,模型从"Ingredients: eggs, flour, sugar. Steps:"中学到要续写烘焙步骤。在指令微调阶段,模型学会了区分两种完全不同的场景:当它看到"续写以下食谱:"时→输出步骤;当它看到"总结以下段落的要点:"时→输出要点。同一个模型权重被调整到:不根据固定模式做最常见的续写,而是根据指令的类型选择正确的行为。

2021 年底到 2022 年,两个关键研究成果相继问世:

  • Google 的 FLAN(Finetuned Language Net)——把 62 个 NLP 任务集全部格式化为指令模板,然后在上面微调 1370 亿参数的 LaMDA 模型。结果:FLAN 在多个未见过的新任务上的 zero-shot 表现大幅超越裸模型——换句话说,模型学会了泛化到没见过的指令类型上
  • BigScience 的 T0——用类似思路在多任务指令数据集上训练 T5 变体,也展示了指令微调显著提升 zero-shot 任务泛化能力。

这两个工作的共同结论比人们预期的更加深刻:"遵循指令"这种能力本身可以被当作一个元技能来训练——在足够多样化的任务指令上微调后,模型面对全新类型的指令时也能做出合理回应。 指令微调不是在教模型某一个具体技能——是在教模型"当别人告诉你做什么时,怎么理解并执行"。


29.3 指令数据的格式:三部分就够了

指令微调的训练数据只有三种字段:

{  "instruction": "将以下句子翻译成英文。",  "input": "猫坐在垫子上。",  "output": "The cat sat on the mat."}
字段含义是否必需
instruction描述模型应该执行的任务
input任务操作的具体材料否(纯指令任务可以没有)
output期望的目标输出在训练时需要

在训练时,instruction 和 input 被拼接成模型的输入——通常用一段固定的模板(prompt template)。output 作为标签进行有监督的交叉熵训练——和第二章的损失函数同款,不过这时的标签是"回答的真正 tokens"。

指令多样性是指令微调成功的关键。如果你的训练集里只有"翻译"和"摘要"两种指令类型,模型不会理解"解释"、"对比"、"列表"、"判断"、"归纳"——因为它的权重调整没有被暴露给足够丰富的指令→回答映射模式。Google 的 FLAN 用了 62 个不同任务的集合——翻译、自然语言推理、常识推理、情感分析、句子关系、结构→文本等——关键在于指令的类型丰富度,而非每个任务的数据量。

后续的研究进一步证明:指令微调的数据质量比数据量重要得多。 少量高质量、多样化的指令示例带来的能力提升,往往超过大量嘈杂、重复的低质量指令数据。这推动了后来整个"高质量指令数据构建"方向的发展——包括 LLaMA、Alpaca、Vicuna 等开源模型的指令数据集建设。


29.4 指令微调 vs 预训练:两个阶段的根本区别

维度预训练指令微调
训练目标预测下一个 token根据指令生成正确的输出
数据来源互联网文本、书籍、代码等海量语料人工构造/筛选的指令-回答对
数据量万亿级 tokens万到十万级条指令对
学到什么语言、知识、推理模式如何理解任务指令并按要求执行
结果"续写器""指令跟随器"

如果你把预训练比喻成"读了几十亿页书,了解了世界"——那指令微调就是"读了几万条'别人问+理想答'的对话范例,学会了怎么和别人交流"。

这两者的规模差异是巨大的。预训练可能需要读取数万亿 token、花费数千万美元的计算量。指令微调可能只需要几万条高质量指令数据,在一个预训练好的基础模型上跑几十分钟到几小时。

这也是为什么基础模型可以被无限次地复用来做各种微调——昂贵的预训练只做一次;轻量的指令微调每次只需要很少的计算量。


29.5 最小代码:从裸模型到指令模型的行为差异

以下代码在同一台机器上加载一个裸的 GPT-2 和一个指令微调过的 FLAN-T5,输入同样的指令,观察输出的巨大差异:

python
from transformers import pipeline, AutoModelForCausalLM, AutoTokenizer# ---- 裸模型:GPT-2(只做过语言建模) ----gpt2 = pipeline("text-generation", model="gpt2")prompt = "Summarize the following text: A recent study "\    "shows that regular exercise improves cognitive function "\    "in older adults."print("GPT-2 (裸):",      gpt2(prompt, max_length=80, do_sample=False)[0]["generated_text"])# GPT-2 大概率会续写更多相关内容——而不是给出"摘要"。# 它可能输出: "... The study, published in the Journal of "#  "Neuroscience, found that..."  ——它在续写"文本",而不是执行"总结指令"。# ---- 指令微调模型:FLAN-T5(在多任务指令上微调过) ----flan = pipeline("text2text-generation", model="google/flan-t5-small")result = flan(prompt, max_length=80)print("FLAN-T5 (指令微调):", result[0]["generated_text"])# FLAN-T5 会输出类似 "Regular exercise can improve cognitive "#  "function in older adults, a study found." ——它在执行指令。

同样的输入,不同的输出模式。裸模型在"续写"——因为这是它在预训练中唯一学过的事。指令微调模型在"执行指令"——因为它被训练过"看到指令格式时要回答,不要续写"。


29.6 本章小实验:构造你自己的指令数据集

用 JSON 格式手工构造 5 条指令数据,感受其结构:

python
instructions = [    {        "instruction": "回答以下问题。",        "input": "太阳系中最大行星是什么?",        "output": "木星。太阳系中最大的行星是木星。"    },    {        "instruction": "将以下句子翻译成英文。",        "input": "我今天感觉很棒。",        "output": "I feel great today."    },    {        "instruction": "判断以下句子的情感倾向(积极/消极/中性)。",        "input": "这部电影太烂了,浪费了我两个小时。",        "output": "消极。理由:'太烂了'、'浪费'表达了不满和失望。"    },    {        "instruction": "根据输入要点,生成一段连贯的简介。",        "input": "产品名:智能浇水壶。功能:自动定时浇水、土壤湿度感应、手机远程控制。",        "output": "智能浇水壶是一款自动化的植物护理设备——内置定时浇水、"                  "土壤湿度感应在缺水时自动补水,并支持手机远程监控。"    },    {        "instruction": "改写以下文本,用更正式的语气。",        "input": "嘿,那个会议我们推到下周三吧,周一我不行。",        "output": "会议建议推迟至下周三进行,因周一无法参加,不便之处请谅解。"    },]

注意这五条数据的多样性——问答、翻译、情感分析、内容生成、语气改写。五条很少,但如果你用一千条这样不同类型的高质量指令对去微调一个裸模型,它就会开始"理解指令"——这不是因为模型变聪明了,而是因为它在权重中编码了一个通用模式:"当输入以指令开头时,输出应该匹配指令的类型。指令要求X,那我就输出X。指令要求Y,那我就输出Y。" 指令类型越多,这个模式越泛化。


29.7 本章地图

text
问题:为什么裸模型什么都会,但什么都不听你的?原因:裸模型只学过"续写"——它不知道你在下指令,它只是在概率上延续最常见的文本模式。方法:指令微调——收集大量多样化的任务,格式化为 (instruction, input, output) 三元组,在有监督目标下微调预训练模型。关键洞见:"遵循指令"是一个可训练的元技能——在足够多样化的指令集合上微调,模型能泛化到未见的指令类型。规模对比:预训练 = 万亿 tokens、千万美元计算;指令微调 = 几万条指令对、几十分钟到几小时。意义:指令微调将裸模型变成了可沟通的助手——它是裸续写器到对话助手的第一个关键转型步骤。

29.8 本章结语:会听话,比会说话重要得多

全卷三你看到的是语言模型如何被建造成越来越强大的"续写器"。但续写不是帮助。续写只是生成——而生成的内容可能是回答,也可能是胡话,也可能是危险内容。

指令微调是修正这个问题的第一步。它是教会模型"对话的基本礼仪"——理解别人想让你做什么,然后按着做,而不是自顾自地继续打字。

但指令微调有自身的天花板。它依靠的是训练集中标注员写的"理想回答"——标注员是人,人会有偏见,会不一致,会对一些复杂问题产生"什么才是好回答"的根本分歧。同时,当你用指令微调教模型做 N 件事时,它在这 N 件事上的个体表现可能比你只教它一件事专门用普通微调弱——这叫多任务干扰——模型会牺牲某些任务上的最优表现来获取平均改善。

这些问题引出了下一步——如何让模型区分"有帮助的回答"和"有害的回答"?如何让模型理解不是所有问题都应该被回答?如何让回答不只是正确——还安全、有边界、有判断力?

这需要比指令微调更强的方法——不仅要告诉模型"怎么做",还要告诉模型"什么是好"。

下一章:RLHF——当人类开始给语言模型的回答打分。

SECTION §02 · ENGAGE

Discussion

留言区 · GitHub-powered comments via Giscus