[真实链路自测]:完成完整流程自测和ACK缓冲修正,包含真实Provider验收、播放回声清理和回归测试

This commit is contained in:
mkbk
2026-06-17 23:47:21 +08:00
parent b3566c2424
commit b2822dc1af
10 changed files with 121 additions and 7 deletions
@@ -57,6 +57,7 @@
15. 降噪缺失问题:正式问题录音直接把原始麦克风帧送入 VAD、partial STT 和 final STT,背景噪声会同时影响端点、实时字幕和最终识别。
16. 本地模型落后问题:默认 STT 仍是 2023 年 14M 小模型,适合最小验收但不适合作为默认实时字幕质量基线;应升级为 sherpa-onnx 官方 2025 中文 CTC int8 模型。
17. 自测闭环问题:现有 `acceptance` 只覆盖旧单轮 pipeline,不能证明当前 `VoiceAssistantPipeline` 在“模拟麦克风 -> wake -> capture -> partial -> final -> LLM -> TTS -> standby -> 第二轮”路径上完整正常;真人测试前缺少可重复的自动调试入口。
18. ACK 缓冲实现偏差:文档要求 `OWNER_POST_PLAYBACK_DRAIN_MS=0` 时仍应清理播放期间已积压的输入队列,但当前实现 `<=0` 直接返回;真实麦克风上可能把“我在”播放回声或旧缓冲送入正式问题 VAD/STT,模拟预排帧又不能直接用真实 flush 语义清空。
## 详细需求
@@ -97,6 +98,10 @@
33. 模拟麦克风输入 SHALL 包含 wake 帧、正式问题主说话人帧、短噪声 partial、背景噪声/非主说话人帧和第二轮重复唤醒帧。
34. 模拟 transport SHALL 有边界保护:如果帧提前耗尽,命令必须结构化失败并退出,不能无限等待。
35. `simulate-live` SHALL 支持写入和回放 JSONL fixture,便于后续持续复现同一组模拟麦克风输入。
36. ACK/TTS 播放完成后的输入清理 SHALL 在 `OWNER_POST_PLAYBACK_DRAIN_MS=0` 时仍执行一次 `flush_input()`,清掉播放期间已进入真实输入队列的回声或旧帧,但不得再主动读取并丢弃新音频。
37. 当 ACK 文本为空且没有实际播放行为时,runtime SHALL NOT 执行 post-playback drain,避免无播放场景误清正式问题开头。
38. 模拟麦克风和 fixture replay 场景 SHALL 能保留预排的未来输入帧,并仍记录 flush 调用次数,用于验证真实队列清理动作不吞掉测试中尚未“发生”的后续用户语音。
39. 完整链路自测 SHALL 尽量使用真实本地 provider 和真实云端 LLM:真实 KWS、VAD、降噪、STT、LLM、TTS 和播放;无法自动使用真人麦克风时,允许用生成的 16 kHz PCM 音频帧替代物理麦克风输入。
### 非功能需求
@@ -127,6 +132,8 @@
12. partial 单字误识别:本地 streaming STT 输出 `家``确``a` 等单字时,终端不得显示为 `实时转写`
13. partial 瞬态跳变:本地 streaming STT 从“你是谁”短暂跳到“加”再回到“你是谁”时,不得显示中间极短跳变。
14. CTC 模型缺旧 transducer 文件:当 manifest 类型为 `sherpa-onnx-streaming-zipformer2-ctc` 时,不应再要求 encoder/decoder/joiner 文件存在。
15. ACK 禁用:当 `OWNER_WAKE_ACK_TEXT=` 时,系统不得因为“播放后清理”逻辑而清空唤醒后的正式问题帧。
16. 模拟预排帧:当 `MemoryAudioTransport` 用于模拟完整 turn 序列时,flush 调用不得把未来 turn 的预排帧删除,否则模拟验收会掩盖真实 pipeline 顺序。
### 输入输出规格
@@ -290,6 +297,8 @@ standby
10. 捕获阶段降噪:`AudioPreprocessStage` 将 int16 PCM 转为 float32,调用 `sherpa_onnx.OnlineSpeechDenoiser.run(samples, sample_rate)`,把返回的 `DenoisedAudio.samples` 转回 int16 PCM,并在 metadata 中加入 `denoised=True``noise_filter_provider=sherpa_onnx_gtcrn`
11. CTC STT 加载:manifest `stt.type=sherpa-onnx-streaming-zipformer2-ctc` 时,只校验 `tokens``model`,调用 `OnlineRecognizer.from_zipformer2_ctc`;旧 manifest 仍兼容 transducer 路径。
12. partial 稳定过滤:实时字幕会先去除空白和标点,计算有效字符数;有效字符数小于 2 的文本直接忽略;若新文本比上一次已显示文本短且不构成稳定前缀推进,也忽略,避免把瞬时噪声显示给用户。
13. 零时长播放后清理:`_drain_input_after_playback()` 先执行一次 `transport.flush_input()`;若 `post_playback_drain_ms <= 0` 立即返回;若配置为正数,才按用户显式配置继续 read/drop drain window 并最终再次 flush。
14. 模拟 flush 隔离:`MemoryAudioTransport` 默认保持 flush 清空语义;模拟 live pipeline 显式设置 `flush_clears_input=False`,只记录 flush 调用,不删除预排帧,避免将真实时间队列与离线 fixture 序列混淆。
### 数据库/状态管理变更
@@ -341,6 +350,7 @@ standby
| 模拟验收与真实麦克风仍有差异 | 中 | 中 | 明确模拟验收用于自动调试 live pipeline 状态机和事件顺序;仍保留 4.3 真人 `run-live` 验收,不在用户确认前归档 |
| 模拟帧耗尽导致测试卡死 | 中 | 高 | 使用 bounded simulated transport,空读超过阈值直接抛结构化错误并让命令返回非 0 |
| 模拟 provider 掩盖真实模型加载问题 | 中 | 中 | 模拟命令只验证 pipeline;模型加载仍由 `model-check` 真实加载 KWS/VAD/STT/denoiser 覆盖 |
| `0ms` drain 不执行 flush 导致播放回声污染正式问题 | 中 | 高 | `_drain_input_after_playback()` 无论 drain window 是否为 0 都先 flush 一次真实输入队列;新增回归测试验证 flush 发生且首句不丢 |
## 任务分解
@@ -414,6 +424,14 @@ standby
- [ ] 11.4 补充 README 和自动化测试;前置条件:11.3 完成;验收标准:README 包含模拟验收命令,测试验证两轮闭环、partial 噪声过滤、第二轮临时上下文、fixture 写入/回放;测试要点:unittest;优先级:P0;预计:35 分钟。
- [ ] 11.5 执行全量门禁并提交“模拟麦克风验收”模块;前置条件:11.1 至 11.4 完成;验收标准:`simulate-live --turns 2`、compileall、unittest、security-check、model-check、device-check、OpenSpec strict、git diff check 通过后中文 commit;优先级:P0;预计:45 分钟。
### 12. 真实完整链路自测与 ACK 缓冲修正
- [ ] 12.1 更新 OpenSpec 描述真实完整链路自测和 ACK 零时长 flush 偏差;前置条件:模拟验收已提交且本机模型齐全;验收标准:proposal/design/spec/tasks/spec delta 覆盖真实 provider 验收、0ms flush、模拟预排帧隔离和 ACK 禁用边缘案例;测试要点:OpenSpec strict;优先级:P0;预计:35 分钟。
- [ ] 12.2 修正 `VoiceAssistantPipeline` 和兼容 `LiveVoiceRuntime` 播放后输入清理;前置条件:12.1 完成;验收标准:ACK/TTS 播放后即使 `OWNER_POST_PLAYBACK_DRAIN_MS=0` 也执行一次 flush,ACK 文本为空时不执行 post-playback drain;测试要点:零时长 flush 单测、ACK 禁用不清空单测;优先级:P0;预计:45 分钟。
- [ ] 12.3 调整 `MemoryAudioTransport` 和模拟验收;前置条件:12.2 完成;验收标准:默认 flush 仍清空输入,模拟 live 显式保留预排帧并记录 flush 调用次数;测试要点:transport flush 双语义测试、两轮 simulated live 回归;优先级:P0;预计:35 分钟。
- [ ] 12.4 执行真实 provider 脚本化闭环验收;前置条件:本地模型、`.env` LLM key、macOS TTS/播放可用;验收标准:生成 wake/question 音频帧驱动真实 KWS、VAD、denoiser、本地 STT、云端 LLM、本地 TTS、播放,两轮上下文可引用第一轮历史;测试要点:输出不泄露 key,模型文件不进 Git;优先级:P0;预计:60 分钟。
- [ ] 12.5 执行全量门禁并提交“真实链路自测”模块;前置条件:12.1 至 12.4 完成;验收标准:compileall、unittest、simulate-live、security-check、model-check、device-check、OpenSpec strict、git diff check 全通过后中文 commit;优先级:P0;预计:45 分钟。
## Spec Deltas
### 新增能力
@@ -434,6 +452,7 @@ standby
10. `Realtime partial transcript output`:新增录音期间 partial transcript 事件、终端显示和上下文隔离要求。
11. `Local voice chain and noise filtering`:新增本地 STT/TTS 默认、GTCRN 降噪、CTC 模型、partial 稳定过滤和音频不上传要求。
12. `Simulated microphone live acceptance`:新增不依赖真人麦克风的 live pipeline 模拟验收,覆盖两轮重复对话、短噪声过滤、背景噪声端点、fixture 写入/回放和空帧防卡死。
13. `Real provider live fixture acceptance`:新增真实 provider 脚本化闭环验收和 ACK/TTS 播放后 0ms flush 语义,确保真实本地模型、云端 LLM、本地 TTS/播放在同一 pipeline 中可连续运行。
### 删除项
@@ -455,6 +474,7 @@ standby
8. M8:录音期间实时转写显示完成后提交,保留真人 `run-live` 验收任务,不在用户确认前归档。
9. M9:本地语音链路、高质量实时字幕和正式问题降噪完成后提交,继续保留真人 `run-live` 验收任务,不在用户确认前归档。
10. M10:模拟麦克风自动验收完成后提交,作为真人验收前的可重复自测入口;仍不归档变更,直到真实 `run-live` 行为由用户确认。
11. M11:真实 provider 脚本化闭环和 ACK 缓冲修正完成后提交;仍保留用户真人 `run-live` 体验验收,不在用户确认前归档。
估时: