Qwen3-ASR 0.6B / 1.7B 在 ncnn 上的推理部署 #6811
Chisato623
started this conversation in
Show and tell
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Qwen3-ASR 0.6B / 1.7B 在 ncnn 上的推理部署
https://github.com/Chisato623/QWEN-ASR-2-ncnn
本文介绍如何将 Qwen3-ASR 0.6B 与 Qwen3-ASR 1.7B 部署到 ncnn,并使用 C++ 示例程序完成离线语音识别。项目目前提供两个可执行示例:
qwen_asr_0_6_b.cpp:Qwen3-ASR-0.6B 推理程序qwen_asr_1_7_b.cpp:Qwen3-ASR-1.7B 推理程序两份代码均支持:
项目目标
Qwen3-ASR 是一个基于多模态大模型结构的语音识别模型。它由音频编码模块和文本生成模块共同完成识别:
<audio_pad>对应位置。本项目的目标是将上述流程尽量完整地迁移到 ncnn C++ 推理环境中,使其可以在本地离线运行,并适配 CPU / Vulkan 两种推理路径。
模型导出
Qwen3-ASR 的模型可以拆分为以下模块:
audio_cnn、audio_transformer、audio_projtext_embedtext_decoder_prefill_layer_XX、text_decoder_step_layer_XXtext_norm、lm_headmel_filters.f32.bin、vocab.json、merges.txt模型的大部分静态图可以使用以下项目导出:
https://github.com/Chisato623/QWEN-ASR-PNNX
也可以直接下载已经导出的 ncnn 模型文件:
https://github.com/Chisato623/QWEN-ASR-2-ncnn/releases
部分权重与TouchScript的比对:
0.6B:
audio_cnn: max_abs=0.000327766, mean_abs=4.76076e-05, rmse=6.25224e-05
audio_transformer: max_abs=0.00306034, mean_abs=0.00016181, rmse=0.000209131
audio_proj: max_abs=0.000214409, mean_abs=1.48482e-05, rmse=1.96686e-05
1.7B:
audio_cnn: max_abs=0.00049448, mean_abs=8.05587e-05, rmse=0.000104114
audio_transformer: max_abs=0.00576448, mean_abs=9.27923e-05, rmse=0.000121464
audio_proj: max_abs=0.000158463, mean_abs=1.62128e-05, rmse=2.12519e-05
看起来不错。
需要注意的是,Qwen3-ASR 中仍有一部分动态逻辑不适合直接导出为单个静态计算图,例如 prompt 构造、语言控制、KV cache 更新、自回归 token 选择等。因此这些逻辑在 C++ 示例程序中手动实现。
音频处理
本项目参考了 ncnn 官方示例中的 Whisper 实现:
https://github.com/Tencent/ncnn/blob/master/examples/whisper.cpp
同样地,当前程序只支持以下 wav 输入格式:
不过,相比 Whisper 示例中常见的 15 秒音频输入,本项目将音频最大处理长度扩展到约 30 秒。程序内部最多读取
480000个采样点,对应:音频前处理流程如下:
int16音频归一化为 float。Spectrogramlayer 计算频谱。mel_filters.f32.bin转换为 128 维 fbank。文本解码
Qwen3-ASR 的文本生成分为两步:
prefill:一次性处理完整 prompt,得到第一步 logits 和每层 KV cache。step:每次输入一个 token,更新 KV cache,并生成下一个 token。程序中使用 greedy search:
当生成到
<|im_end|>或<|endoftext|>时停止。指定语言时,程序会把类似下面的文本提前放入 prompt:这样模型可以跳过语言预测部分,直接生成识别文本。通常这会减少 decoder step 次数,因此比不指定语言略快。
目录结构
模型文件需要放在对应目录中:
程序默认从当前工作目录加载模型文件。因此建议进入模型目录后运行可执行文件。
编译方法
在 ncnn 根目录下使用 CMake 构建:
编译完成后,可执行文件位于:
如果需要 Vulkan 支持,ncnn 需要在配置阶段开启:
单文件识别
Qwen3-ASR-0.6B
进入模型目录:
自动检测语言:
..\..\build\examples\qwen_asr_0_6_b.exe input.wav指定语言:
指定最大输出 token 数:
Qwen3-ASR-1.7B
进入模型目录:
运行:
批量识别
批处理模式会只加载一次模型,然后连续识别多个音频文件,适合数据集测试。
命令格式:
audio_list.tsv每行包含两列,用 tab 分隔:示例:
运行示例:
输出 CSV 字段为:
Vulkan 加速
程序默认关闭 Vulkan,因为部分文本侧网络在 Vulkan 下可能出现精度差异,导致生成文本偏离 CPU 结果。
启用音频侧 Vulkan:
默认情况下,开启该变量后,以下模块会使用 Vulkan:
audio_cnnaudio_transformeraudio_proj文本 decoder 默认仍使用 CPU,以保证识别文本稳定。
Vulkan fp16
默认 Vulkan 使用 fp32,以尽量贴近 CPU 输出。如果想测试 fp16:
fp16 可以降低显存占用,但可能放大自回归文本生成中的数值误差。
文本侧 Vulkan 实验开关
文本侧 Vulkan 目前作为实验功能保留:
也可以只打开部分模块:
测试结果示例
在 Qwen3-ASR-0.6B 上,使用QWEN-ASR官方的测试音频:
CPU baseline 输出:
开启音频侧 Vulkan 后,两条音频的识别文本与 CPU baseline 一致,同时推理时间明显降低。
与pytorch输出结果的对比
利用批处理模式识别了dataset(一个kaggle上的数据集,不过很可惜我忘记它的出处了)中的音频文件,并与pytorch识别结果对比,除了格式不对的wav外识别结果一致。在https://github.com/Chisato623/QWEN-ASR-2-ncnn/releases/tag/dataset_result 中可以看到识别结果
支持平台
这个项目在Ubuntu和Windows系统上都能正常运行,不过需要注意的是:一些云服务器上文件的IO很慢,可能会拖累推理效率(autodl误我!)
总结
本项目完成了 Qwen3-ASR 0.6B 和 1.7B 在 ncnn C++ 环境中的基本部署,覆盖了音频前处理、音频 encoder、Qwen prompt 构造、文本 prefill、KV cache 更新、step 解码、语言控制和批处理评测等完整流程。
相关项目
https://github.com/Chisato623/QWEN-ASR-PNNX
参考项目
https://github.com/Tencent/ncnn/discussions
Beta Was this translation helpful? Give feedback.
All reactions