feat: add governed embedding client with batching
This commit is contained in:
@@ -341,3 +341,48 @@ def _guard_stall(settings: GatewaySettings) -> None:
|
||||
def _load_lease_ttl(env: Mapping[str, str]) -> float:
|
||||
found = _first(env, "PGW_LEASE_TTL_S")
|
||||
return float(_cast(found[1], "float", found[0])) if found else _DEFAULT_LEASE_TTL_S
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class EmbeddingSettings:
|
||||
"""Embedding scope 装配配置(M2 §7): 复用 GatewaySettings + embedding 专用键。
|
||||
|
||||
专用键不进 GatewaySettings(LLM scope 不受影响): `{SCOPE}__BATCH_SIZE`
|
||||
必填(分批是行为关键,不设默认)、`{SCOPE}__NORMALIZE`/`{SCOPE}__EXPECTED_DIM`
|
||||
可选。cache/structured 键对 embedding 无意义,装配时忽略。
|
||||
"""
|
||||
|
||||
gateway: GatewaySettings
|
||||
batch_size: int
|
||||
normalize: bool = False
|
||||
expected_dim: int | None = None
|
||||
|
||||
@classmethod
|
||||
def from_env(
|
||||
cls,
|
||||
scope: str = "EMBED",
|
||||
env: Mapping[str, str] | None = None,
|
||||
*,
|
||||
env_file: str = ".env",
|
||||
) -> EmbeddingSettings:
|
||||
if env is None:
|
||||
env = {
|
||||
k: v for k, v in {**dotenv_values(env_file), **os.environ}.items() if v is not None
|
||||
}
|
||||
scope_u = scope.upper()
|
||||
gateway = GatewaySettings.from_env(scope_u, env=env)
|
||||
key, raw = _require(env, f"{scope_u}__BATCH_SIZE")
|
||||
batch_size = int(_cast(raw, "int", key))
|
||||
if batch_size < 1:
|
||||
raise ValueError(f"{scope_u}__BATCH_SIZE 必须 ≥ 1")
|
||||
norm = _first(env, f"{scope_u}__NORMALIZE")
|
||||
dim = _first(env, f"{scope_u}__EXPECTED_DIM")
|
||||
expected_dim = int(_cast(dim[1], "int", dim[0])) if dim else None
|
||||
if expected_dim is not None and expected_dim < 1:
|
||||
raise ValueError(f"{scope_u}__EXPECTED_DIM 必须 ≥ 1")
|
||||
return cls(
|
||||
gateway=gateway,
|
||||
batch_size=batch_size,
|
||||
normalize=bool(_cast(norm[1], "bool", norm[0])) if norm else False,
|
||||
expected_dim=expected_dim,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user