cockpit_realtime_tutorial

Chapter 14|测试计划与验收标准(Test & Acceptance)

1. 开篇段落

在智能座舱领域,将基于 LLM 的实时语音助手(Realtime AI)引入量产车,面临着前所未有的质量挑战。传统的 IVI(车载信息娱乐系统)测试依赖于确定性的输入输出(点击按钮 A -> 界面跳转 B),而本系统面临的是概率性的自然语言理解不可预测的生成式输出复杂的声学环境以及严苛的行车安全标准的叠加。

本章旨在构建一套从原子级单元测试到整车路测的全链路质量保障体系(Quality Assurance, QA)。我们将重点关注 Realtime API 的时延稳定性、Agents SDK 的多轮对话逻辑闭环、RAG 的知识准确性边界,以及最重要的——在任何极端情况下,系统都不会危及驾驶安全。我们的目标是建立一道坚固的“防波堤”,确保 SOP(Start of Production)时交付的是一个既聪明又守规矩的副驾驶。

2. 测试体系架构:从代码到沥青路

我们将测试体系划分为四个层级(L1-L4),每个层级有不同的关注点、工具链和通过标准。

2.1 L1: 单元测试与离线评估 (Unit Test & Offline Eval)

2.2 L2: 服务端端到端集成 (Service E2E Integration)

2.3 L3: 硬件在环与台架测试 (HIL - Hardware in the Loop)

2.4 L4: 实车路测 (Field / Road Test)


3. 专项测试策略详解

3.1 Realtime 交互体验测试

实时语音对话的核心在于“流式”和“可打断”。

3.2 车控安全“红线”测试 (Safety Guardrails)

这是车厂最关注的部分,必须进行破坏性测试。

3.3 GUI Agent 自动化测试

App 自动化面临 UI 变动和非标弹窗的挑战。

3.4 RAG 知识准确性与拒识


4. 验收标准 (Acceptance Criteria)

4.1 性能指标 (Performance KPIs)

| 指标维度 | 关键指标 (Metric) | 达标阈值 (SOP Criteria) | 测试条件 | | :— | :— | :— | :— | | 实时性 | Audio-to-Audio Latency | P90 < 1.2s | 4G 正常信号,简单问答 | | | 首字生成延迟 (TTFT) | P90 < 600ms | 纯文本/JSON 输出 | | | 打断响应时间 (Barge-in) | < 350ms | 包含 VAD 切断与播放器停止 | | 资源 | 端侧 CPU 占用 | < 15% (单核) | 持续对话状态 | | | 流量消耗 | < 50MB/小时 | 连续语音通话模式 | | 稳定性 | Session 建立成功率 | > 99.5% | 首次连接与断网重连 | | | Crash Free Rate | > 99.9% | 客户端 SDK 崩溃率 |

4.2 质量指标 (Quality KPIs)

| 指标维度 | 关键指标 (Metric) | 达标阈值 | 说明 | | :— | :— | :— | :— | | 意图 | 车控意图识别率 | > 97% | 包含模糊指令 | | 执行 | 工具调用成功率 | > 99% | 排除硬件故障因素 | | 知识 | RAG 事实准确率 | > 95% | 基于 Golden Set | | 安全 | 高危指令拦截率 | 100% | 绝对红线,不可妥协 | | | 幻觉率 | < 3% | 主要是非车控类闲聊 |


5. 本章小结

本章构建了一个金字塔式的测试框架:

  1. 底座是安全:通过白名单、状态机和对抗测试,确保 AI 绝不越权。
  2. 核心是体验:通过 Realtime 专项测试,确保“快”和“流畅”。
  3. 保障是全链路:从 Unit 测试的逻辑校验,到 HIL 的声学校验,再到 Road Test 的真实场景校验。

我们必须认识到,车载 AI 的验收不是一个“点”,而是一个“面”。任何一个环节(如 VAD 误切、RAG 检索过慢、GUI 识别错误)的短板,都会导致用户对整个系统的信任崩塌。


6. 练习题

基础题

练习 1:延迟分段分析 场景:用户反馈“我说话它反应很慢”。通过埋点数据,我们得到了以下时间戳(单位 ms):

参考答案 * **(T3-T2)** 代表 **服务端推理/思考耗时 (Inference/Prefill Latency)**。这包括了 ASR(如果是级联)、Prompt 构建、RAG 检索(如果有)、以及 LLM 生成首个 Token 的时间。 * 如果 **(T5-T4)** 很大,代表 **客户端播放缓冲耗时**。可能原因包括: 1. 网络下行抖动,导致数据包堆积。 2. 客户端播放器 Buffer 设置过大(为了防卡顿而牺牲了实时性)。 3. 车机音频通道(Audio Focus)申请被阻塞(例如导航正在播报)。

练习 2:RAG 引用测试 场景:用户问“胎压多少算正常?”,系统回答“2.3-2.5 bar”,并引用了手册第 42 页。 问题:设计一个自动化测试脚本逻辑,用来验证这个引用的正确性。

参考答案 1. **输入**:Question, Answer, Citation_ID。 2. **获取原文**:根据 Citation_ID 从向量库/文档库中提取对应的原始文本块(Chunk Text)。 3. **LLM 判题 (LLM-as-a-Judge)**:构造一个 Prompt,输入 Answer 和 Chunk Text。 * *Prompt*:“请判断 Answer 中的事实是否完全被 Chunk Text 所包含和支持?输出 Yes/No。” 4. **判定**:如果输出 Yes,通过;如果输出 No,标记为“引用错误”或“幻觉”。

挑战题

练习 3:Realtime 打断与工具竞争 场景:用户说“打开空调”,Realtime 模型触发了 VehicleControl(ac=on) 工具,此时工具正在执行(耗时 2 秒)。在第 1 秒时,用户突然说“不对,是打开车窗”。 问题:基于 OpenAI Realtime API 的 session.update 和工具回调机制,设计一套处理逻辑,确保系统不会既打开空调又打开车窗,或者造成状态错乱。

参考答案 这是典型的**竞态条件 (Race Condition)** 处理: 1. **工具状态标记**:当 `VehicleControl` 开始执行时,在 Session 状态中标记 `executing_tool_id`。 2. **打断检测**:Realtime API 检测到用户新语音(VAD Triggered),发送 `input_audio_buffer.speech_started` 事件。 3. **客户端动作**:收到打断事件,客户端立即发送 `response.cancel`,尝试取消当前的生成流。 4. **原子性/回滚**: * 如果空调指令**尚未**发给 CAN 总线:立即丢弃该指令,不执行。 * 如果指令**已经**发给 CAN 总线:无法撤回。 5. **新指令优先**:处理用户的新语音“打开车窗”。 6. **反馈修正**:在回复“打开车窗”时,如果空调已经误开,Agent 应补充说明:“刚才的空调指令已发出,正在为您打开车窗,需要我关闭空调吗?”(检测到状态变更与意图冲突)。

练习 4:GUI Agent 的可观测性设计 场景:GUI Agent 在帮用户点咖啡时失败了,用户投诉。路测工程师拿回了 Log。 问题:为了复现和调试这个问题,Log 中最少需要包含哪信息?请设计一个轻量级的 GUI Trace 数据结构。

参考答案 GUI Trace 必须能还原“看到什么”和“做了什么”。 结构建议: ```json { "trace_id": "uuid", "steps": [ { "timestamp": 1700000001, "screen_snapshot_hash": "a1b2...", // 截图的哈希,原图存对象存储 "screen_accessibility_tree": "{...}", // 此时的 UI 树精简版 "agent_thought": "检测到弹窗,准备点击关闭", // Chain-of-Thought "action": {"type": "click", "x": 500, "y": 300, "element_id": "close_btn"}, "result": "success" }, { "timestamp": 1700000005, "screen_snapshot_hash": "c3d4...", "agent_thought": "找不到下单按钮,尝试滚动", "action": {"type": "scroll", "direction": "down"}, "result": "element_not_found_error" // 故障点 } ] } ``` **关键点**:必须保存 UI 树或截图指纹,否则无法知道当时屏幕上到底有什么。

7. 常见陷阱与错误 (Gotchas)

7.1 忽略音频处理管线 (The DSP Trap)

7.2 “测试集泄露” (Data Leakage)

7.3 误判网络环境 (The Network Fallacy)

7.4 权限蔓延 (Permission Creep)