1538 字
8 分钟
手把手教你微调 DeepSeek 模型:从数据准备到模型部署完整指南

手把手教你微调 DeepSeek 模型:从数据准备到模型部署完整指南#

🎯 开场白:相信很多人都听说过”微调”这个词,但真正动手做过的人不多。原因是啥?门槛太高了呗!又要准备数据、又要调参数、又要租 GPU……听起来就劝退。但其实在 2026 年的今天,微调一个 DeepSeek 模型比你想的要简单得多。今天我就带你走一遍完整流程,保证从零跑到起飞。


一、为什么选 DeepSeek 做微调?#

选 DeepSeek 做微调,有这几点好处:

  1. 模型开源 —— 权重随便下,不用看任何人脸色
  2. 参数量适中 —— 7B/14B,单卡 24G 显存就能跑
  3. 中文底子好 —— 微调后特别适合中文垂直场景
  4. 社区活跃 —— 有问题在 GitHub 上吼一声就有人回

二、环境准备#

2.1 硬件要求#

模型最低显存推荐配置训练方式
DeepSeek-7B16GB24GB (RTX 3090)QLoRA
DeepSeek-14B24GB48GB (A6000)QLoRA
DeepSeek-67B48GB80GB (A100)LoRA

不用怕,后面的示例我用 7B + QLoRA,一张 RTX 3090 就能跑。

2.2 安装依赖#

Terminal window
# 创建虚拟环境
python -m venv finetune-env
source finetune-env/bin/activate
# 安装核心库
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
pip install transformers datasets accelerate peft bitsandbytes
# 安装 DeepSeek 相关
pip install deepseek-llm

三、数据准备#

这是微调最关键的步骤。数据质量决定了模型微调的上限

3.1 数据格式#

DeepSeek 微调使用的是对话格式:

[
{
"instruction": "用 Python 实现一个二分查找算法",
"input": "",
"output": "```python\ndef binary_search(arr, target):\n left, right = 0, len(arr) - 1\n \n while left <= right:\n mid = (left + right) // 2\n if arr[mid] == target:\n return mid\n elif arr[mid] < target:\n left = mid + 1\n else:\n right = mid - 1\n \n return -1\n```\n\n**算法说明**:\n- 时间复杂度:O(log n)\n- 空间复杂度:O(1)\n- 前提条件:数组必须是有序的"
},
{
"instruction": "解释什么是 RESTful API",
"input": "",
"output": "RESTful API(Representational State Transfer)是一种 API 设计规范...(省略 200 字)..."
}
]

3.2 数据增强技巧#

我自己用的一个数据增强脚本,能把少量数据变成大量高质量数据:

import json
import random
from typing import List, Dict
class DataAugmenter:
"""数据增强器:一条数据变成 N 条"""
def __init__(self, seed_data: List[Dict]):
self.data = seed_data
def paraphrase_instruction(self, text: str) -> str:
"""改写指令(用 LLM 做同义改写)"""
templates = [
f"请解释一下:{text}",
f"跟我说说 {text} 是怎么回事",
f"给我详细讲讲 {text}",
f"你能介绍一下 {text} 吗?",
f"关于 {text},你知道些什么?"
]
return random.choice(templates)
def split_long_output(self, output: str) -> List[str]:
"""拆分长输出为多个知识点"""
sections = output.split("\n\n")
return [s.strip() for s in sections if len(s.strip()) > 50]
def augment(self, multiplier: int = 3) -> List[Dict]:
"""增强数据集"""
augmented = []
for item in self.data:
augmented.append(item) # 保留原始
for _ in range(multiplier - 1):
new_item = {
"instruction": self.paraphrase_instruction(item["instruction"]),
"input": item["input"],
"output": item["output"]
}
augmented.append(new_item)
return augmented
# 使用
augmenter = DataAugmenter(raw_data)
final_data = augmenter.augment(multiplier=5)
print(f"数据量:{len(raw_data)}{len(final_data)}")

四、开始微调#

4.1 加载模型和分词器#

import torch
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
BitsAndBytesConfig
)
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
# 4-bit 量化配置(省显存的关键)
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16,
bnb_4bit_use_double_quant=True,
)
# 加载模型
model = AutoModelForCausalLM.from_pretrained(
"deepseek-ai/deepseek-llm-7b-chat",
quantization_config=bnb_config,
device_map="auto",
trust_remote_code=True,
)
# 加载分词器
tokenizer = AutoTokenizer.from_pretrained(
"deepseek-ai/deepseek-llm-7b-chat",
trust_remote_code=True,
)
tokenizer.pad_token = tokenizer.eos_token

4.2 配置 LoRA#

# LoRA 配置——只训练一小部分参数
lora_config = LoraConfig(
r=16, # LoRA 秩,越大效果越好但也越耗显存
lora_alpha=32, # 缩放参数
target_modules=[ # 要微调的目标模块
"q_proj",
"k_proj",
"v_proj",
"o_proj",
"gate_proj",
"up_proj",
"down_proj",
],
lora_dropout=0.05, # Dropout 防止过拟合
bias="none",
task_type="CAUSAL_LM",
)
# 应用 LoRA
model = prepare_model_for_kbit_training(model)
model = get_peft_model(model, lora_config)
# 看看有多少参数被训练
model.print_trainable_parameters()
# 输出: trainable params: 8,388,608 || all params: 6,743,363,584 || trainable%: 0.12%

注意看!总共 67 亿参数,我们只训练了 838 万参数,只占 0.12%!这就是 LoRA 的魔力——少花钱、多办事。

4.3 训练#

from transformers import TrainingArguments, Trainer
training_args = TrainingArguments(
output_dir="./deepseek-finetuned",
num_train_epochs=3,
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
warmup_steps=100,
learning_rate=2e-4,
fp16=True,
logging_steps=10,
save_strategy="epoch",
report_to="none", # 不想看 wandb 可以关掉
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_dataset,
data_collator=default_data_collator,
)
# 开跑!(去泡杯咖啡,半小时后回来)
trainer.train()

4.4 保存模型#

# 保存 LoRA 权重(只有几十 MB)
model.save_pretrained("./my-deepseek-lora")
tokenizer.save_pretrained("./my-deepseek-lora")
# 如果想把 LoRA 合并到原模型(会变大)
from peft import PeftModel
merged_model = PeftModel.from_pretrained(model, "./my-deepseek-lora")
merged_model = merged_model.merge_and_unload()
merged_model.save_pretrained("./my-deepseek-merged")

五、模型评估#

训练完了,效果到底怎么样?来跑个测试:

def evaluate_model(model, tokenizer, test_data):
"""评估微调后的模型"""
results = []
for item in test_data:
prompt = f"### Instruction:\n{item['instruction']}\n\n### Response:\n"
inputs = tokenizer(prompt, return_tensors="pt").to("cuda")
outputs = model.generate(
**inputs,
max_new_tokens=512,
temperature=0.7,
do_sample=True,
)
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
response = response.replace(prompt, "").strip()
results.append({
"instruction": item["instruction"],
"expected": item["output"][:100],
"actual": response[:100],
"match": response[:50] == item["output"][:50]
})
return results
# 执行评估
eval_results = evaluate_model(model, tokenizer, test_data)
accuracy = sum(r["match"] for r in eval_results) / len(eval_results)
print(f"准确率: {accuracy:.2%}")

六、模型部署#

6.1 使用 vLLM 部署#

Terminal window
# 安装 vLLM
pip install vllm
# 启动推理服务
python -m vllm.entrypoints.openai.api_server \
--model ./my-deepseek-merged \
--port 8000 \
--tensor-parallel-size 1

6.2 调用 API#

Terminal window
curl -X POST http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "my-deepseek-merged",
"messages": [
{"role": "user", "content": "用 Python 实现冒泡排序"}
]
}'

6.3 集成到 Hermes#

# hermes config.yaml
custom_providers:
my-finetuned-deepseek:
api_base: http://localhost:8000/v1
model: my-deepseek-merged
api_key: "not-needed"

然后你就可以在 Hermes 里用微调后的模型了:

Terminal window
hermes config set provider custom
hermes config set custom_providers.my-finetuned-deepseek.api_base http://localhost:8000/v1
hermes config set custom_providers.my-finetuned-deepseek.model my-deepseek-merged

七、常见问题#

Q1: 显存不够怎么办?#

QLoRA + 4-bit 量化,7B 模型只需要 8-10GB 显存:

Terminal window
# 用 accelerate 做 CPU offload
accelerate launch --cpu_offload train.py

Q2: 训练完效果不好?#

大概率是数据问题。检查:

  • 数据量是否够(至少 500+ 条)
  • 数据质量(有没有错别字、格式问题)
  • 训练轮数(太多会过拟合,太少学不到)

Q3: 模型回答变得很啰嗦?#

调低 repetition_penalty

outputs = model.generate(
**inputs,
repetition_penalty=1.1, # 默认 1.0,适当提高
)

八、总结#

微调 DeepSeek 的完整流程其实就 5 步:

准备数据 → 配置 LoRA → 开始训练 → 评估效果 → 部署上线

最难的是第一步(数据准备),最花钱的其实没有(一张 3090 就能跑)。比起每个月花几百刀调 API,一次微调,终身受益

💡 最后提醒:微调不是万能药。如果你的场景是通用编程/问答,直接用原版模型就好。微调最适合的是垂直领域——比如你们公司的代码规范、特定业务逻辑、专有术语体系等。


快去看看你的硬盘上有没有合适的训练数据,动手试试吧!

手把手教你微调 DeepSeek 模型:从数据准备到模型部署完整指南
https://www.oferry.com/posts/a95/
作者
晨平安
发布于
2026-05-30
许可协议
CC BY-NC-SA 4.0
封面
示例歌曲
示例艺术家
封面
示例歌曲
示例艺术家
0:00 / 0:00