为什么你的语音智能体显得很没礼貌:话轮转换是你从未记录过的延迟预算
当你第一次发布语音智能体(voice agent)时,你会听到两个相同的抱怨:“它打断了我”和“它感觉很不礼貌”。这两者其实是同一个 Bug。智能体并不是真的没礼貌——它只是在运行一个你从未明确记录过的延迟预算(latency budget)。聊天机器人那种“在输入完成后响应”的直觉,在语音场景下会产生一种挫败感:就像在和一个人聊天,他总是打断你的话,又在不该沉默的时候突然安静。
人类在对话中的轮换(turn-taking)通常发生在约 100 到 300 毫秒的窗口内,这在所有已测量的语言中都是一致的。中位数 200ms 的说话者间隙不是一个目标,而是一个人类校准的基准。任何更慢的反应都会被解读为困惑,任何更快的反应都会被解读为打断。如果语音智能体没有明确模拟这种节奏,每一轮对话都会掉进这两个坑里的其中一个。
解决方案不是用更快的模型,而是承认语音 AI 是一个软实时系统(soft real-time system),其预算由人类对话的物理特性决定,并在发 布前记录下这个预算。
Time-to-First-Token 的谎言
每个聊天 AI 团队都将首个 Token 时间(TTFT)内化为最重要的延迟指标。在聊天产品中,600ms 的 TTFT 感觉很敏捷,因为用户的注意力还在输入框上,在接下来的一秒内出现的第一个词都会被登记为“快”。
语音完全打破了这一点。用户已经停止说话了。没有可以看的输入框。取而代之的是沉默,而语音通道中的沉默是一个承载信息的信号。超过约 300ms 的死寂,用户就会开始怀疑系统是否听到了他们;超过约 1.5 秒,他们会认为系统坏了,要么重复一遍,要么挂断。让聊天用户满意的 TTFT 却会让语音用户体验崩溃,因为缺乏可感知性(affordance)——没有加载圈、没有闪烁、没有代表正在输入的点来填补空白。
陷阱在于,当语音产品失效时,聊天的仪表盘看起来依然正常。模型在 SLA 范围内响应。P95 的 TTFT 很健康。而支持团队却在不断接到电话,抱怨那个“奇怪的、机器人式的、老是打断别人的智能体”。TTFT 从来都不是语音的正确指标;它只是恰好是你的推理平台所暴露出来的指标。
在优化预算之前,先分解它
语音团队能做的最有用的改变,就是停止将端到端延迟视为一个单一数字,而是开始追踪构成用户感知体验的四个部分:
- VAD 检测 (50–80ms):用户停止说话后多久,系统确认一轮对话结束。
- ASR 部分匹配与最终确定 (150–200ms):转写文本何时变得足够稳定以便发送给模型。
- 模型 TTFT (流式管道 300–500ms;原生音频模型 250–500ms):首个响应 Token 到达的时间。
- TTS 首字节音频 (100–150ms):从首个模型 Token 到发出第一个音节的时间。
这些加在一起,600 到 800 毫秒的端到端目标是对话的上限——超过这个数值,即使每个阶段都“很快”,智能体也会显得迟钝。如果你不分解预算,你就会花三个 Sprint 去优化分布式追踪碰巧突出的阶段,而那很少是真正的罪魁祸首。负责 VAD 的团队没有动力去了解瓶颈其实在 TTS 首字节;负责模型的团队坚信问题出在网络。
分解预算还能揭示出真正能扭转局面的非对称优化。在模型仍在流式输出时预热 TTS。在语音音频的第一帧就尝试启动 ASR,而不是等到 VAD 确认。将部分转写结果流式传输给模型,以便在用户说话结束前预热上下文。如果你的仪表盘只报告一个端到端数值,这些优化都是不可见的。
半双工管道在对话这件事上撒了谎
语音 AI 中最常见的架构错误也最容易被忽略:一种在智能体说话时静音麦克风的半双工管道。这很有吸引力,因为它消除了一个真正的工程难题(即智能体通过麦克风听到自己的 TTS 输出),但它在结构上让 “插话”(barge-in)变得不可能。用户无法打断,因为系统字面上听不见他们。
真正的对话是全双工的。双方可以随时发出声音,轮换谈判是通过重叠而非整齐的交替进行的。一个在 TTS 期间静音麦克风的语音智能体并不是在对话;它是在运行一个带有可预测中断点的脚本,用户必须等待。用户很快就会学会这一点——他们不再尝试插话,并开始过度解释,因为他们无法在响应中途进行纠偏,导致对话变得更长且更令人沮丧。
实现全双工需要三件半双工设计可以跳过的事情:
- 回声消除(Acoustic echo cancellation):这样麦克风流就不会拾取扬声器输出并触发伪 VAD 事件。
- 并发音频流:麦克风和 TTS 独立路由,而不是通过单个音频会话串行化。
- 显式的插话处理:在模型和工具层处理,因为用户现在可以在句子中途闯入,你必须决定这对正在进行的响应意味着什么。
前两点是平台层面的问题,成熟的语音 SDK 基本已经解决。第三点是架构决策所在,也是大多数团队发现自己没有优雅的抢占(preemption)机制的地方。
优雅打断是一个状态管理问题
当用户打断(barge in)时,通常有三件事正在进行中:TTS 音频播放、模型 Token 生成,可能还有工具调用。取消音频播放是最简单的部分。在不破坏状态的情况下取消模型生成和工具调用,才是系统容易崩溃的地方。
最小可行打断契约(Minimum viable preemption contract)包含四个部分:
- 在切分块(chunk)边界处切断 TTS 音频,而不是在音节中间。如果你的 TTS 产生 100–200ms 的切分块,你可以在一帧内干净地停止;如果它产生的是单个长缓冲区,你要么会尴尬地截断,要么会等待太久才响应用户。
- 将模型输出截断为用户实际听到的内容,而不是模型生成的内容。用户最后听到的那个 Token 才是对话的真相。将完整的生成响应传回上下文会产生一份错误的记录,其中智能体声称说了用户从未听过的话。
- 针对每个工具,决定是取消还是静默完成。 只读查询可以放心取消。但支付授权则不行——一旦发出,你必须对账结果,这意味着下一轮对话必须确认它,即使对话在用户听到结果前就被打断了。
- 重置响应生成状态,而不重置对话状态。 用户的新话语不是一个新会话;它是一个恰好打断了前一个响应的延续。模型对截断回复的记忆必须准确,否则下一轮对话将会重复或自相矛盾。
跳过其中任何一步,失败模式都是一样的:智能体对“自己说了什么”的认知与用户对“自己听到了什么”的认知发生了分歧。从用户的角度看,智能体显得困惑不解。而从日志看,一切正常。
静音并不总是代表话轮结束
经典的 VAD 设计将固定的静音阈值(例如 700ms 无人声)视为话轮结束信号。这是一个正确的基准线,但却是一个错误的默认值。人 类在说话中间经常会停顿——寻找词汇、呼吸或思考数字。700ms 的阈值会将所有这些情况都捕获为话轮结束,导致智能体跳出来抢答用户还没说完的话。
现代的话轮检测在 VAD 之上叠加了语义和韵律信号,使“静音等于话轮结束”的假设变得更聪明:
- 语义 VAD 对部分转录内容进行分类,并询问“这看起来像是一个完整的想法吗?” 结尾的“嗯……”或以“而且”结尾的句子会获得更长的宽限期;而确定性的“……就这些”则会获得更短的宽限期。
- 韵律模型(Prosodic models) 观察语调轮廓、音高下降和末尾音节延长,以预测用户是在收尾还是仅仅在停顿。这些是人类实际使用的线索,也是你纯 VAD 流水线所抛弃的线索。
- 语音活动投影(Voice activity projection) 使用在对话数据上训练的 Transformer 模型来预测即将到来的话轮结束窗口的可能性,让系统在静音到来之前就能预先准备响应。
正确的架构应该是混合的。VAD 仍然是廉价、快速的基线。语义和韵律模型根据用户实际说了什么以及怎么说的,来拉伸或缩短宽限期。需要追踪的指标不是孤立的 VAD 准确率,而是误切率(智能体在用户思考时打断)与冷场率(在明确的话轮结束后智能体等待太久)。孤立地优化其中一个指标总是会破坏另一个。
原生语音模型并不能消除预算——它们只是重塑了预算
2026 代的语音转语音模型——gpt-realtime、gemini-live 等——将 ASR-LLM-TTS 流水线折叠成一个处理音频输入并产生音频输出的单一模型。营销说辞是“250–500ms 端到端延迟”,这基本属实。陷阱在于假设原生语音模型消除了对话轮预算的需求。
事实并非如此。它重塑了预算。在级联流水线中,延迟由串行阶段主导,你通过并行化来优化。在原生语音模型中,主要成本是模型自身产生首个音频的时间,以及仍然必须决定何时提交话轮的 VAD/话轮检测层。端到端的时间数值变小了,但对话的人性面没有改变——200ms 仍然是目标,300ms 仍然感觉慢,1500ms 仍然会让用户流失。
原生语音模型真正改变的是失败面。韵律保留变得更好,因为模型没有经过文本瓶颈。打断处理变得更难,因为模型的音频输出与其内部状态交织得更深——你无法像以前那样干净地截断 TTS 缓冲区。工具调用变得更尴尬,因为模型在工具结果返回前就在产生音频。那些转向原生语音模型却不重新设计其抢占和工具编排层的团队,最终会得到一个速度更快、但在不同方面表现失败的产品。
发布前需要记录下来的内容
这项工作的规范版本并不神秘。它是一份命名如下内容的单页文档:
- 四部分延迟预算,包括每个阶段的目标数值和端到端上限。
- 全双工音频路由图,带有明确的声学回声消除(AEC)和打断(barge-in)处理。
- 针对 TTS、模型输出 以及智能体可调用的每个工具的打断契约。
- 话轮检测策略:以 VAD 为基准,包含语义和韵律覆盖,以及团队优化的误切率与冷场率指标。
- 原生 vs 级联的决策,以及为该产品选择该流水线的具体理由。
如果没有这份文档,团队交付的只是一个连接在音频 API 上的聊天机器人,并会对用户将产品描述为“奇怪”而不是抱怨具体功能感到惊讶。有了它,工作就有了雏形:瓶颈是可识别的,权衡是可协商的,最终用户的抱怨可以映射到你可以调整的编号预算项上。
需要落地的架构认知很小但至关重要。语音 AI 不是捆绑了麦克风的文本 AI。它是一个实时系统,其延迟预算由人类对话的节奏决定,而不是由你推理平台的 SLA 决定。内化了这一点的团队构建的智能体感觉像是在对话。没能内化的团队交付的是一个带有无礼停顿的聪明脚本,并从支持队列中学习这种差距。
- https://livekit.com/blog/turn-detection-voice-agents-vad-endpointing-model-based-detection
- https://www.assemblyai.com/blog/turn-detection-endpointing-voice-agent
- https://blog.speechmatics.com/semantic-turn-detection
- https://pmc.ncbi.nlm.nih.gov/articles/PMC10077995/
- https://www.pnas.org/doi/10.1073/pnas.0903616106
- https://openai.com/index/introducing-gpt-realtime/
- https://cresta.com/blog/engineering-for-real-time-voice-agent-latency
- https://www.twilio.com/en-us/blog/developers/tutorials/product/token-streaming-interruption-handling-twilio-voice-openai
- https://docs.livekit.io/agents/build/turns/
- https://www.arunbaby.com/speech-tech/0066-tau-voice-benchmark-full-duplex-voice-agents/
