架构与端到端合同
为什么需要
“输入语音、输出语音”描述不了系统怎样调试、替换组件或证明工具调用正确。实时 Agent 至少有两条路线:显式级联 ASR → LLM/runtime → TTS,以及直接或联合的 speech-to-speech(S2S)。它们都能做流式、半双工或全双工;全双工是交互能力,不是某一种模型架构的同义词。
怎样实现
| 维度 | 级联 ASR→LLM→TTS | Speech-to-speech |
|---|---|---|
| 中间表示 | transcript、tool call、合成文本显式 | 可能以连续音频/音频 token 为主 |
| 可替换性 | 可分别替换和回归 ASR、推理、TTS | 组件耦合较高,需端到端适配 |
| 语气与非语言信息 | 必须显式保留 prosody/时间信息 | 有机会直接利用,但不能假设一定正确 |
| 延迟 | 多跳延迟相加,可逐段优化 | 可减少显式跳数,实际延迟仍需实测 |
| 审计 | 文本和边界较清晰 | 需额外生成可审计 transcript/event |
| 故障定位 | 可按段隔离 | 更依赖端到端 trace 与消融基线 |
无论选择哪条路线,应用 runtime 都应拥有以下合同:
{ // 一条可关联、可排序的实时会话事件最小信封
"session_id": "s-1", // 事件属于哪条会话;不能与 bearer/用户身份凭据混用
"event_id": "e-18", // 事件去重与审计用的稳定 ID
"turn_id": "t-3", // 关联用户当前轮次,方便打断或取消整轮输出
"response_id": "r-3", // 关联本次 assistant 生成响应,可能包含多种模态事件
"type": "response.audio", // 明确载荷类别,consumer 据此选择音频处理分支
"sequence": 4, // 同一 stream 内的单调序号,重放/乱序处理不能只靠到达时间
"at_ms": 8120 // 会话相对时间戳,用于延迟和 VAD/打断诊断
}JSONC 教学表示
//为行尾讲解;传输严格 JSON event 时请先删除注释。
模型可以决定内容,但不能独占权限、工具副作用、审批、event log 或终态。直接 S2S 也必须把工具参数变成可校验结构,而不是从正在播放的音频猜测。
架构 ADR 至少记录:目标任务、交互模式、隐私/部署约束、失败预算、可解释性、降级路径、基线、端到端评测和重新核验日期。不要先选模型再反推需求。
常见失败
- 用单个“voice latency”隐藏 VAD、推理、工具、首包和播放缓冲。
- 级联中把会被修订的 partial transcript 当作最终用户意图。
- S2S 中没有独立 event log,无法解释哪段音频触发了哪次写操作。
- 认为切换到“原生实时模型”自动解决 echo、网络抖动、授权和恢复。
- 没有文本/按钮降级;麦克风权限失败后整个任务不可用。
怎样验证
对同一任务集同时运行:确定性文本基线、级联基线和候选 S2S。按相同初始状态、工具沙箱和终态 grader 比较任务成功、打断、延迟、成本与安全;对 ASR、turn detection、工具和 TTS 分别做消融。只有端到端更好且风险可控,才值得增加架构复杂度。
实践任务
为“电话改签”或“浏览器内语音检索”写一页 ADR:列出输入/输出、必须保留的证据、三种降级、级联与 S2S 各一个主要失败,并定义可推翻当前选择的评测结果。
依据与下一步
实时轮次和打断需要独立评测,可参考 Full-Duplex-Bench。产品实现只作候选证据;例如 OpenAI Realtime 概览 当日同时给出 speech-to-speech、transcription 和不同连接方法,具体能力必须按目标版本复核。下一步:会话、事件与传输边界。