在众多的开源模型中基本上没有可以准确识别藏语的语音识别模型,无论是国外开源的Whisper,还是国内阿里开源的Qwen3-ASR,均无法识别藏语,这个你们可以自行测试。如果我们需要本地化私有化部署一个可以识别藏语的语音识别项目,那么就需要使用大量的藏语数据集来训练模型。这里记录一位客户找到我训练藏语语音识别模型的过程,供你们参考学习。
首先我使用基于FunASR这个依赖使用Paraformer和SenseVoiceSmall都训练过,但是效果不理想,后面客户要求使用Qwen3-ASR来训练藏语语音识别模型,下面主要记录基于阿里开源的Qwen3-ASR-1.7B这个大模型来训练藏语语音识别模型的过程。
2. 数据集的准备首先需要准备数据集,这里客户提供了10多个小时的藏语数据集,这些数据均是客户自己安排人员采集制作的。数据集要符合一定的格式要求,需要整理为jsonl格式文件,分为两个jsonl文件,一个是train.jsonl文件,这是训练集,还有一个是验证集val.jsonl。格式可以参考下面这样的:
{”audio”: ”/data/corpus/2026-08-11/converted/1000.wav”, ”text”: ”language Tibetanརང་ཉིད་ངལ་རྩོལ་གྲལ་རིམ་གྱི་བསམ་བློ་བཡིན་རློམ་བྱེད་བཞིན་དུ།”}其中这个audio是指音频所在的绝对路径,然后这个text是音频对应的文字内容,当然前面还添加了语种标识language Tibetan,如果不想要语种标识,可以不添加这个,可以直接写音频对应的文字内容即可。
这里由于先做的paraformer训练,我这里编写了一个python脚本直接把paraformer_train.jsonl这样的数据转为这个Qwen3-ASR训练用的数据,下面是这个脚本代码。
# !/usr/bin/env python# _*_ coding utf-8 _*_# @Time: 2026/8/24 14:51# @Author: Luke Ewin# @Blog: https://blog.lukeewin.top# 转换 paraformer 的训练的 jsonl 格式为符合 Qwen3-ASR 训练的格式import jsonimport sys def convert_jsonl(input_file, output_file): ””” 将原始JSONL转换为目标格式: - 原 'source' -> 新 'audio' - 原 'target' -> 新 'text',并在最前面添加 ”language Tibetan” ””” with open(input_file, 'r', encoding='utf-8') as fin, \ open(output_file, 'w', encoding='utf-8') as fout: for line in fin: line = line.strip() if not line: continue try: data = json.loads(line) except json.JSONDecodeError as e: print(f”跳过无效JSON行: {e}”, file=sys.stderr) continue # 提取所需字段 audio_path = data.get('source') target_text = data.get('target') # 如果缺少必要字段,跳过该行(也可选择报错) if audio_path is None or target_text is None: print(”跳过缺少 'source' 或 'target' 的行”, file=sys.stderr) continue # 构建新记录 new_record = { ”audio”: audio_path, ”text”: f”language Tibetan{target_text}” } # 写入输出文件 fout.write(json.dumps(new_record, ensure_ascii=False) + '\n') if __name__ == ”__main__”: # 使用方法:python script.py input.jsonl output.jsonl if len(sys.argv) != 3: print(”用法: python convert.py ”, file=sys.stderr) sys.exit(1) input_file = sys.argv[1] output_file = sys.argv[2] convert_jsonl(input_file, output_file) print(f”转换完成,结果已保存至 {output_file}”)上面准备好了数据集,就可以开始搭建训练的Python环境了,这里使用uv,当然你也可以使用其它的,比如conda。
如何安装uv这里就不说了,比较简单,网上也可以很容易找到安装的文档。
安装好uv之后,就可以使用下面的命令创建一个python运行环境了。
uv venv --python 3.12
这里使用的python版本指定为3.12版本,其它的版本不知道是否可以。
激活环境:
source .venv/bin/activate
激活之后,就可以安装对应的python依赖了。
uv pip install -e .
这里是通过源码方式安装的qwen-asr依赖,此外,训练还需安装datasets依赖。
uv pip install datasets
需要主要的是一定要安装上这个cuda版本的torch,你执行上面两条安装命令的时候默认会给你安装上这个torch,可以检查一下,是否安装对了。
import torchtorch.cuda.is_available()
如果返回的是True就说明可以使用cuda。
4. 开始训练系统安装的CUDA版本是13.2,如果使用的是5090显卡,需要安装的CUDA版本大于等于12.8。这里尽量选择安装最新版本的CUDA和显卡驱动。
经过上面的步骤,环境和数据集都做好了,就可以开始训练了,这里为了访问编写一个shell脚本,执行这个脚本就可以开始训练了。
#!/usr/bin/env bashset -e export CUDA_VISIBLE_DEVICES=0 MODEL_PATH=”/opt/asr/Qwen3/models/Qwen3-ASR-1.7B”TRAIN_FILE=”/opt/asr/Qwen3/finetuning/data/train.jsonl”EVAL_FILE=”/opt/asr/Qwen3/finetuning/data/val.jsonl”OUTPUT_DIR=”/opt/asr/Qwen3/output” torchrun --nproc_per_node=1 qwen3_asr_sft.py \ --model_path ${MODEL_PATH} \ --train_file ${TRAIN_FILE} \ --eval_file ${EVAL_FILE} \ --output_dir ${OUTPUT_DIR} \ --batch_size 2 \ --grad_acc 4 \ --lr 2e-5 \ --epochs 10 \ --log_steps 10 \ --save_strategy steps \ --save_steps 200 \ --save_total_limit 5 \ --num_workers 32 \ --pin_memory 1 \ --persistent_workers 1 \ --prefetch_factor 2需要根据自己的硬件条件修改上面的数值,比如服务器有一张显卡,那么就指定CUDA_VISIBLE_DEVICES=0,如果有多张,就可以使用CUDA_VISIBLE_DEVICES=0,1,这种方式添加多张显卡。还有这个batch_size的值一定要是2的n次方,这个n可以是非负整数。然后这个num_workers的值最大填写你服务器CPU核心数,比如这里有32个核心,就最大可以填写32,这个值也尽量填写2的n次方,同样这个n可以是非负整数。
授予可执行权限。
chmod +x finetun.sh
然后执行这个脚本,开始训练,如果你的显存不够,就可以减小batch_size值。
./finetun.sh
可以看到下面日志中输出的loss值一直在减小,说明训练是有效果的。

可以看到,刚开始这个loss值很高,随着训练的进行,这个loss值会越来越小,如果这个loss值不减小,反而变大,说明这个训练参数设置的不对。
然后可以观察训练中,这个显卡的情况。

从上面可知,如果训练的数据集是10多个小时,那么至少需要一张24GB显存的显卡。如果你的数据集更大,就需要更大显存的显卡。
5. 效果检验经过上面的训练,现在已经完成了训练,我们可以使用下面的python代码测试一下是否真的有效果。
# !/usr/bin/env python# _*_ coding utf-8 _*_# @Time: 2025/2/28 1:53# @Author: Luke Ewin# @Blog: https://blog.lukeewin.topimport torchfrom qwen_asr import Qwen3ASRModel model = Qwen3ASRModel.from_pretrained( ”/opt/asr/Qwen3/output/checkpoint-12830”, dtype=torch.bfloat16, device_map=”cuda:0”, attn_implementation=”flash_attention_2”, max_inference_batch_size=32, # Batch size limit for inference. -1 means unlimited. Smaller values can help avoid OOM. max_new_tokens=256, # Maximum number of tokens to generate. Set a larger value for long audio input.) results = model.transcribe( audio=input(”请输入音频路径:”), language=None, # set ”English” to force the language) print(results[0].language)print(results[0].text)
这个/opt/asr/Qwen3/output/checkpoint-12830是我上面训练输出的模型权重路径,你需要修改你自己保存训练后的模型权重路径,这里最后填写绝对路径。
然后这里还需要说明一下,我这里开启了flash_attention_2,你需要提前安装好这个依赖flash-attn。我这里使用的是whl方式安装的,如果执行下面方式安装,速度会很慢,会编译很长时间,所以这里找了一个编译好的whl文件直接安装。
uv pip install flash-attn --no-build-isolation
我这里下载的这个whl文件是:
aria2c -x 16 -s 16 -c ”https://github.com/mjun0812/flash-attention-prebuild-wheels/releases/download/v0.9.47/flash_attn-2.6.3+cu130torch2.13-cp312-cp312-linux_x86_64.whl”
执行上面的python代码,可以看到有输出藏文,相比训练之前来说好很多,训练之前输出的是中文。

如果要测试训练之前的效果,只需要修改上面python代码中的加载模型权重路径为训练之前的模型权重路径即可。

可以对比发现,原先模型不能识别藏语,输出的直接是中文,并且意思也不对,并不是翻译为中文输出,你可以理解为模型胡乱输出了中文来应付我们。然后经过训练之后的模型,可以看到输出了藏文,由于我看不懂藏文,这里我发送给AI大模型分析,这意思和音频对应藏文意思是差不多的。
