feat: model the thinking switch as shape plus capability (issue #5)
enable_thinking=False was a no-op for minimax and openai sources: both profiles had empty dicts on each side, so the payload update injected nothing while the caller believed reasoning had been turned off. A downstream project was blocked on exactly this. The root cause is that an empty dict meant two different things -- "no injection needed" and "we do not know how this provider spells it" -- and that a provider-level table cannot express what turned out to be a per-model property. Live testing showed MiniMax-M3 can disable reasoning via reasoning_effort while M2.7 and M2.5 cannot be disabled at all, which two external registries independently confirm. So the shape stays at provider level and a capability table joins it at model level. Unknown, unsupported and no-opinion are now three distinct values, and resolve_thinking is the single place they meet: it raises at assembly time when a model cannot honour the request, warns and injects for unregistered models, and injects silently otherwise. Every registered capability carries the evidence it was derived from. enable_thinking also joins the cache fingerprint, since it now really does change the request body.
This commit is contained in:
@@ -202,6 +202,33 @@ class TestModelFingerprint:
|
||||
assert plain != tuned
|
||||
assert tuned.startswith("qwen-max|") # 旧字面量仍是前缀,便于人眼辨认
|
||||
|
||||
def test_enable_thinking_changes_fingerprint(self):
|
||||
"""issue #5 配套: thinking 一旦真正改变请求体,就必须进缓存身份。
|
||||
|
||||
否则"关掉推理后重启"会读到开着推理时缓存的旧响应——issue #4 为
|
||||
temperature 写过逐字相同的理由。
|
||||
"""
|
||||
from polygateway.client import build_model_fingerprint
|
||||
|
||||
plain = build_model_fingerprint([_source()])
|
||||
off = build_model_fingerprint([_source(enable_thinking=False)])
|
||||
on = build_model_fingerprint([_source(enable_thinking=True)])
|
||||
assert len({plain, off, on}) == 3
|
||||
|
||||
def test_extra_body_only_fingerprint_is_byte_identical_to_before(self):
|
||||
"""只配 extra_body、不表态 thinking 的存量源不得触发冷启动。
|
||||
|
||||
字面量在此硬编码: 这条断言的价值全在"逐字相同",改实现时必须先看见它红。
|
||||
"""
|
||||
import hashlib
|
||||
import json
|
||||
|
||||
from polygateway.client import build_model_fingerprint
|
||||
|
||||
mark = json.dumps(["qwen-max", {"temperature": 0}], sort_keys=True, ensure_ascii=False)
|
||||
expected = "qwen-max|" + hashlib.sha256(mark.encode("utf-8")).hexdigest()
|
||||
assert build_model_fingerprint([_source(extra_body={"temperature": 0})]) == expected
|
||||
|
||||
def test_source_rename_does_not_change_fingerprint(self):
|
||||
"""指纹按 (model, extra_body) 而非源名: 改名不该误触全量冷启动。"""
|
||||
from polygateway.client import build_model_fingerprint
|
||||
|
||||
Reference in New Issue
Block a user