diff --git a/research-wiki/designs/2026-09-04-reasoning-effort-design.md b/research-wiki/designs/2026-09-04-reasoning-effort-design.md index 25cbbf3..ec98d51 100644 --- a/research-wiki/designs/2026-09-04-reasoning-effort-design.md +++ b/research-wiki/designs/2026-09-04-reasoning-effort-design.md @@ -191,13 +191,16 @@ request.reasoning_effort > source.reasoning_effort > source.enable_thinking(语 | 1 | `.env` / `from_env()` / `from_settings()` | `config._cast` 委托 `coerce_effort` | | 2 | 构造函数全量注入 `SourceConfig(...)` 与 `chat(reasoning_effort=...)` | `SourceConfig.__post_init__` / `chat()` 入口 | | 3 | **缓存命中回放** `LLMResponse.applied_effort` | `CacheMW._coerce_applied_effort` | +| 4 | **公共函数 `resolve_thinking()` 直调** | 函数入口自行 `coerce_effort`(2026-09-05 独立验证查出) | 第 3 条是 T8 加 `applied_effort` 字段时才浮现的: 响应进 Redis 走 JSON,`StrEnum` 存成裸串, 命中回放时类型已丢。与 `thinking_observation` 当年的坑**逐字相同**(见 issue #16/#17),故按同一 先例处置: 域外取值降级为 `None` 且**不作废整条缓存**——多项目共用 Redis 时互相打缓存是老问题, 为一个可观测字段丢掉整条响应不划算。 -新增第四条入口时(新工厂、新 transport 参数、新的反序列化路径)必须同样过 `coerce_effort`。 +第 4 条是本次换代**自己造出来的**: 该函数在 `__all__` 里,第三参数由 `bool` 换成 `Effort` 后,下游最自然的写法就是从 JSON/配置读出来的裸串 `"low"`。不归一则 `_inject` 撞 `.value` 抛 `AttributeError`——一个未文档化、不属四分类的异常。 + +新增第五条入口时(新工厂、新 transport 参数、新的反序列化路径)必须同样过 `coerce_effort`。 ## 5. 缓存 key @@ -252,7 +255,9 @@ request.reasoning_effort > source.reasoning_effort > source.enable_thinking(语 |---|---| | 档位清单与「能否关闭」皆无冲突 | 直接登记 | | **档位清单三源一致,仅「能否关闭」存疑**(如 kimi-k3: 官方档位无 `none`,OpenRouter 却标 `mandatory:false`) | 按**保守方向**登记(不含 `none`),evidence 注明存疑点。理由: 不登记会退回 Phase 3 的「尽力注入」,下游配 `none` 时静默失效——**那正是 issue #20 的病**;保守登记则报错并给出最低档,明确且有出路 | -| 档位清单本身未知(`未查到`/`推定同上`) | 不登记,走 Phase 3 |`default` 列只是调研记录,按 §3.2 并入 `evidence` 文本,不进字段。 +| 档位清单本身无该型号直接证据(`未查到`,或仅由**同系**推定如 `推定同上`) | 不登记,走 Phase 3 | + +第二档与第三档的分界是**有没有该型号自己的档位证据**,不是「关不关得掉存不存疑」: `kimi-k3` 进第二档,因为月之暗面官方文档直接写明它的三档是 `low/high/max`,只有「能否关」两源分歧;而 `gemini-3-flash`、`claude-haiku-5` 的档位清单是从同系型号(3.1-pro / opus-5)推来的,**没有该型号自己的文档**,故进第三档。Phase 3 并非静默——它会 warning 指路「实测后用 `register_capability` 登记」,且未登记模型的运行期对账文案也专门写了这一句;登记一个纯推定值反而会让下游以为库确认过。T10 实测时这三个型号优先补。`default` 列只是调研记录,按 §3.2 并入 `evidence` 文本,不进字段。 | 模型 | supported_efforts(推定) | 厂商默认(入 evidence) | 关? | |---|---|---|---| @@ -309,7 +314,17 @@ request.reasoning_effort > source.reasoning_effort > source.enable_thinking(语 ## 12. 迁移与兼容 -**破坏性变更一处**: `ThinkingCapability` 的构造签名(`can_disable` → `supported_efforts`)。 +**破坏性变更五处**(初稿只列了第 1 条,其余四条为 2026-09-05 独立验证实测补全——照初稿写 CHANGELOG 会让下游撞上没有预告的 `TypeError`): + +| # | 位置 | 变更 | 谁会断 | +|---|---|---|---| +| 1 | `ThinkingCapability` | 构造签名 `can_disable` → `supported_efforts` | 自建能力表的调用方 | +| 2 | `ports.Transport.complete()` | 新增**无默认值**参数 `reasoning_effort` | 任何自建 transport 实现 | +| 3 | `ports.TelemetryRecorder.record_llm_call()` | 新增无默认值参数 `reasoning_effort` | 任何自建 recorder 实现 | +| 4 | `thinking.resolve_thinking()` | 第三参数换语义(`bool` → `Effort`),**返回类型由 `Mapping` 改为 `ThinkingResolution`** | 读侧代码一律断 | +| 5 | `providers.ProviderProfile` | `thinking_on`/`thinking_off` → `thinking: ThinkingWire` | 自建 profile 的调用方 | + +五者都在包根导出面或端口面上。 **先更正**(Codex 审查指出): 初稿称「已核实 `reference/` 三项目无调用点,实际影响面为零」——**该结论不成立**。`reference/` 下当前**没有** GovDoc-SaaS / Video-Tree-TRM5 / CHSAnalyzer 三个目录(工作区实际只有本次调研克隆的四个开源项目),此前的 `grep` 因目录不存在而输出空,被误读成「无匹配」。