通用大模型懂天下事,但不懂你的业务:客服话术对不上、输出格式飘忽、行业术语乱用。微调就是把”懂行”这件事写进模型权重里。这篇以 DeepSeek 的开源蒸馏模型为例,用 LLaMA-Factory 走一遍从整理数据到产出可部署模型的完整流程,全部步骤在一块消费级显卡上能跑完。
这篇解决什么问题
先划清边界:DeepSeek 官方 API 目前不提供微调接口,所以微调走的是开源权重路线。对个人开发者,现实的选择是 DeepSeek-R1 蒸馏系列——DeepSeek-R1-Distill-Qwen-1.5B / 7B / 14B / 32B,权重 MIT 协议可商用,底座来自 Qwen2.5 系列,能力保留了大成,尺寸又小到消费级显卡装得下。
微调和 RAG 怎么选,一句话:知识频繁更新、要求可溯源,用 RAG;说话风格、固定格式、任务行为要贴业务,用微调。两者不冲突,常见做法是微调打底、RAG 供料。
环境与版本
| 项目 | 要求 | 说明 |
|---|---|---|
| 显卡 | NVIDIA,显存 12GB 起步(7B + QLoRA 量级),24GB 更从容 | 显存不够先降 batch 和上下文长度 |
| Python | 3.10+ | 与 PyTorch 生态匹配 |
| CUDA | 12.x【待补:实际版本】 | 跟显卡驱动走 |
| 微调框架 | LLaMA-Factory【待补:实际版本号】 | 支持主流开源模型的 LoRA / QLoRA |
| 模型 | DeepSeek-R1-Distill-Qwen-7B(fp16 权重约 15GB,4bit 加载后显存压力小得多) | HuggingFace 或国内镜像下载 |
7B 用 QLoRA(4bit 量化 + LoRA)微调是消费级显卡的标准玩法:LoRA 只训练插进去的低秩小矩阵,显存和磁盘开销都是模型本体的零头。
分步骤走一遍
第一步:定任务,攒数据
微调的天花板是数据。先确定一个窄任务——比如”按固定话术回复物流催单”,再围绕它收集几百条问答对【待补:实际数据条数与来源】。新手最常见的错误是拿三五十条杂乱数据开训,那练不出任何稳定行为。
整理成 alpaca 格式的 JSON,每条包含 instruction、input、output 三个字段:
[
{
"instruction": "把下面的客服问题归类:退款、物流、投诉、咨询。",
"input": "我上周买的鞋码数不对,想换一双。",
"output": "咨询"
},
{
"instruction": "按公司话术回复用户的物流催单问题。",
"input": "快递三天没动了,怎么办?",
"output": "您好,已为您加急查询物流状态,预计 24 小时内同步最新进展,请留意短信通知。"
}
]
第二步:安装 LLaMA-Factory
git clone https://github.com/hiyouga/LLaMA-Factory.git
cd LLaMA-Factory
pip install -e ".[torch,metrics]"
把数据放进 data/ 目录,并在 data/dataset_info.json 里登记一个数据集名,训练配置里引用这个名字:
{
"my_customer_service": {
"file_name": "my_customer_service.json"
}
}
第三步:写训练配置
建一个 r1_lora_sft.yaml,QLoRA 微调 7B 蒸馏模型的典型配置:
### 模型
model_name_or_path: deepseek-ai/DeepSeek-R1-Distill-Qwen-7B
trust_remote_code: true
### 微调方式:LoRA + 4bit 量化(QLoRA)
stage: sft
do_train: true
finetuning_type: lora
lora_target: all
lora_rank: 16
lora_alpha: 32
quantization_bit: 4
### 数据
dataset: my_customer_service
template: TEMPLATE_NAME # 【待补:查 LLaMA-Factory 模板列表,选 DeepSeek-R1 蒸馏模型对应的模板】
cutoff_len: 1024
### 训练参数
per_device_train_batch_size: 1
gradient_accumulation_steps: 8
learning_rate: 1.0e-4
num_train_epochs: 3
lr_scheduler_type: cosine
warmup_ratio: 0.1
bf16: true
gradient_checkpointing: true
### 输出
output_dir: saves/r1-distill-7b-lora
logging_steps: 10
save_steps: 500
plot_loss: true
关键参数的取舍逻辑:lora_rank: 16 对窄任务够用,任务复杂可升到 32 或 64;learning_rate: 1.0e-4 是 LoRA 的常见起点,出问题先往低调;gradient_checkpointing: true 用时间换显存,12GB 显卡的救命开关。
第四步:启动训练
llamafactory-cli train r1_lora_sft.yaml
训练中的正常信号:loss 一路下行并在后段趋平;显存峰值稳定不涨【待补:实际训练时长、峰值显存与最终 loss】。plot_loss: true 会在输出目录生成 loss 曲线图,收工后先看图再下结论。
第五步:合并导出,对话验证
训练完得到的是 LoRA 适配器,合并回基座模型才能独立部署:
model_name_or_path: deepseek-ai/DeepSeek-R1-Distill-Qwen-7B
adapter_name_or_path: saves/r1-distill-7b-lora
template: TEMPLATE_NAME # 与训练时保持一致
export_dir: models/r1-distill-7b-sft
export_size: 4
export_device: cpu
llamafactory-cli export r1_merge.yaml
# 合并完先用命令行聊两句验货
llamafactory-cli chat --model_name_or_path models/r1-distill-7b-sft --template TEMPLATE_NAME
验证满意后,转成 GGUF 量化包,就能丢给 Ollama 常驻运行,部署流程见Ollama 跑 DeepSeek 一篇。

常见坑
坑一:模板选错,模型开始胡言乱语。 每个模型家族有自己的对话模板,训练时 template 配错了,数据会被拼成模型没见过的格式,输出自然混乱。表现是 loss 降了但生成内容前言不搭后语。解法:查 LLaMA-Factory 内置模板列表,选蒸馏模型对应的那个,训练、合并、对话三处保持一致【待补:确认对应模板名】。
坑二:思维链被洗掉。 R1 蒸馏模型的输出自带 <think>...</think> 推理段,如果你的训练数据全是直答、不带思维链,微调会把这个习惯覆盖掉,模型推理能力跟着退化。解法二选一:数据里保留思维链;或者干脆换普通 instruct 底座(比如直接微调 Qwen2.5-7B-Instruct),别在推理模型上做纯直答微调。
坑三:显存 OOM。 12GB 显卡跑 7B QLoRA 也有翻车可能。按顺序降:per_device_train_batch_size 降到 1 → cutoff_len 砍半 → 确认 gradient_checkpointing 已开 → 还不行就把 quantization_bit 保持 4 的同时降 lora_rank。
坑四:学过头。 小数据集训太多轮,模型过拟合到只会背训练集,换个问法就露馅。窄任务 2~3 个 epoch 是常见起点,loss 还在高位的另说;验证时专门准备几条训练集里没出现过的问题。
最终效果
微调成功的判定标准很朴素:拿训练集外的问题问它,输出风格、格式、话术与训练数据一致,且没有出现”整段复读训练样本”的过拟合迹象。量化验收:
- loss 曲线收敛【待补:贴最终 loss 与曲线截图】;
- 微调前后对同一组业务问题的输出对比【待补:贴真实对比样例】;
- 用 20 条训练集外问题做小评测,符合预期格式的比例【待补:实测 %】。
相关阅读
- Ollama 跑 DeepSeek:下载与调用全流程:微调产物的零成本部署去处。
- Ollama 安装与镜像加速:模型下载慢先看这篇。
- DeepSeek API 快速上手:微调值不值,先用官方 API 的 deepseek-chat 验证任务上限。