feat: carry the reasoning verdict through to LLMResponse
Both assembly paths fill it, streaming and non-streaming alike. Filling only one is exactly the divergence this issue exposed: M3 returns reasoning prose over SSE and nothing at all over the plain endpoint, so a verdict computed on one path says nothing about the other. The field defaults to UNKNOWN on both TransportResult and LLMResponse. A transport that does not judge should not get to declare absence on the provider's behalf, and a default that stays silent is the only one that cannot lie.
This commit is contained in:
@@ -28,6 +28,7 @@ from polygateway.thinking import (
|
||||
ThinkingCapability,
|
||||
ThinkingUnsupportedError,
|
||||
get_capability,
|
||||
observe_thinking,
|
||||
resolve_thinking,
|
||||
)
|
||||
from polygateway.transports._http_errors import compose_message, summarize_body
|
||||
@@ -459,6 +460,7 @@ class OpenAICompatTransport:
|
||||
content, thinking = self._finalize_text(content_parts, thinking_parts, profile)
|
||||
self._reject_empty_completion(content, source)
|
||||
prompt, completion, usage_source = _resolve_stream_usage(sink, salvaged)
|
||||
reasoning_tokens = _coerce_reasoning_tokens(sink.get("usage"))
|
||||
return TransportResult(
|
||||
content=content,
|
||||
thinking=thinking,
|
||||
@@ -470,7 +472,12 @@ class OpenAICompatTransport:
|
||||
raw={"usage": sink.get("usage")},
|
||||
cached_prompt_tokens=_coerce_cached_tokens(sink.get("usage")),
|
||||
model_reported=_coerce_model_reported(sink.get("model")),
|
||||
reasoning_tokens=_coerce_reasoning_tokens(sink.get("usage")),
|
||||
reasoning_tokens=reasoning_tokens,
|
||||
# 两条组装路径必须同口径裁定: 只在一条路径上给结论,下游就得靠
|
||||
# "这次是不是流式"去猜可观测性,那正是 issue #16/#17 的根因形态
|
||||
thinking_observation=observe_thinking(
|
||||
thinking=thinking, reasoning_tokens=reasoning_tokens
|
||||
),
|
||||
)
|
||||
|
||||
def _check_done(
|
||||
@@ -544,6 +551,7 @@ class OpenAICompatTransport:
|
||||
)
|
||||
self._reject_empty_completion(content, source)
|
||||
prompt, completion, usage_source = _resolve_usage(body.get("usage") or {})
|
||||
reasoning_tokens = _coerce_reasoning_tokens(body.get("usage"))
|
||||
return TransportResult(
|
||||
content=content,
|
||||
thinking=thinking,
|
||||
@@ -555,7 +563,12 @@ class OpenAICompatTransport:
|
||||
raw={"usage": body.get("usage")},
|
||||
cached_prompt_tokens=_coerce_cached_tokens(body.get("usage")),
|
||||
model_reported=_coerce_model_reported(body.get("model")),
|
||||
reasoning_tokens=_coerce_reasoning_tokens(body.get("usage")),
|
||||
reasoning_tokens=reasoning_tokens,
|
||||
# 本路径的裁定多半落 UNKNOWN(M3 实测: 推理已计费却正文与 details 双
|
||||
# 缺)。如实标记"观测不到",好过让下游误读成"没推理"
|
||||
thinking_observation=observe_thinking(
|
||||
thinking=thinking, reasoning_tokens=reasoning_tokens
|
||||
),
|
||||
)
|
||||
|
||||
async def aclose(self) -> None:
|
||||
|
||||
Reference in New Issue
Block a user