Phase 4B:接入 RNNoise/Silero 节流并拆分 ASR 结束权 - #2398
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. 🗂️ Base branches to auto review (3)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7a8c638153
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
已补充并复核 RNNoise / Silero 语音存在检测预备报告 和可复现评测工具。 二次审计修正了三个口径:RNNoise 持续条件现在直接捕获真实 10ms frame;Silero 使用生产 gate(0.5 onset、<0.35 reset、至少7个窗口);性能同时记录 CPU/wall,并拆分共享 ONNX Runtime 与 Silero session RSS。 核心结果(307 个固定片段、767.5 秒):
确认后的结论:
|
e203e11 to
0c771e2
Compare
6d75045 to
99b67c3
Compare
0c771e2 to
5b5d8e8
Compare
关于“关闭 Silero”实验图的口径与最终决策(已按 3 个 PR 收敛)图片中的表格不是独立 ASR 整体准确率评测,而是分段式 ASR 关闭 Silero 的消融实验,分别验证 RNNoise 能否负责 onset,以及移除 Silero 后能否靠每 500ms 轮询 SmartTurn 判断结束。
架构与决策
Phase 4 收敛方案Phase 4 总计 3 个 PR:
不再为 RNNoise 真实设备验证单开 Phase 4 PR;评测与策略边界保持在 #2398。小游戏迁移不计入 Phase 4,待 ASR 接口稳定后单独实施。 |
5d382a2 to
abb7b18
Compare
99b67c3 to
aa13f85
Compare
两项跨轮竞态已收敛(当前 head
|
aa13f85 to
fa31299
Compare
c324e53 to
4240984
Compare
|
本次已把 Phase 4B 对旧碎片模块的修改迁入 #2345 确立的 owner:音频证据并入 |
|
已复核 #2396 的两个 P2 修复( #2398 的自有提交没有修改
|
MomiJiSan
left a comment
There was a problem hiding this comment.
Soniox fail-closed 边界需要在 transport 重构中保持。
4240984 to
4f48780
Compare
Soniox failure contract stacked 收敛Soniox failure contract 已按 stacked owner 完成收敛:
回归覆盖同 Provider 重试成功、250/500 ms 退避、重试耗尽、Provider selection/持久配置不变、core-follow resolver 零调用、取消与四类过期连接、失败 candidate 迟到 callback、pending speech 恢复、Provider endpoint authority、SmartTurn 零 pin,以及用户可见 Soniox unavailable 状态。 最终验证:
#2398 与 #2408 的 GitNexus detect_changes 均为 LOW、0 affected flows。建议仍按 #2345 → #2396 → #2398 → #2408 顺序合并。 |
0fb3c77 to
2d6a6be
Compare
4f48780 to
b9e4098
Compare
|
已在 Soniox 三次建联失败后, 新增回归覆盖关闭资源优化时三次同 selection 失败、250/500 ms 退避、三个 candidate 全部关闭、Soniox unavailable 恰好一次,以及第三次成功、endpointing 失败、非 Soniox 失败、stale epoch 和 cancellation。ASR 回归为 405 passed, 本提交只处理双重最终状态;未修改重试次数、Provider selection/fallback、用户配置、Soniox worker/endpoint、SmartTurn、TTL、 |
|
Phase 4B 的两个资源生命周期问题已分别收敛:
两项修改均未改变 Provider selection、Soniox retry、endpoint、SmartTurn authority、candidate generation、PCM replay 或 lifecycle 状态转换。定向与组合回归共 413 项通过; #2408 已 rebase 到本 PR 最新 head,仅执行 Speaker Shadow 组合回归,没有复制 TTL 或 binding cleanup 实现。 |
|
Phase 4B 的两个检测边界问题已完成收敛(
两项修改均未改变 Provider selection、Soniox retry/fail-closed、fallback、Provider endpoint/final authority、SmartTurn authority 或 5/25 秒 TTL。#2408 已 rebase 到本 head( 验证结果:#2398 为 464 passed / 84.47% coverage;#2408 完整组合为 521 passed / 3 skipped / 84.89% coverage。两边 Ruff、 |
|
Phase 4B 的 DRAINING successor overflow / Provider final fence 已按状态所有权完成收敛:
本次没有修改 Soniox retry/fallback、Provider selection、endpoint/final authority、worker replay、RNNoise prewarm、5/25 秒 TTL、SmartTurn completion fence、PCM replay、buffer 阈值、前端状态码或 i18n,也没有新增 Provider 名称特判或增长型 completed set。 验证:完整 ASR 组合回归 434 passed, |
3a1e124 to
b35c325
Compare
2d6a6be to
392e89e
Compare
Restack 完成回执本 PR 已完成 restack:
验证结果:
上游 |
27d0aff to
362f999
Compare
362f999 to
4a2cbde
Compare
|
已完成本轮 stacked rebase 并解决冲突:
下一步继续按 stacked 顺序处理 #2408。 |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4a2cbdeac5
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| self._asr_provider or "unknown", | ||
| status_code="ASR_ENDPOINTING_FAILED", | ||
| ) | ||
| return True |
There was a problem hiding this comment.
Return an AsrSubmitResult on dispatcher failure
When detector dispatcher backpressure happens while the throttle-unavailable/fail-open path is opening, this branch returns a bare bool even though submit() otherwise returns AsrSubmitResult and Core immediately reads result.status after awaiting it. That turns the handled endpointing failure into an AttributeError: 'bool' object has no attribute 'status' in main_logic/core/asr_runtime.py instead of the intended unavailable submit result.
Useful? React with 👍 / 👎.
| sample_rate_hz: int | ||
| speech_probability: float | None | ||
| rnnoise_available: bool = False | ||
| rnnoise_evidence: RnnoiseEvidence | None = None |
There was a problem hiding this comment.
Propagate RNNoise evidence through Core
Although the pipeline now attaches rnnoise_evidence, the production microphone route drops it before IndependentAsrRuntime.submit(): Core forwards only speech_probability/rnnoise_available into _route_microphone_audio and then recreates ProcessedVoiceFrame without this field. As a result live 48 kHz audio falls back to synthetic one-frame evidence, so the new adaptive baseline and shadow metrics do not use the real RNNoise frame_count, mean, or ema values this change computes.
Useful? React with 👍 / 👎.
改动概述
本 PR 已 rebase 到 #2396
2d6a6bec3,是其上的 Phase 4B 数据面:提供与 Provider 无关的 RNNoise/Silero 活动证据、资源节流和语音生命周期,并明确拆分两条结束判断路径。WARM_IDLE下则坚持“非ACTIVE不上云”,continuous wake 生效前只缓冲 PCM。关键技术决策
idle_transport_close_ms;Provider final 后的 WARM_IDLE 使用provider_policy.warm_transport_ms。Soniox 因而保持默认 25 秒 WSS 保温,不新增 Provider 特判;旧 epoch 或旧 lifecycle 的计时器不能关闭 successor。_bound_turns;重复、旧 epoch 和 callback 异常不会恢复或保留旧 binding,也不新增随 turn 增长的 completed set。connect_transport()两个入口均使用 3 次总尝试与 250/500 ms 退避;每次只用原始 Soniox selection 创建新 candidate,失败 candidate 必须关闭。重试不改写_asr_transport_selection、_asr_provider或lifecycle.provider_policy;耗尽后进入BLOCKED,通过统一终止入口只发送一次ASR_INDEPENDENT_PROVIDER_UNAVAILABLE。release_deferred_turn():解除旧轮屏障,但不清空可能已经到达的下一轮音频。SmartTurn COMPLETE 通过SmartTurnCompletionFence固定旧 candidate;fail-open 仅触发通用 continuous wake,不能越过 lifecycle 直接发送 PCM。“关闭 Silero”消融结论
该实验只回答“分段式 ASR 能否移除 Silero”,不用于决定流式 ASR 的 endpoint。
因此当前不关闭 Silero。节省的内存不足以抵消 CPU、调用压力和结束可靠性回归。
RNNoise / Silero 评估与发布门槛
仓库语料按原始来源拆分 calibration/holdout;同一 TTS 的 clean 与不同 SNR 变体不跨集合:
这些数据仍来自仓库 TTS 与合成噪声。评测工具已支持匿名
--real-device-manifest,报告不写入录音路径或 PCM;当前没有带标签真实麦克风语料,所以明确记录real_device_metrics.available=false。在多设备、长时间 false-prewarm、onset P95 和首字丢失率达到门槛前,不切换 RNNoise-only。不拆分理由 / Why Not Split
RNNoise/Silero 决策、SmartTurn 动态生命周期、transport generation 屏障和 pre-roll/首字保护共同构成同一条数据面状态机。若拆成独立 PR,中间状态可能出现“已节流但 endpoint 未就绪”“旧 transport 接受新音频”或“final 清空下一轮首帧”等不可安全发布组合。
评测工具与报告保留在本 PR 中,用来约束默认策略仍为 RNNoise + Silero,并防止代码先切换到尚未通过真实设备门槛的 RNNoise-only。声纹属于独立身份 gate,不进入本 PR。
回归报告 / Regression Report
feed()曾丢失 RNNoisePREWARM决策,Provider final 也没有完成本地 candidate;统一 5 秒计时又会过早关闭 Provider warm transport,完成后的 binding 则会在长会话中按 turn 累积;DRAINING overflow 过去会完整 reset Detector、销毁旧 Provider fence,使旧 final 被标记 accepted 后静默丢弃并最终触发 watchdog。ASR_ENDPOINTING_FAILEDfail-closed。runtime.py与detector_runtime.py合计覆盖率 82.49%;VoiceTurn 回归 65 passed / 2 skipped。新增覆盖 Soniox/Qwen DRAINING overflow、旧 final 单次交付、watchdog 不触发、overflow 后 successor 保留、重复 discard、stale fence、Silero reset 异常、两种 final/overflow 锁竞争、session/lifecycle/detector identity 替换与 100 轮有界性。Ruff、git diff --check通过;GitNexus detect_changes 为 LOW / 0 affected flows。风险与边界
本 PR 不实现声纹,不修改小游戏,不允许 RNNoise/Silero 发布 logical final,也不回退 Omni 或其他 ASR Provider 做独立 ASR 的故障兜底;不修改
workers/soniox.py的已连接后 recovery/replay、Provider<end>、partial/final 或错误分类。TTL 修复不改变 Provider selection、重试和 endpoint;binding 修复不改变 SmartTurn 决策、candidate generation 或 PCM replay。Transport-only prewarm 只拥有资源预热权;Provider candidate fence 只封存和完成本地资源边界,两者均不取得 Provider endpoint/final 权限。用户明确关闭独立 ASR 时仍保留 Core/Omni 原生语音路径。Phase 4 收敛为 3 个 PR:4A(#2396,控制面)、4B(本 PR,节流和生命周期数据面)、4C(#2408,声纹 shadow/可选 gate)。小游戏迁移待接口稳定后单独实施。