跳到主要内容

语音智能体并非带麦克风的聊天机器人:半双工税

· 阅读需 12 分钟
Tian Pan
Software Engineer

一个在所有转写层级基准测试(benchmark)中得分完美的语音智能体,在实际通话中可能仍然让人感觉有些微妙的不对劲。文字没错,推理也没错。仪表盘上的端到端延迟显示为 520ms,这正是预期的目标。然而,电话另一端的人却不断卡顿、抢话、重说,甚至提前挂断。团队发布了更好的模型,数据提升了,但体感依然没有改善。

究其原因,与模型说了什么几乎无关,而与它何时说话几乎全盘相关。语音并非仅仅是附带了音频的文本。人类的对话运行在一个严密的半双工(half-duplex)协议之上,包含插话(barge-in)、反馈信号(backchannel)和重叠语音,其时间预算是以毫秒计算的。大多数语音智能体的问题,在解决了第一周的幻觉修复后,本质上都是轮次协商(turn-negotiation)问题。而轮次协商是架构层面的问题——你无法通过提示词工程(prompting)来解决它。

延迟预算并非仪表盘上显示的那样

当团队将聊天产品迁移到语音时,第一直觉通常是沿用之前的延迟 SLO。 “我们承诺过 p95 延迟低于 1 秒,语音产品也要做到这一点。”这其实已经太慢了,而且这种“慢”是仪表盘无法察觉的。

对话中真正关键的数字不是从请求到响应的端到端延迟,而是用户停止说话到智能体开始说话之间的感知间隔。对话分析师测量了各种语言的平均轮次间隙(inter-turn gap),通常集中在 200 毫秒左右——在某些文化中更短,有些则更长,但绝不会接近一整秒。一旦超过 300ms,用户就会开始下意识地察觉到停顿。超过 800ms,他们就会以为电话断线了。

延迟预算的残酷之处在于:200ms 的目标并不是指“将音频发送到服务器”到“扬声器开始播放音频”的时间。它是指“用户的最后一个音素进入麦克风”到“智能体响应的第一个音素进入听筒”的时间。在这段时间内,你必须支付以下成本:语音活动检测(VAD)、话语结束判定、音频传输、语音转文本(STT)完成、LLM 首字延迟、文本转语音(TTS)首块延迟以及输出音频传输。每个组件都要瓜分这有限的时间。如果你的 STT 在确定结束前需要等待 400ms 的静默,那么在调用 LLM 之前,你其实就已经输了。

另一种失败模式则违反直觉:太快也是错的。现代端到端语音模型可以在 150ms 内做出响应,这在基准测试中听起来很棒,但在通话中却感觉像机器人。人类对话有一种认知形态——在给出深思熟虑的回答前会有合理的停顿——而打破这种形态会使智能体陷入“恐怖谷”,显得极不自然。目标不是“越快越好”,而是“与低延迟电话连接中专注的人类真无异”。

轮次检测是模型问题,而非静默问题

语音智能体的默认架构使用语音活动检测(VAD)来判定用户何时停止说话。VAD 观察音频信号并判断“有声音”或“无声音”。当“无声音”持续时间超过预设阈值(通常为 500 到 800 毫秒)时,系统会判定轮次结束并触发响应。

这种方式在基准测试中表现出色,因为测试中的用户会说完整且连贯的句子。但在实际通话中,它会因为三个原因而失败。

第一,人们在思考时会停顿。当他们在组织词汇而停顿 600 毫秒时,仅靠 VAD 的系统已经切断了输入,并将截断的话语发送给了 LLM。LLM 对这段残缺的句子做出了自信的回答。当智能体开始说话时,用户正处于话说到一半的状态,于是双方陷入了抢话(overlap)的尴尬境地。

第二,人们会发出反馈信号(backchannel)。“嗯哼”、“对”、“好”——这些并不是为了抢话,而是表示正在关注的信号。简单的 VAD 会将它们视为用户开启了新轮次,从而中断智能体正在进行的发言。智能体在话说到一半时停下,用户意识到自己被误解了,对话随即崩溃。

第三,环境噪音——咳嗽声、关门声、路过的警笛声——在 VAD 看来与人声无异。在嘈杂的电话线路上,仅靠 VAD 的轮次检测会导致智能体频繁分心。

解决方案是语义化的轮次结束检测(semantic end-of-turn detection)。这种方法不再仅仅测量静默时间,而是利用一个基于 Transformer 的小型分类器来分析部分转写文本,并预测该句子在语法和语义上是否完整。生产系统现在使用参数量在 8M 到 135M 之间的紧凑型模型,在每次转写更新时运行,输出用户是否真正说完的概率。当概率较低时,系统会延长静默超时时间;当概率较高时,它可以在早于静默阈值的时间点完成判定。

这种架构上的细微差别在离线评估中是体现不出来的。你无法用 BLEU、WER 或任务成功率来衡量它。你需要通过误中断率、错误过早完成率和用户重说率来衡量。那些将轮次检测视为核心模型组件,而非仅仅是可调静默阈值的团队,才能让他们的智能体听起来像是在认真倾听。

插话功能(Barge-in)并非可选功能

一个无法被打断的语音智能体(voice agent)感觉就像是一个有性格的 IVR 菜单。一旦用户意识到自己陷入了单向的独白中,他们就会开始狂按 0、大喊“人工客服”或直接挂断电话。

实现插话功能需要深入架构底层。这不仅仅是一个可以随意切换的开关。当智能体正在讲话而用户开始说话时,系统必须在 100 毫秒内判定这是真正的打断,还是仅仅是简单的反馈信号(backchannel)。如果是真正的打断,系统必须立即停止 TTS 播放,取消正在进行的 LLM 生成,丢弃未完成的响应,重新转录用户的新输入,并生成一个既能回应打断又不会重复已被切断内容的回答。

这会引发一系列团队在发布后才会发现的连锁反应。

针对吞吐量优化的 TTS 系统通常会在播放前缓冲整段音频,以保证交付流畅。如果你想要灵敏的插话响应,缓冲区就成了你的敌人——用户打断了,但由于音频已经发出,智能体会继续说话 800 毫秒。你必须针对短数据块、低延迟流式传输和激进的取消机制进行设计,而这与技术栈中的每一项吞吐量优化都背道而驰。

LLM 的部分输出承诺(partial-output commitment)会变成正确性问题。如果智能体已经读出了回答的第一句话,而用户此时打断了它,那么模型尚未生成完的第二句话就应该被丢弃。但如果智能体已经根据完整的响应计划承诺执行某个工具调用(tool call),除非你的编排层明确将工具执行与用户实际听到的输出绑定,否则该调用可能仍会触发。不止一起生产事故源于智能体在语音中确认“我将取消你的预订”,但在完成确认前被打断,结果预订还是被取消了,因为 LLM 的响应已经完成了解析。

回声消除也成为了正确性问题。如果智能体自己的声音泄露到电话的麦克风输入中,原始的 VAD 会将其视为用户语音,导致智能体开始自我打断。具备良好回声抑制的双工处理(Duplex processing)是“语音智能体”与“虚有其表的语音工具”之间的本质区别。

200 毫秒预算的分配

拆解一次真实通话中的时间去向很有帮助。以下是详细分解,我们将预算视为必须守住的底线,而不是可以体面错过的目标。

  • 话语结束判定(End-of-utterance decision):50–150 毫秒。 语义话轮检测模型运行在每个 ASR 中间结果上。当其置信度超过阈值时,它会跳过 VAD 静音计时器。有了这一机制,你通常可以在用户最后一个音素结束后的 100 毫秒内定稿,而不是等待完整的 VAD 阈值。
  • 音频传输(Audio transport):30–80 毫秒。 网络往返加缓冲。在蜂窝网络上,这可能会剧烈波动。低码率 WebRTC 加 Opus 编码是现实中的底线。
  • ASR 定稿(ASR finalization):50–150 毫秒。 流式 ASR 在整个话轮中交付中间假设。定稿是最后的重新评分过程。将所有工作推迟到最后一步的模型会耗尽这部分预算。
  • LLM 首字延迟(LLM first-token latency):200–500 毫秒。 这通常是预算超支的地方。推理模型在此处尤为不友好——它们的首个 Token 可能需要数秒才能生成,而“思考”过程是不可见的。需要推理能力的语音智能体应该在话轮结束之前针对缓存的上下文进行推理,或者在关键路径上使用更轻量、更快速的模型,而将推理层放在后台。
  • TTS 首块延迟(TTS first-chunk latency):100–300 毫秒。 在第一个文本 Token 出现时就开始合成的流式 TTS,其首音获取时间(time-to-first-audio)远低于缓冲式 TTS。语音克隆和表现力强的 TTS 通常在此处成本更高。
  • 输出传输(Output transport):30–80 毫秒。 与输入相同。

算下来,在乐观情况下你已经超过了 600 毫秒。进入 300 毫秒这个心理关键区间的唯一方法是高度重叠这些阶段——在 LLM 输出第一个 Token 时就开始 TTS,在静音达到阈值前预测话轮结束,并利用激进的上下文缓存或投机性解码来压缩 LLM 延迟。

那些试图用通用组件搭建级联流水线来实现这一预算的团队注定会失败。向集成的语音原生技术栈(voice-native stacks)转型并非炒作——无论是支撑实时 API 的端到端语音模型,还是经过严密工程设计的混合系统。这是找回足够的毫秒数以使声音听起来自然的唯一途径。

这对你的路线图意味着什么

对工程团队来说,实际的影响是语音产品不能仅仅是“更换了传输层的聊天产品”。它需要不同的技能集、不同的评估方法论和不同的故障处理文化。

评估(Evals)必须包含时间维度。仅看转录文本层面的任务成功率是不够的——你需要衡量误插话率(false-interrupt rate)、智能体被打断耐受率(当用户想要打断时,插话功能是否奏效?)、话语结束后的首音获取时间以及话轮重叠率。这些是关于对话形态(conversation-shape)的指标,而非内容指标,大多数 LLM 评估框架默认不会输出这些数据。你必须对语音栈本身进行埋点监控。

事故分类必须考虑新的故障模式。“智能体说错了话”是最简单的案例。更难处理的工单是“智能体一直打断我”、“智能体回应慢了整整一秒”、“智能体帮我把话说完了”。这些是时间步(timing)上的 Bug,而不是提示词(prompt)Bug,诊断它们需要带有音素级精确时间戳的音频轨迹追踪。

招聘也必须随之转变。擅长提示词工程和工具设计的人,未必能调试蜂窝网络音频下的 VAD 误报率。成功的语音团队中,一定有人曾在职业生涯中深受 WebRTC 之苦,且有人在问题变成 P0 级别之前就开始思考回声消除。

模型是容易的部分,对话协议才是难点。感觉自然的语音智能体,其背后的团队将话轮协商(turn negotiation)视为一等公民级别的工程问题,并花费数月时间来抢回那些毫秒。而那些让人感觉怪异的智能体,只是将聊天产品塞进了电话拨号中,寄希望于模型能弥补时间上的瑕疵。

References:Let's stay in touch and Follow me for more thoughts and updates