
Deepseek本地部署、训练与网站集成
Deepseek部署、训练、网站集成
·
Deepseek 模型本地化部署、训练与网站集成指南
目录
使用ollama部署见专栏下篇文章
1. Deepseek 模型概述
Deepseek 是由深度求索科技开发的大型语言模型系列,具有出色的中文理解和生成能力。该模型系列提供了不同参数规模的版本,从轻量级到大规模均有覆盖。
主要模型系列:
- Deepseek-LLM: 基础大语言模型
- Deepseek-Coder: 专注于代码生成的模型
- Deepseek-VL: 视觉语言模型
- Deepseek-MoE: 混合专家模型
2. 环境准备
2.1 硬件要求
根据模型的规模,硬件要求会有所不同:
模型规模 | 最低 GPU 显存 | 推荐配置 |
---|---|---|
7B | 16GB | NVIDIA RTX 3090/4090 或 A100 |
13B | 24GB | NVIDIA A10G 或 A100 |
70B | 80GB+ | 多卡设置或 NVIDIA A100 80GB |
2.2 软件环境
# 创建虚拟环境
conda create -n deepseek python=3.10
conda activate deepseek
# 安装 PyTorch (CUDA 11.8 版本示例)
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
# 安装 Deepseek 相关依赖
pip install transformers>=4.34.0
pip install accelerate>=0.23.0
pip install bitsandbytes>=0.41.0
pip install sentencepiece
pip install einops
3. 本地部署 Deepseek
3.1 下载模型
从 Hugging Face 下载 Deepseek 模型:
from huggingface_hub import snapshot_download
# 下载 Deepseek-LLM-7B 模型
model_path = snapshot_download(
repo_id="deepseek-ai/deepseek-llm-7b-base",
local_dir="./models/deepseek-llm-7b-base"
)
或使用命令行:
git lfs install
git clone https://huggingface.co/deepseek-ai/deepseek-llm-7b-base
3.2 基础推理
使用 Transformers 库进行简单推理:
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
# 加载模型和分词器
model_path = "./models/deepseek-llm-7b-base" # 或使用 "deepseek-ai/deepseek-llm-7b-base"
tokenizer = AutoTokenizer.from_pretrained(model_path)
model = AutoModelForCausalLM.from_pretrained(
model_path,
torch_dtype=torch.bfloat16,
device_map="auto",
)
# 构建输入
input_text = "你好,请介绍一下你自己"
inputs = tokenizer(input_text, return_tensors="pt").to(model.device)
# 生成回答
with torch.no_grad():
outputs = model.generate(
inputs["input_ids"],
max_new_tokens=512,
do_sample=True,
temperature=0.7,
top_p=0.95,
)
# 解码输出
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(response)
3.3 量化部署
对于内存受限的环境,可以使用量化技术降低内存占用:
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
# 4-bit 量化配置
quantization_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_compute_dtype=torch.bfloat16,
bnb_4bit_quant_type="nf4",
bnb_4bit_use_double_quant=True,
)
# 加载量化模型
model_path = "deepseek-ai/deepseek-llm-7b-base"
tokenizer = AutoTokenizer.from_pretrained(model_path)
model = AutoModelForCausalLM.from_pretrained(
model_path,
quantization_config=quantization_config,
device_map="auto",
)
3.4 使用 vLLM 加速推理
vLLM 是一个高效的 LLM 推理引擎,可以显著提升推理速度:
pip install vllm
使用 vLLM 部署 Deepseek:
from vllm import LLM, SamplingParams
# 初始化 LLM
llm = LLM(
model="deepseek-ai/deepseek-llm-7b-base",
dtype="bfloat16",
gpu_memory_utilization=0.8,
)
# 设置生成参数
sampling_params = SamplingParams(
temperature=0.7,
top_p=0.95,
max_tokens=512,
)
# 生成回答
prompts = ["你好,请介绍一下你自己"]
outputs = llm.generate(prompts, sampling_params)
# 打印结果
for output in outputs:
print(output.text)
3.5 创建本地 API 服务
使用 FastAPI 创建本地 API 服务:
# api_server.py
from fastapi import FastAPI, Request
import uvicorn
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
app = FastAPI()
# 全局模型和分词器
model_path = "deepseek-ai/deepseek-llm-7b-base"
tokenizer = AutoTokenizer.from_pretrained(model_path)
model = AutoModelForCausalLM.from_pretrained(
model_path,
torch_dtype=torch.bfloat16,
device_map="auto",
)
@app.post("/generate")
async def generate(request: Request):
data = await request.json()
prompt = data.get("prompt", "")
max_tokens = data.get("max_tokens", 512)
temperature = data.get("temperature", 0.7)
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
with torch.no_grad():
outputs = model.generate(
inputs["input_ids"],
max_new_tokens=max_tokens,
do_sample=True,
temperature=temperature,
top_p=0.95,
)
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
return {"response": response}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
启动服务:
python api_server.py
4. 模型训练与微调
4.1 数据准备
准备训练数据格式:
[
{
"instruction": "解释量子计算的基本原理",
"output": "量子计算是一种利用量子力学现象(如叠加和纠缠)进行计算的技术..."
},
{
"instruction": "写一篇关于人工智能伦理的短文",
"output": "人工智能伦理是一个日益重要的领域,涉及到 AI 系统的设计、开发和应用..."
}
]
4.2 使用 LoRA 进行高效微调
LoRA (Low-Rank Adaptation) 是一种参数高效的微调方法,可以大大降低显存需求:
from peft import prepare_model_for_kbit_training, LoraConfig, get_peft_model
# 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,
bias="none",
task_type="CAUSAL_LM",
)
# 准备模型
model = prepare_model_for_kbit_training(model)
model = get_peft_model(model, lora_config)
4.3 训练脚本
import torch
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
BitsAndBytesConfig,
TrainingArguments
)
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
from trl import SFTTrainer
import json
# 1. 加载数据
with open("training_data.json", "r", encoding="utf-8") as f:
data = json.load(f)
# 2. 准备数据集
from datasets import Dataset
dataset = Dataset.from_list(data)
# 3. 初始化量化配置
quantization_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_compute_dtype=torch.bfloat16,
bnb_4bit_quant_type="nf4",
bnb_4bit_use_double_quant=True,
)
# 4. 加载基础模型和分词器
model_path = "deepseek-ai/deepseek-llm-7b-base"
tokenizer = AutoTokenizer.from_pretrained(model_path)
model = AutoModelForCausalLM.from_pretrained(
model_path,
quantization_config=quantization_config,
device_map="auto",
)
# 5. 配置 LoRA
lora_config = LoraConfig(
r=16,
lora_alpha=32,
target_modules=[
"q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj",
],
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
)
# 6. 准备 LoRA 模型
model = prepare_model_for_kbit_training(model)
model = get_peft_model(model, lora_config)
# 7. 设置训练参数
training_arguments = TrainingArguments(
output_dir="./deepseek-lora-output",
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
learning_rate=2e-4,
num_train_epochs=3,
logging_steps=10,
save_steps=100,
save_total_limit=3,
report_to="tensorboard",
fp16=True,
)
# 8. 创建训练器
def formatting_func(examples):
texts = []
for instruction, output in zip(examples["instruction"], examples["output"]):
text = f"<|user|>\n{instruction}\n<|assistant|>\n{output}<|endoftext|>"
texts.append(text)
return {"text": texts}
trainer = SFTTrainer(
model=model,
train_dataset=dataset,
formatting_func=formatting_func,
args=training_arguments,
tokenizer=tokenizer,
max_seq_length=2048,
)
# 9. 开始训练
trainer.train()
# 10. 保存模型
trainer.save_model("./deepseek-finetuned")
# 11. 合并 LoRA 权重到基础模型 (可选)
from peft import PeftModel
base_model = AutoModelForCausalLM.from_pretrained(
model_path,
torch_dtype=torch.bfloat16,
device_map="auto"
)
lora_model = PeftModel.from_pretrained(base_model, "./deepseek-finetuned")
merged_model = lora_model.merge_and_unload()
merged_model.save_pretrained("./deepseek-merged")
5. 网站集成
5.1 使用 JavaScript 与模型 API 交互
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Deepseek 演示</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.chat-container {
border: 1px solid #ddd;
padding: 20px;
height: 400px;
overflow-y: auto;
margin-bottom: 20px;
border-radius: 8px;
}
.user-message {
background-color: #e6f7ff;
padding: 10px;
border-radius: 8px;
margin-bottom: 10px;
}
.bot-message {
background-color: #f0f0f0;
padding: 10px;
border-radius: 8px;
margin-bottom: 10px;
}
.input-container {
display: flex;
}
#user-input {
flex: 1;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
margin-right: 10px;
}
button {
background-color: #1890ff;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
}
</style>
</head>
<body>
<h1>Deepseek 对话演示</h1>
<div class="chat-container" id="chat-container"></div>
<div class="input-container">
<input type="text" id="user-input" placeholder="输入您的问题...">
<button id="send-button">发送</button>
</div>
<script>
const chatContainer = document.getElementById('chat-container');
const userInput = document.getElementById('user-input');
const sendButton = document.getElementById('send-button');
function addMessage(text, isUser) {
const messageDiv = document.createElement('div');
messageDiv.className = isUser ? 'user-message' : 'bot-message';
messageDiv.textContent = text;
chatContainer.appendChild(messageDiv);
chatContainer.scrollTop = chatContainer.scrollHeight;
}
async function sendMessage() {
const message = userInput.value.trim();
if (!message) return;
// 添加用户消息到聊天框
addMessage(message, true);
userInput.value = '';
userInput.disabled = true;
sendButton.disabled = true;
try {
// 发送请求到您的本地API
const response = await fetch('http://localhost:8000/generate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
prompt: message,
max_tokens: 512,
temperature: 0.7,
}),
});
const data = await response.json();
// 添加模型回复到聊天框
addMessage(data.response, false);
} catch (error) {
console.error('Error:', error);
addMessage('抱歉,连接服务器时出现错误', false);
} finally {
userInput.disabled = false;
sendButton.disabled = false;
userInput.focus();
}
}
sendButton.addEventListener('click', sendMessage);
userInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') sendMessage();
});
// 初始欢迎消息
addMessage('你好!我是 Deepseek 助手,有什么可以帮助你的吗?', false);
</script>
</body>
</html>
5.2 使用 Python 框架集成
Flask 示例
from flask import Flask, render_template, request, jsonify
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
app = Flask(__name__)
# 全局模型和分词器
model_path = "./deepseek-finetuned" # 使用微调后的模型
tokenizer = AutoTokenizer.from_pretrained(model_path)
model = AutoModelForCausalLM.from_pretrained(
model_path,
torch_dtype=torch.bfloat16,
device_map="auto",
)
@app.route('/')
def index():
return render_template('index.html') # 创建HTML模板
@app.route('/api/chat', methods=['POST'])
def chat():
data = request.json
user_message = data.get('message', '')
# 构建输入
prompt = f"<|user|>\n{user_message}\n<|assistant|>\n"
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
# 生成回答
with torch.no_grad():
outputs = model.generate(
inputs["input_ids"],
max_new_tokens=512,
do_sample=True,
temperature=0.7,
top_p=0.95,
)
# 处理回答
full_response = tokenizer.decode(outputs[0], skip_special_tokens=False)
assistant_response = full_response.split("<|assistant|>\n")[-1].replace("<|endoftext|>", "").strip()
return jsonify({"response": assistant_response})
if __name__ == '__main__':
app.run(debug=True)
Django 示例
# views.py
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.shortcuts import render
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
import json
# 全局模型和分词器
model_path = "./deepseek-finetuned"
tokenizer = AutoTokenizer.from_pretrained(model_path)
model = AutoModelForCausalLM.from_pretrained(
model_path,
torch_dtype=torch.bfloat16,
device_map="auto",
)
def index(request):
return render(request, 'index.html')
@csrf_exempt
def chat_api(request):
if request.method == 'POST':
data = json.loads(request.body)
user_message = data.get('message', '')
# 构建输入
prompt = f"<|user|>\n{user_message}\n<|assistant|>\n"
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
# 生成回答
with torch.no_grad():
outputs = model.generate(
inputs["input_ids"],
max_new_tokens=512,
do_sample=True,
temperature=0.7,
top_p=0.95,
)
# 处理回答
full_response = tokenizer.decode(outputs[0], skip_special_tokens=False)
assistant_response = full_response.split("<|assistant|>\n")[-1].replace("<|endoftext|>", "").strip()
return JsonResponse({"response": assistant_response})
return JsonResponse({"error": "仅支持 POST 请求"}, status=400)
6. 性能优化
6.1 模型量化与优化
除了前面提到的 4-bit 量化,还可以尝试:
- GPTQ 量化:
pip install auto-gptq
from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig
quantize_config = BaseQuantizeConfig(
bits=4,
group_size=128,
desc_act=False,
)
# 量化模型
model = AutoGPTQForCausalLM.from_pretrained(
model_path,
quantize_config=quantize_config,
)
- ONNX 格式转换:
pip install optimum
from optimum.onnxruntime import ORTModelForCausalLM
# 转换为 ONNX 格式
model = ORTModelForCausalLM.from_pretrained(
model_path,
export=True,
provider="CUDAExecutionProvider",
)
6.2 推理优化
-
使用持久连接:
在网站和 API 之间使用 WebSocket 或持久化 HTTP 连接,减少连接建立的开销。 -
实现请求队列:
使用 Redis 或 RabbitMQ 等消息队列系统管理高负载下的请求。 -
模型并行推理:
from concurrent.futures import ThreadPoolExecutor
import queue
request_queue = queue.Queue()
response_dict = {}
def worker():
while True:
request_id, prompt = request_queue.get()
# 处理推理请求
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
with torch.no_grad():
outputs = model.generate(
inputs["input_ids"],
max_new_tokens=512,
)
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
response_dict[request_id] = response
request_queue.task_done()
# 启动工作线程
executor = ThreadPoolExecutor(max_workers=1)
executor.submit(worker)
7. 常见问题解答
7.1 模型加载失败
问题: CUDA out of memory
错误。
解决方案:
- 尝试 4-bit 或 8-bit 量化
- 减小批处理大小
- 使用较小的模型版本
7.2 生成速度慢
问题: 模型响应时间长。
解决方案:
- 使用 vLLM 加速推理
- 应用 ONNX 转换
- 减少生成的最大 token 数
- 考虑使用更小的模型
7.3 训练不稳定
问题: 微调过程中损失值不收敛或出现 NaN。
解决方案:
- 降低学习率
- 增加梯度截断值
- 检查数据集格式和质量
- 增加 warmup 步数
7.4 内存泄漏
问题: 长时间运行后内存占用持续增加。
解决方案:
- 确保每次推理后调用
torch.cuda.empty_cache()
- 考虑定期重启服务
- 检查代码中可能的引用循环
7.5 模型输出质量问题
问题: 微调后的模型输出质量下降。
解决方案:
- 检查训练数据质量
- 降低训练 epoch 数,避免过拟合
- 尝试不同的微调参数
- 增加训练数据的多样性
更多推荐
所有评论(0)