打断不是听到声音就闭嘴:语音 Agent 的话权状态怎样真正收敛
打断不是听到声音就闭嘴语音 Agent 的话权状态怎样真正收敛元信息文章类型语音交互状态机与事件协议目标读者实时语音 Agent、智能硬件、客服语音和多模态系统的工程师与技术负责人读者问题怎样区分打断、附和、旁人语音、环境声和停顿并让取消、播放与历史最终一致核心结论打断不是一次 VAD 命中而是一条从候选检测到物理停止、再到历史修复的状态收敛链。可带走产物六阶段状态机、播放确认字段、四类重叠输入测试表。备用标题用户说“等等”之后语音 Agent 到底要停掉哪几层VAD 检测到声音为什么还不能直接判定用户打断模型已经取消扬声器为什么还在说一次打断的完整闭环开头最危险的不是慢半秒而是停错语音 Agent 正在解释一个步骤用户轻声说了句“嗯”。系统立刻停止播放把“嗯”当成一个新问题随后又问“你想了解什么”另一次用户明确说“等等不是杭州是青岛”。模型端很快返回取消成功但播放器缓冲里还有一秒多语音旧答案继续说完下一轮上下文里还保留了用户没有听见的后半段。系统表面上支持打断实际同时犯了三类错误错误让出话权、停止不彻底、历史不一致。这类问题无法靠把 VAD 阈值再调灵敏一点解决。因为 VAD 回答的是“这里像不像有人声”而产品真正要回答的是这段声音是否面向系统、是否意图接管话权、当前输出是否应撤销、已经播出的内容保留到哪里。一句话结论是自然打断需要两次判断和两次确认。先把重叠声音判成一个交互动作再让模型、TTS、网络队列、播放器和会话历史收敛到同一事实。一、静音边界只是候选事件不是对话句号OpenAI Realtime API 的 VAD 文档把公开能力分得很清楚server_vad主要依据静音切分音频semantic_vad则结合用户说出的词判断话语是否完成。系统会收到input_audio_buffer.speech_started和input_audio_buffer.speech_stopped等事件也可以配置threshold、prefix_padding_ms、silence_duration_ms、create_response与interrupt_response。这些配置很有用但它们仍然不是完整话权策略。较短的silence_duration_ms能更快产生结束边界却更容易把思考停顿当成说完较高的激活阈值可能更抗噪也可能漏掉轻声纠正。semantic_vad增加了语义完成度判断却不能自动知道一句“嗯”是听者附和、不同意、催促还是准备接管。即使interrupt_response被设为自动中断应用仍需要决定怎样处理已经进入播放器的音频和已经写入会话的 assistant 内容。因此第一条工程原则是VAD_EVENT ! FLOOR_DECISIONVAD 事件应该进入话权控制器成为判定依据之一而不是直接等同YIELD_TO_USER。至少还要结合声学持续时间、AEC 残留、ASR 稳定前缀、当前会话状态、是否唤醒了设备、说话人方向或身份以及最近一次用户动作。这里没有一个适合所有场景的固定阈值。车内、客厅、耳机、客服热线和会议终端的噪声、回声与说话距离完全不同。正确做法是保留可观察字段和场景化策略而不是在文章里发明一个“300ms 最佳阈值”。二、重叠声音至少要分成四类动作Full-Duplex-Bench v1.5 把重叠处理拆成四类场景用户打断、听者附和、旁人对话和环境语音。这个分类对工程非常重要因为四类输入虽然都可能触发 VAD却要求完全不同的系统动作。1. 竞争性打断例如“等等”“不是杭州”“先别执行”。用户的目标是接管话权并修改当前目标。系统应尽快降低或停止输出同时保留一个很短的语义确认窗口避免由回声或误识别触发不可逆取消。2. 听者附和例如“嗯”“对”“我在听”。它通常表示继续而不是接管。系统可以不做任何响应也可以播放极短 backchannel但不能把附和自动提交成新的业务轮次更不能因此丢弃当前 assistant 的主回答。3. 旁人语音例如设备附近有人说“把门关一下”但并非面向 Agent。没有说话人、方向、唤醒状态或上下文证据时系统应倾向IGNORE_AMBIENT或请求澄清而不是把旁人的话变成用户指令。4. 环境语音与非语音声电视、人声播客、咳嗽、碰撞和回声都可能形成活动片段。仅凭幅度或持续时间无法稳定判断其交互意义。端侧 AEC、声源特征和服务端语义应共同降低误触发但任何一层都不应被写成绝对正确。这四类不是为了给模型贴漂亮标签而是为了定义不同副作用继续、短附和、让出话权、忽略或澄清。只有动作不同分类才有工程价值。三、打断要经过六个收敛阶段把“用户开口”直接连到“取消回答”会把一个时间序列问题压成一个布尔值。更稳妥的状态机至少包含六个阶段。阶段 1SPEAKING系统正在生成或播放主要回答。此时仍持续接收输入但新的语音活动只产生候选事件不立即改写会话主状态。阶段 2INTERRUPT_CANDIDATE端侧检测到疑似用户语音。为了降低用户感知停止时间可以先做可逆动作快速 ducking、冻结新音频入队、保留当前播放位置。这里不宜立刻删除上下文或撤销有副作用的工具。阶段 3CLASSIFYING话权控制器合并多类证据输出明确动作CONTINUE_SPEAKING BACKCHANNEL YIELD_TO_USER IGNORE_AMBIENT ASK_CLARIFICATION动作必须携带event_id、response_id、置信度、原因和所用证据。没有身份的“stoptrue”无法在重连、迟到事件或并发输出中正确归属。阶段 4YIELDING只有判定为YIELD_TO_USER后系统才进入撤销链停止继续生成、停止 TTS、丢弃尚未发送的音频块、清空客户端播放队列。每一层都应返回独立确认而不是共用一个“取消成功”。阶段 5PLAYBACK_STOPPED客户端确认扬声器已经停止产生可听输出并上报实际播放位置。到这里用户体验层的停止才算完成。模型取消成功或 WebSocket 不再收到新 chunk都不能替代这个确认。阶段 6HISTORY_REPAIRED服务端按客户端确认已播放的范围截断 assistant 内容随后把新的用户输入接到正确历史上。只有历史修复完成系统才重新进入LISTENING或开始下一次响应。这个确认是软件播放链路的代理信号不证明用户在声学环境中一定听见。六个阶段的关键不在状态名称而在每一步都有进入条件、退出确认和超时策略。超时也不能静默如果模型已取消但播放器未确认应标记STOP_UNKNOWN阻止旧输出被当成已经安静。四、取消请求不等于用户已经听不到一次实时输出常同时存在四个进度generated_until_ms模型或语音解码已经生成到哪里sent_until_ms服务端已经发送到客户端哪里buffered_until_ms客户端播放器已经缓冲到哪里played_until_ms客户端播放器确认推进到哪里是比生成/发送进度更接近用户侧的代理信号。假设回答共生成 10 秒服务端已经发送 8 秒客户端缓冲 4 秒用户在实际播放 2.3 秒时打断。若服务端只停止生成仍有 1.7 秒缓冲可能继续播放若历史保留 8 秒或 10 秒下一轮模型会误以为用户已经听过后面的前提。因此客户端需要回报与具体response_id绑定的播放确认例如{type:playback.ack,event_id:evt_demo_ack_01,response_id:resp_demo_07,received_until_ms:8040,buffered_until_ms:3980,played_until_ms:2310,device_output_delay_ms:36}这些字段是本文给出的工程设计示例不是 OpenAI 公布的内部协议。实际实现还要考虑播放器时钟、解码延迟、音频设备重采样和 ACK 频率。静音、蓝牙切换或物理扬声器故障也说明播放 ACK 不能证明人耳确实听见它只是应用通常能获得的最近代理。关键语义是历史优先依据用户侧确认的播放进度而不是依据生成端进度。五、历史修复必须和播放停止绑定同一个 response如果只截断文本而不绑定音频时间系统很难知道 2.3 秒对应哪一段语义。一个可实现的方法是让每个音频 chunk 记录response_id、chunk_seq、时间区间和semantic_span{type:response.audio.chunk,response_id:resp_demo_07,chunk_seq:18,start_pts_ms:2160,duration_ms:120,semantic_span:[42,51]}发生打断时服务端用最后确认的played_until_ms映射到可保留语义前缀。为了避免切在半个词、半个数字或否定词之前还应按稳定语义边界向前收缩并明确记录history.truncated事件。这里还要防两个竞态旧 response 的迟到音频在队列清理后再次到达新 response 已开始旧 response 的取消确认才返回。处理方法不是“谁最后到就信谁”而是所有输出、取消与 ACK 都绑定response_id和单调递增的状态版本。旧版本事件可以留在审计日志中但不能再次推动当前播放器和会话状态。六、Backchannel 应是动作不是普通消息很多系统把“嗯”“好”“对”交给普通 ASR 和对话轮次处理。结果是一次不想接管话权的附和触发了四件不该发生的事提交用户消息、结束 assistant 输出、生成新回答、把短词写进长期上下文。更合理的做法是让 backchannel 成为交互动作{type:turn.action,action:BACKCHANNEL,target_response_id:resp_demo_07,reason:listener_acknowledgement,commit_as_user_turn:false,interrupt_output:false}这个示例仍是工程设计不是公共 API 字段。它表达的边界是附和可以被观测、计数和评测但默认不改变任务目标不创建完整用户轮次也不要求主回答停止。当然短词不能只靠词表硬编码。“不对”可能是明确纠正“对”也可能是在回答系统提问。分类必须结合系统是否正在说、当前问题类型、语调和后续语音。不能确认时ASK_CLARIFICATION比错误执行更安全。七、一个能落地的事件信封话权事件至少需要以下公共字段{event_id:evt_demo_01,schema_version:1,session_id:sess_demo_42,response_id:resp_demo_07,source:client_audio,monotonic_ns:938472993822,seq:1201,type:turn.action,payload:{}}排序不能只依赖跨机器 wall clock。客户端、服务端和音频设备的时钟会漂移重连还会改变连接身份。更稳妥的是在每个来源内使用单调时钟和序号同时记录时钟偏移估计跨来源因果通过event_id、response_id和父事件关系连接。事件信封还让以下问题可诊断是谁先判定了打断取消发给了哪个 response播放 ACK 是否来自旧连接历史截断依据哪个播放位置没有这些字段现场只会留下“用户说停了但系统还说了一会儿”的主观描述。八、四类场景必须分别验收不能用十条干净的“用户说停止”音频证明打断系统可用。至少需要以下四组对抗场景场景期望动作关键失败核心指标明确纠正或取消YIELD_TO_USER漏打断、停止过慢、旧结果继续播放有效打断率、物理停止延迟、历史修复成功率听者附和BACKCHANNEL或继续错误让出话权、主回答被切断附和误中断率、回答连续性旁人语音忽略或澄清错误执行旁人指令非目标说话误接管率环境声与回声忽略误停止、循环触发环境误打断率、恢复时间还要覆盖不同播放音量、设备距离、AEC 状态、网络抖动和语言现象。中文里的“嗯”“啊”“那个”“不是”承担的功能不同不能直接照搬英文数据集阈值。指标也必须成对看。降低物理停止延迟可能提高误打断提高语义确认门槛可能减少误停却增加真正纠正的等待。Full-Duplex-Bench v1.5 报告的“快速让出并修复”与“优先保持连续”两类策略正说明不存在脱离场景的单一最优点。九、什么时候更简单的方案反而更好不是所有产品都需要复杂话权状态机。对于短命令、强确认、不可逆动作或合规播报清晰回合边界通常更容易审计。用户说完、系统复述、用户确认、再执行虽然不够像自然闲聊却可能更可靠。此时可以只保留硬停止按钮和明确取消协议而不追求附和、重叠生成和动态话权。即使需要自然打断也可以分阶段实现先让播放队列可撤销并有PLAYBACK_STOPPED确认再绑定played_until_ms修复历史最后才增加 backchannel 和旁人语音分类。把所有能力一次性堆进去会让误判来源难以定位。十、发布前评审清单在声称系统“支持打断”前至少回答以下问题VAD 事件和最终话权动作是否分开记录每次动作是否绑定正确的 session、response 和 event模型取消、TTS 取消、网络丢弃和播放器停止是否分别确认PLAYBACK_STOPPED超时后系统怎样降级是否会继续接受旧 chunk历史是否按played_until_ms而不是生成进度截断Backchannel 是否默认不提交完整用户轮次旁人语音和环境声是否有独立对抗测试指标是否同时覆盖漏打断与误打断而不是只追求最快停止如果其中任何一项仍只能回答“应该没问题”系统支持的更可能只是停止按钮而不是可靠打断。事实、推导与未知项已确认事实OpenAI Realtime API 公开server_vad与semantic_vad两种模式并提供 speech started/stopped 事件以及interrupt_response等配置。Full-Duplex-Bench v1.5 分别评测用户打断、听者附和、旁人对话和环境语音并使用停止/响应延迟等指标分析重叠处理。GPT-Live 官方描述产品能在输出期间持续处理输入并多次选择说、继续听、暂停、打断或调用工具。本文工程设计六阶段收敛状态机、统一事件信封、played_until_ms、semantic_span、Backchannel 动作和历史修复协议。模型、TTS、网络和播放器分层确认以及旧 response 迟到事件的版本隔离。未知项GPT-Live 内部怎样识别 backchannel、旁人语音与有效打断。OpenAI 产品内部是否使用播放 ACK、何种时间轴或历史截断协议。任一固定阈值在具体设备、语言与声学环境中的最优性。参考资料OpenAI Developers, Voice activity detection (VAD)访问于 2026-08-08。OpenAI, Introducing GPT-Live2026-07-08。Lin et al., Full-Duplex-Bench v1.5: Evaluating Overlap Handling for Full-Duplex Speech Models2025。Full-Duplex-Bench, official code repository访问于 2026-08-08。