机战私服层层封锁穿墙vLLM、ollama方式部署本地大模型(单机)
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)" 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/ModelfileModelfile内容如下:
# 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 :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: - - - show_channel_urls: true default_channels: - - - custom_channels: conda-forge: msys2: bioconda: menpo: pytorch: pytorch-lts: simpleitk:查看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版本的。
下载: (cu124 指的是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 端口,客户端可以通过这个端口发送推理请求。
例子: 你可以用 <服务器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-size和tensor-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 :$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.jinjatemplate_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 :8000/v1/models对话测试:
curl :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 模型)。
注意:
可能面临的问题:
可能面临的报错:
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的长文本。
在进行生成应用时,我们除了关注模型本身的能力外,还需要关注其服务化的性能。
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"]}'