微调与私有化部署
绝大多数「我们需要微调」的需求,其实是RAG 或 Prompt 没做好。 这篇先讲什么时候真的该微调,再讲怎么做、怎么部署、怎么算钱。
一、先判断:微调是不是你需要的
| 你的问题 | 该用什么 |
|---|---|
| 模型不知道你们公司的业务知识 | RAG(知识时效性强、要引用来源) |
| 输出格式总是不对 | Prompt + 结构化输出(JSON Mode),实在不行再微调 |
| 语气/风格要像某个角色 | Prompt 写人设,微调是加分项 |
| 某类任务要稳定达到高准确率(分类、抽取、改写) | 微调 |
| 要降低延迟/成本(用小模型替代大模型) | 微调小模型(蒸馏) |
| 数据不能出内网 | 私有化部署(未必需要微调) |
一条经验:先 Prompt,再 RAG,最后微调。微调是「改模型的行为」,不是「塞知识」—— 用微调记知识,会遇到更新困难、幻觉、以及「问细节就崩」的问题。
二、微调能改什么、不能改什么
| 能 | 不能 |
|---|---|
| 输出格式、风格、语气 | 记住大量事实性知识(会编) |
| 特定任务的模式(分类口径、抽取规范) | 实时信息 |
| 减少对长 Prompt 的依赖 | 解决「推理能力不足」(那是模型规模问题) |
| 让小模型逼近大模型在窄任务上的表现 | 通用能力全面提升 |
三、SFT 的数据怎么造
数据三条来源
| 来源 | 质量 | 成本 |
|---|---|---|
| 人工标注(专家写) | 最高 | 最贵 |
| 业务日志清洗(真实问答 + 人工修正) | 高 | 中 |
| 强模型生成 + 人工筛选(蒸馏) | 中 | 低 |
数据格式(对话式 SFT)
json
{"messages": [
{"role": "system", "content": "你是客服助手,只回答退换货相关问题。"},
{"role": "user", "content": "耳机坏了能退吗"},
{"role": "assistant", "content": "7 天内非人为损坏可退,请提供订单号。"}
]}{"messages": [
{"role": "system", "content": "你是客服助手,只回答退换货相关问题。"},
{"role": "user", "content": "耳机坏了能退吗"},
{"role": "assistant", "content": "7 天内非人为损坏可退,请提供订单号。"}
]}五条数据纪律
- 量不是关键,一致性才是:500 条高质量 > 5000 条噪声;
- 覆盖边界:正例之外要有「不该回答时怎么拒绝」的样本;
- 去重:重复样本会让模型过拟合到特定表述;
- 划分验证集:训练/验证/测试分开,测试集绝不参与调参;
- 清洗掉模型自身错误(用模型生成的数据要先筛,否则错误会被固化)。
四、LoRA 与 QLoRA
全参数微调要更新所有参数(7B 模型也要几十 GB 显存)。LoRA 的思路:冻结原模型,只训练很小的低秩矩阵。
原始权重 W(冻结) + ΔW = B·A(低秩,可训练)
h = Wx + (α/r)·BAx原始权重 W(冻结) + ΔW = B·A(低秩,可训练)
h = Wx + (α/r)·BAx| 参数 | 含义 | 常用值 |
|---|---|---|
r(rank) | 低秩维度,越大容量越强 | 8 / 16 / 32 |
alpha | 缩放系数,通常 = 2r | 16 / 32 |
target_modules | 加到哪些层 | q_proj/k_proj/v_proj/o_proj(或全部线性层) |
dropout | 防过拟合 | 0.05 ~ 0.1 |
learning_rate | 学习率(比全参大) | 1e-4 ~ 3e-4 |
QLoRA = LoRA + 4bit 量化基座(NF4),让 7B 模型能在单卡 24GB 上训练。
python
# 伪代码(transformers + peft)
model = load_quantized("qwen2-7b", load_in_4bit=True) # QLoRA
model = get_peft_model(model, LoraConfig(
r=16, lora_alpha=32, lora_dropout=0.05,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],
task_type="CAUSAL_LM",
))
trainer.train()
model.save_pretrained("out/lora") # 只存几十 MB 的 adapter# 伪代码(transformers + peft)
model = load_quantized("qwen2-7b", load_in_4bit=True) # QLoRA
model = get_peft_model(model, LoraConfig(
r=16, lora_alpha=32, lora_dropout=0.05,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],
task_type="CAUSAL_LM",
))
trainer.train()
model.save_pretrained("out/lora") # 只存几十 MB 的 adapter优势:显存小、训练快、adapter 只有几十 MB,可热插拔多套。 代价:容量有限,复杂任务不如全参;推理时多一次矩阵乘(可合并进原权重)。
五、训练流程与坑
造数据 → 划分集 → 基线评测(不微调先测一遍!)→ 训练 → 验证集看 loss
→ 测试集评测(规则 + judge)→ 人工抽检 → 上线灰度造数据 → 划分集 → 基线评测(不微调先测一遍!)→ 训练 → 验证集看 loss
→ 测试集评测(规则 + judge)→ 人工抽检 → 上线灰度必须先跑基线:不微调前测一遍,否则你不知道微调到底提升了多少(甚至可能变差)。
| 坑 | 表现 | 处理 |
|---|---|---|
| 过拟合 | 训练 loss 降、验证 loss 升 | 减 epoch、加 dropout、减 r |
| 灾难性遗忘 | 通用能力下降 | 混入通用数据、降低学习率 |
| 格式崩坏 | 输出不带标签了 | 检查模板是否与推理一致 |
| 数据泄漏 | 测试集分数虚高 | 严格切分、去重 |
| 模板不一致 | 线上效果远差于训练 | 训练与推理用同一 chat template |
六、私有化部署:四种形态
| 形态 | 说明 | 适用 |
|---|---|---|
| 裸模型 + 推理框架 | vLLM / SGLang 起服务,自己封装 API | 有运维能力 |
| 一体化平台 | 平台包办部署、监控、扩缩容 | 中小团队 |
| 一体机 | 厂商交付硬件 + 模型 | 强合规、无运维 |
| 云上专属实例 | 云厂商托管的独享资源 | 弹性需求 |
七、推理优化(部署侧最值钱的部分)
| 手段 | 原理 | 收益 |
|---|---|---|
| PagedAttention(vLLM) | KV Cache 分页管理,消除碎片 | 吞吐 2~4 倍 |
| Continuous Batching | 请求动态进出批 | 高并发下吞吐大涨 |
| 量化(INT8/FP8/AWQ/GPTQ) | 权重降精度 | 显存降一半,速度升,质量略降 |
| KV Cache 复用 / prefix caching | 相同系统提示复用缓存 | 长 system prompt 场景显著 |
| 投机解码(speculative) | 小模型起草、大模型校验 | 延迟降低 |
| 张量并行 | 大模型切到多卡 | 能跑更大模型 |
关键指标:TTFT(首字延迟)、TPOT(每 token 时间)、吞吐(tokens/s)、显存占用。 注意:量化会带来质量损失,必须用量化后的模型重跑评测集,不能沿用原分数。
八、成本怎么算
显存 ≈ 参数量 × 精度字节数(FP16: 2B/参数)+ KV Cache
· 7B FP16 ≈ 14GB(还要给 KV Cache 留 10~20GB)
· 7B INT4 ≈ 4GB
吞吐估算:单卡 A100 跑 7B + vLLM,batch 下可达 2000~4000 tokens/s(视输入长度)
成本 ≈ 单卡时价 × 小时数 / 总 token 数显存 ≈ 参数量 × 精度字节数(FP16: 2B/参数)+ KV Cache
· 7B FP16 ≈ 14GB(还要给 KV Cache 留 10~20GB)
· 7B INT4 ≈ 4GB
吞吐估算:单卡 A100 跑 7B + vLLM,batch 下可达 2000~4000 tokens/s(视输入长度)
成本 ≈ 单卡时价 × 小时数 / 总 token 数国产/开源模型自建 vs 调 API 的分水岭:日调用量稳定且大(比如日均千万 token 以上)、或有数据不出内网要求时,自建才划算;否则 API 更省心。
九、速查
| 问题 | 答案 |
|---|---|
| 什么时候该微调 | 要稳定格式/风格/窄任务准确率,或蒸馏小模型 |
| 什么时候不该 | 要模型「知道」业务知识 → 用 RAG |
| 顺序 | Prompt → RAG → 微调 |
| LoRA 是什么 | 冻结原模型,只训低秩矩阵(几十 MB 的 adapter) |
| QLoRA 加了什么 | 4bit 量化基座,单卡可训 7B |
| 微调前必须做什么 | 先跑基线评测 |
| 最常见的坑 | 数据不一致、模板不一致、灾难性遗忘 |
| 部署用什么 | vLLM / SGLang(PagedAttention + 连续批处理) |
| 量化后要注意 | 必须重跑评测集,分数会变 |
| 什么时候自建 | 量大稳定 + 数据不出内网 |
Cao Note