mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-12 08:42:18 +00:00
fix(proxy): drop a wildcard's model info row when named deployments serve every name it lists
This commit is contained in:
parent
30ec65b038
commit
5431a52bb5
2 changed files with 41 additions and 23 deletions
|
|
@ -527,23 +527,11 @@ def _routed_deployment_model(name_pattern: str, listed_name: str, deployment_mod
|
|||
)
|
||||
|
||||
|
||||
def _names_listed_under_wildcard(
|
||||
deployment: Mapping[str, object],
|
||||
wildcard_pattern: str,
|
||||
litellm_params: LiteLLM_Params | None,
|
||||
routed_models: Callable[[str, str | None], frozenset[str]] | None,
|
||||
deployed_by_name: Callable[[str, str | None], bool],
|
||||
def _names_no_deployment_serves_by_name(
|
||||
deployment: Mapping[str, object], names: Sequence[str], deployed_by_name: Callable[[str, str | None], bool]
|
||||
) -> tuple[str, ...]:
|
||||
team_id: Final = _deployment_team_id(deployment)
|
||||
return tuple(
|
||||
name
|
||||
for name in get_known_models_from_wildcard(
|
||||
wildcard_model=wildcard_pattern,
|
||||
litellm_params=litellm_params,
|
||||
routes_to_model=_routes_to_model(routed_models, team_id),
|
||||
)
|
||||
if not deployed_by_name(name, team_id)
|
||||
)
|
||||
return tuple(name for name in names if not deployed_by_name(name, team_id))
|
||||
|
||||
|
||||
def expand_wildcard_deployments_for_model_info(
|
||||
|
|
@ -584,14 +572,16 @@ def expand_wildcard_deployments_for_model_info(
|
|||
except Exception:
|
||||
expanded.append(deployment)
|
||||
continue
|
||||
expanded_names = _names_listed_under_wildcard(
|
||||
deployment, wildcard_pattern, litellm_params, routed_models, deployed_by_name
|
||||
expanded_names = get_known_models_from_wildcard(
|
||||
wildcard_model=wildcard_pattern,
|
||||
litellm_params=litellm_params,
|
||||
routes_to_model=_routes_to_model(routed_models, _deployment_team_id(deployment)),
|
||||
)
|
||||
if not expanded_names:
|
||||
expanded.append(deployment)
|
||||
continue
|
||||
|
||||
for name in expanded_names:
|
||||
for name in _names_no_deployment_serves_by_name(deployment, expanded_names, deployed_by_name):
|
||||
row = copy.deepcopy(deployment)
|
||||
row["model_name"] = name
|
||||
params = row.get("litellm_params")
|
||||
|
|
|
|||
|
|
@ -1394,7 +1394,11 @@ def test_catch_all_wildcard_model_info_keeps_only_the_concrete_row_for_a_deploye
|
|||
|
||||
@contextmanager
|
||||
def _openrouter_catalog_beside_a_named_deployment(
|
||||
monkeypatch: pytest.MonkeyPatch, wildcard_name: str, named: str
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
wildcard_name: str,
|
||||
named: str,
|
||||
catalog: tuple[str, ...] = ("openai/gpt-5.4-mini", "anthropic/claude-haiku-5-5"),
|
||||
wildcard_key: str | None = None,
|
||||
) -> Generator[Router, None, None]:
|
||||
import litellm
|
||||
|
||||
|
|
@ -1402,15 +1406,16 @@ def _openrouter_catalog_beside_a_named_deployment(
|
|||
monkeypatch.delenv("OPENROUTER_API_BASE", raising=False)
|
||||
with respx.mock(assert_all_called=False) as respx_mock:
|
||||
respx_mock.get("https://openrouter.ai/api/v1/models/user").mock(
|
||||
return_value=httpx.Response(
|
||||
200, json={"data": [{"id": "openai/gpt-5.4-mini"}, {"id": "anthropic/claude-haiku-5-5"}]}
|
||||
)
|
||||
return_value=httpx.Response(200, json={"data": [{"id": catalog_id} for catalog_id in catalog]})
|
||||
)
|
||||
yield Router(
|
||||
model_list=[
|
||||
{
|
||||
"model_name": wildcard_name,
|
||||
"litellm_params": {"model": "openrouter/*", "api_key": f"sk-or-wildcard-{wildcard_name}"},
|
||||
"litellm_params": {
|
||||
"model": "openrouter/*",
|
||||
"api_key": wildcard_key or f"sk-or-wildcard-{wildcard_name}",
|
||||
},
|
||||
},
|
||||
{
|
||||
"model_name": named,
|
||||
|
|
@ -1450,6 +1455,29 @@ def test_provider_wildcard_lists_a_name_a_named_deployment_serves_once(
|
|||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("wildcard_name", "named"),
|
||||
[("openrouter/*", "openrouter/openai/gpt-5.4-mini"), ("or-team/*", "or-team/openai/gpt-5.4-mini")],
|
||||
)
|
||||
def test_provider_wildcard_whose_whole_catalog_is_deployed_by_name_shows_only_the_named_row(
|
||||
monkeypatch: pytest.MonkeyPatch, wildcard_name: str, named: str
|
||||
) -> None:
|
||||
from litellm.proxy.auth.model_checks import expand_wildcard_deployments_for_model_info
|
||||
|
||||
with _openrouter_catalog_beside_a_named_deployment(
|
||||
monkeypatch,
|
||||
wildcard_name,
|
||||
named,
|
||||
catalog=("openai/gpt-5.4-mini",),
|
||||
wildcard_key=f"sk-or-one-model-{wildcard_name}",
|
||||
) as router:
|
||||
rows: Final = expand_wildcard_deployments_for_model_info(
|
||||
[dict(deployment) for deployment in router.get_model_list() or ()], llm_router=router
|
||||
)
|
||||
|
||||
assert [(row["model_name"], row["litellm_params"]["api_key"]) for row in rows] == [(named, "sk-or-named")]
|
||||
|
||||
|
||||
@respx.mock
|
||||
def test_custom_prefix_that_starts_a_discovered_id_still_prefixes_every_listed_model(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue