跳转至

基于Kit真实听写片段的词汇

状态: 研究,2026-10-23。无产品变更。承接自 parakeet-boost-spike.md (分支 spike/parakeet-boost)、custom-vocabulary.md 和 ../plans/transcription-quality.md。

问题: 在 Kit 自己的日常口述中,带识别提示(hints)的 Qwen3-ASR 1.7B 能否修正 Parakeet Unified 遗漏的词汇,代价是什么?

答案: 部分可以。提示将术语召回率从 7/13(Hex 粘贴出的结果)提高到 10/13,但大部分提升并非来自提示本身。六个未命中中有两个是 Rune 被听成 “Ruin” 和 “Roon”。Parakeet 自身的整段音频解码已经能正确识别这两个词,因此它们是流式错误。未加提示的 Qwen 已经能听出 “grill”。提示列表本身只修正了大小写(Hex 一次、HiveMind)和 dotfiles,而且 dotfiles 是在它从这些片段中被加入列表之后才修正的。Qwen 的整体 WER 是 Unified 的 2 到 3 倍,并且消耗约 5 倍于 Unified 离线模式的计算量。更长的提示列表使 Qwen 在 49 个短片段中的 4 个上返回空文本。基于这一证据,不要为了词汇正确性而将口述识别切换到 Qwen。

方法

  • 片段。 50 个来自 diagnostic-dictation-audio 的保留 WAV(10 月 22 日 23:06 到 10 月 23 日 14:46),转换为 16 kHz 单声道 PCM16 副本。文件名即保存时间,其历史条目在 140–400 毫秒后出现,一一对应。49 个匹配到历史条目。一个 1.1 秒的片段没有条目,不计分。计分音频共 219.9 秒,733 个参考词。每个片段都送入了 OpenCode Beta。
  • 参考。 每个参考都以历史文本为起点(原文 = 最终文本,因为 Kit 未配置任何替换、转换或后处理)。在任何模型运行之前,我做了上下文修正:grow→grill(grilling 技能)、defiles→dotfiles、Ruin/Roon→Rune、hex→Hex。我还标记了 12 个措辞不清的片段。推理后,我又做了两处模型一致且上下文支持的编辑,并都做了标记:“only worth”→“probably worth”(Unified 离线模式和每个 Qwen 方案都一致)和 “macro gear change”→“MacBook Air change”(每个 Qwen 方案都一致,而且那周 Air 已离开设备群)。第二处编辑偏向 Qwen,因此下面的召回率列中不包含 MacBook Air。没有播放音频,因此这些是判断性代理指标,而非人工审核。
  • 术语。 10 个片段中预先登记了 13 处出现:Dax ×3、Rune ×4、Hex ×2、HiveMind、dotfiles、grill、Adam。名称按大小写敏感匹配,因此 “hex” 计为未命中。如果忽略大小写,每个方案都能得到 Hex。
  • 提示。 hints17 是 boost spike 的冻结列表(Hex、Cappuccino、OpenCode、Rune、Scrawl、Effect、Anomaly、Dax、Aiden、Kit、Parakeet、Moonshine、GPUI、Sparkle、Argon、Astra、HiveMind)。它是在这些片段出现之前就确定的。hints27 增加了 Psychopomp、dotfiles、Qwen、Claude、Opus、Sonnet、Gemini、skulk、Zen 和 “grill me”。dotfiles 和 “grill me” 来自这些片段的未命中,因此它的召回率是乐观的。两者都使用 spike 的提示词:Names and technical terms: <list>.
  • 运行环境。 spike 的 model-runner、未打补丁的 transcribe-cpp 0.4.1,运行在 M4 Pro Mac mini 上(64 GB、严格 Metal、单 CPU 线程、每个片段新建会话、平均负载约 6.5)。Studio 的 HiveMind 拒绝执行 cargo 工作,而 Pro 的平均负载为 51。本次运行包括一次预热轮次加两次测量轮次,每个片段的方案顺序轮换。准确度来自第 1 轮,第 2 轮没有转录发生变化。Unified streaming 在 0.4.1 上复现了生产环境在 49 个片段中 48 个的粘贴结果,只是标点不同。
  • 修正方案 (d)。 Kit 的 dictation_processing 没有替换或重写,personal-commands.json 也没有转换。因此,Parakeet 加上修正就是生产环境那一行。

结果

系统 术语召回 (13) 错误提示插入 WER,全部 49(733 词) WER,37 个确信片段(598 词) 空输出 每音频秒中位 ms
生产粘贴 = Parakeet + 修正(0.2.4 流式) 7 0 0.95% 1.17% 0 —
Parakeet Unified,流式 7 0 1.09% 1.17% 0 38.2 总计算量 / 11.9 finalize
Parakeet Unified,整段 9 0 3.00% 2.01% 0 14.6
Qwen3-ASR 1.7B,无提示 8 0 6.55% 5.02% 0 70.3
Qwen3-ASR 1.7B,hints17 10 0 6.00% 4.18% 0 74.9
Qwen3-ASR 1.7B,hints27 10 0 8.19% 6.35% 4 73.1
  • 若计入推理后的 MacBook Air 术语,每个 Qwen 方案都会增加一次命中,而 Parakeet 不会。
  • 每个片段的中位时间:Unified 整段为 64 ms,流式 finalize 为 53 ms,三个 Qwen 方案分别为 267、295 和 310 ms。Qwen 的 p95 为 519 到 565 ms,而 Unified 为 100 ms。
  • 在使用提示的情况下,Qwen 每音频秒的毫秒数是 Unified 离线模式的 5.1 倍,是流式 finalize 的 6.3 倍,后者大致相当于生产环境中用户松开后的等待时长。对于 5 秒的口述,这大约是 370 ms 对 60 ms。
  • WER 是代理指标的不一致程度。生产文本作为参考的种子,因此对 Parakeet 的行有利。

没有哪个提示词被插入到没有说过的地方。 各方案在其他方面会失败。hints27 下的短片段返回空文本(2.0–2.6 秒)。未加提示的 Qwen 将一个无声、不计分的片段转成了中文(“玩呢啊。”),而这个结果会被 Hex 粘贴。Qwen 还会改写措辞。

五个最能说明问题的片段

片段 参考 生产 / Unified 流式 Unified 整段 Qwen 无提示 Qwen hints17 Qwen hints27
1792736041649 push the dotfiles commits and what's up with the MacBook Air change push the defiles commits … macro gear change defiles … macro gear change push the .diff files commits … MacBook Air change push the death files commits … MacBook Air change push the dotfiles commits … MacBook Air change
1792735783602 anything else you'd like to ask me or grill me about grow me grow me grill me grill me grill me
1792736219057 Can we talk to Rune and get this started? talk to Roon talk to Rune Rune Rune Rune
1792735967611 Why don't you measure first Why don't you measure first Why don't you measure first? Why don't you measure first? Why don't you measure first? (空)
1792735980294 … the A-B test. Do whatever you want to do … A-B test. Do whatever you want to do 相同 … AB test. Do it in VLAN two. … A/B test. Do it in VLAN two. 与 hints17 相同
  • Dotfiles 只有在提示列表中出现该词本身时才会被识别出来。冻结列表产生的是 "death files"。
  • Grill 的识别并非提示词的功劳。Qwen 在没有任何提示的情况下也能听出来。
  • Rune 是 Parakeet 流式解码的错误,而不是词汇表缺口。1792736124209 中也出现了同样的情况:流式版本给出 "I own Ruin",而整段解码两次都给出 "Rune"。在该片段中,每个 Qwen 分支也都把句子改写成 "what I own Rune, we both work on",并漏掉了一个 Rune。
  • 空输出是更长提示词的失败模式,在 49 个片段中影响了 4 个。
  • VLAN two 看起来是 Qwen 编造的内容。两种 Parakeet 模式对原始措辞都一致,但没有人听过该片段,因此它仍保持标记状态。

主要结论

  1. 在 Kit 的日常听写中,词汇漏识别很少见:在约 3.7 分钟的语音中,13 处词汇出现里有 6 处。大多数并非由缺少词汇表所致。
  2. 成本最低的实际收益来自 Parakeet 的整段解码,它修复了两次 Rune 漏识别,成本约为每音频秒 15 ms。它还在三个片段中丢失了尾部词语("nice to"、"other principles"、"permodal change"),因此在将其用作最终处理之前要测试尾部填充。
  3. 带提示的 Qwen 能恢复需要词汇表的名称(dotfiles、大小写),且没有插入任何错误内容。但它仍需要约 5 倍的计算资源,不支持流式,在这里使代理 WER 变为三倍,并且随着列表增长会退化为空输出。这与 spike 的会议结果一致:名称的召回更好,其他一切更差。
  4. 字面替换(defiles→dotfiles、Roon/Ruin→Rune)可以修复这些片段,但这只是因为列表本身就是从相同的片段构建的。custom-vocabulary.md 中的冲突警告仍然适用。

注意事项

  • 49 个片段、13 处词汇出现,一天、一位说话人、一个麦克风。单条片段就会使召回率改变约 8 个百分点。
  • 参考标注是根据模型一致性和上下文判断的,而非实际试听。有 12 个片段被标记为不明确(confident-WER 列将其排除),且有两处编辑是在推理之后进行的。
  • 计时数据来自两个模型都常驻内存的共享工作进程,且仅覆盖解码器。它们不是从快捷键到粘贴的延迟。
  • 汇总数据和逐片段统计位于 vocabulary-real-clips.json。逐片段的转录文本则保留在 git 之外。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 hex19/hex