昇腾 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--versionpython3-mpip--versionuname-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正常。
二、网络受限环境的处理思路
容器内部可能无法访问公网,但宿主机或外部电脑可以访问网络。这种情况下建议:
- 在外部机器下载 Git 仓库和 Python 安装包;
- 通过 CANNLab 文件上传、挂载目录或共享盘传入容器;
- 模型提前下载到
/mnt/workspace/models; - 容器内部使用本地源码安装,不依赖外网。
模型目录:
/mnt/workspace/models/Qwen3-VL-32B-Instruct确认模型文件:
find/mnt/workspace/models/Qwen3-VL-32B-Instruct-maxdepth2-typef|head三、vLLM 与 vLLM-Ascend 版本匹配
最初尝试安装:
pip3install\"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-srcVLLM_TARGET_DEVICE=empty\python3-mpipinstall-e.\--no-build-isolation\--no-deps第一次可能报错:
ModuleNotFoundError: No module named 'setuptools_scm'如果容器可以访问镜像源,可以安装:
python3-mpipinstall--usersetuptools_scm如果网络不可用,则需要在外部机器下载对应 wheel,再上传到容器离线安装。
安装成功后应看到:
Successfully built vllm Successfully installed vllm-0.11.0+empty五、安装 vLLM-Ascend
假设源码位于:
/mnt/workspace/vllm-ascend-src由于容器缺少部分自定义编译依赖,使用以下方式安装:
cd/mnt/workspace/vllm-ascend-srcCOMPILE_CUSTOM_KERNELS=0\python3-mpipinstall-e.\--no-build-isolation\--no-deps\--config-settingseditable_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-mpipinstall--userprometheus-client python3-mpipinstall--useruvloop python3-mpipinstall--userstarlette python3-mpipinstall--useryarl python3-mpipinstall--userpkg_resourcespkg_resources通常由 setuptools 提供:
python3-mpipinstall--user-Usetuptools推荐一次性安装:
python3-mpipinstall--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-mpipinstall--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-namelibatb.so-typef没有找到文件,以为容器没有 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/-namelibatb.so-typef2>/dev/nullfind/-path'*nnal*'-nameset_env.sh2>/dev/null启动前必须加载 NNAL:
source/opt/home/developer/Ascend/nnal/atb/set_env.shsource/opt/home/developer/Ascend/ascend-toolkit/set_env.sh2>/dev/null||true测试动态库:
python3 -<<'PY' import ctypes ctypes.CDLL("libatb.so") print("libatb.so 加载成功") PY如果仍然找不到:
exportLD_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 bashset-esource/opt/home/developer/Ascend/nnal/atb/set_env.shsource/opt/home/developer/Ascend/ascend-toolkit/set_env.sh2>/dev/null||trueexportASCEND_RT_VISIBLE_DEVICES=0,1exportHCCL_OP_EXPANSION_MODE=AIVexportPYTORCH_NPU_ALLOC_CONF=expandable_segments:TrueexportVLLM_ASCEND_ENABLE_NZ=0exportCOMPILE_CUSTOM_KERNELS=0exportOMP_PROC_BIND=falseexportOMP_NUM_THREADS=1exportTASK_QUEUE_ENABLE=1exportPATH=/home/developer/.local/bin:$PATHcd/mnt/workspace/vllm-src python3-mvllm.entrypoints.openai.api_server\--model/mnt/workspace/models/Qwen3-VL-32B-Instruct\--host0.0.0.0\--port8000\--served-model-name qwen3-vl-32b\--tensor-parallel-size2\--dtypebfloat16\--trust-remote-code\--max-model-len4096\--max-num-seqs1\--max-num-batched-tokens2048\--gpu-memory-utilization0.90\--no-enable-prefix-caching\--mm-processor-cache-gb0\--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. 查看模型列表
curlhttp://127.0.0.1:8000/v1/models\-H"Authorization: Bearer sujiapikey"2. 测试文本对话
curlhttp://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-n1npu-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 allow7000/tcp ufw allow18000/tcpNPU 容器 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公网测试:
curlhttp://公网虚拟机IP:18000/v1/models\-H"Authorization: Bearer sujiapikey"十四、安全建议
不要直接使用:
sujiapikey建议生成随机 Key:
openssl rand-hex32然后修改启动脚本:
--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_client | vLLM API 服务依赖 | 手动安装 prometheus-client |
缺少uvloop | API Server 依赖 | 安装 uvloop |
缺少starlette | FastAPI 依赖未完整安装 | 安装 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_PATH和ldd |
| JSON decode error | curl 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 对外提供服务。