学习进度 · 登录后可记录
模型项目地址:hf_mirrors/openai/whisper-large-v3-turbo 课程难度:中级 · 需要 vLLM-Ascend 基础和语音处理经验 | 预估学时:20~30 分钟 部署架构:基于 vLLM-Ascend 推理引擎 + 昇腾 NPU + OpenAI 兼容 Audio API 部署
本章结束后,你能够:
--compilation-config 中自定义算子编译对昇腾 ASR 性能的关键作用/v1/audio/transcriptions 接口,实现语音转文字本节课的目标是:在昇腾 NPU 上,基于 vLLM-Ascend 推理引擎,部署 Whisper-Large-V3-Turbo——OpenAI 开源的语音识别(ASR, Automatic Speech Recognition)模型,提供兼容 OpenAI 的音频转写 API 服务。
Whisper-Large-V3-Turbo 是 Whisper V3 的加速版,相比标准版推理速度提升约 8 倍,同时保持了接近的识别精度。它非常适合昇腾部署——模型本身基于 Transformer Encoder-Decoder 架构,vLLM-Ascend 已对其核心算子做了深度适配。
很多习惯了 CUDA 的开发者会认为:ASR 不就是输入音频、输出文本嘛,跟 LLM 差不多——这个"差不多"掩盖了关键的架构差异。
| 计算特征 | 纯文本 LLM | ASR 模型(Whisper-Large-V3-Turbo) |
|---|---|---|
| 输入形态 | 离散 Token 序列 | 连续音频频谱(Mel Spectrogram),需要 Conv1D 预处理 |
| 核心架构 | Decoder-Only | Encoder-Decoder,Encoder 处理音频特征,Decoder 生成文本 |
| 关键算子 | Self-Attention(纯 Cube) | Cross-Attention(Cube)+ Conv1D(Vector)+ Rotary Embedding |
| 特殊算子 | 无 | RMS Norm、Rotary Embedding——昇腾需要自定义算子编译 |
| 输出解析 | 直接 decode token | 直接 decode token(与 LLM 相同) |
┌──────────────────────────────────────────────────────┐
│ vLLM OpenAI 兼容 Audio API 服务层 │
│ ┌────────────────────────────────────────────────┐ │
│ │ vllm serve → 兼容 /v1/audio/transcriptions │ │
│ │ ├─ /health → 健康检查 │ │
│ │ └─ /v1/audio/transcriptions → 音频转写接口 │ │
│ └──────────────────┬───────────────────────────────┘ │
│ │ │
├─────────────────────┼────────────────────────────────┤
│ vLLM-Ascend 推理引擎 │
│ ┌──────────────────────┐ ┌──────────────────┐ │
│ │ PagedAttention NPU │ │ 音频预处理 │ │
│ │ 显存管理 │ │ (Mel Spectrogram) │ │
│ └──────────────────────┘ └──────────────────┘ │
│ ┌──────────────────────┐ ┌──────────────────┐ │
│ │ Encoder (音频编码) │ │ Decoder (文本生成)│ │
│ │ Conv1D + Self-Attn │ │ Cross-Attn + LM │ │
│ └──────────────────────┘ └──────────────────┘ │
│ ┌──────────▼──────────┐ │
│ │ CUBE + Vector 混合执行 │
│ │ (RMS Norm + Rotary Emb 优化) │
├──────────────────────────────────────────────────────┤
│ 昇腾 NPU 硬件层 │
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ Scalar │ │ Vector │ │ CUBE 矩阵乘 │ │
│ │ 控制流 │ │ Conv1D │ │ Attention │ │
│ └──────────┘ │ RMS Norm │ │ Encoder+Dec │ │
│ └──────────┘ └──────────────┘ │
└──────────────────────────────────────────────────────┘设计思路:Whisper-Large-V3-Turbo 模型权重托管在 AtomGit 平台,使用 atomgit_hub 的 snapshot_download 下载。
# [工具安装] 安装 atomgit SDK
!pip install -U atomgit atomgit_hub -i https://mirrors.huaweicloud.com/repository/pypi/simple# [模型下载] 从 AtomGit 平台下载 Whisper-Large-V3-Turbo 模型
from atomgit_hub import snapshot_download
model_repo = "hf_mirrors/openai/whisper-large-v3-turbo"
local_dir = "/opt/atomgit/whisper-large-v3-turbo"
snapshot_download(model_repo, local_dir=local_dir)
print(f"模型已下载到: {local_dir}")设计思路:Whisper 模型对文件完整性要求较高,缺少 config.json 或 tokenizer.json 会导致 vLLM 启动失败。在启动服务前先验证关键文件是否存在。
# [文件验证] 检查模型关键文件是否完整
import os
model_path = '/opt/atomgit/whisper-large-v3-turbo'
print("模型目录内容:")
print("=" * 60)
for item in sorted(os.listdir(model_path)):
item_path = os.path.join(model_path, item)
if os.path.isfile(item_path):
size_mb = os.path.getsize(item_path) / (1024 * 1024)
print(f" {item} ({size_mb:.1f} MB)")
else:
print(f" {item}/")
print("=" * 60)
required_files = ['config.json', 'tokenizer.json']
all_ok = True
for f in required_files:
full_path = os.path.join(model_path, f)
status = "✅" if os.path.exists(full_path) else "❌"
if not os.path.exists(full_path):
all_ok = False
print(f"{status} {f}")
if all_ok:
print("\n✅ 模型文件验证通过!可以开始部署了。")
else:
print("\n❌ 模型文件验证失败,请重新下载。")设计思路:这是整个课程的核心知识点。Whisper-Large-V3-Turbo 在昇腾上通过 vLLM-Ascend 部署,与纯文本 LLM 有一个关键差异:必须通过 --compilation-config 指定自定义算子编译策略,将 rms_norm 和 rotary_embedding 算子切换到昇腾原生优化实现。否则这两个算子会走 GE 图引擎的通用路径,推理性能大幅下降。
# [服务启动] 启动 vLLM ASR 服务
!vllm serve /opt/atomgit/whisper-large-v3-turbo \
--served-model-name whisper-large-v3-turbo \
--host 0.0.0.0 \
--port 8016 \
--tensor-parallel-size 1 \
--dtype bfloat16 \
--compilation-config '{"custom_ops":["none", "+rms_norm", "+rotary_embedding"]}' \
--max-num-seqs 4 \
--gpu-memory-utilization 0.8这个参数是 Whisper 在昇腾上获得高性能推理的决定性配置:
"custom_ops": ["none"]:默认不使用任何自定义算子(全部走 GE 图引擎通用路径)"+rms_norm":将 RMS Norm 算子切换到昇腾原生优化实现"+rotary_embedding":将 Rotary Embedding(旋转位置编码)算子切换到昇腾原生优化实现Whisper 模型的 Encoder 和 Decoder 中大量使用 RMS Norm 和 Rotary Embedding,这两个算子在 GE 图引擎通用路径下的性能远低于昇腾原生实现。不配置这两个自定义算子,推理速度可能慢 3-5 倍。
很多习惯了 CUDA 的开发者容易踩坑:直接复制 LLM 的 vLLM 启动命令,不加 --compilation-config,结果推理速度极慢却不知道原因。
设计思路:服务启动后,在另一终端或新的 Notebook 中,先下载一段测试音频,然后通过 /v1/audio/transcriptions 接口进行语音转写测试。
# [测试准备] 下载测试音频
!wget -O test_speech.wav https://www.voiptroubleshooter.com/open_speech/american/OSR_us_000_0010_8k.wav# [ASR 推理] 调用语音转写接口
!curl http://localhost:8016/v1/audio/transcriptions \
-H "Content-Type: multipart/form-data" \
-F "file=@test_speech.wav" \
-F "model=whisper-large-v3-turbo"--compilation-config 自定义算子很多习惯了 CUDA 的开发者在这里容易踩坑:直接用 LLM 的 vLLM 启动参数部署 Whisper,不加 --compilation-config,结果推理速度极慢。
根本原因:Whisper 模型中的 RMS Norm 和 Rotary Embedding 算子在 GE 图引擎通用路径下,会逐元素调用 Scalar/Vector 计算单元,无法充分利用昇腾 NPU 的并行计算能力。而昇腾原生优化版本会将这些算子融合为单一 Kernel,大幅减少 Kernel Launch 开销和显存访问次数。
解决方案:始终在 vLLM 启动命令中添加:
--compilation-config '{"custom_ops":["none", "+rms_norm", "+rotary_embedding"]}'--max-model-len另一个高频踩坑点:从 LLM 部署经验出发,习惯性地加上 --max-model-len 参数。
根本原因:Whisper 是 Encoder-Decoder 架构,其序列长度由音频时长和采样率决定(通过 Mel Spectrogram 预处理自动计算),而非像 LLM 那样由用户指定。vLLM-Ascend 会根据模型配置自动计算最大序列长度,手动设置 --max-model-len 反而会与模型内部的序列长度计算冲突。
解决方案:启动 Whisper 服务时,不要设置 --max-model-len 参数。
| 环境变量 | 默认值 | 说明 |
|---|---|---|
ASCEND_RT_VISIBLE_DEVICES | 0 | 昇腾 NPU 可见设备 ID |
CUDA_VISIBLE_DEVICES | (空) | 必须清空,防止 CUDA 回退 |
MODEL_DIR | /opt/atomgit/whisper-large-v3-turbo | 模型本地目录 |
PORT | 8016 | API 服务监听端口 |
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 推理速度极慢(3-5倍差距) | 未配置 --compilation-config | 添加 --compilation-config '{"custom_ops":["none", "+rms_norm", "+rotary_embedding"]}' |
ModuleNotFoundError: No module named 'atomgit_hub' | 安装后未重启内核 | 重启 Jupyter 内核后重试 |
启动报 max-model-len 相关错误 | 错误设置了 --max-model-len | 移除该参数,让 vLLM 自动计算 |
| 音频转写返回空文本 | 音频格式不支持或文件损坏 | 使用 wav/mp3/flac 格式,确认文件可正常播放 |
No CUDA GPUs are available | CUDA_VISIBLE_DEVICES 未清空 | 执行 export CUDA_VISIBLE_DEVICES= 后重新启动 |
| 端口 8016 被占用 | 旧服务未停止 | pkill -f "vllm serve" 杀掉旧进程 |
GET /health响应:200 OK
POST /v1/audio/transcriptions
Content-Type: multipart/form-data请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
file | file | ✅ | 上传的音频文件(wav/mp3/flac 等) |
model | string | ✅ | 填写 whisper-large-v3-turbo |
响应:
{
"text": "The birch canoe slid on the smooth planks..."
}登录后即可查看完整教程内容、运行代码和参
与学习互动
还没有账号?