随手记两件反直觉的事:同一段合成音频三次三种错法,配错模型的热词表照样生效
最近在搞语音转文字,顺手把热词的三条通道各试了一遍。本来只想确认"哪条通道能修对专名",结果记下的是两件跟我直觉相反的事,写在下面。
先说个语境。这周 Hacker News 上有两篇语音转文字的帖子排着队上首页,一篇是 10-08 的,一个 16.9 MB 的端侧转写工具,961 分;另一篇是 10-13 的,有人把一个嵌入模型改造成语音转文字,397 分。热闹归热闹,做过客服通话或会议转写的人都知道,卡人的从来不是"能不能转",是产品名、人名、地名永远听错。"珞珈"听成"洛家",同音不同字,后面全跟着错。
工具是阿里云百炼的 CLI。CLI 就是命令行工具,不开网页,在终端敲一行字让平台干活,百炼那个叫 bl,我是在 GitHub 上翻它的仓库时看到这组 speech 命令的。ASR 是语音识别,声音进去文字出来;热词表是你提前递给它的一张清单,意思是"这些词请按我给的字形写",每个词能带一个权重,权重越高越倾向于照你写的出。

读数都是 2026-10-14 我在自己电脑上敲出来的,bl 2.1.0。合成音频两段是我用语音合成现做的,不是真实通话,这点先说清楚,带噪环境上的表现以你自己那次为准。工作空间里别人建的热词表我只看不碰,自己建的两张测完就删。
一、先要有一段会听错的音频
热词有没有用,得先有个"听错"的基线。我合成了一句故意塞满生僻专名的话:
请把 XQ-7734 号工单转给岑巩县的冉雍,抄送珞珈三号项目组的仇池和濮阳办事处。
三个模型各转一遍:fun-asr 全对,fun-asr-flash-2026-06-15 全对,qwen-audio-3.0-asr-flash 把珞珈三号转成了洛家三号,其余全对。只有第三个会错,实验就在它身上做。
反直觉的第一件在这儿。同一段合成音频连着转三次,我拿到的是"洛家三号""洛家三号""洛嘉3号"三种写法。不是同一个错重复三遍,是三次里换了字形。我原来以为专名听错是个稳定现象,错就固定错成那一个,拿一次结果当结论完全够了。实际上语音识别有随机性,"我试了一次生效/没生效"这种话一句都站不住,后面每条结论我都标了重复次数。
顺带记一条:我本想加第四个模型 qwen3-asr-flash 做对照,跑不了,返回 HTTP 403 AllocationQuota.FreeTierOnly,提示免费额度用尽、要续费用或去控制台关掉"仅用免费额度"模式。剩多少我看不到,控制台会话过期了。这类数字你去控制台额度页看当天读数,别抄文章里的。

二、三条通道各试一次,都修对了
在会听错的那个模型上,三条通道各跑一次,各 1 次都把珞珈三号修对了。
第一条是预编译热词表,先建一张表,把词和权重写进去:
bl speech vocabulary create --model qwen-audio-3.0-asr-flash --prefix hw1014a --words '{"珞珈三号":4,"仇池":4}'
--prefix 只能用小写字母和数字、最长 10 位;权重 1 到 5,帮助文本推荐 4,Qwen-Audio-3.0 系还能用 50 的超级热词。建完拿到一个 vocab- 开头的 ID,转写时带上:
bl speech recognize --url audio2.mp3 --model qwen-audio-3.0-asr-flash --language zh --vocabulary-id <表 ID>
第二条是即时热词,不建表,词直接塞进这次调用:
bl speech recognize --url audio2.mp3 --model qwen-audio-3.0-asr-flash --language zh --vocabulary '{"珞珈三号":4,"仇池":4}'
第三条是上下文词表,不给权重只给词:
bl speech recognize --url audio2.mp3 --model qwen-audio-3.0-asr-flash --language zh --context "珞珈三号 仇池"
三条的生效模型范围不一样,这是选通道时唯一真正要看的:--vocabulary-id 支持面最宽,含 Fun-ASR 与 Paraformer;--vocabulary 只对 Qwen-Audio-3.0-ASR-Flash 系列生效,别的模型上带了也白戴;--context 只对 Qwen-Audio-3.0-ASR-Flash 和 Fun-ASR-Flash 生效,且最长 400 字。
我的选法是按词表寿命:长期不变、几个服务共用,建一次表反复用;临时一两次调用,直接塞 json;手里只有一份词清单不想管权重,走 context。
三、反直觉的第二件:配错模型的那张表,三次都生效了
帮助文本对 --vocabulary-id 和建表时的 --model 都写着"必须与之后 recognize 传的完全一致,否则热词表被静默忽略"。我按这句话的理解去验:另建一张表,建的时候声明给 fun-asr 用,事后用 bl speech vocabulary get --id <表 ID> 核实过,target_model 字段确实是 fun-asr,然后把它喂给 qwen-audio-3.0-asr-flash:
bl speech recognize --url audio2.mp3 --model qwen-audio-3.0-asr-flash --language zh --vocabulary-id <fun-asr 的表>
我预期是"照旧听错",因为帮助文本说会被忽略。实际连试三次,三次都把珞珈三号修对了,没有被忽略。
反方向(3.0 的表喂给 fun-asr)我没法观察,fun-asr 基线本来就全对,修没修看不出来。所以这条我只能记到这儿:帮助文本说的"错配静默忽略"在我这个组合上没复现,连试三次都生效;哪边是常态、是不是模型族之间互通,我没查明,也不打算猜。
留一句实操:别依赖"配错会自动忽略"这句话做兜底设计。建表的 --model 和调用的 --model 写成一样,是最不需要解释的做法。

四、还有一条边界,跟帮助文本一致
把 context 的参数换成主题描述,不写词本身:
bl speech recognize --url audio2.mp3 --model qwen-audio-3.0-asr-flash --language zh --context "卫星工单项目组办事处"
连试两次,两次都还是洛家三号。帮助文本原话是"必须包含目标词本身,只写主题描述作用很小",实测一致。我原来隐隐觉得给个话题方向多少有点用,没有。这条通道不是话题提示器,是词表。
五、建表删表的纪律,和一个参数名的坑
删表这条有闸:
bl speech vocabulary delete --id <表 ID>
不带确认参数直接跑会被拦下来,提示该操作永久删除、不可撤销、加 --yes 重跑。我把自己建的两张删掉之后做了两次复核:bl speech vocabulary list(无参数)里只剩别人 09-09 建的三张表,一张没碰;再 get 已删的那个 ID,返回 400 资源不存在。删干净了,也没动别人的东西。
参数名不统一,抄命令时留意:get 和 delete 都叫 --id,recognize 那边叫 --vocabulary-id。我一开始在 get 上写成 --vocabulary-id,报的是"未知参数"。
六、记下来的六条,和这篇没写的
- 先跑基线,确认你的合成音频和模型组合真的会听错再上热词,全对的组合加热词没有可测量的增量
- 识别有随机性,任何通道结论至少重复两次
- 长期词表走
vocabulary create+--vocabulary-id;临时调用走--vocabulary;只有词清单走--context --context必须含目标词本身,写主题没用(实测两次仍错)- 建表与调用的
--model保持一致;"错配静默忽略"我这次没复现(连试三次都生效),别拿它当兜底 - 删表有高风险闸,不加
--yes会被拦;删完 list + get 双重复核
没写的:字幕那条链路是另一篇的事;实时流式识别(realtime 系列模型)不在本包;带噪通话我没素材,合成音频上的结论不外推到噪声音频;花费与额度去控制台看,我这边会话过期了,查不了也不编数字。
合成音频、转写、建表删表都要 Key,list 和 get 同样要 Key,没有完全免鉴权的那一档。API Key 在密钥管理页签创建,地域选北京;想自己走一遍的话 CLI 安装页在这,也可以先去百炼首页看看平台侧长什么样。
会变的:模型在架名单、额度状态、热词表清单。重跑一遍就有当天读数,结论以你那次为准,别抄我的快照。

浙公网安备 33010602011771号