工程

语音输入架构:Loqua 三模型语音输入栈内部解析

为什么我们把语音识别、语言智能和屏幕上下文拆成三层,以及我们如何诚实看待内部指标。

TL;DR

这是一篇 blog 级别的 Loqua 语音输入架构说明,也解释为什么真正适合听写的 voice ai architecture 不是一个巨大的 ASR 模型。Loqua 由三层协作构成:语音识别、语言智能和多模态上下文。原因很简单:听写质量不只是 word error rate。一个有用的 dictation model stack 必须听清词,理解技术名称,并按目标 app 组织输出。我们的内部目标是 200ms 级响应、高技术词汇识别率,以及在支持条件下低个位数 WER;在公开 benchmark 页面发布前,请把这些视为内部测量,而不是第三方结论。

我是 Shuran,带着一个小型算法研究团队,我们每天都用语音输入。我们做 Loqua,是因为评估过的听写工具虽然大多工程质量不错,也确实有用,但一旦推到代码、中英混合和 app-aware formatting 场景,就都撞到了同一个上限。这个上限是结构性的,不是调参问题。下面是我们决定必须改变结构之后,最终走到的架构。

这不是论文,而是一篇 blog 级别的 walkthrough:每一层背后的直觉、跑出来的指标,以及我们实际拿这套栈做什么。如果你想看更深的学术背景,文末的延伸阅读会列出我们参考过的论文。

套壳 Whisper 的陷阱

OpenAI 的 Whisper 改变了英语语音识别的可能性。它是一个非常出色的模型。Whisper 论文展示了,扩展弱监督音频训练可以得到强鲁棒性的通用 ASR,覆盖口音、环境和 99 种语言,而且不需要按领域 fine-tuning。这对整个领域都是结构性进展。

但 Whisper 是 ASR 模型,不是听写产品。"准确转录语音" 和 "生成我可以不编辑就贴进邮件的文字" 之间差距很大。套壳 Whisper 的做法,也就是把 Whisper 输出再交给格式化层,能补上一部分差距。但在我们关心的三个地方会失败:

  • 技术词汇。Whisper 听到 "react query" 会给你 "react query"。它不知道在你的代码库里这其实是 @tanstack/react-query,也不知道你想要的是 package import。技术词汇上的 NER 需要一个能看到周围上下文的模型,而不是只听音素的模型。
  • App-aware formatting。Whisper 做转录;它不知道你在 Slack 里,还是在 Python 文件里。在上面再接 formatter,要么依赖脆弱的 heuristic,要么每次 utterance 都调用重型 LLM,既慢又依赖云端。
  • 紧延迟预算下的流式输出。Whisper 很适合 batch transcription。要做低延迟、设备端、流式 Whisper,要么牺牲(更小模型、更低准确率),要么做大量和模型结构对抗的工程优化。

我们在研究原型里试过套壳 Whisper 这条路。它足够用来验证想法,但不够好到成为我们每天使用的工具。

三模型直觉:另一种语音识别栈

核心直觉是:语音输入其实是三件事,而同一个模型很难把三件都做好。这三件事是:

  1. 听清词。Acoustic-to-token。这是 ASR 擅长的事。
  2. 理解意图。清理填充词、错误开头、句中修正。识别技术实体。判断用户真正想输入什么。
  3. 放到正确位置。按目标 app 格式化输出。让同一个意图在 VS Code 里变成代码,在 Slack 里变成消息,在 Cursor 里变成结构化 prompt。

一个端到端模型试图同时做三件事,会遇到很硬的结构性问题:"转录音素" 的 loss surface 和 "按 Slack 格式输出" 的 loss surface 指向不同方向。联合训练会同时折中两边。我们自己的 ablation 也能确认这一点:我们试过把第 2 层和第 3 层合并成一个用 multi-task data 训练的 transformer,结果两边准确率都下降。

拆成三层,每个模型就能把一件事做好。代价是层间 hand-off 会增加一点延迟;我们通过让整条 pipeline 都跑在 Neural Engine 上把它追回来。这就是 Loqua 语音输入架构的核心:不是一个单体转录器,而是一个小型 dictation model stack,每一层都为自己负责的部分专门训练。

第 1 层:语音识别

Acoustic input → token sequence。这是一套任务特定的语音识别器,而不是直接套 Whisper。架构选择由三个我们不愿妥协的约束驱动:

  • Streaming-first。说话人还没说完,输出就要开始。这排除了默认对完整音频序列做 non-causal attention 的方案,我们使用的是更适合流式的变体。
  • 设备端 Neural Engine 兼容。模型大小和 operator 选择,都受限于能否通过 Apple Core ML 在 Neural Engine 上高效运行。这是一个真实约束;论文里看起来没问题的 operator,可能会掉出 Neural Engine 路径,最后变成 CPU-bound。
  • 低音量鲁棒性。我们的训练数据有意包含 whisper-volume input,比如在咖啡馆、深夜小声听写。大多数通用 ASR 训练数据是正常音量;小声输入需要显式覆盖。

这一层输出的是带 timing 和 confidence scores 的 token sequence。它还不是最终文字,而是下一层要清理的原始识别结果。

第 2 层:语言智能

Token sequence → cleaned, intent-resolved text。这里是我们投入最多研究精力的地方,因为大部分用户可感知质量都在这一层。

这一层的任务是:把语音模型听到的内容,变成用户真正想写下的内容。三件事会并行发生:

  • 移除填充词和错误开头。"Um, so, basically, we should — actually wait, let me start over — we should cache this" 会变成 "We should cache this." 句中修正会被保留,清嗓式内容会被去掉。
  • 技术词汇 NER。这一层会学习常见库、框架、模型家族、文件扩展名、终端命令和惯用 API surface 的名称。当周围上下文是 JavaScript 文件时,"React query" 会变成 @tanstack/react-query。我们的内部目标是在 curated in-domain technical vocabulary 上达到 high-90s 识别率,让常见标识符不需要每个都进 personal dictionary 也能写对。
  • 结构化成形。输出应该是一句话、项目符号列表、Markdown 表格,还是代码注释,会在这里根据下一层(多模态上下文)提供的目标位置判断来决定。

按参数量算,这一层是栈里最小的模型;但按用户体验影响,它最大。我们投入在这一层的团队工时,比另外两层加起来还多。

第 3 层:多模态上下文

App state + screen + cursor → format directive。这是 omni-modal 层,也是我们不只把 Loqua 称为“听写 app”的原因。Loqua 的工作不是转录,而是在你想写的位置,写出你真正想表达的内容。

上下文层会通过 macOS Accessibility 读取当前活动 app、选中文本(如果有)、可见的相邻文本,以及目标位置的结构线索(Gmail compose vs Slack thread vs VS Code Python file vs Cursor chat panel)。它输出一条 format directive,语言层会用它来塑造最终文本。

更深的直觉,也就是为什么 omni-modal architecture 改变了语音输入而不只是增强它,是另一篇文章的主题。如果你想沿着这个线索继续看,可以读 voice meets vision: how omni-modal models unlock context-aware dictation

我们跟踪的指标

指标当前内部目标为什么重要
端到端延迟Apple Silicon 上 200ms 级低于用户开始觉得“我在等”的阈值
Time-to-first-token (TTFT)常见流式场景低于 200ms较长 utterance 还在说时,前几个词已经出现
NER accuracycurated in-domain technical vocab 上 high 90s标识符、库名和模型名必须写对
Multilingual WER支持测试条件下低个位数中英混合和带口音英语必须能在真实工作流里使用

这些是内部 benchmark 和 dogfooding 数字,不是第三方 benchmark suite。测试集包含我们自己的技术词汇、中英切换样例、带口音英语样本,以及日常噪声环境。下一步内容上应该发布一个公开方法论页面,让这些数字能被引用,而不是靠含糊表述支撑。

我们自己怎么用

关于这套栈,最重要的一点是:我们写它,是因为我们自己要用。团队每个人每天都会听写:commit、PR、内部 Slack、更长的技术写作,以及(对我来说)像这篇 blog 里的大部分 prose。塑造这套架构的决策来自真实使用,而不是产品规格书。

日常使用里,架构和功能清单的差异在三个地方很明显:

  • 代码听写。NER 质量决定了语音是能成为代码可用界面,还是只能当玩具。想看它能做什么,可以读 代码听写指南
  • 多语言 code-switching。我们内部 Slack 有一半是中文夹英文。语言层不是绕开 code-switched data,而是直接在它上面训练;句中切换不需要模式开关。
  • App-aware formatting。同一句语音在 VS Code 里变成代码注释,在 GitHub 上变成结构化 PR 描述,这就是普通语音输入和真正有用产品之间的区别。

我们是小团队。这个故事诚实的版本是:我们没有资源同时维护一个 wrapped-Whisper 产品和一个三模型研究栈。我们选择结构性路径,是因为自己需要这种质量。相比做一个更宽但质量不够的东西,我们宁愿先交付一个范围更窄、质量更好的产品。

2026 年每一层如何重建

第 1 层:语音识别。识别器围绕 streaming、低音量语音和技术词汇重新收紧;更深入的 walkthrough 在 inside our omni-modal voice stack,post-training 细节在 RL in our voice stack

第 2 层:语言智能。语言层现在把 cleanup、entity preservation 和 app-aware structure 当作同一个 dictation model stack,而不是分开的后处理器。强化学习在这里帮助最大:选择用户最少编辑的输出。

第 3 层:多模态上下文。上下文层围绕本地屏幕证据重建:当前 app、选中文本、可见标识符和光标周围内容。架构细节见 building a listener that sees what you see

下一条前沿是非词语音频:把 AED 和 audio captioning 作为可选、local-first 的上下文。我们在 sounds with meaning 中介绍了这个原型阶段的工作。

延伸阅读

如果你想看比这篇 blog 更深的内容:

如果你对这套架构有问题,或者想深入聊其中某一层,欢迎给我们发邮件。我们是小团队,每封邮件都会读。

常见问题

为什么是三个模型,而不是一个大 LLM?
单一端到端模型有结构性问题:"正确转录音素" 的 loss surface 和 "为 Slack 格式化输出" 的 loss surface 指向不同方向。我们试过把第 2 层和第 3 层合并成一个用 multi-task data 训练的 transformer,结果两边准确率都下降。三个面向任务训练、各自做好一件事的模型,胜过一个试图同时做三件事的模型。
为什么不直接套 Whisper?
Whisper 是很好的 ASR 模型,但不是听写产品。套壳 Whisper 在技术词汇(没有 in-context NER)、app-aware formatting(需要重型后处理器)和设备端流式输出(Whisper 为 batch 优化)上都不够。我们自己的日常使用需要三者同时成立。
你们是从零训练模型的吗?
语音识别层和语言智能层是的。多模态上下文层基于 omni-modal research patterns(谱系可看 omni-modal blog post),并用我们自己的训练数据和听写任务特定 fine-tuning 做成。
每个模型有多大?
我们不公布具体参数量;它们被调到能放进 Neural Engine 预算,同时达到延迟和准确率目标。三层都会在 stack 的设备端部分运行。云端只保留给特定情况(更长的改写、某些翻译),并且由用户开关控制。
你们如何评估准确率?
我们用每一层的内部 benchmark suite,加上团队日常 dogfooding。语音识别会在支持条件下用 WER-style protocols 测量。NER 用 curated technical vocabulary 测量。在把任何数字当成外部 benchmark claim 之前,我们应该先公开方法论。
你们会开源其中一部分吗?
生产 stack 目前没有计划开源。团队很小,在产品之外维护一份干净的公开 release 会拖慢我们。我们会在有值得说的内容时发布类似这篇的技术笔记。如果你想做研究合作,可以给我们发邮件。

今天就试试 Loqua

免费开始。Mac 原生。由每天都在使用它的算法研究者打造。

下载

更多 Loqua 博客文章

工程
全模态语音输入:多模态理解、MoE 与流式文本输出
工程
语音输入中的强化学习:Loqua 语音栈里的 GRPO、DPO 与 on-policy distillation
工程
多模态语音识别:打造一个能看见你所见的监听器
效率
语音生产力栈:我们实际用来写作、交付和思考的 9 个工具
教程
Mac 会议语音笔记:从语音到笔记、行动项和完成