diff --git a/README.md b/README.md index a0d4a73..9df603b 100644 --- a/README.md +++ b/README.md @@ -149,6 +149,27 @@ 且 r2v 判定加「输出为视频」限定防误吸文本输出模型); `_MEDIA_INPUT_CAPS` 加 m2t(模板生成按输入媒体处理)。 +## 统一超时预算(2026-09-16 用户裁定:单点收敛,禁散落) + +**语义**:`payload._timeout` = 一次调用的【总预算】秒数(含内部重试),由调用侧 +bridge(`pipeline_service.llm_bridge._resolve_budget`)恒传——忘传走平台缺省 +(chat 300 / 生成类 900),不再落到供应商端点小配置。 + +**端点侧单点**(`inference._post_upstream` deadline): +- `ctx['budget']` = 总预算;attempt 超时 = 剩余预算,总时长≈预算(旧实现每 + attempt 独享全额超时,最坏 3×预算+退避 > 客户端等待 → 客户端先断连报模糊 + TimeoutError → 分类器误判永久错误,2026-09-16 pbls QC 事故链一环)。 +- 剩余 < `_MIN_ATTEMPT_SECONDS`(15s) 不再发起必然超时的 attempt,抛结构化错误。 +- **端点配置 timeout(llm_vendor.endpoints,百炼 120 等)不再掐断 attempt**—— + 供应商参数不知道调用方需求,正是 09-05/09-14/09-16 三次事故共同根因;仅在 + 直连端点未传 `_timeout` 时与 `_TOTAL_TIMEOUT`(300) 取大兜底。 +- 异步模型轮询总预算同语义(`_async_inference`:req_timeout 覆盖,缺省 600)。 + +**三层对齐铁律**:调用方总预算 T → `_timeout`=T(端点 deadline)→ bridge 客户端 +aiohttp=T+60(恒覆盖上游)→ 调用方外层 wait_for(若有)≥ T+60。 +验证特征串:`[inference] 组包 ... 预算=Ns` 日志行;llm_call_trace status_code=0 +断连计数(治理前 27 次/日 → 治理后 0)。 + ## 治理页面(弹窗化,2026-09-07 用户定夺) `wwwroot/index.ui` 顶部统计条(llm_dashboard_widget)+ 7 张功能卡片。