学习进度 · 登录后可记录
⚠️ 重要声明
- 本教程适配 Notebook 云平台环境
- 服务端口:18004
- 环境:Ubuntu 22.04 | CANN 8.5 | Python 3.11.14
- 下载源:仅 AtomGit
本节课的目标是:在昇腾 NPU 上完成 Qwen3-ASR-1.7B 语音识别模型的端到端部署——从模型获取、服务启动,到 API 调用跑通转录。
很多习惯了 CUDA 的开发者在这里容易踩坑:他们会把"在 GPU 上怎么跑"的经验直接搬过来,然后发现 NPU 上的设备标识、依赖安装、模型加载方式完全不同。这节课,我将从昇腾的计算架构出发,让你真正理解"为什么要这样适配"。
先看一张对比图:

理解这个,你就能理解为什么代码要这么写:
这段代码背后发生了什么?(此处不需要执行)
torch_npu.npu.set_device(0) # 告诉运行时:"用第0块 NPU"
这行代码的背后,是运行时层在设置:

📖 图文说明
为什么第一步必须配置 Python 环境?
因为 Notebook 云平台使用的 Python 3.11.14 安装在
/usr/local/python3.11.14/,默认不会自动加入 PATH。如果不先执行此步骤,后续的 pip install 和依赖安装都会失败!
必须先执行此配置,否则后续所有命令都会报错!
🖥️ Notebook 实操
# ⚠️ 必须首先执行:配置 Python 3.11.14 环境
# ================================================================
# 配置 PATH(必须先执行,否则 pip 命令会失败)
!export PATH=/usr/local/python3.11.14/bin:$PATH
!export PYTHONPATH=/usr/local/python3.11.14/lib/python3.11/site-packages:$PYTHONPATH
# 验证 Python 版本
!python --version📖 图文说明
在昇腾 NPU 环境下,需要显式告诉运行时使用哪块 NPU 设备。
torch_npu.npu.set_device(0)的含义:
- 告诉 PyTorch NPU 后端:"用第 0 块 NPU"
- 如果不执行此语句,可能会出现设备未指定的错误
🖥️ Notebook 实操
# 阶段二:配置 NPU 设备
# ================================================================
import torch_npu
# 告诉运行时:"用第 0 块 NPU"
torch_npu.npu.set_device(0)
print("✅ NPU 设备已配置为: 0")为什么要先装 atomgit,而不是直接 pip install?
这里有个反直觉的地方:很多开发者习惯先装 torch 和 transformers,然后发现模型加载总是出问题。
正确的顺序是:
这样做的好处是:模型在本地,运行时直接加载本地路径,避免了网络波动导致的下载失败,也让你对模型资产有完全的控制权。
🖥️ Notebook 实操
# 阶段三:安装 atomgit(AtomGit 平台下载工具)
# ================================================================
# ⚠️ 必须先配置 Python PATH,否则 pip 命令会失败
!export PATH=/usr/local/python3.11.14/bin:$PATH
!export PYTHONPATH=/usr/local/python3.11.14/lib/python3.11/site-packages:$PYTHONPATH
%pip install -U atomgit -i https://mirrors.huaweicloud.com/repository/pypi/simple
get_ipython().kernel.do_shutdown(restart=True)为什么必须用 AtomGit?
很多开发者习惯了 from_pretrained("Qwen/Qwen3-ASR-1.7B") 自动下载的模式。这在昇腾环境下是个陷阱:
正确做法:使用 AtomGit 国内镜像下载模型到本地,再用 from_pretrained() 加载本地路径。
🖥️ Notebook 实操
# 阶段四:下载模型(从 AtomGit 平台)
# ================================================================
import os
from atomgit import snapshot_download
# 使用 $HOME 环境变量(在 Python 中使用 os.path.expanduser)
HOME = os.path.expanduser("~")
# 定义模型仓库和本地路径(使用绝对路径)
# 模型存放根目录
MODEL_BASE_DIR = f"{HOME}/models"
# ASR 模型
ASR_MODEL_REPO = "hf_mirrors/Qwen/Qwen3-ASR-1.7B"
ASR_MODEL_PATH = f"{MODEL_BASE_DIR}/Qwen3-ASR-1.7B"
# ASR 项目代码
ASR_PROJECT_REPO = "atomgit-ascend/Qwen3-ASR-1.7B"
ASR_PROJECT_PATH = f"{HOME}/Qwen3-ASR-1.7B"
# 创建目录
os.makedirs(MODEL_BASE_DIR, exist_ok=True)
# 下载 ASR 模型
print("=" * 60)
print("📥 正在下载 Qwen3-ASR-1.7B 模型...")
print(f" 仓库: {ASR_MODEL_REPO}")
print(f" 路径: {ASR_MODEL_PATH}")
print("=" * 60)
snapshot_download(
ASR_MODEL_REPO,
local_dir=ASR_MODEL_PATH
)
print("✅ 模型下载完成!")
# 下载 ASR 项目代码
print("\n" + "=" * 60)
print("📥 正在下载 Qwen3-ASR-1.7B 项目代码...")
print(f" 仓库: {ASR_PROJECT_REPO}")
print(f" 路径: {ASR_PROJECT_PATH}")
print("=" * 60)
snapshot_download(
ASR_PROJECT_REPO,
local_dir=ASR_PROJECT_PATH
)
print("✅ 项目代码下载完成!")
# 验证下载结果
print("\n" + "=" * 60)
print("📋 验证下载结果")
print("=" * 60)
print(f"模型目录: {ASR_MODEL_PATH}")
print(f"文件列表: {os.listdir(ASR_MODEL_PATH)[:10]}...") # 显示前10个文件📖 图文说明
模型部署需要安装项目目录中的
requirements.txt。必须先进入项目目录再执行安装!
🖥️ Notebook 实操
# 阶段五:安装 Python 依赖
# ================================================================
import os
HOME = os.path.expanduser("~")
%cd {HOME}/Qwen3-ASR-1.7B
!pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
!pip install --no-deps qwen-asr -i https://pypi.tuna.tsinghua.edu.cn/simple ⚠️ 系统依赖(需要 sudo)
# 系统依赖安装
!sudo apt-get update && sudo apt-get install -y libsndfile1 ffmpeg
为什么需要设置这些环境变量?
昇腾的运行时需要明确的设备配置,不像 CUDA 那样有默认的设备选择。理解这些变量:
| 环境变量 | 作用 | 类比 |
|---|---|---|
NPU_VISIBLE_DEVICES | 告诉 PyTorch "哪些 NPU 可用" | CUDA_VISIBLE_DEVICES |
ASCEND_RT_VISIBLE_DEVICES | 告诉 CANN 运行时 "用哪块 NPU" | 昇腾特有的设备选择 |
ASCEND_DEVICE_ID | 单卡场景的设备 ID | NPU 卡的编号 |
DEVICE=npu | 强制模型加载到 NPU | 设备类型声明 |
TORCH_DEVICE_BACKEND_AUTOLOAD=0 | 禁用自动设备检测 | 手动指定设备 |
%%bash
cd /opt/atomgit/Qwen3-ASR-1.7B
# 使用 cann-8.5.0 的环境
if [ -f "/usr/local/Ascend/cann-8.5.0/set_env.sh" ]; then
source /usr/local/Ascend/cann-8.5.0/set_env.sh
echo "使用 cann-8.5.0 环境"
else
source /usr/local/Ascend/ascend-toolkit/set_env.sh
echo "使用 ascend-toolkit 环境"
fi
# 确保 tbe 路径在前
export PYTHONPATH="/usr/local/Ascend/cann-8.5.0/python/site-packages:/usr/local/Ascend/cann-8.5.0/opp/built-in/op_impl/ai_core/tbe:$PYTHONPATH"
# 设置其他变量
export NPU_VISIBLE_DEVICES=0
export ASCEND_RT_VISIBLE_DEVICES=0
export ASCEND_DEVICE_ID=0
export PYTHONPATH="$(pwd):$PYTHONPATH"
export LOCAL_MODEL_PATH="/opt/atomgit/models/Qwen3-ASR-1.7B"
export MODEL_CACHE_DIR="/opt/atomgit/model"
export DEVICE=npu
export TORCH_DEVICE_BACKEND_AUTOLOAD=0
export PORT=18004
# 启动
python -m uvicorn api.main:app --host 0.0.0.0 --port 18004 --app-dir "$(pwd)"

为什么健康检查要先于转录调用?
服务启动后,模型加载需要时间。如果直接发送转录请求,可能会遇到:

🖥️ 新窗口 Notebook 实操
# 阶段七:API 调用与验证
# ================================================================
# ⚠️ 此代码块必须在 新窗口 或 终端 中执行,不能与启动命令在同一 ipynb
import requests
import json
import os
# 使用 $HOME 环境变量
HOME = os.path.expanduser("~")
# 服务地址
BASE_URL = "http://localhost:18004"
MODEL_NAME = "Qwen3-ASR-1.7B"
# 1. 健康检查
print("=" * 60)
print("🔍 健康检查")
print("=" * 60)
response = requests.get(f"{BASE_URL}/health", timeout=10)
health_data = response.json()
print(f"服务状态: {health_data.get('status')}")
print(f"模型已加载: {health_data.get('model_loaded')}")
print(f"NPU 可用: {health_data.get('npu_available')}")
print(f"CUDA 可用: {health_data.get('cuda_available')}")
# 2. 准备测试音频
print("\n" + "=" * 60)
print("📥 准备测试音频")
print("=" * 60)
# 官方测试音频 URL
ZH_AUDIO_URL = "https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen3-ASR-Repo/asr_zh.wav"
EN_AUDIO_URL = "https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen3-ASR-Repo/asr_en.wav"
import urllib.request
# 下载中文测试音频
urllib.request.urlretrieve(ZH_AUDIO_URL, f"{HOME}/asr_zh.wav")
print(f"✅ 中文测试音频已下载: {HOME}/asr_zh.wav")
# 下载英文测试音频
urllib.request.urlretrieve(EN_AUDIO_URL, f"{HOME}/asr_en.wav")
print(f"✅ 英文测试音频已下载: {HOME}/asr_en.wav")
# 3. 测试中文转录
print("\n" + "=" * 60)
print("🎤 测试中文转录")
print("=" * 60)
with open(f"{HOME}/asr_zh.wav", "rb") as f:
files = {"file": f}
data = {
"model": MODEL_NAME,
"language": "zh",
"response_format": "json"
}
response = requests.post(
f"{BASE_URL}/v1/audio/transcriptions",
files=files,
data=data,
timeout=120
)
result = response.json()
print(f"识别语言: {result.get('language')}")
print(f"转录文本: {result.get('text')}")
# 4. 测试英文转录
print("\n" + "=" * 60)
print("🎤 测试英文转录")
print("=" * 60)
with open(f"{HOME}/asr_en.wav", "rb") as f:
files = {"file": f}
data = {
"model": MODEL_NAME,
"language": "en",
"response_format": "json"
}
response = requests.post(
f"{BASE_URL}/v1/audio/transcriptions",
files=files,
data=data,
timeout=120
)
result = response.json()
print(f"识别语言: {result.get('language')}")
print(f"转录文本: {result.get('text')}")
print("\n" + "=" * 60)
print("✅ 部署验证完成!")
print("=" * 60)
很多开发者在 NPU 上遇到 "设备找不到" 的问题,99% 是因为只设置了一个环境变量。
昇腾的设备配置需要三个变量协同工作:
# ❌ 错误写法(只设置一个)
!export NPU_VISIBLE_DEVICES=0
# ✅ 正确写法(三个同时设置)
!export NPU_VISIBLE_DEVICES=0 # PyTorch 可见设备
!export ASCEND_RT_VISIBLE_DEVICES=0 # CANN 运行时可见设备
!export ASCEND_DEVICE_ID=0 # 单卡设备 ID原理:这三个变量分别作用在不同的层次:
NPU_VISIBLE_DEVICES → PyTorch 层ASCEND_RT_VISIBLE_DEVICES → CANN 运行时层ASCEND_DEVICE_ID → GE 图引擎层缺少任何一个,都可能导致设备初始化失败。
网络下载模型是生产环境的性能杀手。
| 加载方式 | 首次加载 | 后续加载 | 稳定性 | 推荐场景 |
|---|---|---|---|---|
from_pretrained("Qwen/...") | 慢(网络下载) | 慢(每次都下载) | ⭐⭐ | ❌ 不推荐 |
snapshot_download() + from_pretrained("./local") | 快(一次性下载) | 快(本地读取) | ⭐⭐⭐⭐⭐ | ✅ 推荐 |
性能差异实测:
网络下载模式:平均 5-15 分钟(受网络波动影响大) 本地加载模式:首次 3 分钟,后续 < 5 秒
# ================================================================
# 一键部署命令(复制到 Terminal 执行)
# 需要确定端口是否被占用
# ps -ef | grep 18004
# 如果占用了,需要kill掉
# ================================================================
#!/bin/bash
# 设置基础目录变量
BASE_DIR="${HOME}"
MODELS_DIR="${BASE_DIR}/models"
PROJECT_DIR="${BASE_DIR}/Qwen3-ASR-1.7B"
# 0. 必须首先配置 Python 环境
export PATH=/usr/local/python3.11.14/bin:$PATH
export PYTHONPATH=/usr/local/python3.11.14/lib/python3.11/site-packages:$PYTHONPATH
# 1. 安装 atomgit
pip install -U atomgit -i https://mirrors.huaweicloud.com/repository/pypi/simple
# 2. 创建目录
mkdir -p "${MODELS_DIR}" "${PROJECT_DIR}"
# 2. 下载模型和项目
python << EOF
from atomgit import snapshot_download
snapshot_download("hf_mirrors/Qwen/Qwen3-ASR-1.7B", local_dir="${MODELS_DIR}/Qwen3-ASR-1.7B")
snapshot_download("atomgit-ascend/Qwen3-ASR-1.7B", local_dir="${PROJECT_DIR}")
EOF
# 3. 安装系统依赖
sudo apt-get update && sudo apt-get install -y libsndfile1 ffmpeg
# 4. 安装 Python 依赖(进入项目目录)
pip install -r "${PROJECT_DIR}/requirements.txt" -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install --no-deps qwen-asr -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install tbe
# 5. 配置环境变
cd "${PROJECT_DIR}"
export PYTHONPATH="$(pwd)"
export LOCAL_MODEL_PATH="${MODELS_DIR}/Qwen3-ASR-1.7B"
export MODEL_CACHE_DIR="${BASE_DIR}"
export DEVICE=npu
export TORCH_DEVICE_BACKEND_AUTOLOAD=0
export NPU_VISIBLE_DEVICES=0 # PyTorch 可见设备
export ASCEND_RT_VISIBLE_DEVICES=0 # CANN 运行时可见设备
export ASCEND_DEVICE_ID=0 # 单卡设备 ID
# 6. 加载cann & 启动
source /usr/local/Ascend/ascend-toolkit/set_env.sh
python -m uvicorn api.main:app --host 0.0.0.0 --port 18004 --app-dir "$(pwd)"登录后即可查看完整教程内容、运行代码和参
与学习互动
还没有账号?