模型微调从决策到训练上线完整总览
模型微调是在已有基础模型上继续训练,使模型参数或新增适配器更稳定地表达某类任务行为。它可以改善固定格式、领域表达、分类、抽取和工具参数生成,但不是给模型同步实时知识的万能方案,更不是 AI 项目的默认第一步。
最容易犯的错误是把“回答不好”直接翻译成“需要微调”。回答不好可能来自 Prompt 不清楚、RAG 没召回、工具没接入、权限过滤错误、基础模型能力不足或评估方式错误。微调只适合其中一部分问题,而且会引入数据治理、GPU训练、模型版本、评估、部署和回滚成本。
学习目标
完成本页后,你应该能够:
- 区分 Prompt、RAG、Tool Calling、继续预训练、SFT、偏好对齐和微调。
- 判断一个需求为什么该微调或为什么不该微调。
- 解释微调怎样通过损失、梯度和优化器改变模型行为。
- 区分全量微调、LoRA、QLoRA 和厂商托管微调。
- 设计任务定义、基线、数据集、训练、评估、灰度和回滚链路。
- 解释为什么训练 Loss 下降不等于商业效果提升。
- 识别过拟合、灾难性遗忘、数据泄漏和错误行为固化。
- 为商业分类、抽取、话术和工具参数任务设计微调验收标准。
- 估算训练和推理新增的资源、存储与运维成本。
- 根据线上退化建立版本和证据链。
一、先理解微调到底改变了什么
基础模型可以抽象为带参数的函数:
下一个Token概率 = Model(已有Token, 参数θ)训练样本给出“输入上下文”和“期望输出”。模型前向计算得到概率,与正确输出计算 Loss;反向传播得到参数梯度,优化器更新参数。微调就是在已有参数起点上继续这个过程:
flowchart TD
A["基础模型参数θ"] --> B["输入微调样本"]
B --> C["前向传播得到Token概率"]
C --> D["与期望输出计算Loss"]
D --> E["反向传播计算梯度"]
E --> F["优化器更新全部或部分参数"]
F --> G["得到参数θ'或Adapter"]
G --> H["验证集与业务评估"]微调不是把问答对作为可检索记录存进去。它把样本模式压入参数变化,因此:
- 不能保证逐条精确记忆和引用来源。
- 数据更新通常需要重新训练、评估和发布。
- 错误样本可能系统性改变相似场景行为。
- 小而窄的数据可能损害原有通用能力。
- 模型输出仍是概率生成,不能替代数据库约束。
二、Prompt、RAG、工具和微调怎样选择
| 问题 | 首选方案 | 为什么 |
|---|---|---|
| 回答角色和格式没有写清 | Prompt | 修改快、可版本化、无需训练 |
| 企业制度和接口文档频繁更新 | RAG | 文档可增量更新、可引用和权限过滤 |
| 查询实时订单、库存、指标 | Tool Calling | 数据来自权威业务系统 |
| 固定分类、抽取或表达模式长期不稳定 | SFT/LoRA | 让行为模式进入参数或Adapter |
| 领域原始语料分布与基础模型差异大 | 继续预训练 | 学习领域语言分布和术语 |
| 需要更符合偏好和安全取向 | 偏好对齐 | 用比较或奖励信号优化偏好 |
| 基础模型根本没有足够能力 | 更强基础模型/任务拆解 | 小数据微调不能凭空制造能力 |
2.1 决策流程
flowchart TD
A["固定失败样本并定义指标"] --> B{"Prompt是否表达清楚"}
B -->|"否"| C["先改Prompt并评估"]
B -->|"是"| D{"缺少可更新知识吗"}
D -->|"是"| E["RAG、搜索或知识图谱"]
D -->|"否"| F{"缺少实时事实或动作吗"}
F -->|"是"| G["Tool Calling"]
F -->|"否"| H{"行为模式是否稳定且重复"}
H -->|"否"| I["澄清需求或改工作流"]
H -->|"是"| J{"基础模型有潜在能力吗"}
J -->|"否"| K["换模型、拆任务或人工"]
J -->|"是"| L["建立数据与基线后考虑微调"]
C --> M["同一评估集比较"]
E --> M
G --> M
L --> M2.2 一个需求可以组合多个方案
医疗采集异常助手可以这样组合:
微调:把错误日志稳定分类成标准errorCode
RAG:查询当前版本Runbook和制度
工具:查询实时任务状态和数据源健康
工作流:控制创建工单、审批和重跑微调只负责稳定的“日志 → 分类/字段”映射,不承担实时状态、权限和执行动作。
三、微调主要类型
3.1 继续预训练
使用领域原始文本继续下一个 Token 预测,让模型适应术语、文体和分布。它不天然教会模型按指令回答,也不等同于把文档变成可准确查询的知识库。
适合:大量合法授权的领域语料、基础模型对领域语言明显不适应。成本和遗忘风险通常高于小规模 SFT。
3.2 监督微调SFT
使用输入—期望输出或多轮 Messages,优化模型生成标准回答。常用于:
- 分类和信息抽取。
- 固定 JSON Schema。
- 客服语气和拒答边界。
- 工具选择与参数格式。
- 领域问答表达方式。
SFT 学到的是样本所展示的行为。训练数据只包含“成功回答”时,模型不会自动学会何时澄清、拒绝或转人工。
3.3 偏好对齐
给同一输入提供更优与较差回答,或通过奖励信号,使模型更偏向有用、安全、符合风格的结果。它不能替代事实来源,也会继承偏好数据和评审标准的偏差。
3.4 全量微调
更新基础模型大部分或全部参数。表达能力强,但需要保存权重、梯度、优化器状态和激活,训练资源、存储和灾难性遗忘风险高。
3.5 LoRA和QLoRA
LoRA 冻结基础权重,在目标线性层旁增加低秩矩阵,只训练少量 Adapter 参数。QLoRA 进一步以低比特加载冻结基础权重,同时训练较高精度的 LoRA Adapter。详细原理见 LoRA与QLoRA。
3.6 托管微调
模型厂商管理训练基础设施,用户上传数据并选择参数。优点是运维简单,缺点是模型、数据格式、评估、地域、费用、数据保留和导出能力受平台约束。上传前必须完成数据授权和合规审查。
四、一条完整微调流水线
flowchart TD
A["定义任务、风险和验收指标"] --> B["建立原模型+Prompt/RAG基线"]
B --> C["收集和授权原始数据"]
C --> D["清洗、去重、脱敏、标注"]
D --> E["按实体/时间/来源分组切分"]
E --> F["冻结独立测试集"]
F --> G["选择基础模型和微调方式"]
G --> H["Chat Template、Tokenize和Label Mask"]
H --> I["小规模冒烟训练"]
I --> J["正式训练、验证和Checkpoint"]
J --> K["质量、安全、回归和成本评估"]
K --> L{"是否超过基线且硬门槛达标"}
L -->|"否"| M["回到数据、任务或训练配置"]
L -->|"是"| N["Shadow与小流量Canary"]
N --> O["线上监控、人工反馈和漂移检测"]
O --> P{"是否稳定"}
P -->|"否"| Q["路由回滚并保留证据"]
P -->|"是"| R["逐步扩流并进入下一数据闭环"]任何一个模型产物都要能回答:
基于哪个基础模型和Tokenizer
使用哪个数据版本和切分清单
使用哪个代码Commit和训练配置
在哪种硬件和库版本训练
选择哪个Checkpoint以及为什么
通过哪些评估集和安全门槛
使用什么推理参数和Prompt
当前灰度范围和回滚目标是什么五、先写任务定义,不要先写训练脚本
一个可训练任务说明至少包含:
| 字段 | 采集异常分类示例 |
|---|---|
| 输入 | 脱敏错误摘要、数据源类型、阶段 |
| 输出 | category、severity、reasonCode、needHuman |
| 类别定义 | DB_TIMEOUT 与 NETWORK_TIMEOUT如何区分 |
| 禁止行为 | 不输出连接密码,不建议自动重跑 |
| 澄清条件 | 日志不足或错误码冲突时 needHuman=true |
| 业务指标 | Macro-F1、关键类别召回率、JSON合法率 |
| 安全硬门槛 | 敏感字段泄露率0、越权建议率0 |
| 延迟/成本 | P95和单请求成本阈值 |
| 回归范围 | 通用问答、拒答和中文表达不明显退化 |
目标“让模型更懂医疗”无法直接标注和验收。目标必须转成具体输入、输出、边界和指标。
六、为什么必须先建立基线
至少比较:
基础模型 + 当前Prompt
基础模型 + 优化Prompt
基础模型 + RAG/Tool(若适用)
微调模型 + 同等Prompt/上下文没有基线会产生两个误判:
- 微调后分数 85%,看起来很好,但优化 Prompt 已经能达到 88%。
- 微调后输出更像训练话术,被主观认为“更懂业务”,实际事实正确率下降。
评估必须固定数据、推理参数和评分规则。若微调模型和基线使用不同 RAG 结果或不同最大输出长度,差异不能全部归因于微调。
七、训练内部发生了什么
7.1 Chat样本如何成为训练序列
原始样本:
{
"messages": [
{"role": "system", "content": "输出故障分类JSON。"},
{"role": "user", "content": "连接数据库30秒后超时。"},
{"role": "assistant", "content": "{\"category\":\"DATABASE\",\"reasonCode\":\"DB_TIMEOUT\"}"}
]
}必须使用基础模型配套 Chat Template 转为模型约定的角色 Token 和文本,再由 Tokenizer 生成 input_ids。不同模型模板不同,手工拼接 system: ... user: ... 可能与模型训练格式不一致。
7.2 Labels和Loss Mask
自回归模型通常把序列右移作为下一个 Token 标签。SFT 常只希望对 Assistant 答案计算 Loss,将 System/User/Pad 位置的 label 设置为忽略值,例如 -100:
Token位置: [System] [User问题] [Assistant答案] [PAD]
是否算Loss: 否 否 是 否如果所有位置都计算 Loss,模型会花能力学习复述用户和模板;如果 Mask 错把 Assistant 答案也遮住,训练 Loss 可能异常但模型根本学不到目标。
7.3 Forward、Loss、Backward和Step
flowchart TD
A["Batch的input_ids和labels"] --> B["前向传播得到每位置Logits"]
B --> C["只在未Mask位置计算交叉熵"]
C --> D["得到当前Batch Loss"]
D --> E["反向传播累积梯度"]
E --> F{"达到梯度累积步数"}
F -->|"否"| A
F -->|"是"| G["梯度裁剪与优化器Step"]
G --> H["学习率调度器更新"]
H --> I["清空梯度进入下一轮"]一个 Optimizer Step 不一定等于一个小 Batch。梯度累积用多个 Micro Batch 的梯度近似更大的有效 Batch:
有效Batch ≈ 每设备Batch × 梯度累积步数 × 数据并行设备数7.4 Epoch、Step和Checkpoint
- Epoch:训练集被遍历一遍。
- Micro Step:一个小批次前向/反向。
- Optimizer Step:真正更新参数一次。
- Checkpoint:保存可恢复的模型/Adapter、优化器、调度器和随机状态。
训练三轮不意味着第三轮最好。验证指标可能第一轮后开始下降,必须按验证集和业务指标选择 Checkpoint,而不是只拿最后一个。
八、训练Loss下降为什么不等于有效
可能出现:
| 现象 | 原因 |
|---|---|
| Train Loss下降,Validation Loss上升 | 过拟合 |
| Loss下降,业务指标不变 | Loss与业务指标不完全一致 |
| JSON更稳定,事实更差 | 样本过度强化格式但事实不足 |
| 测试分数极高,线上差 | 数据泄漏或分布不一致 |
| 目标任务提高,通用能力下降 | 灾难性遗忘 |
| 离线好,延迟成本不可接受 | 模型/输出变大或部署配置不同 |
Loss 是训练优化信号,不是最终商业验收。生产上线必须同时看任务质量、安全、回归、延迟和成本。
九、过拟合和灾难性遗忘
9.1 过拟合
模型记住训练样本表述,却不能泛化到新输入。信号包括 Train Loss 持续下降、验证指标不升反降,以及改写问题后性能骤降。
治理:提高数据多样性、去重、降低 Epoch/学习率、Early Stopping、正则化、增加真实验证样本,而不是盲目扩大 Rank。
9.2 灾难性遗忘
过窄数据和过强更新会让模型在目标任务变好时损害原能力。要建立通用能力保持集、安全回归集,并考虑较小学习率、参数高效微调、混合少量高质量保持样本。保持样本也必须合法且与目标权衡经过评估。
十、基础模型怎样选择
| 维度 | 检查 |
|---|---|
| 基础能力 | 未微调时是否已经接近目标 |
| 许可证 | 是否允许训练、商业使用、分发和合并权重 |
| 语言领域 | 中文、代码、医疗术语表现 |
| 上下文 | 实际输入长度和有效利用能力 |
| 架构支持 | 训练框架是否支持对应层名和精度 |
| 推理成本 | 微调后能否在生产SLO和预算内服务 |
| Tokenizer | 特殊术语和结构化文本Token效率 |
| 安全 | 原模型拒答、偏见和高风险能力 |
微调通常改善已有潜在能力,不应指望一个完全不会目标任务的小模型通过几十条样本超越强基础模型。
十一、微调方式选择
| 方式 | 训练参数 | 优点 | 代价/边界 |
|---|---|---|---|
| 全量微调 | 全部或大部分 | 调整空间大 | 显存、存储、遗忘和发布成本高 |
| LoRA | 低秩Adapter | 成本低、可多Adapter | Rank/目标层有限,仍需评估 |
| QLoRA | 量化基础权重+LoRA | 进一步降低权重显存 | 量化和Kernel兼容复杂,训练不等于纯4bit计算 |
| 托管微调 | 平台决定 | 基础设施简单 | 数据、能力、导出和成本受平台约束 |
选择不是越省显存越好,还要看任务提升、训练稳定性、部署引擎是否支持动态 Adapter,以及多租户 Adapter 隔离。
十二、可运行Demo:微调方案决策记录
下面的脚本不替代专家评审,而是强制团队把需求分类和证据写清楚,避免“因为大家都在微调”就启动训练。
from dataclasses import dataclass
from enum import Enum
class PrimaryGap(str, Enum):
INSTRUCTION = "INSTRUCTION"
KNOWLEDGE = "KNOWLEDGE"
REALTIME_DATA = "REALTIME_DATA"
STABLE_BEHAVIOR = "STABLE_BEHAVIOR"
BASE_CAPABILITY = "BASE_CAPABILITY"
@dataclass(frozen=True)
class ProjectEvidence:
gap: PrimaryGap
prompt_baseline_ready: bool
frozen_test_set_ready: bool
authorized_training_data: bool
stable_task_definition: bool
base_model_has_potential: bool
def recommend(evidence: ProjectEvidence) -> tuple[str, list[str]]:
reasons: list[str] = []
if evidence.gap == PrimaryGap.KNOWLEDGE:
return "RAG", ["知识需要更新、引用和权限过滤"]
if evidence.gap == PrimaryGap.REALTIME_DATA:
return "TOOL_CALLING", ["实时事实必须来自权威业务系统"]
if evidence.gap == PrimaryGap.INSTRUCTION and not evidence.prompt_baseline_ready:
return "PROMPT_FIRST", ["尚未证明Prompt优化不能解决问题"]
if evidence.gap == PrimaryGap.BASE_CAPABILITY or not evidence.base_model_has_potential:
return "CHANGE_MODEL_OR_TASK", ["微调不能凭少量数据创造缺失的基础能力"]
if evidence.gap != PrimaryGap.STABLE_BEHAVIOR:
reasons.append("问题不是稳定、重复的行为映射")
if not evidence.stable_task_definition:
reasons.append("输入、输出和验收标准尚未冻结")
if not evidence.prompt_baseline_ready:
reasons.append("缺少可比较的Prompt基线")
if not evidence.frozen_test_set_ready:
reasons.append("缺少独立冻结测试集")
if not evidence.authorized_training_data:
reasons.append("训练数据授权或合规未完成")
if reasons:
return "NOT_READY", reasons
return "CONSIDER_SFT_LORA", ["满足进入小规模微调实验的前置条件"]
if __name__ == "__main__":
evidence = ProjectEvidence(
gap=PrimaryGap.STABLE_BEHAVIOR,
prompt_baseline_ready=True,
frozen_test_set_ready=True,
authorized_training_data=True,
stable_task_definition=True,
base_model_has_potential=True,
)
print(recommend(evidence))脚本输出“考虑微调”也不是批准上线,只说明可以开始小规模实验。真实项目还需安全、法务、数据负责人和资源预算审批。
十三、商业场景:采集故障分类
目标:把脱敏错误摘要转换为稳定 JSON,供规则引擎决定告警路由。
{
"category": "DATABASE",
"reasonCode": "DB_TIMEOUT",
"severity": "P2",
"needHuman": false
}边界:
- 模型不直接重跑任务。
- 模型不决定是否删除数据。
- 实时任务状态由工具查询。
- Runbook 通过 RAG 获取。
- 输出必须经过 JSON Schema 和枚举校验。
- P0/P1 和低置信场景转人工。
基线与实验:
A:基础模型+结构化Prompt
B:基础模型+Few-shot
C:LoRA微调模型+相同Schema校验按类别看 Macro-F1 和关键类别召回,不只看总体 Accuracy,因为大量普通错误可能掩盖稀少但高风险类别。
十四、微调项目版本清单
推荐为每个候选模型保存 Manifest:
model_id: collection-classifier-lora-v3
base_model: approved-base-model@immutable-revision
tokenizer_revision: immutable-revision
dataset_version: collection-sft-2026-07-v5
split_manifest: sha256:replace-me
code_commit: replace-me
training_config: configs/lora-v3.yaml
adapter_checkpoint: checkpoint-1200
prompt_version: classify-v7
evaluation_report: reports/eval-v3.json
license_review: APPROVED
security_review: APPROVED
rollback_target: base-model-prompt-v7Tag 如 latest 不能证明内容。基础模型、数据、代码和评估报告都应使用不可变版本或摘要。
十五、成本不能只算GPU训练时间
微调总成本 = 数据授权与清洗
+ 标注与复核
+ 训练与失败实验
+ 评估和人工审核
+ 模型/Adapter存储
+ 推理服务与显存
+ 监控、灰度和回滚
+ 后续数据闭环维护一次训练便宜不代表方案便宜。如果每周知识变化都重训,RAG 可能更可维护;如果微调让小模型达到任务阈值并替代昂贵大模型,长期可能降低推理成本,但必须用真实流量和质量评估证明。
十六、生产排查Runbook
16.1 训练Loss正常但业务指标没提升
检查 Label Mask、Chat Template、截断是否保留答案、训练集与评估任务是否一致、指标实现和解码参数。先抽样对照原始样本、Token和Label,不要直接增加 Epoch。
16.2 验证很好,线上很差
检查实体/时间/模板泄漏、测试集是否来自同一工单复制、线上输入长度和类别分布、Prompt/RAG差异、模型服务是否加载正确 Adapter。冻结线上失败样本,不能拿回训练后继续声称原测试独立。
16.3 输出风格改善但事实错误增加
微调学到了“回答得像”,没有实时事实来源。恢复 RAG/Tool,增加拒答和不确定样本,并把事实/引用作为独立硬指标。高质量措辞不能抵消事实错误。
16.4 通用能力下降
使用通用保持集定位退化类别,比较不同 Checkpoint、学习率、Epoch、Rank和目标层。必要时降低更新强度、增加合法保持样本或放弃该基础模型微调方案。
16.5 无法复现训练结果
检查基础模型 Revision、数据 Manifest、代码 Commit、依赖/驱动、随机种子、硬件、训练配置和 Checkpoint。随机种子不能保证跨硬件和Kernel绝对逐位一致,但缺少这些信息连合理复现都无法开始。
十七、常见误区
数据越多越好
错误。重复、矛盾、错误、越权和泄露样本会放大坏模式。质量、覆盖和合法性优先。
微调能让模型知道最新订单
错误。订单是实时事实,应查询业务工具。
微调后可以不要Prompt
错误。运行时任务、权限、输出Schema和当前上下文仍需Prompt或应用配置。
Loss越低模型越好
错误。Loss不直接等于业务正确率、安全和泛化。
测试集只要不用于梯度更新就没泄漏
错误。反复根据测试结果调数据、Prompt和超参数也会把团队决策过拟合到测试集。
LoRA一定不会损害基础能力
错误。Adapter仍会改变目标层输出,过强或窄数据同样可能导致回归。
十八、面试标准回答
微调是什么
微调是在已有基础模型上,用目标任务数据继续训练全部参数或Adapter,使模型更稳定地学习某类输入到输出的行为映射。它适合格式、风格、分类、抽取和工具参数等稳定模式,不适合替代实时数据库或频繁更新且要求引用的知识。
RAG和微调怎么选
缺外部、私有、频繁更新且要引用的知识优先RAG;缺实时状态或动作使用Tool Calling;Prompt已明确、任务行为长期稳定且基础模型有潜在能力时才考虑微调。实际系统可以组合:微调做分类,RAG给Runbook,工具查实时状态。
为什么训练Loss下降不代表可上线
Loss衡量训练Token预测目标,可能因记忆训练数据而下降。上线还要在独立测试集与基线比较业务指标、安全硬门槛、通用回归、延迟和成本,并通过Shadow、Canary和回滚验证真实分布。
SFT中的Label Mask做什么
Chat样本通常包含System、User和Assistant。若只希望模型学习Assistant答案,就把其他位置和Padding的Label设为忽略值,只在答案Token计算Loss。Mask错误可能让模型学习复述输入,或把答案全部遮掉而学不到目标。
十九、学习验收
不看答案完成:
- 为十个需求分别选择 Prompt、RAG、Tool或微调并说明原因。
- 为一个任务写输入、输出、禁止行为和硬门槛。
- 设计基础模型+Prompt与LoRA的公平基线实验。
- 画出 Forward、Loss、Backward、Optimizer Step链路。
- 解释为什么Chat Template和Tokenizer必须匹配基础模型。
- 解释Label Mask错误的两种后果。
- 区分Train Loss、Validation指标和最终测试指标。
- 列出过拟合与灾难性遗忘的证据。
- 运行方案决策Demo,并制造NOT_READY输出。
- 为模型产物填写完整Manifest。
- 计算总成本时加入数据、评估、部署和维护。
- 为线上退化建立版本、流量和样本证据链。
专栏学习顺序
- 微调数据准备:数据授权、清洗、去重、切分、Chat Template、Labels和质量报告。
- LoRA与QLoRA:低秩更新、量化、显存、训练配置和故障排查。
- 微调评估与上线:离线对比、安全门槛、Shadow、Canary、回滚与漂移。
