feat: let a source name its reasoning tier, and say so when it contradicts itself
This commit is contained in:
@@ -22,6 +22,7 @@ from loguru import logger
|
||||
from polygateway.types import (
|
||||
BackpressurePolicy,
|
||||
BreakerConfig,
|
||||
Effort,
|
||||
GlobalLimits,
|
||||
RetryPolicy,
|
||||
SourceConfig,
|
||||
@@ -43,6 +44,10 @@ _SOURCE_FIELDS: dict[str, tuple[str, str]] = {
|
||||
"TTFT_TIMEOUT_S": ("ttft_timeout_s", "float"),
|
||||
"INTER_TOKEN_TIMEOUT_S": ("inter_token_timeout_s", "float"),
|
||||
"ENABLE_THINKING": ("enable_thinking", "bool"),
|
||||
# 档位两键(issue #20);值域校验分工: 档位在此(解析即校验,报错点得出 env 键名),
|
||||
# fallback 交给 SourceConfig 构造期(那道同时覆盖构造函数注入与 dataclasses.replace)
|
||||
"REASONING_EFFORT": ("reasoning_effort", "effort"),
|
||||
"EFFORT_FALLBACK": ("effort_fallback", "str"),
|
||||
"MISSING_DONE": ("missing_done", "str"),
|
||||
"TRUST_ENV": ("trust_env", "bool"),
|
||||
"EXTRA_BODY": ("extra_body", "json"),
|
||||
@@ -93,6 +98,8 @@ def _cast(raw: str, kind: str, key: str) -> object:
|
||||
if lowered in ("0", "false", "no", "off"):
|
||||
return False
|
||||
raise ValueError(f"非法布尔值: {raw!r}")
|
||||
if kind == "effort":
|
||||
return _to_effort(raw)
|
||||
if kind == "json":
|
||||
# JSONDecodeError 是 ValueError 子类,复用下方的统一包装
|
||||
parsed = json.loads(raw)
|
||||
@@ -104,6 +111,25 @@ def _cast(raw: str, kind: str, key: str) -> object:
|
||||
raise ValueError(f"配置 {key} 解析失败: {exc}") from exc
|
||||
|
||||
|
||||
def _to_effort(raw: str) -> Effort:
|
||||
"""把 env 字符串解成 `Effort`;越界时报错并**列出全部八档**。
|
||||
|
||||
列全八档不是啰嗦: 档位词汇是封闭的,而下游会照着别处的习惯写
|
||||
(`lowest`/`off`/`disabled` 都出现过),只说"非法值"等于让人去翻源码。
|
||||
|
||||
`strip().lower()` 与 `bool` 分支同一先例: `.env` 里的行尾空格与大写写法
|
||||
是常态,而档位取值本身没有大小写语义(`Effort` 的值全小写)。
|
||||
"""
|
||||
try:
|
||||
return Effort(raw.strip().lower())
|
||||
except ValueError:
|
||||
# 不 `from exc`: 枚举原生的 "'lowest' is not a valid Effort" 只是同一
|
||||
# 件事的英文复述,链上去反而把可操作的那句挤到后面
|
||||
raise ValueError(
|
||||
f"非法推理档位 {raw!r};允许: {', '.join(e.value for e in Effort)}"
|
||||
) from None
|
||||
|
||||
|
||||
def _first(env: Mapping[str, str], *keys: str) -> tuple[str, str] | None:
|
||||
for key in keys:
|
||||
raw = env.get(key)
|
||||
|
||||
Reference in New Issue
Block a user