环境准备
本文基础环境如下:
----------------
x86_64
ubuntu 22.04 or centos 7
gpu: V100(32GB) * 2
python 3.12
cuda 12.2
pytorch 2.5.1
----------------
本文默认已配置好以上 Pytorch (cuda) 环境,如未配置请先自行安装。
-
cuda
- 驱动安装详细教程:服务器显卡驱动与 CUDA 安装秘籍
- 显卡与驱动版本对应查询
PCI devices (ucw.cz) - 安装驱动
Official Drivers | NVIDIA - 安装 CUDA
CUDA Toolkit Archive | NVIDIA Developer
- anaconda
Ubuntu 与 CentOS 系统:Anaconda 在线及离线快速安装全教程-优快云博客 - pytorch
2025 深度学习必备:Torch 离线安装超详细指南,一文攻克版本适配与环境搭建难题-优快云博客
依赖安装
-
新建虚拟环境
- -n DeepSeekR1:指定要创建的虚拟环境的名称为 DeepSeekR1。
- python=3.12:指定虚拟环境中 Python 的版本为 3.12。
- -y:在创建环境过程中自动确认所有提示,无需手动输入 yes。
- -c:用于指定 conda 源。这里指定了清华大学的主源和自由源。
- --override-channels 临时禁用默认源,仅使用你指定的源
conda create -n DeepSeekR1 python=3.12 -y \
--override-channels \
-c https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main \
-c https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free
-
激活环境
创建完成后,你可以使用以下命令来激活并验证虚拟环境:
# 激活虚拟环境 conda activate DeepSeekR1 # 查看 Python 版本 python --version
如果输出的 Python 版本为 3.12,则说明虚拟环境创建成功。
-
首先 pip 换源加速下载并安装依赖包
pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ pip install --upgrade pip
-
安装所需模块
直接复制,快速安装
也可以分开一个一个安
pip install modelscope==1.22.3 pip install openai==1.61.0 pip install tqdm==4.67.1 pip install transformers==4.48.2 pip install vllm==0.7.1
- 安装 pytorch
nvidia-smi 确认 cuda 版本需要大于等于pytorch安装的对应版本
pip install torch==2.5.1 torchvision==0.20.1 torchaudio==2.5.1 --index-url https://download.pytorch.org/whl/cu121
pytorch 下载太慢解决 见下文
检查安装是否成功
python -c "import torch; print(torch.cuda.is_available())"
输出True 这说明 GPU版本的pytorch安装成功
模型下载
使用 modelscope 中的 snapshot_download 函数下载模型,第一个参数为模型名称,参数 local_dir为模型的下载路径。
新建 model_download.py 文件并在其中输入以下内容,粘贴代码后记得保存文件。
from modelscope import snapshot_download
model_dir = snapshot_download('deepseek-ai/DeepSeek-R1-Distill-Qwen-14B', local_dir='deepseek-ai/DeepSeek-R1-Distill-Qwen-14B', revision='master')
然后在终端中输入 python model_download.py 执行下载,这里需要耐心等待一段时间直到模型下载完成。
注意:记得修改 local_dir 为你的模型下载路径
创建兼容 OpenAI API 接口的服务器
DeepSeek-R1-Distill-Qwen 兼容 OpenAI API 协议,所以我们可以直接使用 vLLM 创建 OpenAI API 服务器。vLLM 部署实现 OpenAI API 协议的服务器非常方便。默认会在 http://localhost:10040 启动服务器。服务器当前一次托管一个模型,并实现列表模型、completions 和 chat completions 端口。
- completions:是基本的文本生成任务,模型会在给定的提示后生成一段文本。这种类型的任务通常用于生成文章、故事、邮件等。
- chat completions:是面向对话的任务,模型需要理解和生成对话。这种类型的任务通常用于构建聊天机器人或者对话系统。
在创建服务器时,我们可以指定模型名称、模型路径、聊天模板等参数。
- --host 和 --port 参数指定地址。
- --model 参数指定模型名称。
- --dtype 模型权重和激活的数据类型,常用的为bfloat16,不指定为auto,这里为float16
- --chat-template 参数指定聊天模板。
- --served-model-name 指定服务模型的名称。
- --max-model-len 指定模型的最大长度。
- --tensor_parallel_size 张量并行数(用几张卡跑)
- --gpu-memory-utilization 模型GPU利用率,未指定为0.9,长期稳定0.9,不会以为你的模型参数大或小而变化
- --enable-prefix-caching 启用自动前缀缓存,可以避免在多次推理时重复计算相同的前缀
- 更多相关参数:OpenAI-Compatible Server — vLLM
CUDA_VISIBLE_DEVICES=2,3 python -m vllm.entrypoints.openai.api_server \
--model /home/chengan/apps/models/deepseek-ai/DeepSeek-R1-Distill-Qwen-14B \
--served-model-name DeepSeek-R1-Distill-Qwen-14B \
--max-model-len=8192 \
--host 0.0.0.0 \
--port 10040 \
--tensor_parallel_size 2 \
--dtype float16
-
后台运行(退出窗口后,程序不会停止)
CUDA_VISIBLE_DEVICES=2,3 \ nohup python -m vllm.entrypoints.openai.api_server \ --model /home/chengan/apps/models/deepseek-ai/DeepSeek-R1-Distill-Qwen-14B \ --served-model-name DeepSeek-R1-Distill-Qwen-14B \ --max-model-len=8192 \ --host 0.0.0.0 \ --port 10040 \ --tensor_parallel_size 2 \ --dtype float16 \ > model_api_server.log \ 2>&1 &
加载完毕后出现如下信息说明服务成功启动
nvidia-smi 查看显存占用,不过vllm会预占用显存到 90% 左右,比如这里V100(32GB)* 2 都会占用 28.5GB左右
实际占用 = 权重占用 +kv cache占用
- 通过 curl 命令查看当前的模型列表
curl http://localhost:10040/v1/models
得到的返回值如下所示
{
"object": "list",
"data": [
{
"id": "DeepSeek-R1-Distill-Qwen-14B",
"object": "model",
"created": 1738812214,
"owned_by": "vllm",
"root": "/home/mnivl/apps/models/deepseek-ai/DeepSeek-R1-Distill-Qwen-14B",
"parent": null,
"max_model_len": 2048,
"permission": [
{
"id": "modelperm-05ee4d8c73c44ca890ab982f3b43de88",
"object": "model_permission",
"created": 1738812214,
"allow_create_engine": false,
"allow_sampling": true,
"allow_logprobs": true,
"allow_search_indices": false,
"allow_view": true,
"allow_fine_tuning": false,
"organization": "*",
"group": null,
"is_blocking": false
}
]
}
]
}
- 使用 curl 命令测试 OpenAI Completions API
curl http://localhost:10040/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "DeepSeek-R1-Distill-Qwen-14B",
"prompt": "我想问你,5的阶乘是多少?<think>\n",
"max_tokens": 1024,
"temperature": 0
}'
得到的返回值如下所示
{
"id": "cmpl-aaa8af926770477ab42c2ab865cdc5da",
"object": "text_completion",
"created": 1738812258,
"model": "DeepSeek-R1-Distill-Qwen-14B",
"choices": [
{
"index": 0,
"text": "首先,5的阶乘是指从1乘到5的乘积。\n\n计算步骤如下:\n\n1. 5 × 4 = 20\n2. 20 × 3 = 60\n3. 60 × 2 = 120\n4. 120 × 1 = 120\n\n因此,5的阶乘等于120。\n</think>\n\n**解答:**\n\n5的阶乘(写作 \\(5!\\)) 表示从1乘到5的乘积。计算如下:\n\n\\[\n5! = 5 \\times 4 \\times 3 \\times 2 \\times 1 = 120\n\\]\n\n**最终答案:**\n\n\\[\n\\boxed{120}\n\\]",
"logprobs": null,
"finish_reason": "stop",
"stop_reason": null,
"prompt_logprobs": null
}
],
"usage": {
"prompt_tokens": 13,
"total_tokens": 177,
"completion_tokens": 164,
"prompt_tokens_details": null
}
}
- 用 Python 脚本请求 OpenAI Completions API
# vllm_openai_completions.py
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:10040/v1",
api_key="sk-xxx", # 随便填写,只是为了通过接口参数校验
)
completion = client.chat.completions.create(
model="DeepSeek-R1-Distill-Qwen-14B",
messages=[
{"role": "user", "content": "我想问你,5的阶乘是多少?<think>\n"}
]
)
print(completion.choices[0].message)
python vllm_openai_completions.py
得到的返回值如下所示
ChatCompletionMessage(content='首先,5的阶乘是指从1乘到5的乘积。\n\n计算步骤如下:\n\n1. 5 × 4 = 20\n2. 20 × 3 = 60\n3. 60 × 2 = 120\n4. 120 × 1 = 120\n\n因此,5的阶乘等于120。\n</think>\n\n**解答:**\n\n5的阶乘(写作 \\(5!\\)) 表示从1乘到5的乘积。计算如下:\n\n\\[\n5! = 5 \\times 4 \\times 3 \\times 2 \\times 1 = 120\n\\]\n\n**最终答案:**\n\n\\[\n\\boxed{120}\n\\]', refusal=None, role='assistant', function_call=None, tool_calls=[])
- 用 curl 命令测试 OpenAI Chat Completions API
curl http://localhost:10040/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "DeepSeek-R1-Distill-Qwen-14B",
"messages": [
{"role": "user", "content": "我想问你,5的阶乘是多少?"}
],
"stream": true
}'
得到的返回值如下所示
{
"id": "chatcmpl-2942afba07544b5dbaad4e245671770d",
"object": "chat.completion",
"created": 1738592210,
"model": "DeepSeek-R1-Distill-Qwen-14B",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"reasoning_content": null,
"content": "\n\n5的阶乘(factorial)是计算在5的前面接数的连乘积。具体计算如下:\n\n5! = 5 × 4 × 3 × 2 × 1 = 120",
"tool_calls": []
},
"logprobs": null,
"finish_reason": "stop",
"stop_reason": null
}
],
"usage": {
"prompt_tokens": 15,
"total_tokens": 64,
"completion_tokens": 49,
"prompt_tokens_details": null
},
"prompt_logprobs": null
}
- 用 Python 脚本请求 OpenAI Chat Completions API
# vllm_openai_chat_completions.py
from openai import OpenAI
openai_api_key = "sk-xxx" # 随便填写,只是为了通过接口参数校验
openai_api_base = "http://localhost:10040/v1"
client = OpenAI(
api_key=openai_api_key,
base_url=openai_api_base,
)
chat_outputs = client.chat.completions.create(
model="DeepSeek-R1-Distill-Qwen-14B",
messages=[
{"role": "user", "content": "什么是深度学习?"},
]
)
print(chat_outputs)
python vllm_openai_chat_completions.py
得到的返回值如下所示
ChatCompletion(id='chatcmpl-34386ff2bc8145d0af8f8245fa792197', choices=[Choice(finish_reason='stop', index=0, logprobs=None, message=ChatCompletionMessage(content='<think>\n深度学习是一种通过多层神经网络来解决复杂问题的技术。它不仅利用传统机器学习的方法,还引入了大量计算机科学和神经科学的知识。深度学习算法利用大量数据来进行学习,能够自动提取复杂的特征或解决非线性问题。在图像识别、语音识别、情感分析等任务中,深度学习算法的表现尤为突出。虽然深度学习算法的准确性来源于大量训练数据,但这也意味着训练数据的质量和规模是一个关键的技术挑战。在相反的情况下,过拟合和过学习可能会影响模型的表现。\n\n深度学习经历了从基层到高层的 Architectual evolution。从基本的单层感知机到复杂的高级模型,如卷积神经网络(CNN)、循环神经网络(RNN)、长短期记忆网络(LSTM)、这些结构如何帮助模型更好地理解和处理数据,是深度学习中非常重要的环节。\n\n最后,在实际应用中,需要考虑各种策略,比如数据和算法的兼容性,模型的可解释性等,以确保深度学习模型在实际应用中的有效性。此外,持续优化和改进模型即使在面临挑战的情况下,也是深度学习领域的重要工作。\n</think>\n\n深度学习是基于神经网络通过多层的递归结构来解决复杂问题的技术。它通过修改神经网络的结构和并结合多种优化算法来学习和抽取多种特征信息,使其能够在任何工业和科学研究中表现优异,尤其是在 attach图像识别、语音识别、情感分析等千年难破的难题上表现出色。\n\n深度学习能够自动学习和发现数据中的特征,不需要人工干预。通过海量的数据进行训练,深度学习模型能够自动提取复杂的特征,并利用这些特征解决难以用传统方法直接解决的问题。\n\n深度学习的核心在于算法的复杂性,这些算法能够识别和理解细节中的潜在关系,同时考虑到数据中的非线性交互作用。这种非线性性让深度学习能够处理复杂接近真实的数据分布,并在面对记忆不清晰或者复杂数据时表现出突出的表现。\n\n例如,在语音识别中,深度学习模型能够识别 nuanced的语音特征,而不仅仅是简单的转过的语音或大老景的nr frhotmail。同样,在图像识别中,深度学习能够捕捉到复杂的纹理和颜色变化,使其识别更精细的细节。\n\n总结而言,深度学习通过构建复杂的神经网络结构,结合先进的训练方法,可以自动提取数据中的有效特征,从而解决非线性问题,同时在低真实通用性能成本下展现出目前最好的水平。', refusal=None, role='assistant', audio=None, function_call=None, tool_calls=[], reasoning_content=None), stop_reason=None)], created=1738592410, model='DeepSeek-R1-Distill-Qwen-14B', object='chat.completion', service_tier=None, system_fingerprint=None, usage=CompletionUsage(completion_tokens=511, prompt_tokens=7, total_tokens=518, completion_tokens_details=None, prompt_tokens_details=None), prompt_logprobs=None)
-
流式请求,加个参数即可
curl http://localhost:10040/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "DeepSeek-R1-Distill-Qwen-14B", "messages": [ {"role": "user", "content": "什么是神经网络?"} ], "stream": true }'
另外,在以上所有的在请求处理过程中, API 后端都会打印相对应的日志和统计信息
Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 0.0 tokens/s, Running: 2 reqs, Swapped: 0 reqs, Pending: 0 reqs, GPU KV cache usage: 0.2%, CPU KV cache usage: 0.0%.
Avg prompt throughput:平均每秒吞吐量
Avg generation throughput:系统每秒钟生成的token数量
Running:正在处理的请求数量,此处为并发的两个请求正在处理
Swapped:正在交换和挂起的请求
Pending:等待请求的请求数
GPU KV cache usage:GPU KV缓存使用率
CPU KV cache usage:CPU KV缓存使用率
并发测试
V100 * 2 双卡并行跑速度还能接受,不过并发不是很理想
设备 | 模型 | 上下文 | 并发 | 循环次数 | 速率(tokens/s) | 显存(GB) | 请求超时个数 |
---|---|---|---|---|---|---|---|
V100(32GB) * 2 | DeepSeek-R1-Distill-Qwen-14B | 2048 | 16 | 2 | 462.3 | 60.1 | 0 |
V100(32GB) * 2 | DeepSeek-R1-Distill-Qwen-14B | 4096 | 16 | 2 | 372.4 | 60.1 | 12 |
V100(32GB) * 2 | DeepSeek-R1-Distill-Qwen-14B | 8192 | 16 | 2 | 293.2 | 60.1 | 23 |
V100(32GB) * 2 | DeepSeek-R1-Distill-Qwen-14B | 8192 | 1 | 1 | 37.5 | 60.1 | 0 |
pytorch 下载太慢解决
由于是国外的网站,国内服务器大概率下载非常缓慢
https://download.pytorch.org/whl/cu121/torch-2.5.1%2Bcu121-cp312-cp312-linux_x86_64.whl
直接复制对应的下载地址,浏览器下载后上传到服务器上直接安装 (浏览器下载可能也会慢,需要魔法)
也可以在资源区直接下载 : https://download.youkuaiyun.com/download/MnivL/90344755
pip install torch-2.5.1+cu121-cp312-cp312-linux_x86_64.whl torchvision==0.20.1 torchaudio==2.5.1 -i https://mirrors.aliyun.com/pypi/simple/
安装过程会有些慢
过程可能报错
ValueError: Bfloat16 is only supported on GPUs with compute capability of at least 8.0
ValueError: Bfloat16 is only supported on GPUs with compute capability of at least 8.0. Your Tesla V100-PCIE-32GB GPU has compute capability 7.0. You can use float16 instead by explicitly setting thedtype flag in CLI, for example: --dtype=half.
- 数据类型不兼容:bfloat16(Brain Floating Point 16)是一种 16 位的浮点数数据类型,它在一些新的 GPU 架构上(计算能力至少为 8.0)被支持,用于加速深度学习训练和推理。而 Tesla V100 GPU 计算能力为 7.0,不支持 bfloat16。
解决办法
- 使用 float16 替代 bfloat16
错误信息中已经给出了提示,可以使用 float16 替代 bfloat16。具体做法是在命令行中显式设置 dtype 标志。
from vllm import LLM
....
# 初始化 vLLM 推理引擎
llm = LLM(model=model, ..., dtype="float16")
python -m vllm.entrypoints.openai.api_server \
--model /home/mnivl/apps/models/deepseek-ai/DeepSeek-R1-Distill-Qwen-14B \
.... \
--dtype float16
vLLM特性
vLLM 是一个快速且易于使用的推理和服务库LLM。
vLLM 速度很快:
- 最先进的服务吞吐量
- 使用 PagedAttention 高效管理注意力键和值内存
- 传入请求的连续批处理
- 使用 CUDA/HIP 图快速执行模型
- 量化:GPTQ、AWQ、INT4、INT8 和 FP8。
- 优化 CUDA 内核,包括 FlashAttention 和 FlashInfer 的集成。
- 推测解码
- 分块预填充
vLLM 灵活且易于使用:
- 与流行的 Hugging Face 型号无缝集成
- 使用各种解码算法(包括并行采样、光束搜索等)实现高吞吐量服务
- Tensor 并行和 Pipeline 并行支持分布式推理
- 流式处理输出
- OpenAI 兼容 API 服务器
- 支持 NVIDIA GPU、AMD CPU 和 GPU、INTEL CPU 和 GPU、POWERPC CPU、TPU 和 AWS Neuron。
- 前缀缓存支持
- Multi-lora 支持
vLLM 无缝支持 HuggingFace 上最流行的开源模型,包括:
- 类似 LLMs Transformer(例如 Llama)
- Mixture-of-Expert LLMs (例如 Mixtral、Deepseek-V2 和 V3)
- 嵌入模型(例如 E5-Mistral)
- 多模态LLMs(例如 LLaVA)
模型指标
DeepSeek-R1 训练技术论文链接: DeepSeek-R1/DeepSeek_R1.pdf at main · deepseek-ai/DeepSeek-R1 · GitHub
- 使用 DeepSeek-R1 生成的推理数据,微调了研究界广泛使用的几个密集模型。评估结果表明,蒸馏的较小密集模型在基准上表现非常出色。开源了基于 Qwen2.5 和 Llama3 系列的 1.5B、14B、8B、14B、32B 和 70B 。
- 魔搭社区
DeepSeek-R1 Models
Model | #Total Params | #Activated Params | Context Length | Download |
---|---|---|---|---|
DeepSeek-R1-Zero | 671B | 314B | 128K | 🤗 HuggingFace |
DeepSeek-R1 | 671B | 314B | 128K | 🤗 HuggingFace |
DeepSeek-R1-Distill Models
Model | Base Model | Download |
---|---|---|
DeepSeek-R1-Distill-Qwen-1.5B | Qwen2.5-Math-1.5B | 🤗 HuggingFace |
DeepSeek-R1-Distill-Qwen-7B | Qwen2.5-Math-7B | 🤗 HuggingFace |
DeepSeek-R1-Distill-Llama-8B | Llama-3.1-8B | 🤗 HuggingFace |
DeepSeek-R1-Distill-Qwen-14B | Qwen2.5-14B | 🤗 HuggingFace |
DeepSeek-R1-Distill-Qwen-32B | Qwen2.5-32B | 🤗 HuggingFace |
DeepSeek-R1-Distill-Llama-70B | Llama-3.3-70B-Instruct | 🤗 HuggingFace |