DeepSeek-R1-Distill-Qwen 是由中国人工智能公司深度求索(DeepSeek)开发的轻量化大语言模型,基于阿里巴巴的Qwen系列模型通过知识蒸馏技术优化而来。当前模型开源后,我们可以将其部署,使用API方式进行本地调用
本文中的部署基础环境如下所示:
PyTorch 2.5.1
Python 3.12(ubuntu22.04)
Cuda 12.4
GPU RTX 3090(24GB) * 1
CPU 14 vCPU Intel(R) Xeon(R) Platinum 8362 CPU @ 2.80GHz
# 升级pip
python -m pip install --upgrade pip
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
pip install requests==2.32.3
pip install fastapi==0.115.8
pip install uvicorn==0.34.0
pip install transformers==4.48.2
pip install huggingface-hub==0.28.1
pip install accelerate==1.3.0
pip install modelscope==1.22.3
使用 modelscope 中的 snapshot_download 函数下载模型,第一个参数为模型名称,参数 cache_dir 为模型的下载路径,这里放在autodl的数据文件夹中比较合适。
from fastapi import FastAPI, Request
from transformers import AutoTokenizer, AutoModelForCausalLM
import uvicorn
import json
import datetime
import torch
import re
DEVICE = "cuda"
DEVICE_ID = "0"
CUDA_DEVICE = f"{DEVICE}:{DEVICE_ID}" if DEVICE_ID else DEVICE
def clear_gpu_cache():
if torch.cuda.is_available():
torch.cuda.empty_cache()
torch.cuda.ipc_collect()
def split_response(text):
match = re.search(r'(.*?) (.*)', text, re.DOTALL)
if match:
return match.group(1).strip(), match.group(2).strip()
return "", text.strip()
app = FastAPI()
@app.post("/")
async def process_request(request: Request):
data = await request.json()
prompt = data.get('prompt', '')
messages = [{"role": "user", "content": prompt}]
input_text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
model_inputs = tokenizer([input_text], return_tensors="pt").to(model.device)
generated_ids = model.generate(model_inputs.input_ids, max_new_tokens=8192)
response_text = tokenizer.batch_decode(generated_ids[:, model_inputs.input_ids.shape[-1]:], skip_special_tokens=True)[0]
think_content, answer_content = split_response(response_text)
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
log_entry = f"[{timestamp}], prompt:\"{prompt}\", response:\"{repr(response_text)}\", think:\"{think_content}\", answer:\"{answer_content}\""
print(log_entry)
clear_gpu_cache()
return {
"response": response_text,
"think": think_content,
"answer": answer_content,
"status": 200,
"time": timestamp
}
if __name__ == '__main__':
model_path = '/root/autodl-tmp/deepseek-ai/DeepSeek-R1-Distill-Qwen-7B'
tokenizer = AutoTokenizer.from_pretrained(model_path, use_fast=False)
model = AutoModelForCausalLM.from_pretrained(model_path, device_map=CUDA_DEVICE, torch_dtype=torch.bfloat16)
uvicorn.run(app, host='0.0.0.0', port=6006, workers=1)
这段代码的主要作用是构建一个基于 FastAPI 的 HTTP API 服务,用于调用预训练的语言生成模型进行对话生成:
DEVICE
为 “cuda”,并指定 DEVICE_ID
为 “0”。根据是否有设备ID,组合出 CUDA_DEVICE
信息,用于在加载模型时指定使用的 GPU 设备。clear_gpu_cache()
:torch.cuda.empty_cache()
清空未使用的缓存,并用 torch.cuda.ipc_collect()
收集内存碎片,从而确保 GPU 内存得到有效释放。split_response(text)
:...
标签内的内容被认为是“思考过程”;app = FastAPI()
创建 API 应用实例。/
:process_request
,用于处理客户端请求:
await request.json()
获取请求中的 JSON 数据,并从中提取 prompt
(提示内容),如果不存在则默认为空字符串。prompt
以对话消息格式(角色为 “user”)构造为一个列表 messages
。tokenizer.apply_chat_template
方法将消息转换为模型所需的输入文本。generate
方法生成文本,设置 max_new_tokens
为 8192,允许生成较长的文本。tokenizer.batch_decode
方法将生成的 token 转换回可读文本,并跳过特殊标记。这里注意只解码模型生成部分(通过对生成结果进行切片)。split_response
函数,将生成文本分割为思考内容和回答内容。clear_gpu_cache()
清理 GPU 内存,确保内存资源得到释放。加载模型和分词器:
在 if __name__ == '__main__':
代码块中:
'/root/autodl-tmp/deepseek-ai/DeepSeek-R1-Distill-Qwen-7B'
加载预训练的分词器和模型。device_map=CUDA_DEVICE
指定使用 GPU,并设置 torch_dtype=torch.bfloat16
以优化内存使用。启动服务器:
uvicorn.run
启动 FastAPI 应用,绑定主机地址 0.0.0.0
和端口 6006
。这里设置了单个 worker 进程,适用于资源有限或简单部署场景。首先需要启动API:
python api.py
然后使用python的request库进行调用:
import requests
import json
def get_completion(prompt, url='http://127.0.0.1:6006'):
headers = {'Content-Type': 'application/json'}
data = {"prompt": prompt}
try:
response = requests.post(url, headers=headers, data=json.dumps(data), timeout=10)
response.raise_for_status() # 检查 HTTP 状态码
return response.json() # 返回完整 JSON 结果
except requests.exceptions.RequestException as e:
return {"error": str(e)}
def pretty_print_result(result):
# 使用 json.dumps 格式化输出
formatted = json.dumps(result, indent=4, ensure_ascii=False)
print("Structured Output:")
print(formatted)
if __name__ == '__main__':
prompt = '说一下9.11和9.8那个更大,你愿意要9.11吨黄金还是9.8吨'
result = get_completion(prompt)
pretty_print_result(result)