From 9832dcee638d9a8269356732a3a5ec366df08cbf Mon Sep 17 00:00:00 2001 From: iomgaa Date: Sat, 5 Sep 2026 05:12:26 -0400 Subject: [PATCH] docs: name the three doors a tier can enter through, before a fourth appears --- .../2026-09-04-reasoning-effort-design.md | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) 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 3c3e382..25cbbf3 100644 --- a/research-wiki/designs/2026-09-04-reasoning-effort-design.md +++ b/research-wiki/designs/2026-09-04-reasoning-effort-design.md @@ -178,6 +178,27 @@ request.reasoning_effort > source.reasoning_effort > source.enable_thinking(语 - 请求非 `none` 档、观测到 `ABSENT` → 既有文案,保留。 - **不做**「档位高低与 `reasoning_tokens` 多少的对账」: 档位与 token 数没有可判定的函数关系(issue #20 自己的数据里 glm-5.3-flash 的 medium 档 rt 在 8~56 之间跳),拿它报警必然是噪声。这条留给 §11 的压测,不进库。 +### 4.4 归一化不变式(实现期补,2026-09-05) + +库内一切档位判定都是 `is Effort.X` 的身份比较,故**每条能让档位进入库内的入口都必须先归一** +(`types.coerce_effort`)。裸字符串不归一的后果不是报错而是**静默判否**——`("none" is Effort.NONE)` +恒假,于是「已关闭」被当成「没表态」。 + +已知三条入口,缺一即漏: + +| # | 入口 | 归一点 | +|---|---|---| +| 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` | + +第 3 条是 T8 加 `applied_effort` 字段时才浮现的: 响应进 Redis 走 JSON,`StrEnum` 存成裸串, +命中回放时类型已丢。与 `thinking_observation` 当年的坑**逐字相同**(见 issue #16/#17),故按同一 +先例处置: 域外取值降级为 `None` 且**不作废整条缓存**——多项目共用 Redis 时互相打缓存是老问题, +为一个可观测字段丢掉整条响应不划算。 + +新增第四条入口时(新工厂、新 transport 参数、新的反序列化路径)必须同样过 `coerce_effort`。 + ## 5. 缓存 key **更正一个误判(Codex 审查指出)**: 源级 `extra_body` 与 `enable_thinking` **早已进 key**——经 `build_model_fingerprint` 的 `_fingerprint_mark`(`client.py`),由 issue #4/#5 落地,ARCH §7.5 有明文。本设计**不存在**先前稿本断言的「现存毒化缺口」,那是把 `CacheMW` 只读 `request.sampling` 误当成了全部 key 来源。