diff --git a/README.md b/README.md index 46f821c..0557518 100644 --- a/README.md +++ b/README.md @@ -161,3 +161,26 @@ old_string 唯一性校验(0/多次拒绝,replace_all 放行)+ 原子写 + 不能来自 agent 的自我声明;QC 尺子要配「取证失败 ≠ 判 0 分」的出路,否则盲审烧轮次。 + +## LLM 超时预算统一治理(2026-09-16 用户裁定:单点收敛,禁散落) + +**事故背景**:09-05 提取、09-14 develop、09-16 QC 三次事故同一根因——调用方忘传 +timeout → payload 无 _timeout → inference 按供应商端点配置(百炼 120s)掐断长生成; +且超时公式散落在各产线各角色调用点(570/330/+60/-60/min+60 各自为政),按角色 +逐个修必然复发(09-14 只修 develop native,09-16 QC 复发实锤)。 + +**统一架构(全平台只有两处单点)**: +1. `llm_bridge._resolve_budget(timeout, default)`:timeout 语义=一次调用【总预算】 + (0=平台缺省 chat 300 / 生成类 900;封顶 900 下限 60)→ 返回 + (payload._timeout=总预算, 客户端 aiohttp=总预算+60)。四个公开入口 + (llm_call/llm_call_msgs/llm_call_msgs_native/llm_infer)全走它, + payload._timeout 恒传——忘传 timeout 也结构性安全。 +2. `pipeline-llm inference._post_upstream` deadline:attempt 超时=剩余预算, + 总时长≈预算(消灭 3× 放大→客户端先断连→模糊 TimeoutError→误判永久错误链); + 预算耗尽(<15s)不再发起必然超时 attempt;端点配置 timeout 不再掐断 attempt + (仅直连未传 _timeout 时与 _TOTAL_TIMEOUT 取大兜底)。 + +**三层预算对齐铁律**:调用方总预算 T → payload._timeout=T → 客户端=T+60 → +外层 wait_for(若有)≥ T+60。agent_loop:510→570→600 实证对齐。 +验证特征串:inference 日志「预算=Ns」;llm_call_trace status_code=0 计数。 +新增 LLM 调用点只需(可选)声明总预算,禁止自算客户端等待。