feat: let chat() take a tenant and caller-defined dimensions
Validation runs before the request enters the onion: every failure inside it is downgraded to a warning by the telemetry layer, so validating in there would not validate anything. The dimensions stay out of the cache key — cache_namespace already carries tenant isolation, and folding meta in would cold-start every existing entry.
This commit is contained in:
@@ -34,7 +34,12 @@ from polygateway.sources import (
|
||||
SourceCooldownMemo,
|
||||
)
|
||||
from polygateway.transports.openai_compat import OpenAICompatTransport
|
||||
from polygateway.types import ChatRequest, LLMResponse, validate_request_overlay
|
||||
from polygateway.types import (
|
||||
ChatRequest,
|
||||
LLMResponse,
|
||||
validate_caller_dimensions,
|
||||
validate_request_overlay,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Awaitable, Iterable, Mapping
|
||||
@@ -205,12 +210,18 @@ class GatewayClient:
|
||||
structured: type[BaseModel] | Literal["json"] | None = None,
|
||||
stream: bool = True,
|
||||
overlay: Mapping[str, Any] | None = None,
|
||||
tenant_id: str | None = None,
|
||||
meta: Mapping[str, Any] | None = None,
|
||||
) -> LLMResponse:
|
||||
"""一次治理调用(签名冻结,ARCH §5.2;与三项目 LLMProvider 协议兼容)。
|
||||
|
||||
`overlay` 是采样参数覆盖层(`temperature`/`seed`/`max_tokens` 等),优先级
|
||||
高于源级 `extra_body`、低于结构化输出的注入。带默认值的 keyword-only
|
||||
参数不影响既有调用点(issue #4)。
|
||||
|
||||
`tenant_id` 与 `meta` 是调用方自定义维度,只进遥测、**不进缓存 key**
|
||||
(租户隔离由 `cache_namespace` 负责,ARCH §7.5);前者享有真实列待遇
|
||||
(可挂 RLS、可进复合索引),后者是任意 KV 容器(issue #11)。
|
||||
"""
|
||||
if structured is not None and not self._structured_available:
|
||||
raise ImportError(
|
||||
@@ -221,6 +232,12 @@ class GatewayClient:
|
||||
# 造成的竞态。同一份快照填 overlay 与 sampling——前者会被结构化注入,
|
||||
# 后者跨层恒定,供缓存 key 与遥测读取(设计决策 A/B/E)
|
||||
sampling = validate_request_overlay(overlay or {}, origin="chat(overlay=...)")
|
||||
# 同理必须在洋葱之外: 洋葱内的一切失败都被遥测层降级成 warning(库铁律
|
||||
# 「遥测写失败降级不冒泡」),校验放里面等于没有校验——非法维度会变成
|
||||
# 静默丢失的遥测行,而调用照常发出(issue #11 §4.2)
|
||||
dimension_tenant_id, dimensions = validate_caller_dimensions(
|
||||
tenant_id, meta, origin="chat(tenant_id=..., meta=...)"
|
||||
)
|
||||
request = ChatRequest(
|
||||
messages=messages,
|
||||
session_id=session_id,
|
||||
@@ -231,6 +248,8 @@ class GatewayClient:
|
||||
stream=stream,
|
||||
overlay=sampling,
|
||||
sampling=sampling,
|
||||
tenant_id=dimension_tenant_id,
|
||||
meta=dimensions,
|
||||
)
|
||||
return await self._handler(request)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user