docs: fold the Codex review into the issue #7 design and register it
Pins the ARCHITECTURE section 6.1 revision to land before or with the implementation, since the new scope reason contradicts the current single source of truth. Documents why SourceNotConfiguredError may sit outside the four-way classification: that rule governs transport-translated call failures, and the GatewayUnavailableError family already lives outside it. Also collapses the ten per-field response ternaries in emit_attempt into an _AttemptUsage view. They all expressed the same decision and pushed the method to cyclomatic complexity C, which blocked the commit gate.
This commit is contained in:
@@ -12,6 +12,7 @@ import asyncio
|
||||
import json
|
||||
import time
|
||||
import uuid
|
||||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from loguru import logger
|
||||
@@ -28,6 +29,44 @@ if TYPE_CHECKING:
|
||||
from polygateway.types import ChatRequest, LLMResponse, SourceConfig
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class _AttemptUsage:
|
||||
"""一次尝试的用量视图;默认值即"失败尝试"档(无用量可言,记 0 并标 unavailable)。
|
||||
|
||||
存在的理由是把 `emit_attempt` 里逐字段重复的 `X if response else Y` 收敛为
|
||||
一处判定——十处三元把该方法推到圈复杂度 C,而它们表达的是同一件事。
|
||||
"""
|
||||
|
||||
response_text: str = ""
|
||||
thinking: str = ""
|
||||
prompt_tokens: int = 0
|
||||
completion_tokens: int = 0
|
||||
usage_source: str = "unavailable"
|
||||
ttft_ms: float | None = None
|
||||
max_inter_token_ms: float | None = None
|
||||
cached_prompt_tokens: int | None = None
|
||||
model_reported: str | None = None
|
||||
reasoning_tokens: int | None = None
|
||||
|
||||
@classmethod
|
||||
def of(cls, response: LLMResponse | None) -> _AttemptUsage:
|
||||
"""从响应取用量;`None`(失败尝试)返回全默认视图。"""
|
||||
if response is None:
|
||||
return cls()
|
||||
return cls(
|
||||
response_text=response.content,
|
||||
thinking=response.thinking,
|
||||
prompt_tokens=response.prompt_tokens,
|
||||
completion_tokens=response.completion_tokens,
|
||||
usage_source=response.usage_source,
|
||||
ttft_ms=response.ttft_ms,
|
||||
max_inter_token_ms=response.max_inter_token_ms,
|
||||
cached_prompt_tokens=response.cached_prompt_tokens,
|
||||
model_reported=response.model_reported,
|
||||
reasoning_tokens=response.reasoning_tokens,
|
||||
)
|
||||
|
||||
|
||||
class TelemetryEmitter:
|
||||
"""从请求与结果组装 21 字段并写入 recorder;一切写失败降级 warning。"""
|
||||
|
||||
@@ -46,25 +85,26 @@ class TelemetryEmitter:
|
||||
error: str | None,
|
||||
) -> None:
|
||||
"""逐次尝试记录(RetryMW 调用);失败尝试无用量可言,记 0 并标 unavailable。"""
|
||||
usage = _AttemptUsage.of(response)
|
||||
await self._record(
|
||||
request=request,
|
||||
call_id=call_id,
|
||||
model=source.model,
|
||||
provider=source.provider,
|
||||
source_name=source.name,
|
||||
response_text=response.content if response else "",
|
||||
thinking=response.thinking if response else "",
|
||||
prompt_tokens=response.prompt_tokens if response else 0,
|
||||
completion_tokens=response.completion_tokens if response else 0,
|
||||
usage_source=response.usage_source if response else "unavailable",
|
||||
response_text=usage.response_text,
|
||||
thinking=usage.thinking,
|
||||
prompt_tokens=usage.prompt_tokens,
|
||||
completion_tokens=usage.completion_tokens,
|
||||
usage_source=usage.usage_source,
|
||||
latency_ms=latency_ms,
|
||||
ttft_ms=response.ttft_ms if response else None,
|
||||
max_inter_token_ms=response.max_inter_token_ms if response else None,
|
||||
ttft_ms=usage.ttft_ms,
|
||||
max_inter_token_ms=usage.max_inter_token_ms,
|
||||
cache_hit=False,
|
||||
error=error,
|
||||
cached_prompt_tokens=response.cached_prompt_tokens if response else None,
|
||||
model_reported=response.model_reported if response else None,
|
||||
reasoning_tokens=response.reasoning_tokens if response else None,
|
||||
cached_prompt_tokens=usage.cached_prompt_tokens,
|
||||
model_reported=usage.model_reported,
|
||||
reasoning_tokens=usage.reasoning_tokens,
|
||||
# 唯一有"生效源"的入口,故是唯一能并上 extra_body 的(设计决策 D)
|
||||
sampling=canonical_sampling_json(merge_sampling(source.extra_body, request.sampling)),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user