feat: wire the tier through the transport and keep each tier's warning distinct

The transport now hands back the tier it actually sent, and that tier
rides TransportResult into LLMResponse. It is not the requested one:
under EFFORT_FALLBACK=nearest a medium request goes out as low, and
telemetry grouping by the requested tier would file the row under a tier
that never left the process.

Reconciliation judges the same tier instead of the old enable_thinking
bool, and the warning throttle keys on it. Keyed on the bool, every tier
of one model shared a single key, so the second contradiction was
silenced for the lifetime of the transport. The predicate is an identity
check against Effort.NONE on purpose -- the member's value is the
non-empty string "none", so any truthiness test would send every strength
tier down the "asked to disable" branch and invert the alarm.
This commit is contained in:
2026-09-05 05:00:29 -04:00
parent 5dfb15e6a2
commit 848dc0aa7f
8 changed files with 279 additions and 48 deletions
+22 -9
View File
@@ -575,7 +575,7 @@ def _warn_unregistered(
def reconcile_thinking(
*,
enable_thinking: bool | None,
effort: Effort | None,
observation: ThinkingObservation,
capability: ThinkingCapability | None,
model: str,
@@ -585,6 +585,17 @@ def reconcile_thinking(
能力表过期是必然事件(M3 的 evidence 曾停在 8-02 整整 23 天),而过期的
表现是静默错觉。本函数把它变成可报警事件,代价是一次枚举比较。
**判据是档位而非布尔**(2026-09-05,设计 §4.3): `Effort.NONE` 走"要求关闭"
一支,其余任何档走"要求开启"一支,`None`(不表态)仍沉默。判据必须写成
`is Effort.NONE` 的**身份比较**——它的取值是非空串 `"none"`,任何靠真值性
的写法(`if not effort`)都恒为假,会把每个强度档送进关闭分支,告警方向整个
颠倒。传入的应是**实际发出去**的那一档(`nearest` 映射后与请求档分叉),
否则文案会说一个从未发出过的档。
**不新增**「档位高低 vs `reasoning_tokens` 多少」的对账(设计 §4.3/§11 第 1
条): 二者没有可判定的函数关系(实测同一档 rt 在 8~56 之间跳),拿它报警必然
是噪声,而噪声等于没有告警。该问题归 §11 的压测,不进库。
**只判定、不打日志**: 文案作为返回值交给调用点,单测才能直接断言告警内容,
而不必去解析日志格式;节流也才能留在握有实例状态的 transport 里。
@@ -593,24 +604,26 @@ def reconcile_thinking(
与遥测落地,处置权归下游。
"""
# Phase 1: 调用方不表态 —— 没提要求就无从谈"违背"
if enable_thinking is None:
if effort is None:
return None
# Phase 2: 要求关闭 —— 只有 OBSERVED 能证伪。UNKNOWN 没有证伪力,拿它报警
# 等于每次关闭调用都喊一遍(M3 关闭档恒落此档),噪声即等于没有告警
if enable_thinking is False:
if effort is Effort.NONE:
if observation is not ThinkingObservation.OBSERVED:
return None
return _off_but_observed(model, capability)
# Phase 3: 要求开启 —— ABSENT 是正面证伪,UNKNOWN 是"看不见",两者文案不可混
# Phase 3: 要求开启(含 auto 与各强度档)—— ABSENT 是正面证伪,UNKNOWN 是
# "看不见",两者文案不可混。文案写出**是哪一档**: transport 的节流键正按档
# 分离,文案不分档的话,两条告警长得一模一样,看的人分不出是哪一档出的问题
if observation is ThinkingObservation.ABSENT:
return (
f"模型 {model!r}enable_thinking=True 未生效: 已注入开启参数,"
f"模型 {model!r}reasoning_effort={effort.value!r} 未生效: 已注入开启参数,"
f"上游却明确上报本次未推理(reasoning_tokens=0)"
)
if observation is ThinkingObservation.UNKNOWN:
return (
f"模型 {model!r}enable_thinking=True 无法确认是否生效: 已注入开启参数,"
f"但本次响应观测不到任何推理信号(推理正文与 usage 明细双缺)。"
f"模型 {model!r}reasoning_effort={effort.value!r} 无法确认是否生效: "
f"已注入开启参数,但本次响应观测不到任何推理信号(推理正文与 usage 明细双缺)。"
f"若走的是非流式路径,推理内容可能已计费却不回传"
)
return None
@@ -624,12 +637,12 @@ def _off_but_observed(model: str, capability: ThinkingCapability | None) -> str:
"""
if capability is None:
return (
f"模型 {model!r}enable_thinking=False 未被满足: 实测观测到推理发生,"
f"模型 {model!r}reasoning_effort='none' 未被满足: 实测观测到推理发生,"
f"且该模型的推理能力尚未登记(本次按 provider 形态尽力注入)。"
f"请实测后用 register_capability 登记其真实能力"
)
return (
f"模型 {model!r}enable_thinking=False 未被满足: 实测观测到推理发生,"
f"模型 {model!r}reasoning_effort='none' 未被满足: 实测观测到推理发生,"
f"而能力表登记 can_disable={capability.can_disable}(evidence: {capability.evidence})。"
f"能力表可能已过期——请复测后用 register_capability 更新登记"
)