昇腾 Ascend 910C 部署 Qwen3-VL-32B-Instruct 实战教程

本文记录在昇腾 Ascend 910C 双 NPU 环境中,使用 vLLM + vLLM-Ascend 部署 Qwen3-VL-32B-Instruct 的完整过程,包括环境检查、离线安装、常见报错及解决方法,最后通过 OpenAI 兼容接口提供公网服务。

一、硬件与系统环境

本次环境信息:

系统:Ubuntu 20.04.5 LTS
架构:aarch64
Python:3.11.4
NPU:Ascend 910C,2 张
单卡显存:约 64GB
torch:2.7.1+cpu
torch_npu:2.7.1.post4

检查 NPU:

npu-smi info

检查 Python:

python3 --version
python3 -m pip --version
uname -m

检查 NPU 是否可用:

python3 - <<'PY'
import torch
import torch_npu

print("torch:", torch.__version__)
print("torch_npu:", torch_npu.__version__)
print("NPU可用:", torch.npu.is_available())
print("NPU数量:", torch.npu.device_count())
PY

如果显示:

NPU可用: True
NPU数量: 2

说明基础驱动和 torch_npu 正常。


二、网络受限环境的处理思路

容器内部可能无法访问公网,但宿主机或外部电脑可以访问网络。这种情况下建议:

  1. 在外部机器下载 Git 仓库和 Python 安装包;
  2. 通过 CANNLab 文件上传、挂载目录或共享盘传入容器;
  3. 模型提前下载到 /mnt/workspace/models
  4. 容器内部使用本地源码安装,不依赖外网。

模型目录:

/mnt/workspace/models/Qwen3-VL-32B-Instruct

确认模型文件:

find /mnt/workspace/models/Qwen3-VL-32B-Instruct -maxdepth 2 -type f | head

三、vLLM 与 vLLM-Ascend 版本匹配

最初尝试安装:

pip3 install \
  "vllm==0.11.0" \
  "vllm-ascend==0.11.0"

出现依赖冲突:

vllm 0.11.0 depends on torch==2.8.0
vllm-ascend 0.11.0 depends on torch==2.7.1

原因是官方 vLLM 0.11.0 与 vLLM-Ascend 0.11.0 的默认依赖不一致,而当前环境已经固定为:

torch==2.7.1
torch_npu==2.7.1.post4

因此采用源码方式安装 vLLM,并跳过依赖解析。


四、安装 vLLM 源码

假设源码位于:

/mnt/workspace/vllm-src

安装前设置昇腾目标为空设备,避免编译 CUDA:

cd /mnt/workspace/vllm-src

VLLM_TARGET_DEVICE=empty \
python3 -m pip install -e . \
  --no-build-isolation \
  --no-deps

第一次可能报错:

ModuleNotFoundError: No module named 'setuptools_scm'

如果容器可以访问镜像源,可以安装:

python3 -m pip install --user setuptools_scm

如果网络不可用,则需要在外部机器下载对应 wheel,再上传到容器离线安装。

安装成功后应看到:

Successfully built vllm
Successfully installed vllm-0.11.0+empty

五、安装 vLLM-Ascend

假设源码位于:

/mnt/workspace/vllm-ascend-src

由于容器缺少部分自定义编译依赖,使用以下方式安装:

cd /mnt/workspace/vllm-ascend-src

COMPILE_CUSTOM_KERNELS=0 \
python3 -m pip install -e . \
  --no-build-isolation \
  --no-deps \
  --config-settings editable_mode=compat

曾经遇到的错误:

static library kineto_LIBRARY-NOTFOUND not found
ninja: build stopped

原因是环境中缺少 Kineto 相关库,且没有安装 Ninja。对于当前推理部署,可以先关闭自定义 Kernel 编译:

COMPILE_CUSTOM_KERNELS=0

成功后应看到:

Successfully built vllm_ascend
Successfully installed vllm_ascend-0.11.0

六、补齐 Python 依赖

由于使用了 --no-deps,部分 Python 依赖需要手动安装。

常见缺失模块和解决方法:

python3 -m pip install --user prometheus-client
python3 -m pip install --user uvloop
python3 -m pip install --user starlette
python3 -m pip install --user yarl
python3 -m pip install --user pkg_resources

pkg_resources 通常由 setuptools 提供:

python3 -m pip install --user -U setuptools

推荐一次性安装:

python3 -m pip install --user \
  modelscope \
  qwen-vl-utils \
  pillow \
  prometheus-client \
  uvloop \
  starlette \
  watchfiles \
  xgrammar \
  aiohttp \
  yarl

七、解决 Transformers 版本冲突

曾遇到:

transformers requires tokenizers>=0.22.0,<=0.23.0
but found tokenizers==0.23.1

调整为:

python3 -m pip install --user --no-deps --force-reinstall \
  transformers==4.57.1 \
  tokenizers==0.22.2 \
  huggingface-hub==0.36.0

注意,华为镜像可能没有 tokenizers==0.23.0,但有 0.22.2,因此使用 0.22.2 即可。

检查版本:

python3 - <<'PY'
import transformers
import tokenizers
import huggingface_hub

print("transformers:", transformers.__version__)
print("tokenizers:", tokenizers.__version__)
print("huggingface-hub:", huggingface_hub.__version__)
PY

八、解决 libatb.so 缺失问题

启动时曾遇到:

OSError: libatb.so: cannot open shared object file

以及:

Please check that the nnal package is installed.
Please run 'source set_env.sh' in the NNAL installation path.

最初执行:

find /usr/local/Ascend -name libatb.so -type f

没有找到文件,以为容器没有 NNAL。

后来全盘查找发现 NNAL 实际安装在:

/opt/home/developer/Ascend/nnal/atb/set_env.sh
/opt/home/developer/Ascend/nnal/atb/9.0.0/atb/cxx_abi_1/lib/libatb.so
/opt/home/developer/Ascend/nnal/atb/9.0.0/atb/cxx_abi_0/lib/libatb.so

查找命令:

find / -name libatb.so -type f 2>/dev/null
find / -path '*nnal*' -name set_env.sh 2>/dev/null

启动前必须加载 NNAL:

source /opt/home/developer/Ascend/nnal/atb/set_env.sh
source /opt/home/developer/Ascend/ascend-toolkit/set_env.sh 2>/dev/null || true

测试动态库:

python3 - <<'PY'
import ctypes
ctypes.CDLL("libatb.so")
print("libatb.so 加载成功")
PY

如果仍然找不到:

export LD_LIBRARY_PATH=/opt/home/developer/Ascend/nnal/atb/9.0.0/atb/cxx_abi_0/lib:$LD_LIBRARY_PATH

检查依赖:

ldd /opt/home/developer/Ascend/nnal/atb/9.0.0/atb/cxx_abi_0/lib/libatb.so \
  | grep "not found" || echo "libatb依赖正常"

九、创建 Qwen3-VL 启动脚本

创建:

vim /mnt/workspace/start_qwen3vl.sh

内容如下:

#!/usr/bin/env bash
set -e

source /opt/home/developer/Ascend/nnal/atb/set_env.sh
source /opt/home/developer/Ascend/ascend-toolkit/set_env.sh 2>/dev/null || true

export ASCEND_RT_VISIBLE_DEVICES=0,1
export HCCL_OP_EXPANSION_MODE=AIV
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export VLLM_ASCEND_ENABLE_NZ=0
export COMPILE_CUSTOM_KERNELS=0
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=1
export TASK_QUEUE_ENABLE=1
export PATH=/home/developer/.local/bin:$PATH

cd /mnt/workspace/vllm-src

python3 -m vllm.entrypoints.openai.api_server \
  --model /mnt/workspace/models/Qwen3-VL-32B-Instruct \
  --host 0.0.0.0 \
  --port 8000 \
  --served-model-name qwen3-vl-32b \
  --tensor-parallel-size 2 \
  --dtype bfloat16 \
  --trust-remote-code \
  --max-model-len 4096 \
  --max-num-seqs 1 \
  --max-num-batched-tokens 2048 \
  --gpu-memory-utilization 0.90 \
  --no-enable-prefix-caching \
  --mm-processor-cache-gb 0 \
  --api-key "sujiapikey"

赋予执行权限:

chmod +x /mnt/workspace/start_qwen3vl.sh

启动:

/mnt/workspace/start_qwen3vl.sh

看到以下日志表示服务启动成功:

Application startup complete.

十、启动日志中的警告

以下警告不一定影响推理:

Model architecture Qwen3NextForCausalLM is already registered

这是模型架构重复注册提示。

Failed to import vllm_ascend_C
Sleep mode will be disabled

这是因为之前关闭了自定义 Kernel 编译:

COMPILE_CUSTOM_KERNELS=0

会导致 Sleep mode 不可用,但通常不影响基础推理。


十一、测试 OpenAI 接口

1. 查看模型列表

curl http://127.0.0.1:8000/v1/models \
  -H "Authorization: Bearer sujiapikey"

2. 测试文本对话

curl http://127.0.0.1:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sujiapikey" \
  -d '{
    "model": "qwen3-vl-32b",
    "messages": [
      {
        "role": "user",
        "content": "你好,请用一句话介绍你自己。"
      }
    ],
    "max_tokens": 100
  }'

成功时会返回:

{
  "object": "chat.completion",
  "model": "qwen3-vl-32b",
  "choices": [
    {
      "message": {
        "role": "assistant",
        "content": "你好,我是一个多模态大语言模型。"
      },
      "finish_reason": "stop"
    }
  ]
}

之前出现的:

JSON decode error

是由于命令粘贴或 JSON 格式错误,并非模型故障。


十二、查看 NPU 使用情况

另开终端:

watch -n 1 npu-smi info

推理时重点观察:

HBM-Usage
AICore(%)
Process memory

如果两张 NPU 都有显存占用,并且推理时 AICore 利用率变化,说明张量并行正常运行。


十三、通过 FRP 暴露公网接口

网络拓扑:

互联网客户端
      ↓
公网虚拟机 frps
      ↓
NPU容器 frpc
      ↓
127.0.0.1:8000

公网虚拟机 frps 配置

/etc/frp/frps.toml

bindPort = 7000

auth.method = "token"
auth.token = "请修改为复杂随机字符串"

启动:

frps -c /etc/frp/frps.toml

开放端口:

ufw allow 7000/tcp
ufw allow 18000/tcp

NPU 容器 frpc 配置

/mnt/workspace/frpc.toml

serverAddr = "公网虚拟机IP"
serverPort = 7000

auth.method = "token"
auth.token = "请使用与frps相同的随机字符串"

[[proxies]]
name = "qwen3-vl-api"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8000
remotePort = 18000

启动:

frpc -c /mnt/workspace/frpc.toml

公网测试:

curl http://公网虚拟机IP:18000/v1/models \
  -H "Authorization: Bearer sujiapikey"

十四、安全建议

不要直接使用:

sujiapikey

建议生成随机 Key:

openssl rand -hex 32

然后修改启动脚本:

--api-key "生成的随机字符串"

另外建议:

  • FRP 使用 token 认证;
  • 只开放必要端口;
  • 不要暴露 FRP 的管理端口;
  • 公网 API 最好通过 HTTPS;
  • 对接口增加访问频率限制;
  • 不要把模型服务直接裸奔在公网;
  • 长时间运行建议使用 systemd、tmux 或 supervisor。

十五、问题总结

问题原因解决方法
vLLM 与 vLLM-Ascend 依赖冲突两者要求不同 torch 版本源码安装并使用 --no-deps
缺少 setuptools_scm构建依赖未安装安装 setuptools_scm 或离线上传
kineto_LIBRARY-NOTFOUND缺少 Kineto 库使用 COMPILE_CUSTOM_KERNELS=0
缺少 prometheus_clientvLLM API 服务依赖手动安装 prometheus-client
缺少 uvloopAPI Server 依赖安装 uvloop
缺少 starletteFastAPI 依赖未完整安装安装 starlette
transformers 与 tokenizers 冲突版本不匹配使用 transformers 4.57.1、tokenizers 0.22.2
huggingface-hub 版本冲突版本过新降级到 0.36.0
libatb.so 找不到没有加载 NNAL 环境source NNAL 的 set_env.sh
Worker 初始化失败ATB 动态库无法加载检查 LD_LIBRARY_PATHldd
JSON decode errorcurl JSON 格式错误检查引号、逗号和字段格式
API 启动后退出引擎 Worker 初始化失败优先查看最早出现的 Worker 根因

十六、最终验证标准

以下条件全部满足,说明部署成功:

NPU可用: True
NPU数量: 2
vllm: 0.11.0
vllm_ascend: 0.11.0
libatb.so 加载成功
Application startup complete.
/ v1/models 可以返回模型
/ v1/chat/completions 可以正常回答
npu-smi 可以看到两张 NPU 使用情况

至此,Qwen3-VL-32B-Instruct 已经在昇腾双 NPU 环境中成功部署,并通过兼容 OpenAI 的 API 对外提供服务。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐