语音Agent的“打断”不是体验优化,是正确性要求:把barge-in做对的五层设计
用户说“等等,我不是这个意思”时,你的语音Agent还在念完上一段。打断处理不好,不只是显得笨,而是会把用户没说出口的否定吞掉。本文拆解插入检测、VAD阈值、状态回滚与上下文修复的完整链路。
做语音Agent的团队常把打断当成“体验加分项”,排期排在音色优化后面。这是个代价很高的误判。
用户打断你的那一刻,往往携带着最重要的信息——他在纠错、在否定、在补充前提。系统如果把这句打断当成噪声吞掉,后面三轮对话都建立在错误假设上。这不是不礼貌的问题,是把用户的关键输入丢了。
打断为什么难
三段式链路(ASR → LLM → TTS)天然不适合打断:模型在生成时看不见新输入,TTS在朗读时听不见用户。真正的难点不是检测到声音,而是在0.2秒内做出一致的状态决策:
- 已经播出的内容,用户是否已完整听到?
- 已生成但未播出的token,还要不要?
- LLM那边的生成要不要中止?中止后上下文里那句话算不算说过?
任何一个环节答错,都会出现经典问题:用户听到半句,但系统认为话已说完,于是回答“好的,我这就为您办理”——后面全乱。
五层设计
第一层:自己的声音要先排除
没有回声消除(AEC),麦克风会把Agent自己的语音识别成用户说话,导致系统疯狂自打断。这是最高频的线上事故,而且在安静的测试环境里永远复现不出来。
解决方式:打开AEC,再叠加一轮播放侧回声指纹过滤——把当前播放的音频片段做特征比对,相似度过高直接丢弃。
第二层:VAD阈值要“分时段”
10ms的咳嗽、键盘声、背景人声,都会触发标准VAD。把阈值做成动态的:
- Agent播报中:阈值调高,只接受持续200ms以上的语音段。宁可漏掉一次轻打断,也不要频繁自打断。
- Agent静默中:阈值调低,用户轻说一句也要立刻响应。
同一个模型,两套阈值,一次配置能砍掉大半误触发。
第三层:区分“打断”和“附和”
用户说“嗯”“对”“好的”“嗯嗯”,这是反馈信号,不是打断。系统应该借此暂停0.5秒确认,或者说一句更短的总结,而不是立刻中止任务。
粗暴做法:中止检测前先过一层意图分类,三分类即可——backchannel(附和)/ correction(纠错)/ new_topic(换话题)。对应三种动作:不中止、回滚重来、清空转新流程。
第四层:状态回滚必须是原子的
播报被打断时,要把状态回滚到“用户实际听到的那一句”。这需要在TTS输出侧维护一个句子级游标,记录每个句子的播放完成时刻。回滚时:
- 停止TTS流;
- 将上下文里该轮回复截断到最后完成的句子;
- 把用户新输入追加为下一轮;
- 若该句已被用户完整听到且内容是承诺性语句,必须保留(不能假装没承诺过)。
第四条最容易被忽略:用户听到“我们会在24小时内退款”,你却因为打断把这句话从上下文里删了,后面可能会给出自相矛盾的答复。
第五层:打断后的第一句话要短
这是最便宜也最有效的优化。回滚完成后,Agent的第一反应不要是完整重述,而是一句不超过10个字的确认:“明白了,您是说周三,对吧?”
短句带来三个好处:确认快、认知负担小、用户有机会再纠正。长回答在被打断后的语境里,本身就是二次冒犯。
一个可量化的验收标准
上线前用这三个指标卡:
| 指标 | 合格线 |
|---|---|
| 自打断率(Agent打断自己) | < 1% |
| 有效打断响应时延(声音结束→播报停止) | < 300ms |
| 打断后上下文一致率(用户未重复提问) | > 90% |
第三个指标最有说服力。如果用户在你打断后还得再解释一遍,说明第四层和第五层没做对。
打断做得好,用户不会夸你;做得差,用户也说不出哪里不对,只是不再用了。