一. 项目背景

硬件: 2*Atlas 800IA2,每个节点8张910B,共16张910B
操作系统: Linux aarch64
镜像版本: 2.2.T30-800I-A2-py311-openeuler24.03-lts-arm64
驱动版本: Ascend HDK 25.2.0

二. 环境准备

1. 准备安装用户和运行用户

参考官方文档
说白了,使用root用户,且root用户要在HwHiAiUser用户组里面,这样会省掉很多麻烦。

2.在宿主机上安装NPU驱动和固件

因为我们部署的DS-V3.2是要跑在容器里面,所以宿主机只要安装NPU驱动和固件。在安装之前,需要判断你的CPU架构(arch)、软件版本号(version)、产品类型(type)、处理器类型(chip_type),然后在官方网页下载以下内容:

软件类型 软件包说明 软件包名称
昇腾NPU驱动 部署在昇腾AI处理器,用于管理查询昇腾AI处理器,同时为上层CANN软件提供处理器控制、资源分配等接口。 Ascend-hdk-<chip_type>-npu-driver__linux-.run
昇腾NPU固件 固件包含昇腾AI处理器自带的OS 、电源器件和功耗管理器件控制软件,分别用于后续加载到AI处理器的模型计算、处理器启动控制和功耗控制。 Ascend-hdk-<chip_type>-npu-firmware_.run
Toolkit CANN开发套件包,在训练&推理&开发调试场景下安装,主要用于训练和推理业务、模型转换、算子/应用/模型的开发和编译。 Ascend-cann-toolkit__linux-.run
Kernels CANN二进制算子包,包括单算子API执行(例如aclnn类API)动态库/静态库文件,以及kernel二进制文件。 Ascend-cann-kernels-<chip_type>__linux-.run
NNAL CANN神经网络加速库,包含ATB(Ascend Transformer Boost)加速库和SiP(Ascend SiP Boost)信号处理加速库。 Ascend-cann-nnal__linux-.run

3. 安装NPU驱动和固件

3.1 安装依赖

执行如下命令检查源是否可用。

apt-get update

执行命令安装所需依赖

apt-get install -y make dkms gcc linux-headers-$(uname -r)

如果出现报错或者依赖不存在,请参见安装驱动源码编译所需依赖

3.2 安装驱动和固件

  • 以root用户登录安装环境,将驱动包和固件包上传到安装环境的任意目录如“/home”
  • 进入软件包所在目录,执行如下命令增加执行权限。
chmod +x Ascend-hdk-<chip_type>-npu-driver_<version>_linux-<arch>.run
chmod +x Ascend-hdk-<chip_type>-npu-firmware_<version>.run
  • 安装驱动和固件,软件包默认安装路径为“/usr/local/Ascend”。
  • a. 执行如下命令安装驱动。
./Ascend-hdk-<chip_type>-npu-driver_<version>_linux-<arch>.run --full --install-for-all

若系统出现如下关键回显信息,则表示驱动安装成功。

Driver package installed successfully!

b. 执行如下命令安装固件

./Ascend-hdk-<chip_type>-npu-firmware_<version>.run --full

若系统出现如下关键回显信息,表示固件安装成功

Firmware package installed successfully! Reboot now or after driver installation for the installation/upgrade to take effect
  • 根据系统提示信息决定是否重启系统,若需要重启,请执行以下命令;否则,请跳过此步骤。
reboot
  • 执行如下命令查看驱动加载是否成功
npu-smi info

若返回驱动相关信息说明加载成功。否则,说明加载失败:
在这里插入图片描述

4. 安装CANN

安装前需确保已具备Python环境及pip3,当前CANN支持Python3.7.x至3.11.4版本,若不满足可执行以下命令安装。

sudo apt-get install -y python3 python3-pip

4.1 安装Toolkit开发套件包

CANN Toolkit开发套件包,在训练&推理&开发调试场景下安装,主要用于训练和推理业务、模型转换、算子/应用/模型的开发和编译。安装Toolkit软件前请确保安装目录可用空间大于10G,如不满足请清理空间或更换安装目录。

  • 增加对软件包的可执行权限,以aarch64架构为例。
chmod +x Ascend-cann-toolkit_8.2.RC1_linux-aarch64.run
  • 安装软件包(安装命令支持–install-path= 等参数,具体使用方式请参见 参数说明)。
./Ascend-cann-toolkit_8.2.RC1_linux-aarch64.run --install

如果用户未指定安装路径,则软件会安装到默认路径下,默认安装路径如下。root用户:“/usr/local/Ascend”,非root用户:“${HOME}/Ascend”,${HOME}为当前用户目录。

  • 配置环境变量,当前以非root用户安装后的默认路径为例,请用户根据set_env.sh的实际路径执行如下命令。
source ${HOME}/Ascend/ascend-toolkit/set_env.sh

上述环境变量配置只在当前窗口生效,用户可以按需将以上命令写入环境变量配置文件(如.bashrc文件)。

4.2 安装Kernels算子包

CANN二进制算子包,包括单算子API执行(例如aclnn类API)动态库/静态库文件,以及kernel二进制文件。Kernels算子包安装之前,需已安装配套版本的Toolkit并配置环境变量。(注意版本、系统架构区别)

chmod +x Ascend-cann-kernels-910b_8.2.RC1_linux-aarch64.run
./Ascend-cann-kernels-910b_8.2.RC1_linux-aarch64.run --install

4.3 安装NNAL神经网络加速库(可选)

可选,需要安装的话,详见官网

三. 相关资源下载

在准备好宿主机的相关资源之后,就需要下载相关资源,包括:

  • 集成MindIE等环境的镜像:swr.cn-south-1.myhuaweicloud.com/ascendhub/mindie:2.2.T30-800I-A2-py311-openeuler24.03-lts-arm64
  • DeepSeek-V3.2的权重:https://modelers.cn/models/KunLun/DeepSeek-V3.2-Exp

1. 镜像下载

docker pull swr.cn-south-1.myhuaweicloud.com/ascendhub/mindie:2.2.T30-800I-A2-py311-openeuler24.03-lts-arm64

2. 权重下载

这里使用W8A8版本的DeepSeek-V3.2,使用如下命令:
设置环境变量,将保存的路径添加到白名单:

export HUB_WHITE_LIST_PATHS=/你的路径/DeepSeek-V3.2-Exp-w8a8

使用python运行如下代码:

from openmind_hub import snapshot_download
snapshot_download(
    repo_id="Modelers_Park/DeepSeek-V3.2-Exp-w8a8",
    local_dir="/你的路径/DeepSeek-V3.2-Exp-w8a8",
    local_dir_use_symlinks=False
)

下载好后的权重,要在两个节点上都保存,且路径最好一致。

四. 部署流程

部署前,需要根据自己的集群信息,编写除ranktable.json,其中的具体格式和内容详见ranktable文件配置资源信息
这里贴出我自己的ranktable
本案例是部署在两个节点,每个节点有8张卡。该博客参考KunLun/DeepSeek-V3.2-Exp但是会更详细

1. 启动镜像,运行容器

注意:在每个节点上都要运行下面的“启动镜像”和“运行容器”命令,且命令相同。
启动镜像:

docker run -itd -u root --net=host --ipc=host --privileged --shm-size=5g --name=搞个你喜欢的名字 \
--device=/dev/davinci0 \
--device=/dev/davinci1 \
--device=/dev/davinci2 \
--device=/dev/davinci3 \
--device=/dev/davinci4 \
--device=/dev/davinci5 \
--device=/dev/davinci6 \
--device=/dev/davinci7 \
--device=/dev/davinci_manager \
--device=/dev/devmm_svm \
--device=/dev/hisi_hdc \
-v /usr/local/Ascend/driver:/usr/local/Ascend/driver \
-v /usr/local/Ascend/add-ons/:/usr/local/Ascend/add-ons/ \
-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/slog/:/var/log/npu/slog \
-v /var/log/npu/profiling/:/var/log/npu/profiling \
-v /var/log/npu/dump/:/var/log/npu/dump \
-v /var/log/npu/:/usr/slog \
-v /你的权重路径/:/你的权重路径/ \
-v /nfs/:/nfs/ \
swr.cn-south-1.myhuaweicloud.com/ascendhub/mindie:2.2.T30-800I-A2-py311-openeuler24.03-lts-arm64 \
/bin/bash

运行容器(“搞个你喜欢的名字”要和上面的一样):

docker exec -it 搞个你喜欢的名字 bash

2. 设置环境变量

在两个节点上分别进入到容器后,以下命令是在容器内运行的,大致命令都相同,只不过与IP相关的都要留意下。

在两个节点上,设置昇腾推理软件四件套环境变量:

source /usr/local/Ascend/mindie/set_env.sh
source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/atb/set_env.sh
source /usr/local/Ascend/atb-models/set_env.sh

在节点1的容器内运行:

#设置自己的ranktable_file_path,machine_IP, master_IP
chmod 640 /usr/local/Ascend/mindie/latest/mindie-service/ranktable.json
export RANK_TABLE_FILE="/usr/local/Ascend/mindie/latest/mindie-service/ranktable.json"
export MIES_CONTAINER_IP='x.x.x.x' # 本机(容器)IP
export MASTER_IP='x.x.x.x' # 主节点IP

在节点2的容器内运行:

#设置自己的ranktable_file_path,machine_IP, master_IP
chmod 640 /usr/local/Ascend/mindie/latest/mindie-service/ranktable.json
export RANK_TABLE_FILE="/usr/local/Ascend/mindie/latest/mindie-service/ranktable.json"
export MIES_CONTAINER_IP='x.x.x.x' # 本机(容器)IP
export MASTER_IP='x.x.x.x' # 主节点IP

在两个节点的容器内,设置如下环境变量:

export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_HOST_SOCKET_PORT_RANGE=60000-60050
export HCCL_CONNECT_TIMEOUT=7200
export MASTER_PORT=7008
export MINDIE_LOG_TO_STDOUT=1
export ATB_LLM_ENABLE_AUTO_TRANSPOSE=0

在两个节点的容器内,设置权重的权限:

chmod 640 -R /你的权重路径

3. 修改代码

在两个节点的容器内,分别

vim /usr/local/Ascend/atb-models/atb_llm/layers/linear/linear.py +112

将112行代码替换为:

out = torch_npu.npu_quant_matmul(input_tensor_quant, self._weight.transpose(-2, -1), self._weight_scale, pertoken_scale=pertoken_scale, bias=None, output_dtype=torch.bfloat16)

4. 修改DeepSeek-V3.2的配置文件

进入到你下载好的权重路径下:

cd /你的权重路径/

将config.json中的model_type的值改为deepseek_v3:

{
  "architectures": [
    "DeepseekV32ForCausalLM"
  ],
  "attention_bias": false,
  "attention_dropout": 0.0,
  "bos_token_id": 0,
  "eos_token_id": 1,
  "ep_size": 1,
  "first_k_dense_replace": 3,
  "hidden_act": "silu",
  "hidden_size": 7168,
  "index_head_dim": 128,
  "index_n_heads": 64,
  "index_topk": 2048,
  "initializer_range": 0.02,
  "intermediate_size": 18432,
  "kv_lora_rank": 512,
  "max_position_embeddings": 163840,
  "model_type": "deepseek_v3",
  "moe_intermediate_size": 2048,
  "moe_layer_freq": 1,
  "n_group": 8,
  "n_routed_experts": 256,
  "n_shared_experts": 1,
  "norm_topk_prob": true,
  "num_attention_heads": 128,
  "num_experts_per_tok": 8,
  "num_hidden_layers": 61,
  "num_key_value_heads": 128,
  "num_nextn_predict_layers": 1,
  "q_lora_rank": 1536,
  "qk_nope_head_dim": 128,
  "qk_rope_head_dim": 64,
  "rms_norm_eps": 1e-06,
  "rope_scaling": {
    "beta_fast": 32,
    "beta_slow": 1,
    "factor": 40,
    "mscale": 1.0,
    "mscale_all_dim": 1.0,
    "original_max_position_embeddings": 4096,
    "type": "yarn"
  },
  "rope_theta": 10000,
  "routed_scaling_factor": 2.5,
  "scoring_func": "sigmoid",
  "tie_word_embeddings": false,
  "topk_group": 4,
  "topk_method": "noaux_tc",
  "torch_dtype": "bfloat16",
  "transformers_version": "4.44.2",
  "use_cache": true,
  "v_head_dim": 128,
  "vocab_size": 129280
}

5. 修改MindIE的配置文件

在两个节点的容器内,分别运行:

vim /usr/local/Ascend/mindie/latest/mindie-service/conf/config.json

改为以下内容,注意其中的IP要改为当前容器(节点、宿主机)的IP

{
“Version” : “1.0.0”,
“ServerConfig” :
{
“ipAddress” : “你的当前的容器的IP”,
“managementIpAddress” : “127.0.0.2”,
“port” : 1025,
“managementPort” : 1026,
“metricsPort” : 1027,
“allowAllZeroIpListening” : false,
“maxLinkNum” : 1000,
“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” : 1121,
“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” : “vllm”,
“tokenTimeout” : 600,
“e2eTimeout” : 600,
“distDPServerEnabled”:false
},
“BackendConfig” : {
“backendName” : “mindieservice_llm_engine”,
“modelInstanceNumber” : 1,
“npuDeviceIds” : [[0,1,2,3,4,5,6,7]],
“tokenizerProcessNumber” : 8,
“multiNodesInferEnabled” : true,
“multiNodesInferPort” : 1120,
“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” : 8192,
“maxInputTokenLen” : 8192,
“truncation” : false,
“ModelConfig” : [
{
“modelInstanceType” : “Standard”,
“modelName” : “ds3.2”,
“modelWeightPath” : “/你的权重路径”,
“worldSize” : 8,
“cpuMemSize” : 0,
“npuMemSize” : 7,
“backendType” : “atb”,
“trustRemoteCode” : false,
“engine”:{
“graph”:“python”
},
“plugin_params”:“{“plugin_type”:“mtp”,“num_speculative_tokens”: 1}”,
“tp”: 16,“dp”: 1,“sp”:1,“pp”:1,“cp”:1,“moe_ep”: 1,“moe_tp”: 16,
“async_scheduler_wait_time”: 120,
“kv_trans_timeout”: 10,
“kv_link_timeout”: 1080
}
]
},
“ScheduleConfig” :
{
“templateType” : “Standard”,
“templateName” : “Standard_LLM”,
“cacheBlockSize” : 128,
“maxPrefillBatchSize” : 4,
“maxPrefillTokens” : 8192,
“prefillTimeMsPerReq” : 150,
“prefillPolicyType” : 0,
“decodeTimeMsPerReq” : 50,
“decodePolicyType” : 0,
“maxBatchSize” : 8,
“maxIterTimes” : 6400,
“maxPreemptCount” : 0,
“supportSelectBatch” : false,
“maxQueueDelayMicroseconds” : 5000
}
}
}

6. 启动服务

# 第一次请求,需要编译大概20分钟左右。试过直接ctrl+c后再发送请求可以直接返回
cd /usr/local/Ascend/mindie/latest/mindie-service
 ./bin/mindieservice_daemon
 # 或者
 nohup ./bin/mindieservice_daemon > output.log 2>&1 & 

7. 测试服务

curl -H 'accept: application/json' -H 'Content-Type: application/json' -X POST -d '{
    "model":"ds-3.2",
    "messages": [{
    "role":"system",
    "content":"用python写一段快速排序代码"
    }]
}' http://物理机ip(主节点):1025/v1/chat/completions

五. 问题整理和解决方案

1. chat_template

DeepSeek-V3.2在token_config.json中定义了chat_template,但是服务启动后,通过接口测试,发现对function_call的支持较差,以下是request:

curl -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{
    "model": "chatglm3-6b",
    "messages": [
        {
            "role": "system",
            "content": "You are a helpful customer support assistant. Use the supplied tools to assist the user."
        },
        {
            "role": "user",
            "content": "Hi, can you tell me the delivery date for my order?  my order number is 999888"
        }
    ],
    "tools": [
        {
            "type": "function",
            "function": {
                "name": "get_delivery_date",
                "description": "Get the delivery date for a customer\u0027s order. Call this whenever you need to know the delivery date, for example when a customer asks \u0027Where is my package\u0027",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "order_id": {
                            "type": "string",
                            "description": "The customer\u0027s order ID."
                        }
                    },
                    "required": [
                        "order_id"
                    ],
                    "additionalProperties": false
                }
            }
        }
    ],
    "tool_choice": "required",
    "stream": false
}'  https://你的IP:1025/v1/chat/completions

为了解决这个问题,我想的是重新改善下chat_template,我自己定义的chat_template,欢迎下载。
在这里插入图片描述

Logo

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。

更多推荐