端到端评测与离线项目
为什么需要
ASR 的 WER、TTS 的自然度和模型的文本正确率都不能单独证明实时 Agent 可用。系统可能听对、答对,却在用户打断后继续播放旧答案,或把工具执行两次。评测单元应是有初始环境、事件轨迹、副作用和最终结果的 trial。
怎样实现
评测对象与指标
每个 task 固定初始状态、用户脚本/媒体、允许工具、风险和 grader;每个 trial 保存媒体/网络条件、event trace、工具 receipt、最终状态、成本和延迟。随机组件至少多次运行,并报告分布与失败切片。
| 层 | 指标示例 | 不能替代 |
|---|---|---|
| 感知 | ASR WER/CER、音频丢帧、视觉定位 | 用户意图/任务正确性 |
| 轮次 | turn-take、误打断、漏打断、停止旧播放延迟 | 回答事实正确性 |
| 工具 | schema、关联、参数、成功、副作用次数 | 用户是否满意 |
| 结果 | 外部最终状态、约束、安全、人工接管 | 轨迹诊断 |
| 系统 | p50/p95/p99 延迟、超时、恢复、成本 | 质量与风险 |
基础 suite 至少包含:安静/噪声/echo、口音/语言、短停顿、重叠、backchannel、自我修正、工具长尾、断线、迟到事件、重复事件、权限拒绝和恶意音频。发布门禁应同时覆盖任务成功、安全关键失败、副作用重复、p95/p99 延迟和恢复率。
Full-Duplex-Bench提供 pause、backchannel、turn-taking 和 interruption 的公开研究框架。Full-Duplex-Bench v3进一步把自然非流利语音与多步工具调用纳入评测,但截至 2026-07-18 仍属新近预印本;适合观察和补充测试,不应直接作为生产结论或模型排行榜。
离线项目
`realtime_session.py` 是纯标准库事件/会话模拟器。其 fixture parser 拒绝重复 JSON key、NaN/Infinity 等非标准常量,事件与嵌套工具参数也只接受有限、JSON 兼容的值;它实施以下不变量:
- 音频帧从序号 0 连续,只有含 speech 的 turn 才能 commit;
- 同一事件 ID/同一内容幂等忽略,同 ID/不同内容拒绝;
- barge-in 取消旧 response 并清空播放队列;
- tool result 必须匹配既有
call_id + response_id;它只验证离线关联,实际授权、幂等 receipt 和业务对账由生产执行账本负责; WaitingTool会暂停当前 response 的输入/输出,直到所有已声明工具都有结果或用户打断;- 断线保存 checkpoint,只有正确 resume token 能恢复;若旧写调用待核对,恢复后只能先接收其 result/receipt,不能接收新工作;
- timeout/completed 是终态,终态后只允许精确重复事件被忽略;
- 不认识的事件、字段、错误类型、逆序时间和未决工具都被拒绝。
运行:
Set-Location ".\docs\实时多模态交互" # 进入课程项目目录,使 fixture 和示例相对路径稳定
$env:PYTHONDONTWRITEBYTECODE = "1" # 禁止生成本机 Python 缓存文件
python -B .\examples\realtime_session.py .\examples\session_fixture.json --pretty # 运行离线会话 fixture,并格式化输出事件/状态摘要
python -B -W error .\examples\test_realtime_session.py # 普通优化级别下将警告作为失败运行测试
python -B -O -W error .\examples\test_realtime_session.py # 组合优化/严格警告模式验证安全逻辑不依赖 bare assert预期:普通与 -O 模式均为 33 tests / OK,无网络、无第三方依赖、无凭据、无文件输出。夹具展示一次“旧回答被打断→新 turn 调工具→断线恢复→正常终态”的事件序列;回归集还验证重复 JSON key/非标准数值、工具等待门以及恢复后必须先核对旧写调用,才可接收新工作。
模拟器没有证明什么
它没有采集/播放真实音频,也没有验证 codec、echo cancellation、NAT、jitter buffer、电话网关、模型质量、云服务 session 行为、生产授权或真实工具 receipt。它证明的是应用事件合同在确定性边界下保持一致。真实上线还必须运行设备、网络、媒体、执行账本和供应商集成测试。
常见失败
- 测试只看最终 transcript,不看旧音频是否泄漏或工具是否重复。
- 单次 demo 代替多 trial 分布,平均值掩盖尾部故障。
- benchmark 音频与真实设备/语言差异大,却直接宣称生产质量。
- grader 只读模型回答,不查询外部最终状态。
- 只测试 happy path,没有断线、迟到、重复、unknown 与人工接管。
怎样验证
先运行离线合同测试;再把同一 event schema 接到真实媒体适配层,保留确定性 replay。对每次失败定位到感知、turn、模型、工具、播放、传输或状态恢复,而不是笼统归因为“模型不好”。上线前把关键 suite 放入发布门禁,线上采样只记录最小必要数据并能关联相同 grader。
实践任务
- 在夹具中增加第二个 audio frame,并保持连续序号;确认测试仍通过。
- 增加一个“工具 pending 时断线,恢复后收到 receipt”的测试,说明为何不能自动重放写请求。
- 为真实目标场景设计 20 个 task,至少覆盖 4 种网络、4 种轮次和 3 种安全失败。
- 写清从离线模拟器迁移到 WebRTC/电话环境时新增的未知项和验收门禁。
完成检查
- 能解释每个 ID、事件、状态与终态。
- 普通/-O、warnings-as-errors 测试均通过。
- 评测包含初始/最终环境、副作用、trace、成本和延迟。
- 有文本/按钮降级与人工接管路径。
- 动态产品事实已按接入当天官方文档复核。