本文档将详细阐述基于物理机服务的 deepseek-R1-671b 多机部署方案,基于4台昇腾910B物理机进行最佳实践,内容涵盖环境准备、服务启动与可视化界面三个方面。
Tips:DeepSeek的bf16版本部署需要4台昇腾910B物理机服务器,w8a8量化版本需要2台昇腾910B物理机服务器。
一、环境准备
开通物理机资源
可选规格(推荐):建议客户根据实际需求选择。
服务器类型 | 规格名 | 资源池 | CPU | 内存(GB) | GPU |
---|---|---|---|---|---|
910b液冷 | physical.lcas910b.2xlarge11 | 上海15(弹性裸金属)杭州7 (弹性裸金属)武汉41(弹性裸金属)芜湖4 (弹性裸金属)西南1 (弹性裸金属)华北2 (弹性裸金属) | 4路48核 | 1536 | 8*昇腾910B |
910b风冷 | physical.acas910b.2xlarge11 | 华北2 (标准裸金属)华南2 (标准裸金属)西南2 (标准裸金属)中卫5 (标准裸金属)沈阳8 (弹性裸金属) | 4路48核 | 1536 | 8*昇腾910B |
1.1 物料下载
R1模型下载链接:DeepSeek-R1 · 模型库 (modelscope.cn),修改模型文件夹属组为root,执行权限为750:chown -R root:root /path-to-weights/DeepSeek-R1 && chmod -R 750 /path-to-weights/DeepSeek-R1
昇腾镜像下载链接:mindie (hiascend.com)。下载2.0.T3.1 PoC版本(2.0.T3.1-800I-A2-py311-openeuler24.03-lts),该版本支持DeepSeek-V3/R1的BF16/W8A8格式。
docker login -u cn-south-1@{{用户名}} swr.cn-south-1.myhuaweicloud.com
密码:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
拉取镜像:docker pull swr.cn-south-1.myhuaweicloud.com/ascendhub/mindie:2.0.T3.1-800I-A2-py311-openeuler24.03-lts
1.2 配置镜像源(可选)
(仅针对ctyunos系统)根据天翼云镜像站ctyunos的指导文档(天翼云开源镜像站 (ctyun.cn))配置/etc/yum.repos.d/CTyunOS.repo,并且执行yum clean all && yum makecache
安装依赖:
sudo yum install -y gcc make net-tools python3 python3-dev python3-pip
pip3 install attrs cython numpy==1.24.0 decorator sympy cffi pyyaml pathlib2 psutil protobuf==3.20 scipy requests absl-py --user
python3 --version(后续步骤中用于量化的CANN支持Python3.7.x至3.11.4版本)
pip3 --version
1.3 NPU侧权重转换
fp8转为bf16(目前npu转换脚本不会自动复制tokenizer等文件)
git clone https://gitee.com/ascend/ModelZoo-PyTorch.git
cd ModelZoo-PyTorch\MindIE\LLM\DeepSeek\DeepSeek-V2\NPU_inference
python fp8_cast_bf16.py --input-fp8-hf-path /path/to/DeepSeek-R1 --output-bf16-hf-path /path/to/deepseek-R1-bf16
- /path/to/DeepSeek-R1 表示DeepSeek-R1原始权重路径,/path/to/deepseek-R1-bf16 表示权重转换后的新权重路径。
- 由于模型权重较大,请确保您的磁盘有足够的空间放下所有权重,可依据磁盘大小自行选择是否创建LVM磁盘虚拟化,DeepSeek-R1的fp8格式权重约为640G,bf16格式的权重约为1.3T。
- 推理作业时,也请确保您的设备有足够的空间加载模型权重,并为推理计算预留空间。
- 部署DeepSeek-R1模型用bf16权重进行推理至少需要4台Atlas 800I A2(864G)服务器,用W8A8量化权重进行推理则至少需要2台Atlas 800I A2 (864G)。
1.4 权重量化(仅671b在两机部署需要)
1.4.1 CANN安装
说明权重量化(bf16-w8a8)需要安装CANN、msit和msModelSlim,若想直接获取量化后的w8a8文件,可直接跳转本文第1.4.3章节
cd /mnt/matrix/CANN
下载链接:https://www.hiascend.com/developer/download/community/result?module=pt+cann&product=4&model=32
下载安装包:①Ascend-cann-toolkit_8.0.0_linux-aarch64.run ②Ascend-cann-kernels-910b_8.0.0_linux-aarch64.run ③Ascend-cann-nnal_8.0.0_linux-aarch64.run
针对安装包①Ascend-cann-toolkit_8.0.0_linux-aarch64.run:
增加对软件包的可执行权限,校验软件包安装文件的一致性和完整性。
chmod +x Ascend-cann-toolkit_8.0.0_linux-aarch64.run
./Ascend-cann-toolkit_8.0.0_linux-aarch64.run --check
出现如下回显信息,表示软件包校验成功。
Verifying archive integrity... 100% SHA256 checksums are OK. All good.
安装软件包
./Ascend-cann-toolkit_8.0.0_linux-aarch64.run --install
执行以上命令会打屏华为企业业务最终用户许可协议(EULA)的条款和条件,请输入Y或y同意协议,继续安装流程。
安装完成后,若显示如下信息,则说明软件安装成功:
xxx install success
xxx表示安装的实际软件包名。
说明如果用户未指定安装路径,则软件会安装到默认路径下,默认安装路径如下。root用户:“/usr/local/Ascend”,非root用户:“${HOME}/Ascend”,${HOME}为当前用户目录。
配置环境变量,当前以root用户安装后的默认路径为例,请用户根据set_env.sh的实际路径执行如下命令。
source /usr/local/Ascend/ascend-toolkit/set_env.sh
安装后检查。执行如下命令查询CANN版本信息,查询结果与安装软件包的版本一致时,则验证安装成功。
cd /usr/local/Ascend/ascend-toolkit/latest/aarch64-linux/
执行命令,查看version字段提供的版本信息。
cat ascend_toolkit_install.info
针对安装包②Ascend-cann-kernels-910b_8.0.0_linux-aarch64.run
chmod +x Ascend-cann-kernels-910b_8.0.0_linux-aarch64.run
./Ascend-cann-kernels-910b_8.0.0_linux-aarch64.run --check
./Ascend-cann-kernels-910b_8.0.0_linux-aarch64.run --install
./Ascend-cann-kernels-910b_8.0.0_linux-aarch64.run --devel
中间输入Y或y同意条款,继续安装流程
cd /usr/local/Ascend/ascend-toolkit/latest/opp_kernel
cat version.info
针对安装包:③Ascend-cann-nnal_8.0.0_linux-aarch64.run
chmod +x Ascend-cann-nnal_8.0.0_linux-aarch64.run
./Ascend-cann-nnal_8.0.0_linux-aarch64.run --check
./Ascend-cann-nnal_8.0.0_linux-aarch64.run --install
中间输入Y或y同意条款,继续安装流程
source /usr/local/Ascend/nnal/atb/set_env.sh
说明自动配置:执行set_env.sh脚本时,若不加任何参数,且已检测到PyTorch环境时会自动调用torch.compiled_with_cxx11_abi()接口,自动选择PyTorch编译时abi参数作为ATB的abi参数,
如果没有检测到PyTorch环境则默认配置abi=1。
手动配置:执行set_env.sh时,支持用户通过--cxx_abi=1和--cxx_abi=0参数指定ATB的abi参数。
自动配置:执行set_env.sh脚本时,若不加任何参数,且已检测到PyTorch环境时会自动调用torch.compiled_with_cxx11_abi()接口,自动选择PyTorch编译时abi参数作为ATB的abi参数,如果没有检测到PyTorch环境则默认配置abi=1。
手动配置:执行set_env.sh时,支持用户通过--cxx_abi=1和--cxx_abi=0参数指定ATB的abi参数。
cd /usr/local/Ascend/nnal/atb/latest
cat version.info
1.4.2 msit和msModelSlim安装
说明DeepSeek模型当前已验证的量化方法:
W8A8量化:DeepSeek-V2-Lite-Chat-16B, DeepSeek-V2-Chat-236B, DeepSeek-V3, DeepSeek-R1
W8A16量化:DeepSeek-V2-Lite-Chat-16B, DeepSeek-V2-Chat-236
msmodelslim是msit的组件,需依次安装(CANN8.0.RC3之后的版本,将会只支持开源方式使用,通过CANN包直接使用的方式将不再受支持。后续功能优化、新增将更新在开源版本中。):
pip config set global.index-url https://xxxxx(可自行配置较快的镜像源)
git clone https://gitee.com/ascend/msit.git
cd /mnt/matrix/msit/msit-br_noncom_MindStudio_8.0.0_POC_20251231/msit
bash install.sh
cd /mnt/matrix/msit/msit-br_noncom_MindStudio_8.0.0_POC_20251231/msmodelslim
bash install.sh
创建虚拟环境:
python3 -m venv ~/venv3
source /root/venv3/bin/activate
***\*cd /mnt/matrix/msit/msit-br_noncom_MindStudio_8.0.0_POC_20251231/msmodelslim/example/DeepSeek\****
export PYTHONPATH="/mnt/matrix/msit/msit-br_noncom_MindStudio_8.0.0_POC_20251231/msmodelslim:$PYTHONPATH"
cat /usr/local/Ascend/ascend-toolkit/set_env.sh
量化权重可使用quant_deepseek_w8a8.py脚本生成:
DeepSeek-V2/V3/R1 w8a8 混合量化(MLA:w8a8量化,MOE:w8a8 dynamic量化)
生成DeepSeek-V2/V3/R1模型 w8a8 混合量化权重(当前量化只支持输入bf16格式模型):
***\*python3 quant_deepseek_w8a8.py --model_path /mnt/matrix/model/deepseek-R1-bf16 --save_path /mnt/matrix/model/DeepSeek-R1-W8A8\****
(python3 quant_deepseek_w8a8.py --model_path {浮点权重路径} --save_path {W8A8量化权重路径} )
说明fp8(640G左右)转bf16(1.3T左右)转w8a8(600G左右)
1.4.3 直接下载w8a8模型文件(可选)
首先安装git-lfs(git large file管理工具)
(ctyunos系统无法使用官方的安装脚本,需要手动编译,其它系统可执行:
apt/deb类型存储库: curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash && apt-get install git-lfs
yum/rpm类型存储库: curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.rpm.sh | sudo bash && yum install git-lfs)
wget https://github.com/git-lfs/git-lfs/releases/download/v3.6.1/git-lfs-linux-arm-v3.6.1.tar.gz
(或者直接下载https://github.com/git-lfs/git-lfs/releases/download/v3.6.1/git-lfs-linux-arm-v3.6.1.tar.gz,并拷贝至服务器)
tar -xvzf git-lfs-linux-arm64-v3.6.1.tar.gz
cd git-lfs-3.6.1/
./install.sh
git lfs install
mkdir -p /mnt/matrix/model/(自己在nvme盘下做LVM,把模型下到对应目录)
cd /mnt/matrix/model/ && git clone https://modelers.cn/State_Cloud/DeepSeek-R1-W8A8.git
git lfs checkout
(tmux new -s xxx启一个tmux防止传输中断)
(git lfs fetch)
1.5 多机通信检查
1.5.1 TLS检查检查
每台TLS的加密配置,多机通信,需要保证每台机器TLS配置一致,默认TLS处于开启状态,需要关闭:
for i in {0..7}; do hccn_tool -i $i -tls -g ; done |grep switch
如图,此时机器TLS配置是打开,使用以下命令关闭:
for i in {0..7}; do hccn_tool -i $i -tls -s enable 0 ; done
1.5.2 健康状态检查
检查物理链接
for i in {0..7}; do hccn_tool -i $i -lldp -g | grep Ifname; done
检查链接情况
for i in {0..7}; do hccn_tool -i $i -link -g ; done
检查网络健康情况
for i in {0..7}; do hccn_tool -i $i -net_health -g ; done
查看侦测ip的配置是否正确
for i in {0..7}; do hccn_tool -i $i -netdetect -g ; done
查看网关是否配置正确
for i in {0..7}; do hccn_tool -i $i -gateway -g ; done
如果每台读取配置不输出,可以尝试重置NPU,-i 后面的编号0就是卡号,只需要复位一张卡,所有卡都会重置
npu-smi set -t reset -i 0 -c 0
1.5.3 卡间通信测试(可选)
cd /usr/local/Ascend/ascend-toolkit/latest/tools/hccl_test
cat hostfile
第一种配置方式,配置格式“节点IP:每节点进程数”,仅支持使用IPv4协议进行通信的场景
将集群内参与测试的服务器IP都添加到hostfile文件,其中执行测试命令的训练服务器IP放在第1行,每个计算节点进程数需要和NPU数量一致,默认为8。
示例:
训练节点ip:每节点的进程数
203.83.233.236:8
203.83.233.242:8
203.83.238.29:8
203.83.236.35:8
第二种配置方式,配置格式“节点名:每节点进程数”,该配置方式支持使用IPv4或者IPv6协议进行通信的场景。节点名即表14-5中配置的“HostName”;用户也可在服务器上执行hostname查看节点名。
# 训练节点名:每节点的进程数
test1:8
test2:8
test3:8
test4:8
测试前,请确保hccp进程未启动,执行如下命令查看hccp进程是否启动。
for i in {0..7}; do hccn_tool -i $i -process -g; done
执行hccl_test测试工具:
以32个计算节点,总共256个NPU(每个计算节点包含8个NPU)为例,进入/usr/local/Ascend/ascend-toolkit/latest/tools/hccl_test目录,集合通信性能测试文件为“/usr/local/Ascend/ascend-toolkit/latest/tools/hccl_test/bin/all_reduce_test”,执行以下命令,一般测试使用1G数据量,可以根据现场NPU总数量(服务器数量*8),修改-n参数值。
cd /usr/local/Ascend/ascend-toolkit/latest/tools/hccl_test
mpirun -f hostfile -n 256 ./bin/all_reduce_test -p 8 -b 1G -e 1G -f 2
如果现场用户有需求进行集合通信长稳测试时,可以执行以下命令进行持续测试。
nohup mpirun -f hostfile -n 256 ./bin/all_reduce_test -p 8 -b 1G -e 1G -i 0 > /home/hccl_test.log 2>&1 &
执行如下命令,监测测试过程。
tail -f /home/hccl_test.log
长稳测试结束后,执行以下命令结束测试。
ps -ef |grep -i all_reduce_test |grep -i [name] |grep -v grep |awk '{print $2}' |xargs -t -I {} kill -9 {}
二、容器化启动
2.1 启动并进入容器
docker run -itd --net=host --shm-size=500g \
--name=deepseek-r1 \
--device=/dev/davinci_manager \
--device=/dev/hisi_hdc \
--device=/dev/devmm_svm \
--device=/dev/davinci{0,1,2,3,4,5,6,7} \
-v /usr/local/Ascend/driver:/usr/local/Ascend/driver \
-v /usr/local/Ascend/add-ons/:/usr/local/Ascend/add-ons/ \
-v /usr/local/Ascend/firmware:/usr/local/Ascend/firmware \
-v /usr/local/sbin/npu-smi:/usr/local/sbin/npu-smi \
-v /usr/local/sbin/:/usr/local/sbin/ \
-v /var/log/npu/conf/slog/slog.conf:/var/log/npu/conf/slog/slog.conf \
-v /var/log/npu/profiling/:/var/log/npu/profiling \
-v /var/log/npu/dump/:/var/log/npu/dump \
-v /etc/hccn.conf:/etc/hccn.conf \
-v /var/log/npu/:/usr/slog \
-v /etc/localtime:/etc/localtime \
-v /mnt/data/model:/mnt/data/model \
-v /mnt/data/model/DeepSeek-R1-bf16:/mnt/data/model/DeepSeek-R1-bf16 \ # 模型权重路径,根据自己情况调整
swr.cn-south-1.myhuaweicloud.com/ascendhub/mindie:2.0.T3.1-800I-A2-py311-openeuler24.03-lts bash
进入容器:docker exec -it deepseek-r1 bash
2.2 开启通信环境变量
每台机器进入容器后,修改如下环境变量:
export ATB_LLM_HCCL_ENABLE=1
export ATB_LLM_COMM_BACKEND="hccl"
export HCCL_CONNECT_TIMEOUT=7200
export WORLD_SIZE=32
export OMP_NUM_THREADS=1 # 解决权重加载过慢问题
export HCCL_EXEC_TIMEOUT=0
export MIES_CONTAINER_IP=xx # 当前机器IP
export RANKTABLEFILE=/path-to-ranktable.json # 每台机器容器内ranktable.json地址
export HCCL_DETERMINISTIC=true
export NPU_MEMORY_FRACTION=0.95 # 设置显存比,提升NPU显存分配,避免OOM
所有环境变量可在/usr/local/Ascend/ascend-toolkit/set_env.sh查看:
2.3 纯模型测试
2.3.1 前置准备
修改权重目录所在目录下的config.json文件
将 model_type 更改为 deepseekv2 (全小写且无空格)
注意:在本次实现中,DeepSeek-R1目前沿用DeepSeek-V2代码框架
在每台机器上执行如下命令(容器外操作),获取每张NPU卡的ip地址:
for i in {0..7};do hccn_tool -i $i -ip -g; done
参考如下格式,配置rank_table_file.json
{
"version": "1.0",
"server_count": "4", #总节点数
"server_list": [
{
"server_id": "172.16.0.3",
"container_ip": "172.16.0.3",
"device": [
{ "device_id": "0", "device_ip": "100.97.0.1", "rank_id": "0" },# server_list中第一个server为主节点。。。device_id是当前卡的本机编号,取值范围[0, 本机卡数)。。。device_ip是当前卡的ip地址,可通过hccn_tool命令获取。。。rank_id是当前卡的全局编号,取值范围[0, 总卡数)
{ "device_id": "1", "device_ip": "100.97.0.2", "rank_id": "1" },
{ "device_id": "2", "device_ip": "100.97.0.3", "rank_id": "2" },
{ "device_id": "3", "device_ip": "100.97.0.4", "rank_id": "3" },
{ "device_id": "4", "device_ip": "100.97.0.5", "rank_id": "4" },
{ "device_id": "5", "device_ip": "100.97.0.6", "rank_id": "5" },
{ "device_id": "6", "device_ip": "100.97.0.7", "rank_id": "6" },
{ "device_id": "7", "device_ip": "100.97.0.8", "rank_id": "7" }
]
},
{
"server_id": "172.16.0.4",# 当前节点的ip地址
"container_ip": "172.16.0.4", # 容器ip地址(服务化部署时需要),若无特殊配置,则与server_id相同
"device": [
{ "device_id": "0", "device_ip": "100.97.0.25", "rank_id": "8" },
{ "device_id": "1", "device_ip": "100.97.0.26", "rank_id": "9" },
{ "device_id": "2", "device_ip": "100.97.0.27", "rank_id": "10" },
{ "device_id": "3", "device_ip": "100.97.0.28", "rank_id": "11" },
{ "device_id": "4", "device_ip": "100.97.0.29", "rank_id": "12" },
{ "device_id": "5", "device_ip": "100.97.0.30", "rank_id": "13" },
{ "device_id": "6", "device_ip": "100.97.0.31", "rank_id": "14" },
{ "device_id": "7", "device_ip": "100.97.0.32", "rank_id": "15" }
]
},
{
"server_id": "172.16.0.5",
"container_ip": "172.16.0.5",
"device": [
{ "device_id": "0", "device_ip": "100.97.0.65", "rank_id": "16" },
{ "device_id": "1", "device_ip": "100.97.0.66", "rank_id": "17" },
{ "device_id": "2", "device_ip": "100.97.0.67", "rank_id": "18" },
{ "device_id": "3", "device_ip": "100.97.0.68", "rank_id": "19" },
{ "device_id": "4", "device_ip": "100.97.0.69", "rank_id": "20" },
{ "device_id": "5", "device_ip": "100.97.0.70", "rank_id": "21" },
{ "device_id": "6", "device_ip": "100.97.0.71", "rank_id": "22" },
{ "device_id": "7", "device_ip": "100.97.0.72", "rank_id": "23" }
]
},
{
"server_id": "172.16.0.6",
"container_ip": "172.16.0.6",
"device": [
{ "device_id": "0", "device_ip": "100.97.0.73", "rank_id": "24" },
{ "device_id": "1", "device_ip": "100.97.0.74", "rank_id": "25" },
{ "device_id": "2", "device_ip": "100.97.0.75", "rank_id": "26" },
{ "device_id": "3", "device_ip": "100.97.0.76", "rank_id": "27" },
{ "device_id": "4", "device_ip": "100.97.0.77", "rank_id": "28" },
{ "device_id": "5", "device_ip": "100.97.0.78", "rank_id": "29" },
{ "device_id": "6", "device_ip": "100.97.0.79", "rank_id": "30" },
{ "device_id": "7", "device_ip": "100.97.0.80", "rank_id": "31" }
]
}
],
"status": "completed"
}
:wq保存退出后,将rank_table_file.json文件权限设置为640:
sudo chmod 640 /path-to-ranktablefile.json
2.3.2 精度测试(可选)
进入modeltest路径
cd /usr/local/Ascend/llm_model/tests/modeltest/
运行测试脚本
# 需在所有机器上同时执行
bash run.sh pa_bf16 [dataset] ([shots]) [batch_size] [model_name] ([is_chat_model]) [weight_dir] [rank_table_file] [world_size] [node_num] [rank_id_start] [master_address]
Example: 在DeepSeek-R1跑CEVAl数据集主节点的命令
bash run.sh pa_bf16 full_CEval 5 16 deepseekv2 /path/to/weights/DeepSeek-R1 /path/to/xxx/ranktable.json 32 4 0 {主节点IP}
# 0 代表从0号卡开始推理,之后的机器依次从8,16,24。
参数说明:
dataset可选full_BoolQ、full_CEval等,部分数据集需要设置shots
model_name为deepseekv2
weight_dir为模型权重路径
rank_table_file为“前置准备”中配置的rank_table_file.json路径
world_size为总卡数
node_num为当前节点编号,即rank_table_file.json的server_list中顺序确定
rank_id_start为当前节点起始卡号,即rank_table_file.json中当前节点第一张卡的rank_id
master_address为主节点ip地址,即rank_table_file.json的server_list中第一个节点的ip
2.3.3 性能测试(可选)
进入modeltest路径
cd /usr/local/Ascend/llm_model/tests/modeltest/
运行测试脚本
# 需在所有机器上同时执行
bash run.sh pa_bf16 performance [case_pair] [batch_size] [model_name] ([is_chat_model]) [weight_dir] [rank_table_file] [world_size] [node_num] [rank_id_start] [master_address]
参数含义同“精度测试”
Example: 在DeepSeek-R1跑性能测试主节点的命令
bash run.sh pa_bf16 performance [[256,256]] 16 deepseekv2 /path/to/weights/DeepSeek-R1 /path/to/xxx/ranktable.json 32 4 0 {主节点IP}
# 0 代表从0号卡开始推理,之后的机器依次从8,16,24。
2.3.4 服务化配置
首先配置服务化环境变量:
说明所有机器的容器内外的rank_table_file.json和config.json配置应该保持一致,除了环境变量的MIES_CONTAINER_IP为本机ip地址。(容器内自带rank_table_file.json)
说明以下所有export的参数配置均可在/mnt/data/model/***\*serve_run.sh\****中找到并修改
export MIES_CONTAINER_IP=xxx # 当前机器IP
export RANKTABLEFILE=/mnt/data/model/ranktable.json # 每台机器容器内rank_table_file.json地址
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
其次修改服务化参数:
cd /usr/local/Ascend/mindie/latest/mindie-service/
vim conf/config.json
修改以下参数:
"httpsEnabled" : false,
...
"multiNodesInferEnabled" : true, # true为开启多机推理
...
# 若不需要安全认证,则将以下两个参数设为false
"interCommTLSEnabled" : false,
"interNodeTLSEnabled" : false,
...
"modelName" : "DeepSeek-R1" # 不影响服务化拉起
"modelWeightPath" : "权重路径",
说明以下为rank_table_file.json示例,仅供参考:
{
"Version" : "1.0.0",
"LogConfig" :
{
"logLevel" : "Info",
"logFileSize" : 20,
"logFileNum" : 20,
"logPath" : "logs/mindie-server.log"
},
"ServerConfig" :
{
"ipAddress" : "192.168.1.3", # 改成主节点IP
"managementIpAddress" : "192.168.1.3", # 改成主节点IP
"port" : 11025, #根据实际情况修改
"managementPort" : 11026, #根据实际情况修改
"metricsPort" : 11027, #根据实际情况修改
"allowAllZeroIpListening" : false,
"maxLinkNum" : 300, # 如果是4机,建议300
"httpsEnabled" : false,
"fullTextEnabled" : false,
"tlsCaPath" : "security/ca/",
"tlsCaFile" : ["ca.pem"],
"tlsCert" : "security/certs/server.pem",
"tlsPk" : "security/keys/server.key.pem",
"tlsPkPwd" : "security/pass/key_pwd.txt",
"tlsCrlPath" : "security/certs/",
"tlsCrlFiles" : ["server_crl.pem"],
"managementTlsCaFile" : ["management_ca.pem"],
"managementTlsCert" : "security/certs/management/server.pem",
"managementTlsPk" : "security/keys/management/server.key.pem",
"managementTlsPkPwd" : "security/pass/management/key_pwd.txt",
"managementTlsCrlPath" : "security/management/certs/",
"managementTlsCrlFiles" : ["server_crl.pem"],
"kmcKsfMaster" : "tools/pmt/master/ksfa",
"kmcKsfStandby" : "tools/pmt/standby/ksfb",
"inferMode" : "standard",
"interCommTLSEnabled" : false,
"interCommPort" : 11121,
"interCommTlsCaPath" : "security/grpc/ca/",
"interCommTlsCaFiles" : ["ca.pem"],
"interCommTlsCert" : "security/grpc/certs/server.pem",
"interCommPk" : "security/grpc/keys/server.key.pem",
"interCommPkPwd" : "security/grpc/pass/key_pwd.txt",
"interCommTlsCrlPath" : "security/grpc/certs/",
"interCommTlsCrlFiles" : ["server_crl.pem"],
"openAiSupport" : "openai" # 默认是vllm,此处改成openai
},
"BackendConfig" : {
"backendName" : "mindieservice_llm_engine",
"modelInstanceNumber" : 1,
"npuDeviceIds" : [[0,1,2,3,4,5,6,7]],
"tokenizerProcessNumber" : 8,
"multiNodesInferEnabled" : true,
"multiNodesInferPort" : 11120,
"interNodeTLSEnabled" : false,
"interNodeTlsCaPath" : "security/grpc/ca/",
"interNodeTlsCaFiles" : ["ca.pem"],
"interNodeTlsCert" : "security/grpc/certs/server.pem",
"interNodeTlsPk" : "security/grpc/keys/server.key.pem",
"interNodeTlsPkPwd" : "security/grpc/pass/mindie_server_key_pwd.txt",
"interNodeTlsCrlPath" : "security/grpc/certs/",
"interNodeTlsCrlFiles" : ["server_crl.pem"],
"interNodeKmcKsfMaster" : "tools/pmt/master/ksfa",
"interNodeKmcKsfStandby" : "tools/pmt/standby/ksfb",
"ModelDeployConfig" :
{
"maxSeqLen" : 4096,
"maxInputTokenLen" : 2048,
"truncation" : true,
"ModelConfig" : [
{
"modelInstanceType" : "Standard",
"modelName" : "DeepSeek-R1",
"modelWeightPath" : "/mnt/data/model/DeepSeek-R1-bf16",
"worldSize" : 8,
"cpuMemSize" : 5,
"npuMemSize" : -1,
"backendType" : "atb",
"trustRemoteCode" : false
}
]
},
"ScheduleConfig" :
{
"templateType" : "Standard",
"templateName" : "Standard_LLM",
"cacheBlockSize" : 128,
"maxPrefillBatchSize" : 8,
"maxPrefillTokens" : 2048,
"prefillTimeMsPerReq" : 150,
"prefillPolicyType" : 0,
"decodeTimeMsPerReq" : 50,
"decodePolicyType" : 0,
"maxBatchSize" : 8,
"maxIterTimes" : 8192, #默认1024
"max_new_tokens" : 8192, #新增的字段哦
"maxPreemptCount" : 0,
"supportSelectBatch" : false,
"maxQueueDelayMicroseconds" : 5000
}
}
}
2.3.5 服务启动与测试
说明对于容器外主机的内存要求:内存>= 权重大小/机器数x1.3 (free -h)
建议启动服务前清理缓存:
sync; echo 3 > /proc/sys/vm/drop_caches
在每台机器容器内分别执行:
cd /usr/local/Ascend/mindie/latest/mindie-service/
./bin/mindieservice_daemon
(若想退出终端仍然保持运行,需使用nohup ./bin/mindieservice_daemon > /var/log/mindieservice.log 2>&1 &)并通过tail -f /var/log/mindieservice.log 查看输出。
执行命令后,首先会打印本次启动所用的所有参数,然后直到出现以下输出:
Daemon start success!
则认为服务成功启动!
# 执行以下命令向服务发送请求
curl -i --location 'http://{ip}:{port}/v1/chat/completions' --header 'Content-Type: application/json' --data '{ "model": "DeepSeek-R1", "stream": false, "messages": [ {"role": "user", "content": "你是谁"} ] }'
# 参数说明
- 服务ip为master节点IP地址,即为ranktable.json文件中server_list中第一个server_id的IP
- 服务port为前置步骤中配置的config.json中的["ServerConfig"]["port"]字段的值
- 请求体中"model"为4.3步骤中配置的config.json中的["BackendConfig"]["ModelDeployConfig"]["ModelConfig"]["modelName"]字段的值
三、OpenWebUI可视化
3.1 安装Open-WebUI
创建独立Python3.11环境(安装Open-WebUI要求python3.11版本):
sudo yum groupinstall -y "Development Tools"
sudo yum install -y openssl-devel bzip2-devel libffi-devel zlib-devel
wget ``https://www.python.org/ftp/python/3.11.0/Python-3.11.0.tgz``(拉取较慢,可直接本地下载后上传)
tar -xvzf Python-3.11.0.tgz
cd Python-3.11.0
./configure --enable-optimizations
make -j$(nproc)
sudo make altinstall
python3.11 --version
python3.11 -m venv /opt/webui-env
激活虚拟环境(退出虚拟环境命令为deactivate):source /opt/webui-env/bin/activate
在虚拟环境中可使用pip形式安装:pip install open-webui
(本文基于ctyunos23.01系统,ctyunos22系统及其他系统安装时肯能会产生系统不兼容的报错,此时可使用docker方式启动OpenWebUI)
启动Open-WebUI服务:nohup open-webui serve > /var/log/open-webui.log 2>&1 &
查看最新的日志内容:tail -f /var/log/open-webui.log
Open-WebUI默认使用8080端口,如果机器8080端口默认是封了的,需要使用Nginx做代理,将8080端口服务代理到其他可用端口,如8081。
3.2 Nginx反向代理
安装Nginx
yum install -y nginx
在/etc/nginx/conf.d/目录下创建文件openwebui.conf,在文件openwebui.conf中添加以下内容:
# HTTPS server for 你的域名 #填入你的域名
server {
listen 8081;
#server_name 你的域名;#填入你的域名
# SSL 配置
#ssl_certificate /etc/nginx/certs/cert.pem; #证书
#ssl_certificate_key /etc/nginx/certs/key.pem; #证书密钥
# WebSocket support
location /ws/ {
proxy_pass http://127.0.0.1:8080/ws/; # 根据实际 WebSocket 服务路径调整
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# 其他 SSL 配置(例如 TLS 强化配置)
#ssl_protocols TLSv1.2 TLSv1.3;
#ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
# 默认 location 配置
location / {
proxy_pass http://127.0.0.1:8080; #填入你的openwebui的容器名+端口号
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Nginx启动会默认使用80端口,可将/etc/nginx/nginx.conf文件里的include /etc/nginx/sites-enabled/*注释掉:
启动Nginx
systemctl start nginx
3.3 DeepSeek容器内配置
vim /usr/local/Ascend/mindie/latest/mindie-service/conf/config.json
端口设置为11025。因为接下来Open-WebUI将使用OpenAI API调用DS模型服务,因此"openAiSupport"字段需将“vllm”修改为任意其他字段,如 "openai"。
3.4 Open-WebUI界面配置指引
访问Open-WebUI服务页面 http://<公网IP>:8081
创建账号,
在“设置--管理员设置--外部连接”中设置OpenAI API,
- API端点:http://localhost:11025/v1 #11025是前面DS模型部署时config.json文件内设置的端口
- 模型标识:DeepSeek-R1(需与config.json中modelName一致) #模型 ID可以不用添加,留空表示包含来自该端口的所有模型。
Tips:使用OpenAI API时可以选择将Ollama API关闭。
3.5 Open-WebUI服务启动
- 选择设置的模型ID对应的模型,例如:DeepSeek-R1。
- 设置完这些,就可以愉快地使用DeepSeek模型服务开启对话了。
- 可在/opt/webui-env/lib/python3.11/site-packages/open_webui/routers/openai.py添加如下内容,从而去除
<|end_of_sentence|>
字段。
payload["stop"] = ["<|end_of_sentence|>"]
payload["include_stop_str_in_output"] = False
payload["skip_special_tokens"] = True
四、 服务安全配置
为确保模型服务的安全性,建议遵循以下安全配置原则:
4.1 设置访问控制
本指南OpenWebUI使用的端口为8081。
通过配置安全组或ufw/iptables设置IP白名单,对于必须开放的端口(如OpenWebUI的8081端口),通过防火墙规则限制访问来源IP:
# ufw 限制8081端口访问来源ip
sudo ufw allow from <IP地址> to any port 8081
sudo ufw deny 8081/tcp # 禁用其他ip访问8081端口
sudo ufw reload
# iptables 限制8081端口访问来源ip
sudo iptables -A INPUT -p tcp --dport 8081 -s <IP地址> -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 8081 -j DROP # 禁用其他ip访问8081端口
如需禁用所有公网ip访问OpenWebUI的8081端口,可配置安全组或使用ufw或iptables关闭非必要端口:
# ufw 关闭8081端口
sudo ufw deny 8081/tcp
sudo ufw reload
# iptables 关闭8081端口
sudo iptables -A INPUT -p tcp --dport 8081 -j DROP
4.2 身份验证与权限管理
在OpenWebUI中关闭允许用户注册功能(参考“3.1节 安装Open-WebUI”),并定期审计用户列表。