fix(model hub): serve custom tags and metadata on model_group_alias rows
Some checks failed
LiteLLM Rust / rust-lint (push) Has been cancelled
LiteLLM Rust / rust-test (push) Has been cancelled
LiteLLM Rust / rust-wheel (push) Has been cancelled
Terraform Provider / gofmt, vet, build, test (push) Has been cancelled
Terraform Provider / Provider endpoints vs proxy OpenAPI schema (push) Has been cancelled

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
jesus 2026-10-16 23:03:00 +00:00
parent cd2fd91f13
commit 1b05b6e940
4 changed files with 52 additions and 2 deletions

View file

@ -17064,7 +17064,11 @@ def get_model_group_info(
ModelGroupInfoProxy.model_validate(
{
**_model_group_info.model_dump(),
**model_group_custom_fields(llm_router.get_model_list_of_routed_group(model)),
**model_group_custom_fields(
llm_router.get_model_list_of_routed_group(
resolve_model_group_alias(llm_router.model_group_alias, model) or model
)
),
}
)
)

View file

@ -205,6 +205,7 @@ def _yaml_config(
model_info: Mapping[str, object] = MappingProxyType(
{"custom_tags": ["deprecated", "ptu"], "custom_metadata": LIFECYCLE_METADATA}
),
model_group_alias: Mapping[str, str] = MappingProxyType({}),
) -> Path:
config: Final = yaml.safe_load(Path("tests/integration/proxy_config.yaml").read_text())
deployment: Final = {
@ -213,7 +214,12 @@ def _yaml_config(
"model_info": dict(model_info),
}
path: Final = directory / "custom_fields.yaml"
path.write_text(yaml.safe_dump({**config, "model_list": [*config["model_list"], deployment]}))
router_settings: Final = {**config.get("router_settings", {}), "model_group_alias": dict(model_group_alias)}
path.write_text(
yaml.safe_dump(
{**config, "model_list": [*config["model_list"], deployment], "router_settings": router_settings}
)
)
return path
@ -256,3 +262,15 @@ def test_yaml_custom_metadata_that_json_cannot_carry_is_dropped_without_breaking
assert every_group.status_code == 200, every_group.text
group: Final = _model_group(owned.gateway, model_name)
assert _custom_fields(group) == (["ptu"], {"retirement_date": "2027-03-01"}), group
@pytest.mark.timeout(2 * graceful_stop_seconds() + 120)
def test_an_alias_group_serves_the_custom_tags_and_metadata_of_the_group_it_points_to(
gateway: Gateway, tmp_path: Path
) -> None:
model_name: Final = f"integration-yaml-{uuid.uuid4().hex}"
alias: Final = f"{model_name}-alias"
config: Final = _yaml_config(tmp_path, gateway.upstream_url, model_name, model_group_alias={alias: model_name})
with owned_proxy_process(gateway, tmp_path, {}, config=config) as owned:
group: Final = _model_group(owned.gateway, alias)
assert _custom_fields(group) == (["deprecated", "ptu"], LIFECYCLE_METADATA), group

View file

@ -24,6 +24,7 @@ class _FakeRouter:
"""Stands in for the running Router: `_get_model_group_info` only ever asks it these."""
infos: Mapping[str, ModelGroupInfo]
model_group_alias: Mapping[str, str] = MappingProxyType({})
def get_model_group_info(self, model_group: str) -> ModelGroupInfo | None:
return self.infos.get(model_group)

View file

@ -1679,6 +1679,33 @@ def test_get_model_group_info_merges_custom_tags_and_metadata_across_deployments
assert (group.custom_tags, group.custom_metadata) == (expected_tags, expected_metadata)
@pytest.mark.parametrize(
"alias_target",
[pytest.param("gpt-4", id="string"), pytest.param({"model": "gpt-4", "hidden": False}, id="item")],
)
def test_get_model_group_info_serves_the_target_groups_custom_fields_on_an_alias_row(
alias_target: str | dict[str, object],
) -> None:
from litellm.proxy.proxy_server import get_model_group_info
router: Final = Router(
model_list=[
{
"model_name": "gpt-4",
"litellm_params": {"model": "gpt-4", "api_key": "fake"},
"model_info": {"custom_tags": ["deprecated"], "custom_metadata": {"retirement_date": "2027-03-01"}},
}
],
model_group_alias={"gpt-alias": alias_target},
)
groups: Final = get_model_group_info(llm_router=router, all_models_str=["gpt-4", "gpt-alias"], model_group=None)
assert {group.model_group: (group.custom_tags, group.custom_metadata) for group in groups} == {
model_group: (("deprecated",), {"retirement_date": "2027-03-01"}) for model_group in ("gpt-4", "gpt-alias")
}
@pytest.fixture
def mock_team_data():
return [