vLLM、ollama方式部署本地大模型(单机)

1.安装显卡驱动

1.1 查看显卡类型

  • PCI/PCIe 总线的硬件设备信息:
[root@localhost ~]# lspci | grep -E "NVIDIA|VGA"
02:00.0 VGA compatible controller: Huawei Technologies Co., Ltd. Hi171x Series [iBMC Intelligent Management system chip w/VGA support] (rev 01)
3b:00.0 3D controller: NVIDIA Corporation TU104GL [Tesla T4] (rev a1)
3c:00.0 3D controller: NVIDIA Corporation TU104GL [Tesla T4] (rev a1)
5e:00.0 3D controller: NVIDIA Corporation TU104GL [Tesla T4] (rev a1)
86:00.0 3D controller: NVIDIA Corporation TU104GL [Tesla T4] (rev a1)
87:00.0 3D controller: NVIDIA Corporation TU104GL [Tesla T4] (rev a1)
af:00.0 3D controller: NVIDIA Corporation TU104GL [Tesla T4] (rev a1)
d8:00.0 3D controller: NVIDIA Corporation TU104GL [Tesla T4] (rev a1)

可以看到显卡类型:NVIDIA Corporation TU104GL [Tesla T4] (rev a1)

  • 查看系统类型
cat /etc/os-release 

终端输出信息:

NAME="Kylin Linux Advanced Server"
VERSION="V10 (Halberd)"
ID="kylin"
VERSION_ID="V10"
PRETTY_NAME="Kylin Linux Advanced Server V10 (Halberd)"
ANSI_COLOR="0;31"
  • 查看系统架构
lscpu

1.2 下载显卡驱动

NVIDIA显卡下载官网地址:Download The Official NVIDIA Drivers | NVIDIA

根据显卡类型系统平台下载显卡驱动,下载页面选择的下载配置参考如下:

名称 选择值
Select Product Category 选择 Data Center /Tesla
Select Product Series 选择 T-Series
Select Product 选择 Tesla T4
Select Operating System 选择 Linux 64-bit
Any CUDA Toolkit Version (可)选择 12.8
English(US) 默认就选英文(不推荐中文)

注意:Operating System请选择Linux 64-bit,下载后的文件名称:NVIDIA-Linux-x86_64-570.86.15 .run,是.run格式的

1.3 kernel-devel

安装与当前内核版本匹配的 kernel-devel 包:

yum install "kernel-devel-uname-r == $(uname -r)"

重启:

reboot

1.4 禁用Nouveau驱动

参考:禁用nouveau驱动 - 华为鲲鹏服务器 GPU卡操作指导书 03 - 华为

防止冲突,禁用Nouveau驱动;查看命令:

lsmod | grep nouveau

如果终端输出信息中包含Nouveau驱动信息,说明Nouveau驱动已安装,则需要禁用Nouveau驱动,禁用步骤如下:

  • 编辑blacklist.conf文件
vi /etc/modprobe.d/blacklist.conf

编辑内容:

# 注释掉blacklist nvidiafb (# blacklist nvidiafb)
# 添加下面2行
blacklist nouveau
options nouveau modeset=0

执行以下命令,备份并新建一个initramfs

mv /boot/initramfs-$(uname -r).img /boot/initramfs-$(uname -r).img.bak
dracut -v /boot/initramfs-$(uname -r).img $(uname -r)

重启:

reboot

1.5 禁用GUI (图形化)

命令:

systemctl set-default multi-user.target

设置为 multi-user.target 后,系统将启动到命令行界面,多个用户可以同时登录,但不启动图形桌面环境。这个模式适用于服务器环境或需要稳定命令行操作的场景,不需要图形用户界面的干扰。

重启:

reboot

其他命令:

# 如果有需要,执行下面命令恢复默认图形界面 
systemctl set-default graphical.target

1.6 安装显卡驱动

参考:

手动安装GPU加速型ECS的Tesla驱动_弹性云服务器 ECS_华为云

在Centos上为Tesla T4显卡安装NVIDIA驱动以及cuda和cudnn_t4显卡驱动-CSDN博客

命令:

# 添加可运行权限
chmod +x NVIDIA-Linux-x86_64-570.86.15.run
# 安装
sh NVIDIA-Linux-x86_64-570.86.15.run

安装后,重启:

reboot

查看显卡信息:

nvidia-smi
# watch -n 1 nvidia-smi (终端每秒刷新显卡信息)

输出信息参考如下:

(vllm) [root@localhost bin]# nvidia-smi                                                                                                                                                                        
Thu Feb 20 23:52:41 2025                                                                                                                                                                                       
+-----------------------------------------------------------------------------------------+                                                                                                                    
| NVIDIA-SMI 570.86.15              Driver Version: 570.86.15      CUDA Version: 12.8     |                                                                                                                    
|-----------------------------------------+------------------------+----------------------+                                                                                                                    
| GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |                                                                                                                    
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |                                                                                                                    
|                                         |                        |               MIG M. |                                                                                                                    
|=========================================+========================+======================|                                                                                                                    
|   0  Tesla T4                       Off |   00000000:3B:00.0 Off |                    0 |                                                                                                                    
| N/A   69C    P0             30W /   70W |       1MiB /  15360MiB |      0%      Default |                                                                                                                    
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+
|   1  Tesla T4                       Off |   00000000:3C:00.0 Off |                    0 |
| N/A   70C    P0             28W /   70W |       1MiB /  15360MiB |      0%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+
|   2  Tesla T4                       Off |   00000000:5E:00.0 Off |                    0 |
| N/A   69C    P0             31W /   70W |       1MiB /  15360MiB |      0%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+
|   3  Tesla T4                       Off |   00000000:86:00.0 Off |                    0 |
| N/A   73C    P0             32W /   70W |       1MiB /  15360MiB |      0%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+
|   4  Tesla T4                       Off |   00000000:87:00.0 Off |                    0 |
| N/A   75C    P0             33W /   70W |       1MiB /  15360MiB |      0%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+
|   5  Tesla T4                       Off |   00000000:AF:00.0 Off |                    0 |
| N/A   67C    P0             30W /   70W |       1MiB /  15360MiB |      0%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+
|   6  Tesla T4                       Off |   00000000:D8:00.0 Off |                    0 |
| N/A   73C    P0             32W /   70W |       1MiB /  15360MiB |      5%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+
                                                                                         
+-----------------------------------------------------------------------------------------+
| Processes:                                                                              |
|  GPU   GI   CI              PID   Type   Process name                        GPU Memory |
|        ID   ID                                                               Usage      |
|=========================================================================================|
|  No running processes found                                                             |
+-----------------------------------------------------------------------------------------+

1.7 cuda-toolkit安装

下载地址: https://developer.nvidia.com/cuda-toolkit-archive

根据系统信息选择,参考选择如下:

Operating System --> 选择`Linux`
Architecture --> 选择`x86_64`   
Distribution --> 选择`KylinOS`
Version --> 选择`10`
Installer Type --> 选择`runfile(local)`

安装命令:

wget https://developer.download.nvidia.com/compute/cuda/12.8.0/local_installers/cuda_12.8.0_570.86.10_linux.run
chmod +x cuda_12.8.0_570.86.10_linux.run
sudo sh cuda_12.8.0_570.86.10_linux.run

安装成功结果:

[root@localhost nvidia_driver]# ./cuda_12.8.0_570.86.10_linux.run 
===========
= Summary =
===========

Driver:   Not Selected
Toolkit:  Installed in /usr/local/cuda-12.8/

Please make sure that
 -   PATH includes /usr/local/cuda-12.8/bin
 -   LD_LIBRARY_PATH includes /usr/local/cuda-12.8/lib64, or, add /usr/local/cuda-12.8/lib64 to /etc/ld.so.conf and run ldconfig as root

To uninstall the CUDA Toolkit, run cuda-uninstaller in /usr/local/cuda-12.8/bin
***WARNING: Incomplete installation! This installation did not install the CUDA Driver. A driver of version at least 570.00 is required for CUDA 12.8 functionality to work.
To install the driver using this installer, run the following command, replacing <CudaInstaller> with the name of this run file:
    sudo <CudaInstaller>.run --silent --driver

Logfile is /var/log/cuda-installer.log

添加环境变量:

vim ~/.bashrc

编辑内容如下:

# cuda-toolkit
export PATH=/usr/local/cuda-12.8/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda-12.8/lib64:$LD_LIBRARY_PATH
export CUDA_HOME=/usr/local/cuda-12.8

生效配置的环境变量:

source ~/.bashrc

验证安装:

nvcc --version
# 输出内容有 Cuda compilation tools, release 12.8, V12.8.61 类似这种的,代表安装好了。

1.8 cuDNN安装

参考:
Linux-CUDA 和cuDNN安装 - 知乎

下载地址:https://developer.nvidia.com/rdp/cudnn-archive

解压文件:

tar -xvf cudnn-linux-x86_64-8.9.7.29_cuda11-archive.tar.xz

将解压后的头文件和库复制到cuda目录中:

# 切换到 cudnn 安装目录
cd cudnn-linux-x86_64-8.9.7.29_cuda11-archive

# 将 cuDNN 的头文件复制到 CUDA 的 include 目录下
sudo cp include/cudnn* /usr/local/cuda/include

# 将 cuDNN 的库文件复制到 CUDA 的 lib64 目录下
sudo cp lib/libcudnn* /usr/local/cuda/lib64

# 修改文件权限,确保所有用户都可以读取 cudnn 头文件和库文件
sudo chmod a+r /usr/local/cuda/include/cudnn* /usr/local/cuda/lib64/libcudnn*

cuDNN安装完成,查看安装的版本:

# 查看 cudnn_version.h 文件中的 CUDNN_MAJOR 宏定义,并显示该行以及后续的两行
cat /usr/local/cuda/include/cudnn_version.h | grep CUDNN_MAJOR -A 2

终端显示:

#define CUDNN_MAJOR 8
#define CUDNN_MINOR 9
#define CUDNN_PATCHLEVEL 7
--
#define CUDNN_VERSION (CUDNN_MAJOR * 1000 + CUDNN_MINOR * 100 + CUDNN_PATCHLEVEL)

1.9 torch-CUDA虚拟环境安装

参考:Linux-CUDA 和cuDNN安装 - 知乎

2. 下载离线模型

如果已经用迅雷或者其他方式已经下载好了离线的模型库文件,或者有更好的下载离线模型方式,可以略过下载离线模型步骤。

2.1 配置镜像加速

编辑文件:

vim /etc/profile

添加如下内容:

# huggingface.co 加速
export HF_ENDPOINT=https://hf-mirror.com

生效:

source /etc/profile

2.2 创建虚拟环境

venv 是 Python 的内置模块,用于创建虚拟环境。虚拟环境允许你在项目中隔离依赖包,避免与全局环境中的其他项目产生冲突。使用虚拟环境可以确保项目的依赖独立,易于管理和部署。以下步骤请在python3虚拟环境中执行。

创建虚拟环境:

# 切换路径
cd /usr/local/python3/bin
# 退出conda环境
conda deactivate
# 创建虚拟环境
python3 -m venv my-environment

2.3 下载模型到本地

激活虚拟环境:

source my-environment/bin/activate

虚拟环境中执行:

pip install -U huggingface_hub

利用huggingface-cli下载模型语法:

huggingface-cli download --resume-download {填写huggingface.co官网的model name} --local-dir {模型的保存路径}

创建模型保存目录:

mkdir -p /home/data/models/DeepSeek-R1-Distill-Qwen-1.5B

下载模型到本地:

huggingface-cli download --resume-download deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B --local-dir /home/data/models/DeepSeek-R1-Distill-Qwen-1.5B

退出虚拟环境命令:

deactivate

3. 安装Deepseek

3.1 ollama方式

3.1.1 安装

Linux平台安装命令:

curl -fsSL https://ollama.com/install.sh | sh

脚本内容在线参考:ollama/docs/linux.md at main · ollama/ollama · GitHub

3.1.2 配置ollama自启动

编辑systemd自启动文件:

vim /etc/systemd/system/ollama.service

编辑参考内容:

[Unit]
Description=ollama Service
After=network-online.target

[Service]
ExecStart=/usr/bin/ollama serve
Environment="PATH=/usr/local/sbin:/usr/sbin:/usr/local/bin:/usr/bin:/bin:/root/bin"
Environment="OLLAMA_MODELS=/home/data/ollama/models"

[Install]
WantedBy=default.target

3.1.3 运行Deepseek

3.1.3.1 方式一

直接使用使用ollama命令,运行Deepseek:

ollama run deepseek-r1:{参数数量}b

3.1.3.2 方式二

使用下载到本地的模型进行部署

3.1.3.2.1 配置加速
# 编辑文件
vim /etc/profile
# huggingface加速
export HF_ENDPOINT=https://hf-mirror.com
# 生效
source /etc/profile
3.1.3.2.2 下载模型库

创建模型保存的目录:

mkdir -p /home/data/models/deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B

创建虚拟环境:

python3 -m venv my-environment

激活虚拟环境:

source my-environment/bin/activate

虚拟环境中执行:

# 进入虚拟环境中执行
pip install -U huggingface_hub

虚拟环境中执行:

# 下载模型库
huggingface-cli download --resume-download {复制huggingface.co模型的名称} --local-dir /home/data/models/deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B
3.1.3.2.3 转换并运行

把离线下载好的deepseek本地模型转换成ollama能用的,操作步骤如下:

切换到模型库下载目录:

cd /home/yyj/data/models/deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B

创建ollama构建镜像的文件:

vim /home/yyj/data/models/deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B/Modelfile

Modelfile内容如下:

# Modelfile generated by "ollama show"
# To build a new Modelfile based on this, replace FROM with:

# FROM {需要替换成离线模型库保存的位置}
FROM /home/yyj/data/models/deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B
TEMPLATE """{{- if .System }}{{ .System }}{{ end }}
{{- range $i, $_ := .Messages }}
{{- $last := eq (len (slice $.Messages $i)) 1}}
{{- if eq .Role "user" }}<|User|>{{ .Content }}
{{- else if eq .Role "assistant" }}<|Assistant|>{{ .Content }}{{- if not $last }}<|end▁of▁sentence|>{{- end }}
{{- end }}
{{- if and $last (ne .Role "assistant") }}<|Assistant|>{{- end }}
{{- end }}"""
PARAMETER stop <|begin▁of▁sentence|>
PARAMETER stop <|end▁of▁sentence|>
PARAMETER stop <|User|>
PARAMETER stop <|Assistant|>

运行:

ollama create DeepSeek-R1-Distill-Qwen-1.5B -f /home/yyj/data/models/deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B/Modelfile

3.1.4 检验Deepseek状态

检验ollama安装deepseek是否成功,命令如下:

curl http://127.0.0.1:11434

3.1.5 ollama命令

常用命令如下:

# 列出可用的模型
ollama list
# 加载并运行模型
ollama run <model_name>
# 获取模型的信息
ollama info <model_name>
# 列出所有已安装的模型
ollama installed
# 安装特定的模型
ollama pull <model_name>
# 卸载模型
ollama remove <model_name>
# 显示帮助信息
ollama --help

3.2 vLLM方式

3.2.1 安装conda

官网地址:Download Anaconda Distribution | Anaconda (下载精简的Miniconda版本)

查看平台架构:

lscpu

根据平台架构下架(x86_64):

wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh

安装:

chmod +x Anaconda3-2024.10-1-Linux-x86_64.sh
sh Anaconda3-2024.10-1-Linux-x86_64.sh

配置环境变量:

vim ~/.bashrc

参考内容:

export PATH="$PATH:{conda安装路径}/bin"

生效配置的环境变量:

source ~/.bashrc

查看版本:

conda -V
# 初始化 Conda 运行环境
# 适用于 bash 终端用户(如 Ubuntu、CentOS、WSL 等)
conda init bash
# 适用于 zsh 终端用户(如 macOS 默认的终端 shell)
conda init zsh

配置镜像加速:

# vim ~/.condarc
vim /{conda安装目录}/.condarc

.condarc参考内容:

channels:
  - defaults
show_channel_urls: true
default_channels:
  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/
  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/
  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/  
  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
custom_channels:
  conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
  msys2: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
  bioconda: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
  menpo: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
  pytorch: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
  simpleitk: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud

备用加速参考内容:

channels:
  - http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
  - http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
  - http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/
show_channel_urls: true
default_channels:
  - http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
  - http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r
  - http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2
custom_channels:
  conda-forge: http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
  msys2: http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
  bioconda: http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
  menpo: http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
  pytorch: http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
  pytorch-lts: http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
  simpleitk: http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud

查看conda信息:

conda info

其他命令(有需求执行):

# 退出当前的 Conda 环境
conda deactivate
# 退出 base 环境并不再自动激活
conda config --set auto_activate_base false

3.2.2 创建虚拟环境

You can create a new Python environment using conda:

# 创建conda虚拟环境
conda create -n vllm python=3.12 -y
# 激活
conda activate vllm

3.2.3 安装pytorch

切换conda虚拟环境:

conda activate vllm

配置pip加速:

vim /etc/pip.conf

添加如下内容:

[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
timeout = 600

测试生效:

pip config list

下载地址:download.pytorch.org/whl/torch/
根据显卡信息中的CUDA版本下载,因为显卡信息中的CUDA是CUDA Version: 12.8,这里需要下载低于12.8版本的。

下载:torch-2.4.0+cu124-cp312-cp312-linux_x86_64.whlcu124 指的是CUDA版本是12.4、cp312 指的是python 3.12环境),下载后保存到路径/usr/local

安装:

# 安装
pip install /usr/local/torch-2.4.0+cu124-cp312-cp312-linux_x86_64.whl

验证安装:

pip show torch
# 或者
pip list | grep torch

3.2.4 安装vllm

参考vllm官方文档:Installation — vLLM

命令:

# 切环境
conda activate vllm
# 安装
pip install vllm

查看版本:

vllm --version

输出内容参考:

(vllm) [root@localhost bin]# vllm --version
INFO 02-21 08:41:14 __init__.py:207] Automatically detected platform cuda.
0.7.3

升级vllm命令:

pip install --upgrade vllm

3.2.5 vllm运行deepseek

进入虚拟环境:

conda activate vllm

运行命令:

CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6 vllm serve /home/data/models/DeepSeek-R1-Distill-Qwen-32B \
--pipeline-parallel-size 7 \
--tensor-parallel-size 1 \
--host 0.0.0.0 \
--port 8000 \
--max_model_len 2048 \
--gpu-memory-utilization 0.9 \
--max-num-seqs 32 \
--served-model-name "DeepSeek-R1-Distill-Qwen-32B" \
--dtype=half

参数的详细解释:

  • CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6
    含义: 指定使用哪些 GPU 设备。这个环境变量告诉 CUDA 运行时只使用编号为 0 到 4 的 GPU(共 7 个 GPU)。
    作用: 限制模型运行在指定的 GPU 上,而不是系统中的所有 GPU。
    例子: 如果系统中还有其他 GPU(比如 7、8),它们不会被这个进程使用。

  • vllm serve
    含义: 调用 vLLM 的服务启动命令,用于部署模型并提供推理服务。
    作用: 启动一个服务器,允许通过网络请求(比如 HTTP API)对模型进行推理。

  • /home/data/models/DeepSeek-R1-Distill-Qwen-32B
    含义: 指定要加载的模型路径。在 FP16 精度下(--dtype=half),每个参数占 2 字节,模型权重大约需要 64GB 显存。加上激活值、KV 缓存等,显存需求可能接近或超过 80GB。
    作用: 告诉 vLLM 使用这个目录下的模型文件(DeepSeek-R1-Distill-Qwen-32B)进行推理。这通常是一个预训练的大型语言模型。

  • --pipeline-parallel-size 7
    含义: 设置管道并行的大小为 7。
    作用: 将模型的计算任务分成 7 个阶段,每个阶段分配给一个 GPU。这种方式利用多个 GPU 并行处理模型的不同层或部分,适合超大模型推理。
    注意: 这里 7 对应于 CUDA_VISIBLE_DEVICES 中指定的 7 个 GPU。

  • --tensor-parallel-size 1
    含义: 设置张量并行的大小为 1。
    作用: 张量并行是将模型的张量(比如权重矩阵)分割到多个 GPU 上并行计算。这里设为 1,意味着不使用张量并行,每个 GPU 完整持有模型的一部分(配合管道并行使用)。
    对比: 如果设为大于 1,会在多个 GPU 间分割同一层的计算。

  • --host 0.0.0.0
    含义: 指定服务器监听的主机地址。
    作用: 0.0.0.0 表示服务器监听所有网络接口,允许外部设备通过网络访问服务。
    例子: 如果设为 127.0.0.1,则只能本地访问。

  • --port 8000
    含义: 指定服务器监听的端口号。
    作用: 服务将运行在 8000 端口,客户端可以通过这个端口发送推理请求。
    例子: 你可以用 http://<服务器IP>:8000 来访问服务。

  • --max_model_len 2048
    含义: 设置模型支持的最大序列长度为 2048 个 token。
    作用: 限制输入和输出的总长度(包括上下文和生成内容),避免内存溢出。
    注意: 如果输入超过这个长度,可能会被截断或报错。

  • --gpu-memory-utilization 0.9
    含义: 设置 GPU 内存利用率为 90%。
    作用: 控制每个 GPU 上分配给模型的显存比例(这里是 90%),剩余部分留给系统或其他开销。
    例子: 如果一块 GPU 有 24GB 显存,这里会分配约 21.6GB 给模型。

  • --max-num-seqs 32

    指定 vLLM 在一次批处理中最多处理的序列数(即最大 batch size)。它限制了并发请求的上限,直接影响吞吐量和显存使用。

    vLLM 默认可能是 256(视版本而定),但会受显存和 --max_model_len 限制。

  • --served-model-name 'DeepSeek-R1-Distill-Qwen-32B'
    含义: 指定服务中模型的名称。
    作用: 客户端请求时可以用这个名字来标识模型,通常用于区分多个部署的模型。
    例子: 在 API 请求中可能会用 "model": "DeepSeek-R1-Distill-Qwen-32B" 来调用。

  • --dtype=half
    含义: 指定模型的数据类型为半精度浮点数(FP16)。
    作用: 使用 FP16(而不是默认的 FP32)来减少显存占用并加速计算,同时保持合理的精度。
    注意: 需要 GPU 支持 FP16 计算(比如 NVIDIA 的 Volta、Turing、Ampere 架构)。

其他说明

pipeline-parallel-sizetensor-parallel-size这两个参数相乘就是总的GPU需求数量,相乘的积需要小于总的可用的GPU数量,注意配置合理。

​ 实际生产过程中发现(7张T4):pipeline-parallel-size * tensor-parallel-size的积为偶数最佳,单独的一个显存用来分配给嵌入模型使用。

3.2.6 配置启动脚本

创建文件夹

mkdir -p /usr/local/deepseek

3.2.6.1 普通脚本

编辑脚本文件

vim /usr/local/deepseek/start_DeepSeek-R1-Distill-Qwen-32B_By_vLLM.sh

脚本内容参考如下:

#!/bin/bash
# 加载 conda 环境
source /usr/local/miniconda3/etc/profile.d/conda.sh
conda activate vllm
# 启动 vllm 服务
CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6 vllm serve /home/data/models/DeepSeek-R1-Distill-Qwen-32B \
    --pipeline-parallel-size 7 \
    --tensor-parallel-size 1 \
    --host 0.0.0.0 \
    --port 8000 \
    --max_model_len 4096 \
    --gpu-memory-utilization 0.9 \
    --max-num-seqs 32 \
    --served-model-name 'DeepSeek-R1-Distill-Qwen-32B' \
    --dtype=half

注意:如果需要显示Think标签,可以追加如下内容到start_DeepSeek-R1-Distill-Qwen-32B_By_vLLM.sh脚本中:

#!/bin/bash
# 加载 conda 环境
source /usr/local/miniconda3/etc/profile.d/conda.sh
conda activate vllm
# 启动 vllm 服务
CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6 vllm serve /home/data/models/DeepSeek-R1-Distill-Qwen-32B \
    --pipeline-parallel-size 7 \
    --tensor-parallel-size 1 \
    --host 0.0.0.0 \
    --port 8000 \
    --max_model_len 4096 \
    --gpu-memory-utilization 0.9 \
    --max-num-seqs 32 \
    --served-model-name 'DeepSeek-R1-Distill-Qwen-32B' \
    --dtype=half \
	--chat-template /home/data/models/DeepSeek-R1-Distill-Qwen-32B/template_deepseek_r1.jinja

编辑systemd启动文件:

vim  /etc/systemd/system/deepseek.service

内容参考如下:

[Unit]
Description=DeepSeek-R1-Distill-Qwen-32B
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/usr/local/deepseek
ExecStart=/bin/bash /usr/local/deepseek/start_DeepSeek-R1-Distill-Qwen-32B_By_vLLM.sh
Restart=always

[Install]
WantedBy=multi-user.target

生效配置:

systemctl daemon-reload

启动、自启动:

systemctl start deepseek
systemctl enable deepseek

3.2.6.2 高级脚本

#!/bin/bash

# 脚本用途说明
echo "Starting vLLM server for DeepSeek-R1-Distill-Qwen-1.5B..."

# 定义所有需要检查的路径和环境变量
CONDA_BASE="/usr/local/conda"                  # Miniconda 安装路径
CONDA_ENV="vllm"                                    # Conda环境名称
MODEL_PATH="/home/yyj/data/models/DeepSeek-R1-Distill-Qwen-1.5B"  # 模型路径
PORT=8000                                           # vLLM 服务端口
LOG_FILE="/usr/local/deepseek/vllm_server_for_deepseek_1.5B.log"  #日志文件路径

# 设置错误处理:脚本在遇到错误时退出
set -e

# 检查 Conda 路径是否存在
if [ ! -d "$CONDA_BASE" ]; then
    echo "Error: Miniconda not found at $CONDA_BASE. Please update CONDA_BASE in the script."
    exit 1
fi

# 加载 Conda 环境
source "$CONDA_BASE/etc/profile.d/conda.sh"
conda activate "$CONDA_ENV" || {
    echo "Error: Failed to activate conda environment '$CONDA_ENV'. Please ensure it exists."
    exit 1
}

# 检查 NVIDIA GPU 是否可用
if ! command -v nvidia-smi &> /dev/null; then
    echo "Warning: nvidia-smi not found. GPU might not be available."
else
    echo "GPU detected: $(nvidia-smi --query-gpu=name --format=csv,noheader)"
fi

# 检查模型路径是否存在
if [ ! -d "$MODEL_PATH" ]; then
    echo "Error: Model path $MODEL_PATH does not exist. Please update MODEL_PATH in the script."
    exit 1
fi

# 启动 vLLM 服务
echo "Launching vLLM server on port $PORT..."
CUDA_VISIBLE_DEVICES=0 vllm serve "$MODEL_PATH" \
    --pipeline-parallel-size 1 \
    --tensor-parallel-size 1 \
    --host 0.0.0.0 \
    --port "$PORT" \
    --max_model_len 1024 \
    --gpu-memory-utilization 0.85 \
    --max-num-seqs 32 \
    --served-model-name "DeepSeek-R1-Distill-Qwen-1.5B" \
    2>&1 | tee "$LOG_FILE"

# 保存进程 ID 并等待几秒检查是否启动成功
VLLM_PID=$!
sleep 5

if ps -p $VLLM_PID > /dev/null; then
    echo "vLLM server started successfully with PID $VLLM_PID. Logs are saved to $LOG_FILE."
else
    echo "Error: vLLM server failed to start. Check $LOG_FILE for details."
    exit 1
fi

echo "Server is running in the background. Access it at http://0.0.0.0:$PORT."

编辑systemd启动文件:

[Unit]
Description=DeepSeek-R1-Distill-Qwen-1.5B
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/deepseek/start_DeepSeek-R1-Distill-Qwen-1.5B_By_vLLM.sh
ExecStop=/bin/kill -TERM $MAINPID
#Restart=on-failure
#RestartSec=5s
# 设置为脚本或模型所在的目录。
WorkingDirectory=/usr/local/deepseek
#User=
#Group=yyj
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

3.2.7 优化

3.2.7.1 think思考标签

如果需要弃用think思考标签,需要添加--chat-template,修改启动脚本,内容参考如下:

#!/bin/bash
# 加载 conda 环境
source /usr/local/miniconda3/etc/profile.d/conda.sh
conda activate vllm
# 启动 vllm 服务
CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6 vllm serve /home/data/models/DeepSeek-R1-Distill-Qwen-32B \
    --pipeline-parallel-size 7 \
    --tensor-parallel-size 1 \
    --host 0.0.0.0 \
    --port 8000 \
    --max_model_len 4096 \
    --gpu-memory-utilization 0.9 \
    --max-num-seqs 32 \
    --served-model-name 'DeepSeek-R1-Distill-Qwen-32B' \
    --dtype=half \
	--chat-template /home/data/models/DeepSeek-R1-Distill-Qwen-32B/template_deepseek_r1.jinja

template_deepseek_r1.jinja内容如下:

{% if not add_generation_prompt is defined %}{% set add_generation_prompt = false %}{% endif %}{% set ns = namespace(is_first=false, is_tool=false, is_output_first=true, system_prompt='') %}{%- for message in messages %}{%- if message['role'] == 'system' %}{% set ns.system_prompt = message['content'] %}{%- endif %}{%- endfor %}{{bos_token}}{{ns.system_prompt}}{%- for message in messages %}{%- if message['role'] == 'user' %}{%- set ns.is_tool = false -%}{{'<|User|>' + message['content']}}{%- endif %}{%- if message['role'] == 'assistant' and message['content'] is none %}{%- set ns.is_tool = false -%}{%- for tool in message['tool_calls']%}{%- if not ns.is_first %}{{'<|Assistant|><|tool▁calls▁begin|><|tool▁call▁begin|>' + tool['type'] + '<|tool▁sep|>' + tool['function']['name'] + '\\n' + '```json' + '\\n' + tool['function']['arguments'] + '\\n' + '```' + '<|tool▁call▁end|>'}}{%- set ns.is_first = true -%}{%- else %}{{'\\n' + '<|tool▁call▁begin|>' + tool['type'] + '<|tool▁sep|>' + tool['function']['name'] + '\\n' + '```json' + '\\n' + tool['function']['arguments'] + '\\n' + '```' + '<|tool▁call▁end|>'}}{{'<|tool▁calls▁end|><|end▁of▁sentence|>'}}{%- endif %}{%- endfor %}{%- endif %}{%- if message['role'] == 'assistant' and message['content'] is not none %}{%- if ns.is_tool %}{{'<|tool▁outputs▁end|>' + message['content'] + '<|end▁of▁sentence|>'}}{%- set ns.is_tool = false -%}{%- else %}{% set content = message['content'] %}{% if '</think>' in content %}{% set content = content.split('</think>')[-1] %}{% endif %}{{'<|Assistant|>' + content + '<|end▁of▁sentence|>'}}{%- endif %}{%- endif %}{%- if message['role'] == 'tool' %}{%- set ns.is_tool = true -%}{%- if ns.is_output_first %}{{'<|tool▁outputs▁begin|><|tool▁output▁begin|>' + message['content'] + '<|tool▁output▁end|>'}}{%- set ns.is_output_first = false %}{%- else %}{{'\\n<|tool▁output▁begin|>' + message['content'] + '<|tool▁output▁end|>'}}{%- endif %}{%- endif %}{%- endfor -%}{% if ns.is_tool %}{{'<|tool▁outputs▁end|>'}}{% endif %}{% if add_generation_prompt and not ns.is_tool %}{{'<|Assistant|>'}}{% endif %}

参考:本地部署DeepSeek-R1-Distill-Qwen-32B,输出仅有,没有 · Issue #352 · deepseek-ai/DeepSeek-R1

  • QwQ-32B Think标签优化

参考:Tutorial: How to Run QwQ-32B effectively | Unsloth Documentation

{%- if tools %} {{- '<|im_start|>system\n' }} {%- if messages[0]['role'] == 'system' %} {{- messages[0]['content'] }} {%- else %} {{- '' }} {%- endif %} {{- "\n\n# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>" }} {%- for tool in tools %} {{- "\n" }} {{- tool | tojson }} {%- endfor %} {{- "\n</tools>\n\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n<tool_call>\n{\"name\": <function-name>, \"arguments\": <args-json-object>}\n</tool_call><|im_end|>\n" }} {%- else %} {%- if messages[0]['role'] == 'system' %} {{- '<|im_start|>system\n' + messages[0]['content'] + '<|im_end|>\n' }} {%- endif %} {%- endif %} {%- for message in messages %} {%- if (message.role == "user") or (message.role == "system" and not loop.first) %} {{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>' + '\n' }} {%- elif message.role == "assistant" and not message.tool_calls %} {%- set content = message.content.split('</think>')[-1].lstrip('\n') %} {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }} {%- elif message.role == "assistant" %} {%- set content = message.content.split('</think>')[-1].lstrip('\n') %} {{- '<|im_start|>' + message.role }} {%- if message.content %} {{- '\n' + content }} {%- endif %} {%- for tool_call in message.tool_calls %} {%- if tool_call.function is defined %} {%- set tool_call = tool_call.function %} {%- endif %} {{- '\n<tool_call>\n{"name": "' }} {{- tool_call.name }} {{- '", "arguments": ' }} {{- tool_call.arguments | tojson }} {{- '}\n</tool_call>' }} {%- endfor %} {{- '<|im_end|>\n' }} {%- elif message.role == "tool" %} {%- if (loop.index0 == 0) or (messages[loop.index0 - 1].role != "tool") %} {{- '<|im_start|>user' }} {%- endif %} {{- '\n<tool_response>\n' }} {{- message.content }} {{- '\n</tool_response>' }} {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %} {{- '<|im_end|>\n' }} {%- endif %} {%- endif %} {%- endfor %} {%- if add_generation_prompt %} {{- '<|im_start|>assistant\n' }} {%- endif %}

3.2.7.2 优化提示词

参考1:

先思考,然后按照以下格式回答用户的问题:
<think>推理内容</think>
内容

参考2:

先从语义分析用户问题,若无法回答,再检索知识库;回答格式如下:
<think>推理内容</think>
内容

3.2.8 调用测试

查看部署的模型:

curl http://localhost:8000/v1/models

对话测试:

curl http://localhost:8000/v1/completions \
-H "Content-Type: application/json" \
-d '{"model": "DeepSeek-R1-Distill-Llama-70B", "prompt": "1+1=", "max_tokens": 20}'

4.open-webui安装

采用docker方式安装:

docker run -d \
-p 3000:8080 \
--add-host=host.docker.internal:host-gateway \
-v /home/data/open-webui:/app/backend/data \
--restart always \
--name open-webui \
ghcr.nju.edu.cn/open-webui/open-webui:main

注意:将ghcr.io换成 ghcr.nju.edu.cn加速下载,使用教育网镜像加速超级快。

5.嵌入模型安装

参考地址:

5.1 本地方式安装

下载text-embeddings-inference源码,下载地址:Releases · huggingface/text-embeddings-inference · GitHub

解压:

unzip text-embeddings-inference-1.6.0.zip -C /usr/local/

进入源码目录:

cd /usr/local/text-embeddings-inference-1.6.0

卸载Rust:

rustup self uninstall

然后install Rust:

# 配置加速
# export RUSTUP_DIST_SERVER=https://mirrors.ustc.edu.cn/rust-static
# export RUSTUP_UPDATE_ROOT=https://mirrors.ustc.edu.cn/rust-static/rustup
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# 阿里云脚本 curl --proto '=https' --tlsv1.2 -sSf https://mirrors.aliyun.com/repo/rust/rustup-init.sh | sh

然后重新加载环境变量, 使 rustup 命令生效.

source $HOME/.cargo/env

查看Rust版本:

rustc --version

配置cargo加速:

vim ~/.cargo/config.toml

参考内容:

[source.crates-io]
replace-with = 'tuna'

[source.tuna]
registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git"

指定rust版本:

vim /usr/local/text-embeddings-inference-1.6.0/rust-toolchain.toml

修改如下:

[toolchain]
# 这里指定 1.85.0版本
channel = "1.85.0"
components = ["rustfmt", "clippy"]

接着操作如下:

# 安装
cargo install --path router -F mkl
# 这一步做好心里准备,网络不好可能也会弄个几个小时;如果网络有问题,试试命令:curl -I https://github.com,检查下github的网络可达性

安装文本处理工具:

text-embeddings-router --model-id /usr/local/{本地下载好的模型} --port 8080

可能会面临的问题:

5.2 Docker方式安装

5.2.1 安装容器依赖

安装docker容器的NVIDIA Container Toolkit的依赖

参考:

Installing the NVIDIA Container Toolkit — NVIDIA Container Toolkit
1. Introduction — Installation Guide for Linux 12.8 documentation
Ubuntu 22.04离线安装Docker和NVIDIA Container Toolkit - 知乎

如果以来下载慢/下载不下来,直接迅雷本地下载上传Linux后手动离线安装,我这里就离线安装了:
https://nvidia.github.io/libnvidia-container/stable/rpm/x86_64/nvidia-container-toolkit-base-1.17.4-1.x86_64.rpm

Github仓库地址:libnvidia-container/stable/rpm/x86_64 at gh-pages · NVIDIA/libnvidia-container

安装:

rpm -ivh nvidia-container-toolkit-base-1.17.5-1.x86_64.rpm

检验是否安装成功:

rpm -qa | grep nvidia-container-toolkit

5.2.2 下载模型

创建模型模型保存目录:

mkdir -p /usr/local/nomic-embed-text/model

去huggingface.co下载嵌入模型nomic-ai/nomic-embed-text-v1.5,然后保存到路径/usr/local/nomic-embed-text/model

5.2.2 安装嵌入模型

参考:GPTs-0071-部署 text-embeddings-inference:cpu-1.5 - 知乎

创建嵌入模型的基础目录:

mkdir -p /usr/local/embedding-model/

创建模型保存目录:

mkdir -p /usr/local/embedding-model/{你需要安装的嵌入模型的目录}
# 示例 mkdir -p /usr/local/embedding-model/nomic-embed-text-v1.5

下载模型模型保存目录中,下载后的模型路径示例:/usr/local/embedding-model/nomic-embed-text-v1.5/nomic-embed-text-v1.5

注意:模型保存目录下需要保存模型的原有的目录(2个一样的目录才行),这个是需要挂载到容器内部的。

  • CPU部署参考命令如下:
docker run -itd \
-p 9003:80 \
-v /usr/local/embedding-model/nomic-embed-text-v1.5:/data \
--name nomic-embed-text-v1.5 \
--restart=always \
ghcr.nju.edu.cn/huggingface/text-embeddings-inference:cpu-1.6 \
--model-id /data/nomic-embed-text-v1.5

参数解释:

--model-id /data/nomic-embed-text-v1.5

  • 这是传递给容器内应用程序的一个参数。
  • 结合前面的 -v 挂载选项,这实际上是告诉容器使用宿主机上挂载到 /data 的模型文件(可能是 nomic-embed-text-v1.5 模型)。

注意:

  • 注意:将ghcr.io换成 ghcr.nju.edu.cn加速下载,使用教育网镜像加速超级快。
  • 这里安装的是CPU处理类型(ghcr.nju.edu.cn/huggingface/text-embeddings-inference:cpu-1.6),非利用GPU计算类型;
    也可以参考:Using TEI locally with CPU

可能面临的问题:

可能面临的报错:

Caused by:
    0: request error: error sending request for url (https://huggingface.co/nomic-embed-text-v1.5/resolve/main/config.json): error trying to connect: tcp connect error: Connection timed out (os error 110)
    1: error sending request for url (https://huggingface.co/nomic-embed-text-v1.5/resolve/main/config.json): error trying to connect: tcp connect error: Connection timed out (os error 110)
    2: error trying to connect: tcp connect error: Connection timed out (os error 110)
    3: tcp connect error: Connection timed out (os error 110)
    4: Connection timed out (os error 110)
# 如果你出现了上述报错,你一定是没仔细阅读本文档;需要采用离线方式下载模型后,保存到指定的目录下,请按照文档操作
  • GPU 部署参考命令如下:
docker run -itd \
--gpus '"device=4"' \
-p 9003:80 \
-v /home/embedding-models/bge-m3-model:/data \
--name bge-m3 \
--restart=always \
ghcr.nju.edu.cn/huggingface/text-embeddings-inference:89-1.6 \
--model-id /data/bge-m3

# /home/embedding-models/bge-m3-model路径下放了bge-m3下载下来的模型

其他:
在RAG中应用中,BGE-M3可以替代商业的embedding模型,实现低成本、可控的解决方案。它具备的两个重要的功能:

​ 多语言,可以支持100多种工作语言
​ 可输入最长8192个token的长文本。
​ 在进行生成应用时,我们除了关注模型本身的能力外,还需要关注其服务化的性能。

5.2.4 调用测试

BGE-M3调用测试命令:

curl -w "\n总时间: %{time_total}s\n名称解析时间: %{time_namelookup}s\n连接时间: %{time_connect}s\nTLS握手时间: %{time_appconnect}s\n等待时间: %{time_starttransfer}s\n数据传输时间: %{time_total}s\nHTTP状态码: %{http_code}\n" \
--location '10.0.10.251:9003/embeddings' \
--header 'Content-Type: application/json' \
--data '{
    "input":["橘子洲,位于湖南省长沙市区中湘江江心,北纬28°10′23.40″、东经112°57′18.36″,是湘江下游众多冲积沙洲之一。橘子洲西望岳麓山,东临长沙城,四面环水,长达5千米,狭处横约40米,宽处横约140米,最宽处仅300余米,岛形狭长,形似长龙。橘子洲大桥从上横跨而过,离长沙市中心1千米。面积0.614平方千米。从自然演变过程来看,橘子洲为第四纪全新世时期形成的、典型的一级阶地地层,地貌属高河漫滩,主要由以下三方面因素作用而成:一是江心基岩凸起,湘江主流至此分流,分流携带的泥沙通过回流,淤落在江心突起之基岩上形成心滩;二是湘江长沙段江面变宽,江水流速减小,泥沙易于淤落;三是受下游浏阳河、捞刀河以及洞庭湖水顶托,泥沙易于淤落,天长地久,日积月累,“心滩”经新构造运动上升露出水面而形成一座江心岛。橘子洲上生长着数千种花草藤蔓植物,其中名贵植物有143种。有鹤、鹭、鸥、狐、獾等珍稀动物。2012年,长沙市岳麓山-橘子洲旅游区被评为国家AAAAA级景区,橘子洲是其重要组成部分。"],
    "model":"bge-m3"
}'

这段curl会统计请求的各个阶段的耗时,将其在服务器上直接运行,避免网络带来的影响。如果需要对比CPU耗时,请部署CPU架构后测试,再对比数据。

bge-reranker-large调用测试命令:

curl -X 'POST' \
  'http://10.0.10.251:9004/rerank' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{ "query": "What is Deep Learning?", "texts": [ "Deep Learning is ...", "hello"]}'
posted @ 2025-08-27 16:28  youngyajun  阅读(498)  评论(0)    收藏  举报