mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-19 00:01:29 +00:00
Keep staging session fixture (resolve_proxy + build_gateway) and config, retain typed load_all_deployments guards in _compat_models
90 lines
3.1 KiB
Python
90 lines
3.1 KiB
Python
"""Load the claude_code compat matrix's deployment list from
|
|
``test_config.yaml``.
|
|
|
|
``test_config.yaml`` is the ground-truth config the stage deployment
|
|
uses; parsing it at fixture time means a change there (new tier, tier
|
|
retirement, provider swap, endpoint rename) reaches the fixture with
|
|
no extra edit. A drift-check test asserts every ``*_MODELS`` list
|
|
referenced by the compat cells is covered by the yaml, so a cell that
|
|
adds a probe for a name the yaml doesn't know about fails loudly at
|
|
collection instead of at 400-time.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Callable, Mapping
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
from typing import cast
|
|
|
|
import yaml
|
|
|
|
from models import LiteLLMParamsBody
|
|
|
|
CONFIG_PATH = Path(__file__).resolve().parent / "test_config.yaml"
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class CompatDeployment:
|
|
model_name: str
|
|
litellm_params: LiteLLMParamsBody
|
|
|
|
|
|
# The yaml uses ``vertex_ai_*`` for the vertex project/location fields
|
|
# (that is the spelling the proxy config file historically standardized
|
|
# on), while ``LiteLLMParamsBody`` names them without the ``_ai`` infix
|
|
# (matching the proxy's DB column). Both spellings resolve at call time
|
|
# on the proxy side, but pydantic silently drops unknown fields, so a
|
|
# raw ``LiteLLMParamsBody(**entry)`` would produce a body with the
|
|
# vertex project stripped - the resulting deployment 400s at
|
|
# ``/v1/messages`` with "Invalid model name". Normalize the yaml keys
|
|
# to the pydantic names in one place.
|
|
_YAML_TO_PYDANTIC_ALIASES = {
|
|
"vertex_ai_project": "vertex_project",
|
|
"vertex_ai_location": "vertex_location",
|
|
"vertex_ai_credentials": "vertex_credentials",
|
|
}
|
|
|
|
|
|
def _normalize_params(raw: Mapping[str, object]) -> dict[str, object]:
|
|
return {_YAML_TO_PYDANTIC_ALIASES.get(k, k): v for k, v in raw.items()}
|
|
|
|
|
|
ConfigReader = Callable[[Path], str]
|
|
|
|
|
|
def _default_reader(path: Path) -> str:
|
|
return path.read_text()
|
|
|
|
|
|
def load_all_deployments(
|
|
config_path: Path = CONFIG_PATH,
|
|
reader: ConfigReader = _default_reader,
|
|
) -> tuple[CompatDeployment, ...]:
|
|
"""Every deployment declared in the yaml, in file order."""
|
|
doc = yaml.safe_load(reader(config_path))
|
|
if not isinstance(doc, dict):
|
|
return ()
|
|
model_list = doc.get("model_list") or []
|
|
if not isinstance(model_list, list):
|
|
return ()
|
|
return tuple(
|
|
CompatDeployment(
|
|
model_name=str(entry["model_name"]),
|
|
litellm_params=LiteLLMParamsBody(
|
|
**_normalize_params(cast(Mapping[str, object], entry["litellm_params"]))
|
|
),
|
|
)
|
|
for entry in model_list
|
|
if isinstance(entry, dict) and "model_name" in entry and "litellm_params" in entry
|
|
)
|
|
|
|
|
|
def all_expected_model_names(
|
|
*,
|
|
config_path: Path = CONFIG_PATH,
|
|
reader: ConfigReader = _default_reader,
|
|
) -> frozenset[str]:
|
|
"""Every virtual name the compat matrix declares - the ground truth
|
|
the cells are supposed to probe. Used by the drift-check test."""
|
|
return frozenset(d.model_name for d in load_all_deployments(config_path, reader))
|