feat: carry the per-call tier down to the transport that must send it
The Transport port took the request apart into five arguments, so a tier placed on ChatRequest could never reach _build_payload: the field was set, read by nobody, and silently ignored - the exact shape of failure that sent downstream to extra_body in the first place. complete() now takes reasoning_effort with no default, matching the TelemetryRecorder convention: a default would turn a missing hand-off into a silent 'no opinion'. All four fakes move with it, since @runtime_checkable checks method names and not signatures. EmbeddingTransport and OcrTransport are deliberately left alone - they have no reasoning semantics - and a test now holds that line. _build_payload drops its inline sugar conversion for effective_effort(), so the guard and the hot path share one judgement, and passes the source's effort_fallback for the same reason.
This commit is contained in:
@@ -24,6 +24,7 @@ from polygateway.transports.openai_compat import OpenAICompatTransport
|
||||
from polygateway.types import (
|
||||
BackpressurePolicy,
|
||||
BreakerConfig,
|
||||
Effort,
|
||||
GlobalLimits,
|
||||
RetryPolicy,
|
||||
SourceConfig,
|
||||
@@ -219,6 +220,31 @@ class TestReasoningEffortPriority:
|
||||
overrides.setdefault("model", "glm-5.3")
|
||||
return _source(provider="zhipu", **overrides)
|
||||
|
||||
async def test_request_effort_wins_over_source(self):
|
||||
captured = []
|
||||
source = self._zhipu(reasoning_effort=Effort.LOW)
|
||||
async with self._capturing_client(captured, sources=[source]) as client:
|
||||
await client.chat([{"role": "user", "content": "hi"}], reasoning_effort=Effort.MAX)
|
||||
assert captured[0]["reasoning_effort"] == "max"
|
||||
assert captured[0]["thinking"] == {"type": "enabled"}
|
||||
|
||||
async def test_none_request_does_not_clear_source(self):
|
||||
"""请求级不表态 ≠ 请求级要求"不推理": 前者必须让源级默认继续生效。"""
|
||||
captured = []
|
||||
source = self._zhipu(reasoning_effort=Effort.LOW)
|
||||
async with self._capturing_client(captured, sources=[source]) as client:
|
||||
await client.chat([{"role": "user", "content": "hi"}])
|
||||
assert captured[0]["reasoning_effort"] == "low"
|
||||
|
||||
async def test_request_none_tier_is_an_opinion_not_an_absence(self):
|
||||
"""请求级 `none` 是"要求不推理",不得被当成"没表态"而回落到源级档位。"""
|
||||
captured = []
|
||||
source = self._zhipu(model="glm-5.2", reasoning_effort=Effort.MAX)
|
||||
async with self._capturing_client(captured, sources=[source]) as client:
|
||||
await client.chat([{"role": "user", "content": "hi"}], reasoning_effort=Effort.NONE)
|
||||
assert captured[0]["thinking"] == {"type": "disabled"}
|
||||
assert "reasoning_effort" not in captured[0]
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("provider", "model", "fragment"),
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user