Appearance
模型微调与定制化
很多开发者学到 RAG 之后,很快就会冒出下一个问题:既然模型已经能接知识库了,那我什么时候还需要微调?
这是一个特别容易走偏的话题。因为“微调模型”听起来很强,很多人会下意识把它当成通用解法,仿佛只要把数据喂进去,模型就会更懂业务。但真实情况恰恰相反:如果问题判断错了,微调往往会比 Prompt 和 RAG 更贵、更慢,也更难验证。
所以这页的目标不是教你立刻去训练一个大模型,而是先建立一个适合应用开发者的微调判断框架。
先说结论:微调解决的是什么问题
微调更适合解决下面几类问题:
- 你希望模型长期稳定地遵守某种输出风格或任务格式
- 你有一批高质量样本,希望模型在某类任务上表现更接近你的分布
- 你希望减少大量重复示例塞进 Prompt 的成本
- 你做的不是“查资料回答”,而是“把某类输入稳定变成某类输出”
它不太适合直接解决下面这些问题:
- 希望模型知道最新资料或私有文档内容
- 希望模型引用可追溯来源
- 希望今天更新知识,明天立刻生效
- 当前问题其实只是 Prompt 写得不清楚、Schema 约束不稳、评测还没建起来
Prompt、RAG、微调分别适合什么
可以先把它们理解成三种不同层级的调优手段:
| 方法 | 它主要改变什么 | 适合场景 | 不足 |
|---|---|---|---|
| Prompt | 当前这次调用的任务描述与约束 | 规则清楚、变化快、先快速验证 | 稳定性有限,长 Prompt 成本高 |
| RAG | 给模型看的外部知识 | 文档问答、企业知识库、需要引用来源 | 检索质量差时整体效果会塌 |
| 微调 | 模型在某类任务上的输出习惯和能力分布 | 长期重复任务、稳定格式、固定风格 | 成本更高,验证更难,更新不如 RAG 灵活 |
最常见的误区是:把“模型不知道资料”当成微调问题。
如果你的真实需求是“让模型回答公司文档、产品手册、知识库里的最新内容”,那通常更应该先看 RAG 原理,而不是直接做微调。
微调最常见的几条路径
1. API 微调
这是对应用开发者最友好的路径。你不需要从零训练一个模型,而是基于平台提供的微调能力,上传样本数据、触发训练、拿到新模型再调用。
它的优点是门槛相对低,能帮助你先理解“样本长什么样、训练后该怎么评估”。缺点是可控范围和底层透明度通常有限。
2. SFT
SFT(Supervised Fine-Tuning,监督微调)可以先理解成:给模型一批“输入应该对应什么输出”的示范样本,让它在这类任务上更贴近你的期望。
对大部分应用开发者来说,真正会接触到的“微调”通常首先就是这一路径,而不是更复杂的强化学习或底层预训练。
SFT 的输入不是“把一堆文档丢给模型”。更常见的形式是一条条对话样本,每条样本都写清楚用户输入、系统约束和理想回复。以 OpenAI 的 chat fine-tuning 格式为例,一行 JSONL 大概长这样:
json
{"messages":[{"role":"system","content":"你是一个只输出 JSON 的客服分类助手。"},{"role":"user","content":"我昨天买的耳机还没发货,能帮我查一下吗?"},{"role":"assistant","content":"{\"intent\":\"order_status\",\"urgency\":\"normal\"}"}]}这个样本教的不是“耳机知识”,而是“遇到类似表达时,稳定输出指定 JSON 结构”。如果你把产品手册原文直接塞进训练集,模型可能会记住一些片段,但它不能像 RAG 那样稳定引用来源,也不适合做频繁更新的知识库。
3. LoRA / PEFT
LoRA、PEFT 这类方法的核心价值是:不必大改全部模型参数,也能做相对轻量的定制化训练。
如果你后面真的进入开源模型微调,这会是更现实的一步。但它已经明显超出纯 API 应用开发,涉及模型、显存、训练资源和推理部署的额外复杂度。
LoRA 的直觉可以这样理解:全量微调会直接更新模型里大量权重矩阵,成本很高。LoRA 不直接改原矩阵 W,而是在旁边加一个很小的增量矩阵:
text
W' = W + ΔW
ΔW = A × BA 和 B 的秩很低,参数量远小于原始 W。训练时冻结原模型,只训练这两个小矩阵;推理时再把增量合并或挂载上去。这样做牺牲了一部分自由度,换来更低的显存占用和更快的训练速度。对“把一个开源模型适配到固定领域表达风格”这类任务,它通常比全量微调现实得多。
SFT 的完整工作流
一个可靠的 SFT 流程通常分成四步。每一步都很普通,但跳过任何一步都容易把问题拖到线上。
1. 定义任务边界
先把任务写成一句可以验证的话,例如:
- 把客服消息分类为
refund、order_status、shipping、other - 把用户需求转换成固定字段的 JSON
- 把长文本压缩成 200 字以内的结构化摘要
如果任务边界写不清,训练数据就会变成杂烩。SFT 对这种混乱很敏感,因为它会学习样本里的所有模式,包括你不想要的坏习惯。
2. 准备训练集和验证集
训练集用于更新模型,验证集用于判断模型有没有真的泛化。不要把同一批样本既拿来训练又拿来评估,这会让结果看起来很好,线上却不稳定。
我更建议一开始做小而干净的数据集,例如:
- 100-300 条高质量样本先跑通流程
- 每条样本只覆盖一个明确任务
- 保留 20%-30% 作为验证集
- 单独收集边界样本,比如空输入、口语化输入、多意图输入
数据越早被人工抽查,越省钱。等模型训练完才发现标签风格不一致,返工成本会高很多。
3. 触发训练
API 微调的最小流程是:上传 JSONL 文件,创建 fine-tuning job,等待任务完成,再用新模型名调用。下面是一个可以直接改的 Python 示例:
python
from openai import OpenAI
client = OpenAI()
# train.jsonl 每一行都是 {"messages": [...]} 格式
training_file = client.files.create(
file=open("train.jsonl", "rb"),
purpose="fine-tune",
)
job = client.fine_tuning.jobs.create(
training_file=training_file.id,
model="gpt-4o-mini-2024-07-18",
suffix="support-intent-v1",
)
print("job id:", job.id)
# 稍后轮询或在控制台查看;status 为 succeeded 后会有 fine_tuned_model
current = client.fine_tuning.jobs.retrieve(job.id)
print(current.status, current.fine_tuned_model)真实项目里还要加验证文件、训练任务轮询、失败告警和模型版本记录。示例故意没有封装成框架,是为了让你看清楚核心 API 调用。
4. 对比评估
评估不能只看“回答是不是更像训练样本”。至少要比较这些指标:
- 任务准确率,比如分类是否命中、字段是否抽取正确
- 格式稳定性,比如 JSON 是否可解析、字段是否缺失
- 边界输入表现,比如多意图、缺少上下文、无关问题
- 成本和延迟,微调模型是否真的减少了 prompt 长度或重试次数
如果微调后只是常规样本变好了,但边界样本明显变差,这个模型不应该直接上线。
DPO 和 RLHF 的边界
SFT 学的是“给定输入时,理想输出长什么样”。RLHF 和 DPO 处理的是另一个问题:当多个答案都说得过去时,模型应该偏向哪一种。
RLHF(Reinforcement Learning from Human Feedback)通常会先训练一个奖励模型,让奖励模型判断哪个回答更符合人类偏好,再用强化学习方法优化语言模型。它的系统链路比较长,工程复杂度高,不是普通应用团队会轻易自建的东西。
DPO(Direct Preference Optimization)省掉了显式奖励模型。它直接使用偏好数据,例如同一个问题下有 chosen 和 rejected 两个回答,让模型更倾向生成被选择的那类答案。你可以把它理解成更直接的偏好对齐训练。
它们和 SFT 的关系可以这样记:
| 方法 | 训练数据长什么样 | 主要解决什么 |
|---|---|---|
| SFT | 输入 + 标准答案 | 学会完成某类任务 |
| RLHF | 回答偏好 + 奖励模型 + 强化学习 | 按人类偏好调整行为 |
| DPO | 同一输入下的 preferred / rejected 回答 | 更轻量地做偏好对齐 |
应用开发者最先要掌握的是 SFT。只有当你已经有稳定任务能力,还要进一步调整“回答风格、拒答边界、风险偏好”时,才需要讨论 DPO 或 RLHF。
做微调之前,先问自己这 5 个问题
1. 我的问题真的是“知识缺失”吗?
如果是知识缺失,优先考虑 RAG;如果是输出习惯、格式稳定、任务分布问题,才更像微调。
2. 我已经把 Prompt 做到合理水平了吗?
如果 Prompt 还混乱、字段定义不稳、示例很少、约束没写清楚,微调只会把混乱放大。
3. 我有足够好的样本吗?
微调最怕“数据量不大,但质量也不高”。样本不一致、标签风格混乱、任务边界模糊,最后往往只会得到一个不稳定的新模型。
4. 我有评测集吗?
如果你训练前后没有一组稳定测试集,你就无法判断模型到底是真的变好了,还是只是换了种方式出错。
5. 我愿意承担更新成本吗?
RAG 的知识可以随文档更新;微调通常意味着重新准备数据、重新训练、重新验证。你的业务是否值得这套成本,是必须先想清楚的问题。
数据准备时最容易踩的坑
样本看起来很多,其实任务不一致
比如你把摘要、分类、改写、问答全混在一个训练集中,却没有明确说明任务边界。这样做通常不会得到“更聪明”的模型,只会得到更混乱的输出。
只看训练样本,不看线上输入
如果训练数据和真实业务输入分布差异太大,模型在线上仍然会失真。所以数据准备不只是“多收集一些例子”,而是要保证样本像真实输入。
没有负例和边界样本
模型最容易出问题的往往不是常规样本,而是边界条件、不完整输入、异常格式、模糊需求。训练和评测里不覆盖这些,线上就会暴露出来。
过拟合和灾难性遗忘怎么防
微调的两个常见风险,一个是过拟合,一个是灾难性遗忘。
过拟合指模型把训练集记得太死。训练样本里的固定措辞、错误格式、特殊案例,都可能被模型当成通用规则。上线后遇到稍微不同的表达,它就开始失真。
灾难性遗忘指模型在学新任务时,把原来已经会的能力削弱了。小模型、数据分布很窄、训练轮数过多时更容易出现这个问题。比如你只用客服分类样本微调,结果模型对普通问答、拒答边界或多语言输入的表现都变差了。
工程上可以用这些办法降低风险:
- 训练集保持任务一致,但表达方式要有变化,不要只复制一种模板
- 保留验证集和回归评测集,训练后同时测新任务和基础能力
- 控制 epoch 数和学习率,先小步试,不要一上来长时间训练
- 在训练集中加入少量通用能力样本或拒答边界样本,防止模型把世界缩成单一任务
- 给微调模型做版本管理,保留可回滚的基座模型调用路径
- 上线先灰度,只让一部分流量使用新模型,观察错误类型再扩大
我会把“评测集”放在这里的第一优先级。没有评测集,过拟合和遗忘都只能靠感觉判断,而感觉在模型评估里不太可靠。
一个最小判断流程
你可以用下面这条顺序来决定是否进入微调:
- 先明确任务目标:是知识增强,还是输出定制?
- 先把 Prompt、Structured Output、工具流程做稳。
- 如果涉及知识接入,先验证 RAG 是否已经足够。
- 建一组小而稳定的评测样本。
- 只有当问题持续稳定存在,且样本明确可收集时,再进入微调。
和其他章节怎么配合
- 如果你还分不清什么时候该接知识库:先看 RAG 原理
- 如果你还没把输出结构做稳:先看 Structured Output
- 如果你还没有评测意识:先看 AI 应用评测
- 如果你还没建立系统视角:再回看 AI 应用系统设计
小结
微调不是 AI 应用开发的起点,也不是默认答案。先把 Prompt、RAG、工具、评测这些基础链路做稳,再决定某个场景是否值得进入微调。
顺序想清楚,微调就是一项普通的工程选择。
常见面试考点
微调方向的题目容易问得很宽,回答时先把“什么时候该微调”讲清楚,再谈具体方法:
- SFT / RLHF / DPO 区别:SFT 用示范样本学习任务输出;RLHF 通过奖励模型和强化学习做偏好对齐;DPO 直接用 chosen / rejected 偏好样本优化模型。
- OpenAI API 微调流程:准备 JSONL 对话样本,上传训练文件,调用
client.fine_tuning.jobs.create创建任务,训练完成后用fine_tuned_model做线上调用。 - LoRA / PEFT 原理:冻结原模型权重,只训练低秩增量矩阵
A × B,用较少参数适配新任务,适合显存有限的开源模型定制。 - 微调 vs RAG:知识更新、私有文档问答和引用来源通常优先 RAG;输出风格、任务格式和固定分布才更像微调问题。
- 数据质量:样本一致性、真实输入分布、边界样本、负例和验证集划分,比单纯数据量更关键。
- 效果评估:训练前要有稳定评测集,对比微调前后在准确性、格式稳定性、幻觉、成本、延迟和边界输入上的变化。
- 过拟合与遗忘防护:控制训练轮数和学习率,保留回归评测,加入边界样本,做模型版本管理和灰度发布。