Files
Cognitive_Agent/docs/speech-recognition.md
T

117 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 中文语音控制链路
## 整改前的实际链路
```text
getUserMedia
-> ScriptProcessor(4096)
-> 浏览器 RMS 阈值与前后裁剪
-> 单个 16 kHz PCM WAV
-> POST /api/speech/transcribe
-> 单个 sherpa-onnx OfflineStream
-> SenseVoiceSmall 单次 final decode
-> regex 文本清理
-> 直接覆盖输入框
-> 用户提交后进入既有 IntentIR / capability / CAN 链路
```
旧实现没有 AudioWorklet、ASR Web Worker、WASM、streaming partial、VAD segment、
chunk overlap 或 segment assembler。因此观测到的“空调打开打……靠背靠座椅靠背”
不是 partial/final 被前端重复 append,而是 SenseVoice 单次 decode 已返回该 raw 文本;
旧正则层只是尝试掩盖 acoustic false start,且没有结构化 cancelled intent。
## 整改后的链路
```text
Microphone (优先 TAKSTAR V2)
-> AudioContext(跨 utterance 复用)
-> AudioWorklet(旧环境 ScriptProcessor fallback)
-> 自适应 RMS endpoint + 350 ms 前置 / 450 ms 后置采集
-> 16 kHz PCM WAV + utteranceId
-> Silero VAD(0.25 s pre-roll / 0.35 s post-roll,重叠先合并)
-> SenseVoiceSmall zh + ITN(每个 VAD segment 一个 OfflineStream)
-> final ASR callback
-> TranscriptAssembler(replace / commit / order / idempotency / overlap)
-> rawText
-> UnderstandingTranscriptProcessor
-> cleanText + active commands + cancelledFragments + uncertain
-> 页面展示与提交安全门
-> 用户确认后进入既有 IntentIR / capability / CAN 链路
```
模型、tokens、VAD native session 和浏览器 AudioContext 都只初始化一次。服务端请求以
`utteranceId + SHA-256(audio)` 幂等:相同音频返回缓存,不同音频复用同一 ID 返回 409。
## 数据边界
- `raw_text`:SenseVoice 原始证据,只去模型标签和多余空白,永不被语义文本覆盖。
- `clean_text`:用于输入框显示的理解式文本。
- `commands`:与工程 capability catalog 对齐的 active Intent 预览。
- `cancelled_fragments`:否定、自我修正、false start 或显式撤销的证据及 cancelled Intent。
- `uncertain`:参数越界、缺少方向/单位/设备、拼接冲突等不能安全执行的情况。
- `execution_eligible`:存在 active commands、无 uncertain、无校验错误时才为 true。
语音 API 本身不执行任何能力。页面会拒绝直接提交仍带有原始 uncertain 标记的语音结果;
用户编辑后才解除该标记。
## Capability 驱动的语义链路
语音层不再维护可执行设备表。能力事实按以下优先级读取:
1. `domains/*/config/capabilities.yaml` 与
`config/native_can_capabilities/*.yaml`;
2. `CapabilityRegistry` 统一加载 catalog;
3. `NativeCanRuntime.supported_capabilities`、domain runtime、seat compiler 和
mode profile registry 确认可执行性与 executor binding;
4. `CapabilityResolver` 只把中文槽位或既有一句话解析 action 适配到上述事实。
`UnderstandingTranscriptProcessor` 会优先复用
`application/native_can_intent.py` 已有的确定性解析结果,所以驾驶台默认目标、CH1
主驾能力和网页一句话编排保持一致。`vocabulary.py` 只包含 alias、同义词、颜色与
scope 词法映射,不声明车辆支持哪些能力。
每个 command 同时保留 `target_scope`、`property`、`operation`、`value`、`unit`、
`qualifiers`、IntentIR action、executor binding 和 executor payload。`clean_text` 从
这些结构化 command 渲染;unsupported、ambiguous、incomplete 不会产生假的
executor payload,且 UI 会阻止整条原始语音直接提交。
当前代码证据中,前大灯只有反馈和只读 UI,没有控制 capability;因此“打开前大灯”
为 `recognized_unsupported`。零重力是 `config/modes/vehicles/denza_n7/zero_gravity.yaml`
定义的副驾四轴 mode profile,不是主驾单一 capability;明确要求主驾时返回
`recognized_unsupported`。
能力矩阵始终从 catalog 动态生成:
```bash
python tools/report_capability_matrix.py --format markdown
```
## Debug trace
生产默认关闭。设置 `SPEECH_DEBUG=1` 后,每条 JSON 日志包含:
- `utteranceId`;
- `segmentId`、sequence、开始/结束时间、音频 overlap;
- raw ASR final、进入拼接器前文本、拼接后文本;
- clean text、active/cancelled Intent、uncertain reason;
- audio、VAD、每段 ASR、assembly、semantic、recovery、total 耗时。
`SPEECH_DEBUG_RESPONSE=1` 才把 trace 放进 API 响应。浏览器使用 `?speechDebug=1`
查看采集实现、设备、阈值、utteranceId 和服务器结果。
## 默认 VAD 与识别配置
| 配置 | 默认值 |
|---|---:|
| language | `zh` |
| use_itn | `true` |
| Silero threshold | `0.45` |
| min speech | `0.16 s` |
| min silence | `0.65 s` |
| max speech | `12.0 s` |
| pre-roll | `0.25 s` |
| post-roll | `0.35 s` |
参数可通过 `SPEECH_VAD_*` 调整。真实 TAKSTAR V2 车内噪声录音仍需要继续扩展 audio
regression suite;没有真实证据时不自动切换到 int8,也不自动下载 Recovery 模型。