Fun-ASR-Nano 工业级语音识别实战指南:模型架构、推理、微调与评测全流程解析
【免费下载链接】FunASROpen-source speech recognition toolkit for training, inference, streaming ASR, VAD, punctuation, speaker diarization pipelines, and OpenAI-compatible/MCP serving.项目地址: https://gitcode.com/GitHub_Trending/fun/FunASR
Fun-ASR-Nano 是通义实验室推出的端到端语音识别大模型,基于数千万小时真实语音数据训练,在远场高噪声、中文方言/地域口音、多语言混合等工业场景中表现出色。本指南以 examples/industrial_data_pretraining/fun_asr_nano/README.md 为骨架,结合仓库内 model.py、finetune.sh、lora_finetune.sh、decode.py 等源码,带你完整掌握 Fun-ASR-Nano 的架构原理、推理调用、ChatML 数据准备、全量/部分/LoRA 微调以及 WER 评测全链路,读完即可在自有领域数据上落地部署。
Fun-ASR 整体架构:音频编码器(Audio Encoder)、音频适配器(Audio Adaptor)、CTC 解码器(CTC Decoder)与 LLM(Qwen3-0.6B)协同完成语音转写,并支持热词上下文注入。
一、模型定位与核心能力
Fun-ASR 是端到端语音识别大模型,由通义实验室发布,训练数据规模达数千万小时真实语音,具备强大的上下文理解能力与行业适应性。它区别于传统 ASR 工具包的关键点在于:以 LLM 为核心解码器,天然具备"听得清、懂其意、写得准"的语义级转写能力,能有效应对"幻觉"生成和语种混淆等挑战,在教育、金融等垂直领域可准确识别专业术语与行业表达。
仓库内提供两个 checkpoint,参数规模均为 8 亿(0.8B):
| 模型 | 任务范围 | 训练数据 | 参数量 |
|---|---|---|---|
| Fun-ASR-Nano-2512 | 支持中文、英文、日文;中文含 7 种方言(吴语、粤语、闽语、客家话、赣语、湘语、晋语)及 26 种地域口音(河南、陕西、湖北、四川、重庆、云南、贵州、广东、广西等 20 多个地区);英文、日文涵盖多种地域口音;额外支持歌词识别与说唱语音识别 | 数千万小时 | 800M |
| Fun-ASR-MLT-Nano-2512 | 支持中文、英文、粤语、日文、韩文、越南语、印尼语、泰语、马来语、菲律宾语、阿拉伯语、印地语、保加利亚语、克罗地亚语、捷克语、丹麦语、荷兰语、爱沙尼亚语、芬兰语、希腊语、匈牙利语、爱尔兰语、拉脱维亚语、立陶宛语、马耳他语、波兰语、葡萄牙语、罗马尼亚语、斯洛伐克语、斯洛文尼亚语、瑞典语,共 31 种语言 | 数十万小时 | 800M |
核心特性包括四个方面:
- 远场高噪声识别:针对远距离拾音及高噪声场景(如会议室、车载环境、工业现场等)深度优化,README 中给出的识别准确率提升至 93%。
- 中文方言与地方口音:支持 7 大方言与 26 个地区口音,覆盖河南、陕西、湖北、四川、重庆、云南、贵州、广东、广西、河北、天津、山东、安徽、南京、江苏、杭州、甘肃、宁夏等地区。
- 多语言自由说:独立的 MLT-Nano checkpoint 支持 31 种语言识别,重点优化东亚与东南亚语种,支持语种自由切换和混合识别。
- 音乐背景歌词识别:强化音乐背景干扰下的语音识别性能,支持对歌曲中歌词内容的精准识别。
说明:如果只需要 Fun-ASR-Nano 的原生转写能力,可以走 Transformers 5.17.0 原生推理路径(或中文版 transformers_native_zh.md),它加载独立的
-hfcheckpoint,不依赖 FunASR 工具库。而本文与示例目录聚焦funasr.AutoModel工具库路径,两者的依赖、参数与输出契约不可混用。
二、模型架构:从源码看 FunASRNano 的组成
示例目录中的 model.py 通过@tables.register("model_classes", "FunASRNano")注册了FunASRNano类,其构造函数清晰地展示了四段式架构(model.py 第 33-173 行):
1. 音频编码器(audio_encoder)
- 支持两种来源:
hub="ms"时通过funasr.AutoModel从 ModelScope 加载预训练编码器,否则从tables.encoder_classes注册表中按名称实例化。 - 输入为 80 维 fbank 特征(
input_size: int = 80)。 - 默认
freeze=True冻结编码器参数并置为eval()模式(第 68-74 行),这是微调时的关键开关。
2. LLM 解码器(llm)
- 通过
transformers.AutoModelForCausalLM从init_param_path加载因果语言模型(即 Qwen3-0.6B),支持load_kwargs透传、activation_checkpoint梯度检查点(第 77-96 行)。 - 支持
llm_dtype(bf16/fp16/fp32)精度控制,映射关系见文件顶部的dtype_map。
3. 音频适配器(audio_adaptor)
- 从
tables.adaptor_classes注册表实例化,自动将编码器输出维度(encoder_dim)与 LLM 嵌入维度(llm_dim)对齐,是"语音特征 → LLM 词向量空间"的桥梁。 - 支持
use_low_frame_rate低帧率模式(第 112 行),在前向中按(olens - 1) // 2 + 1压缩帧数,降低 LLM 计算量。
4. CTC 解码器(ctc_decoder + ctc)
- 可选组件:当配置了
ctc_decoder时,额外构建 CTC 解码头与 CTC 损失(ctc_weight默认 0.3,blank_id默认ctc_vocab_size - 1)。 - CTC 分支负责流式对齐与字符级时间戳生成——这正是文档中"TODO 支持返回时间戳"已勾选功能的实现基础(model.py 第 644-750 行):CTC logits 经
unique_consecutive去重、去掉 blank 后解码出ctc_text,再由forced_align对齐得到ctc_timestamps与timestamps,时间戳按* 6 * 10 / 1000换算为毫秒。
前向流程(forward,第 180-289 行)将音频编码器输出的语音 token 通过fbank_beg/fake_token_len定位,替换进 LLM 的inputs_embeds中对应的占位位置,与文本 prompt 拼接后交给 LLM 生成,loss 与 token 级 accuracy(compute_accuracy)同时统计,并输出dialog_turns等多轮对话统计信息。
三、环境安装
git clone https://github.com/QwenAudio/Fun-ASR.git cd Fun-ASR pip install -r requirements.txt示例目录自带的 requirements.txt 给出了最小依赖集:
torch>=2.0 funasr websockets>=12.0 regex numpy soundfile其中websockets用于实时 WebSocket 服务场景,soundfile用于音频读取;麦克风输入等可选功能需要额外安装sounddevice与librosa(文件中已注释标注)。
四、推理:两种调用方式
4.1 使用 funasr.AutoModel 推理
这是最推荐的入口,与 FunASR 生态(VAD、热词、批处理)完全打通:
from funasr import AutoModel def main(): model_dir = "FunAudioLLM/Fun-ASR-Nano-2512" model = AutoModel( model=model_dir, trust_remote_code=True, remote_code="./model.py", device="cuda:0", # hub:从 ms(ModelScope)或 hf(Hugging Face)下载模型。 hub="hf" ) wav_path = f"{model.model_path}/example/zh.mp3" res = model.generate( input=[wav_path], cache={}, batch_size=1, hotwords=["开放时间"], # 中文、英文、日文 for Fun-ASR-Nano-2512 # 中文、英文、粤语、日文、韩文、越南语、印尼语、泰语、马来语、菲律宾语、阿拉伯语、 # 印地语、保加利亚语、克罗地亚语、捷克语、丹麦语、荷兰语、爱沙尼亚语、芬兰语、希腊语、 # 匈牙利语、爱尔兰语、拉脱维亚语、立陶宛语、马耳他语、波兰语、葡萄牙语、罗马尼亚语、 # 斯洛伐克语、斯洛文尼亚语、瑞典语 for Fun-ASR-MLT-Nano-2512 language="中文", itn=True, # or False ) text = res[0]["text"] print(text) # 长音频场景:叠加 VAD 分句 model = AutoModel( model=model_dir, trust_remote_code=True, vad_model="fsmn-vad", vad_kwargs={"max_single_segment_time": 30000}, remote_code="./model.py", device="cuda:0", ) res = model.generate(input=[wav_path], cache={}, batch_size=1) text = res[0]["text"] print(text) if __name__ == "__main__": main()关键参数说明(README 参数表 + 源码印证):
model_dir:模型名称,或本地磁盘中的模型路径。trust_remote_code:是否信任远程代码,用于加载自定义模型实现(FunASRNano类即通过远程代码注册)。remote_code:指定模型具体代码的位置(例如示例目录下的model.py),支持绝对路径与相对路径。device:指定使用的设备,如"cuda:0"或"cpu"。language:转写语种,Nano 为中文/英文/日文,MLT-Nano 覆盖 31 种语言。itn:是否启用逆文本规整(Inverse Text Normalization),把数字、标点等规整为可读文本。hotwords:热词偏置列表,README 示例中使用["开放时间"];热词在源码中通过get_prompt拼入 prompt 的"上下文信息"段落(model.py 第 569-582 行),引导模型在歧义处优先输出热词。vad_model/vad_kwargs:叠加 FSMN-VAD 做语音活动检测,max_single_segment_time=30000表示单段最大 30 秒,长音频会自动切句。
4.2 直接推理(绕过 AutoModel 封装)
如果已经持有本地 checkpoint,可以跳过AutoModel的 generate 层,直接调用模型类:
from model import FunASRNano def main(): model_dir = "FunAudioLLM/Fun-ASR-Nano-2512" m, kwargs = FunASRNano.from_pretrained(model=model_dir, device="cuda:0") m.eval() wav_path = f"{kwargs['model_path']}/example/zh.mp3" res = m.inference(data_in=[wav_path], **kwargs) text = res[0][0]["text"] print(text) if __name__ == "__main__": main()从源码看,FunASRNano.from_pretrained内部仍是调用AutoModel.build_model(model.py 第 759-765 行),而inference会依次执行:get_prompt构造带热词/语种/ITN 指令的 prompt →generate_chatml将音频包进<|startofspeech|>!<|endofspeech|>特殊 token →inference_prepare完成 fbank 提取、编码器前向与 LLM embedding 拼接 →inference_llm调用self.llm.generate解码(默认max_new_tokens=512)。
4.3 字符级时间戳的前提条件
README 明确给出一个重要的使用前提:字符级时间戳要求 checkpoint 同时包含完整的ctc_decoder.*和ctc.*权重。当前Fun-ASR-MLT-Nano-2512checkpoint 未包含这些权重,因此 FunASR 会记录警告并仅返回文本,不再使用未初始化的层生成timestamps或ctc_timestamps。
这一行为在源码中有 fail-closed 保护:on_pretrained_model_loaded钩子通过disable_incomplete_ctc(来自 funasr/models/fun_asr_nano/checkpoint_utils.py)检查 checkpoint 中 CTC 权重是否完整,不完整则禁用 CTC 分支;对应的测试 tests/test_fun_asr_nano_missing_ctc_weights.py 覆盖了"权重缺失时禁用时间戳"“权重完整时保留时间戳”“权重不完整/形状不匹配时禁用”等多个分支(如test_native_model_disables_timestamps_when_ctc_weights_are_missing、test_vllm_model_disables_timestamps_when_ctc_weight_shape_mismatches)。因此若要获得时间戳能力,应选择包含完整 CTC 权重的 checkpoint。
五、微调:从数据准备到训练启动
微调部分的完整说明见示例目录内的 docs/finetune_zh.md(英文版 docs/finetune.md)。训练环境要求funasr>=1.3.26:
pip install "funasr>=1.3.26"5.1 数据准备:ChatML 格式
Fun-ASR-Nano 微调使用 ChatML 对话格式,每条样本是一个 JSON 对象。先看示例数据 data/train_example.jsonl 的第一条:
head -n1 data/train_example.jsonl | jq { "messages": [ { "role": "system", "content": "You are a helpful assistant." }, { "role": "user", "content": "语音转写:<|startofspeech|>!https://modelscope.cn/datasets/FunAudioLLM/funasr-demo/resolve/master/audios/IT0011W0002.wav<|endofspeech|>" }, { "role": "assistant", "content": "几点了?" } ], "speech_length": 145, "text_length": 3 }字段规范(README + scp2jsonl.py 源码双重印证):
- system.content固定为
You are a helpful assistant.。 - user.content包含 prompt 与音频路径,音频位于
<|startofspeech|>!与<|endofspeech|>之间:- 默认 prompt 为
语音转写:/Speech transcription:; - 可按语种改写为
语音转写成英文:/Transcribe speech into Chinese:; - 当文本标注不含阿拉伯数字或标点时,可改用
语音转写,不进行文本规整:/Speech transcription without text normalization:。
- 默认 prompt 为
- assistant.content为音频对应的文本标注(转写目标)。
- speech_length:音频的 fbank 帧数(一帧 10ms)。
- text_length:标注文本的 token 数(使用
Qwen/Qwen3-0.6B编码)。
5.2 用 scp2jsonl.py 批量转换
仓库提供了 tools/scp2jsonl.py,可将常见的 wav scp + 转写文本格式批量转成 ChatML JSONL。源文件格式为"ID + 路径/文本",ID 需一一对应:
train_wav.scp
BAC009S0764W0121 https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_audio/BAC009S0764W0121.wav BAC009S0916W0489 https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_audio/BAC009S0916W0489.wavtrain_text.txt
BAC009S0764W0121 甚至出现交易几乎停滞的情况 BAC009S0916W0489 湖北一公司以员工名义贷款数十员工负债千万执行转换:
python tools/scp2jsonl.py \ ++scp_file=data/train_wav.scp \ ++transcript_file=data/train_text.txt \ ++jsonl_file=data/train_example.jsonl从源码看,该工具内部用Qwen/Qwen3-0.6B的 tokenizer 计算text_length,用soundfile读取音频时长计算speech_length(int((duration * 1000 - 25) // 10 + 1)),支持本地路径与 http(s) 远程 URL,并通过ThreadPoolExecutor多线程并行处理,自动校验 scp 与文本的 ID 一致性(UTT mismatch会报错)。
5.3 启动训练:finetune.sh
示例 data/ 目录已提供训练/验证样本(train_example.jsonl、val_example.jsonl、train_wav.scp、val_wav.scp等)。直接执行:
bash finetune.shfinetune.sh 的核心逻辑:
- 通过
CUDA_VISIBLE_DEVICES指定 GPU,支持多卡(gpu_num自动计算)。 - 训练工具为
funasr-train-ds(DeepSpeed 版 trainer),配合torchrun分布式启动,WORLD_SIZE/RANK/MASTER_ADDR/MASTER_PORT均有默认值(默认单机、端口 26669)。 - 关键训练参数(命令行
++覆盖式传参):
| 参数 | 示例值 | 说明 |
|---|---|---|
++model | FunAudioLLM/Fun-ASR-Nano-2512 | 模型名或本地目录 |
++train_data_set_list/++valid_data_set_list | data/train_example.jsonl/data/val_example.jsonl | 训练/验证数据 |
++dataset_conf.batch_sampler | BatchSampler | 批采样器 |
++dataset_conf.batch_type/batch_size | token/6000 | 按 token 数动态组 batch |
++dataset_conf.sort_size | 1024 | 排序桶大小 |
++dataset_conf.num_workers | 4 | 数据加载进程数 |
++train_conf.max_epoch | 50 | 最大训练轮数 |
++train_conf.validate_interval/save_checkpoint_interval | 2000 | 验证/保存间隔(步数) |
++train_conf.keep_nbest_models/avg_nbest_model | 20/10 | 保留/平均最优模型数量 |
++train_conf.use_deepspeed/deepspeed_config | false/deepspeed_conf/ds_stage1.json | DeepSpeed 开关与 stage1 配置 |
++optim_conf.lr | 0.0002 | 学习率 |
冻结算子(finetune 的核心开关):脚本默认只微调 LLM——
++audio_encoder_conf.freeze=true \ ++audio_adaptor_conf.freeze=true \ ++llm_conf.freeze=false \将需要微调的模块freeze设为false即可。推荐配置策略(README 建议):
- 训练数据少于 1000 小时:建议微调 audio_adaptor(适配器参数量小,数据量少时更稳)。
- 训练数据少于 5000 小时:建议微调 audio_encoder 和 audio_adaptor。
- 训练数据大于 10000 小时:建议全量参数微调。
冻结语义与源码一一对应:在 model.py 构造函数 中,freeze=True会把对应子模块所有参数requires_grad=False并置为eval(),避免梯度回传与 BN/dropout 语义干扰。
5.4 LoRA 微调:低成本替代方案
作为全量/部分微调的替代,可以对 Qwen3-0.6B LLM 做 LoRA 微调(在其q_proj/v_proj线性层上挂适配器):
bash lora_finetune.shlora_finetune.sh 的关键参数与语义:
++llm_conf.use_lora=true:在 LLM 目标层注入LoRALinear适配器(基座权重共享并冻结,新增可训练的lora_A/lora_B)。++lora_only=true:冻结所有非 LoRA 参数(音频编码器、适配器、CTC 解码器),只训练适配器;checkpoint 仍保存完整 state dict(基座权重不变 + 适配器参数),因此用相同的use_lora=true配置即可续训或解码。++llm_conf.freeze=true:保持 LLM 基座权重冻结(与lora_only语义重复,但更显式)。- LoRA 超参数位于
llm_conf.lora_conf下(模型配置自带默认值):r、lora_alpha、lora_dropout、target_modules,可在命令行覆盖,例如:
++llm_conf.lora_conf.r=32脚本内注释给出了与模型内置默认值一致的参考配置:r=16、lora_alpha=32、lora_dropout=0.05、target_modules="[q_proj, v_proj]"。
灵活的混合策略:如果希望在只对 LLM 做 LoRA 的同时保持音频编码器/适配器可训练(对数百小时领域数据是不错的折中),可设置lora_only=false、audio_encoder_conf.freeze=false、audio_adaptor_conf.freeze=false,LLM 基座权重仍通过llm_conf.freeze=true保持冻结。
解码/部署:微调后的 checkpoint 可直接用decode.py解码,无需合并步骤——前向时在基座输出上叠加适配器输出。若要把适配器折叠进基座权重以得到独立部署的 checkpoint,对每个目标模块计算W' = W + (lora_alpha / r) * lora_B @ lora_A,并删除lora_A/lora_B键即可。
六、模型评测:decode 与 WER 计算
微调结束后使用 decode.py 对验证集解码:
python decode.py \ ++model_dir=/path/to/finetuned \ ++scp_file=data/val_wav.scp \ ++output_file=output.txt从源码看,decode.py自动选择设备(CUDA → MPS → CPU),加载AutoModel时同样叠加了fsmn-vad(max_single_segment_time=30000),逐行读取 scp,将"ID + 音频路径"解码为"ID\t文本"写入输出文件。
解码后需要对标注和识别结果做文本逆归一化,然后计算 WER(中文语境下即 CER):
python tools/whisper_mix_normalize.py data/val_text.txt data/val_norm.txt python tools/whisper_mix_normalize.py output.txt output_norm.txt compute-wer data/val_norm.txt output_norm.txt cer.txt tail -n8 cer.txtwhisper_mix_normalize.py与cn_tn.py、format5res.py等工具位于 tools/ 目录(funasr/models/fun_asr_nano/tools/下亦有同名实现),负责将中英文混合文本规整到统一形式,保证 WER 计算公平。
七、性能表现
README 报告了 Fun-ASR 在开源基准、行业数据集上的 WER(%)对比结果(数值均引自 README.md,复现需在对应测试集上自行评估)。
开源数据集性能(WER %):Fun-ASR-nano(0.8B)在 AIShell1(1.80)、AIShell2(2.75)、Fleurs-zh(2.56)、Fleurs-en(5.96)、Librispeech-clean(1.76)、Librispeech-other(4.33)、WenetSpeech Meeting(6.60)、WenetSpeech Net(6.01)等测试集上与 GLM-ASR-nano、Whisper-large-v3、Seed-ASR、Kimi-Audio、Step-Audio2、FireRed-ASR 等模型横向对比;其中 Seed-ASR* 结果为 volcengine 官方 API 评估,GLM-ASR-nano* 结果为开源 checkpoint 评估。
行业数据集性能(WER %):覆盖近场、远场、复杂背景、英文通用、开源、方言、口音、歌词、说唱(Hiphop)九类场景,Fun-ASR-nano 平均 WER 16.72,其中方言 28.18、口音 12.90、歌词 30.85、说唱 30.87,显著低于同量级竞品。
各模型在室内近场、远场嘈杂、复杂背景等场景下的识别准确率对比(来源于示例目录性能评测章节)。
八、生态集成:vLLM 加速与实时服务
- 内置 vLLM 推理引擎:使用
AutoModelVLLM可获 2-3 倍解码加速,并支持流式 WebSocket 服务与 tensor parallel 多卡并行,详见 docs/vllm_guide.md。对应实现位于 funasr/models/fun_asr_nano/inference_vllm.py 与 funasr/auto/auto_model_vllm.py,示例脚本见 demo_vllm.py、serve_vllm.py。 - 流式 WebSocket 服务:支持实时语音识别 + VAD 分句 + 说话人分离 + 热词定制,快速上手见 docs/realtime_demo.md:
cd examples/industrial_data_pretraining/fun_asr_nano pip install -r requirements.txt CUDA_VISIBLE_DEVICES=0 python serve_realtime_ws.py --port 10095 --language 中文客户端侧提供 client_python.py、client_test.py 与浏览器端 client_mic.html,另有 realtime_ws_benchmark.py 可做服务压测。
九、引用
若在论文或产品中使用 Fun-ASR,可引用技术报告:
@misc{an2025funasrtechnicalreport, title={Fun-ASR Technical Report}, author={Keyu An and Yanni Chen and Zhigao Chen and Chong Deng and Zhihao Du and Changfeng Gao and Zhifu Gao and Bo Gong and Xiangang Li and Yabin Li and Ying Liu and Xiang Lv and Yunjie Ji and Yiheng Jiang and Bin Ma and Haoneng Luo and Chongjia Ni and Zexu Pan and Yiping Peng and Zhendong Peng and Peiyao Wang and Hao Wang and Haoxu Wang and Wen Wang and Wupeng Wang and Yuzhong Wu and Biao Tian and Zhentao Tan and Nan Yang and Bin Yuan and Jieping Ye and Jixing Yu and Qinglin Zhang and Kun Zou and Han Zhao and Shengkui Zhao and Jingren Zhou and Yanqiao Zhu}, year={2025}, eprint={2509.12508}, archivePrefix={arXiv}, primaryClass={cs.CL}, }十、小结
Fun-ASR-Nano 以"音频编码器 + 适配器 + Qwen3-0.6B LLM + 可选 CTC"的架构,把 LLM 的语义理解能力引入语音识别,在方言、口音、远场噪声、歌词等工业场景中具备实用价值。本文覆盖了从模型选型(Nano vs MLT-Nano)、源码级架构理解、两种推理路径、ChatML 数据构造、scp2jsonl 转换、finetune/lora 微调、WER 评测到 vLLM/WebSocket 部署的完整链路。落地时请牢记三条关键约束:时间戳能力依赖完整 CTC 权重、微调数据量决定冻结算子选择(<1000h 微调适配器 / <5000h 加编码器 / >10000h 全量)、LoRA 微调后无需合并即可用decode.py解码。
【免费下载链接】FunASROpen-source speech recognition toolkit for training, inference, streaming ASR, VAD, punctuation, speaker diarization pipelines, and OpenAI-compatible/MCP serving.项目地址: https://gitcode.com/GitHub_Trending/fun/FunASR
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考