主题
4.6 服务端链路设计(进阶阅读)
这一节讲服务端处理逻辑,让外部研发能理解服务端行为:为什么发
CLIENT_INTERRUPT能打断、roundId怎么用来排查。
链路总览
语音对话链路由三个模块协同:
- ASR:接收上行音频,流式识别成文本
- Flow:接收识别结果,调用 LLM 生成回复文本(AGENT 事件)、触发指令(CALL_SKILL_EVENT)、管理多轮记忆(基于 uid)
- TTS:接收回复文本,分句合成音频,切包流式下发(TTS 事件),完成后下发 TTS_COMPLETE
roundId:端到端排查的主键
每一轮对话有一个 roundId。它是端到端排查的主键:
- 设备端上行音频 → 服务端生成 roundId → 下行事件都带这个 roundId
- 日志中按 roundId 串联 ASR / Flow / TTS 三个模块的日志
- 排查问题时,提供
roundId 和 发生时间给技术支持,可快速定位是哪轮对话出错
roundId 格式形如
c7ec5b003466434b894798ffe2df018d_235807_10(requestId + 时间戳 + 轮次序号),完整规则见 4.3 重要参数介绍。
roundId 串联单轮链路
单轮对话里,roundId 贯穿 ASR→Flow→TTS 全程,用同一 roundId 可定位每个阶段的事件:
ASR 交互
事件清单
| 事件 | 方向 | 作用 |
|---|---|---|
| ASR 流式识别结果 | 下行 | contentType: ASR,textType: IS_FINAL 为最终结果 |
| EMPTY_CONTENT | 下行 | 未识别到有效音频,不开启对话 |
拒识四层防护
ASR 有四层防护机制,避免无效音频触发对话:
- VAD 判定:静音段不送识别
- 能量判定:能量过低判定为噪声
- 语义判定:识别结果无有效语义(如纯语气词)
- 拒识策略:命中拒识规则的内容不下发对话
端侧表现:发音频后收到
EMPTY_CONTENT,代表云端 ASR 未识别到有效音频。详见 9.2 设备不说话。
打断判定
自由对话模式下,云端检测到有效用户语音后,下发 CALL_AGENT_INTERRUPTED 事件,要求端侧打断当前 TTS 播放。
Flow 与 TTS
Flow(智能体编排)
- 接收 ASR 识别结果
- 调用 LLM 生成回复文本(AGENT 事件,流式下发)
- 触发指令事件(CALL_SKILL_EVENT,如音量/电量/IOT 控制)
- 管理多轮记忆(基于 uid)
TTS(语音合成)
- 接收 Flow 生成的回复文本
- 分句合成音频
- 循环拉流,切包下发(TTS 事件,流式)
- 支持快首包(降低首字延迟)
- 完成后下发
TTS_COMPLETE
TTS 打断原理
端侧发 CLIENT_INTERRUPT → 服务端 dispose(释放) 当前 Flow 与 TTS 任务:
端侧发 CLIENT_INTERRUPT 能打断,是因为服务端不是忽略,而是主动释放当前任务。
排查思路:用 roundId 串联
遇到「答非所问」「不说话」「延迟高」等问题时:
- 抓取出问题那一轮的
roundId(从下行事件里找) - 提供给技术支持,或在服务端日志中按 roundId 检索
- 定位是 ASR 识别错、Flow 生成错、还是 TTS 合成错
服务端日志查询见 12.3 roundId 链路定位。排查粒度:
roundId≻requestId≻botId。