mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-05 07:37:50 +00:00
Merge 3ee884a0d9 into cf7c35a117
This commit is contained in:
commit
07c7bd638c
5 changed files with 105 additions and 8 deletions
|
|
@ -12263,6 +12263,25 @@ async def _deployment_hidden_by_listing_callbacks(deployment: Deployment, user_a
|
|||
return listed_name in await _names_hidden_by_listing_callbacks(user_api_key_dict, (listed_name,))
|
||||
|
||||
|
||||
def _model_list_provider(model_id: str, router: Router | None, team_id: str | None) -> str:
|
||||
if router is None:
|
||||
return "openai"
|
||||
model_group: Final = router.routable_model_group(model_id)
|
||||
deployment: Final = router.get_deployment_by_model_group_name(model_group) or next(
|
||||
(Deployment.model_validate(row) for row in router.wildcard_route_deployments(model_group, team_id)), None
|
||||
)
|
||||
if deployment is None:
|
||||
return "openai"
|
||||
try:
|
||||
return litellm.get_llm_provider(
|
||||
model=deployment.litellm_params.model,
|
||||
custom_llm_provider=deployment.litellm_params.custom_llm_provider,
|
||||
api_base=deployment.litellm_params.api_base,
|
||||
)[1]
|
||||
except litellm.BadRequestError:
|
||||
return "openai"
|
||||
|
||||
|
||||
@router.get("/v1/models", dependencies=[Depends(user_api_key_auth)], tags=["model management"])
|
||||
@router.get(
|
||||
"/models", dependencies=[Depends(user_api_key_auth)], tags=["model management"]
|
||||
|
|
@ -12432,7 +12451,7 @@ async def model_list(
|
|||
for response_id, lookup_id in admin_entries:
|
||||
model_info = create_model_info_response(
|
||||
model_id=lookup_id,
|
||||
provider="openai",
|
||||
provider=_model_list_provider(lookup_id, llm_router, team_id or user_api_key_dict.team_id),
|
||||
include_metadata=include_metadata or False,
|
||||
fallback_type=fallback_type,
|
||||
llm_router=llm_router,
|
||||
|
|
@ -12503,7 +12522,7 @@ async def model_list(
|
|||
for response_id, lookup_id in entries:
|
||||
model_info = create_model_info_response(
|
||||
model_id=lookup_id,
|
||||
provider="openai",
|
||||
provider=_model_list_provider(lookup_id, llm_router, team_id or user_api_key_dict.team_id),
|
||||
include_metadata=include_metadata or False,
|
||||
fallback_type=fallback_type,
|
||||
llm_router=llm_router,
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ def patched_models(monkeypatch):
|
|||
monkeypatch.setattr(
|
||||
litellm,
|
||||
"get_llm_provider",
|
||||
lambda model: (model, "openai", None, None),
|
||||
lambda model, **kwargs: (model, "openai", None, None),
|
||||
)
|
||||
|
||||
return router
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ from litellm.proxy.proxy_server import (
|
|||
_get_proxy_model_info,
|
||||
_translate_model_name_for_response,
|
||||
)
|
||||
from litellm.types.router import DeploymentModelListingInfo
|
||||
from litellm.types.router import Deployment, DeploymentModelListingInfo
|
||||
|
||||
|
||||
def _team_row() -> dict:
|
||||
|
|
@ -880,6 +880,7 @@ async def test_v1_models_translates_team_model_for_access_group_key(monkeypatch)
|
|||
},
|
||||
}
|
||||
router = MagicMock()
|
||||
router.get_deployment_by_model_group_name.return_value = Deployment.model_validate(team_dep)
|
||||
router.get_model_names.return_value = ["model_name_teamX_uuid9"]
|
||||
router.get_model_access_groups.return_value = {"grp-a": ["model_name_teamX_uuid9"]}
|
||||
router.get_fully_blocked_model_names.return_value = set()
|
||||
|
|
@ -922,6 +923,7 @@ async def test_v1_models_keeps_internal_names_when_public_name_flag_disabled(
|
|||
},
|
||||
}
|
||||
router = MagicMock()
|
||||
router.get_deployment_by_model_group_name.return_value = Deployment.model_validate(team_dep)
|
||||
router.get_model_names.return_value = ["model_name_teamX_uuid9"]
|
||||
router.get_model_access_groups.return_value = {"grp-a": ["model_name_teamX_uuid9"]}
|
||||
router.get_fully_blocked_model_names.return_value = set()
|
||||
|
|
@ -957,6 +959,7 @@ async def test_v1_models_translates_team_model_with_metadata(monkeypatch):
|
|||
},
|
||||
}
|
||||
router = MagicMock()
|
||||
router.get_deployment_by_model_group_name.return_value = Deployment.model_validate(team_dep)
|
||||
router.get_model_names.return_value = ["model_name_teamX_uuid9"]
|
||||
router.get_model_access_groups.return_value = {"grp-a": ["model_name_teamX_uuid9"]}
|
||||
router.get_fully_blocked_model_names.return_value = set()
|
||||
|
|
@ -979,7 +982,7 @@ async def test_v1_models_translates_team_model_with_metadata(monkeypatch):
|
|||
"id": "tushar-gpt-4.1",
|
||||
"object": "model",
|
||||
"created": 1677610602,
|
||||
"owned_by": "openai",
|
||||
"owned_by": team_dep["litellm_params"]["model"].split("/")[0],
|
||||
"metadata": {"fallbacks": []},
|
||||
}
|
||||
]
|
||||
|
|
@ -1003,6 +1006,7 @@ async def test_v1_models_metadata_fallbacks_use_internal_routing_key(monkeypatch
|
|||
},
|
||||
}
|
||||
router = MagicMock()
|
||||
router.get_deployment_by_model_group_name.return_value = Deployment.model_validate(team_dep)
|
||||
router.get_model_names.return_value = ["model_name_teamX_uuid9"]
|
||||
router.get_model_access_groups.return_value = {"grp-a": ["model_name_teamX_uuid9"]}
|
||||
router.get_fully_blocked_model_names.return_value = set()
|
||||
|
|
@ -1027,7 +1031,7 @@ async def test_v1_models_metadata_fallbacks_use_internal_routing_key(monkeypatch
|
|||
"id": "tushar-gpt-4.1",
|
||||
"object": "model",
|
||||
"created": 1677610602,
|
||||
"owned_by": "openai",
|
||||
"owned_by": team_dep["litellm_params"]["model"].split("/")[0],
|
||||
"metadata": {"fallbacks": ["gpt-4o-backup"]},
|
||||
}
|
||||
]
|
||||
|
|
@ -1060,6 +1064,7 @@ async def test_v1_models_metadata_does_not_leak_other_team_fallbacks(monkeypatch
|
|||
},
|
||||
}
|
||||
router = MagicMock()
|
||||
router.get_deployment_by_model_group_name.return_value = Deployment.model_validate(team_x)
|
||||
router.get_model_names.return_value = ["model_name_teamX_uuid9"]
|
||||
router.get_model_access_groups.return_value = {"grp-a": ["model_name_teamX_uuid9"]}
|
||||
router.get_fully_blocked_model_names.return_value = set()
|
||||
|
|
@ -1086,7 +1091,7 @@ async def test_v1_models_metadata_does_not_leak_other_team_fallbacks(monkeypatch
|
|||
"id": "tushar-gpt-4.1",
|
||||
"object": "model",
|
||||
"created": 1677610602,
|
||||
"owned_by": "openai",
|
||||
"owned_by": team_x["litellm_params"]["model"].split("/")[0],
|
||||
"metadata": {"fallbacks": ["teamX-backup"]},
|
||||
}
|
||||
]
|
||||
|
|
@ -1108,6 +1113,7 @@ async def test_v1_models_team_alias_inherits_token_limits_and_chat_mode(monkeypa
|
|||
},
|
||||
}
|
||||
router = MagicMock()
|
||||
router.get_deployment_by_model_group_name.return_value = Deployment.model_validate(team_dep)
|
||||
router.get_model_names.return_value = ["model_name_teamX_terra_uuid"]
|
||||
router.get_model_access_groups.return_value = {"grp-a": ["model_name_teamX_terra_uuid"]}
|
||||
router.get_fully_blocked_model_names.return_value = set()
|
||||
|
|
@ -1133,7 +1139,7 @@ async def test_v1_models_team_alias_inherits_token_limits_and_chat_mode(monkeypa
|
|||
"id": "GPT Terra",
|
||||
"object": "model",
|
||||
"created": 1677610602,
|
||||
"owned_by": "openai",
|
||||
"owned_by": team_dep["litellm_params"]["model"].split("/")[0],
|
||||
"mode": "chat",
|
||||
"max_input_tokens": 876000,
|
||||
"max_output_tokens": 128000,
|
||||
|
|
@ -1156,6 +1162,7 @@ async def test_v1_models_team_image_alias_inherits_image_generation_mode(monkeyp
|
|||
},
|
||||
}
|
||||
router = MagicMock()
|
||||
router.get_deployment_by_model_group_name.return_value = Deployment.model_validate(team_dep)
|
||||
router.get_model_names.return_value = ["model_name_teamX_image_uuid"]
|
||||
router.get_model_access_groups.return_value = {"grp-a": ["model_name_teamX_image_uuid"]}
|
||||
router.get_fully_blocked_model_names.return_value = set()
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ def patched_model_list(monkeypatch):
|
|||
from litellm.proxy import utils as proxy_utils
|
||||
|
||||
router = MagicMock()
|
||||
router.get_deployment_by_model_group_name.return_value = None
|
||||
router.get_fully_blocked_model_names = MagicMock(return_value=set())
|
||||
router.async_get_fully_unhealthy_model_names = AsyncMock(
|
||||
return_value={"claude-sonnet"}
|
||||
|
|
|
|||
|
|
@ -3857,3 +3857,73 @@ async def test_model_list_return_wildcard_routes_defaults_to_general_setting(
|
|||
|
||||
assert "gpt-6.1-sol" in listed, listed
|
||||
assert ("openai/*" in listed) is wildcard_listed, listed
|
||||
|
||||
|
||||
@pytest.mark.parametrize("scope", [None, "expand"])
|
||||
@pytest.mark.parametrize("provider", ["azure", "anthropic", "openai"])
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_list_provider_matches_retrieval(
|
||||
monkeypatch: pytest.MonkeyPatch, scope: str | None, provider: str
|
||||
) -> None:
|
||||
router: Final = litellm.Router(
|
||||
model_list=[
|
||||
{
|
||||
"model_name": "hosted-model",
|
||||
"litellm_params": {
|
||||
"model": f"{provider}/deployment-model",
|
||||
"api_key": "sk-fake",
|
||||
"api_base": "https://provider.example.com",
|
||||
},
|
||||
},
|
||||
{
|
||||
"model_name": "prompt-model",
|
||||
"litellm_params": {"model": "gitlab/test-prompt"},
|
||||
},
|
||||
],
|
||||
model_group_alias={"friendly-name": "hosted-model"},
|
||||
)
|
||||
monkeypatch.setattr(litellm.proxy.proxy_server, "llm_router", router)
|
||||
monkeypatch.setattr(litellm.proxy.proxy_server, "llm_model_list", router.model_list)
|
||||
monkeypatch.setattr(litellm.proxy.proxy_server, "prisma_client", None)
|
||||
monkeypatch.setattr(litellm.proxy.proxy_server, "user_model", None)
|
||||
monkeypatch.setattr(litellm.proxy.proxy_server, "general_settings", {})
|
||||
caller: Final = UserAPIKeyAuth(api_key="sk-test", user_role=LitellmUserRoles.PROXY_ADMIN)
|
||||
|
||||
listing: Final = await litellm.proxy.proxy_server.model_list(user_api_key_dict=caller, scope=scope)
|
||||
|
||||
owners: Final = {row["id"]: row["owned_by"] for row in listing["data"]}
|
||||
assert owners == {"hosted-model": provider, "friendly-name": provider, "prompt-model": "openai"}
|
||||
for model_id in ("hosted-model", "friendly-name"):
|
||||
retrieved: Final = await litellm.proxy.proxy_server.model_info(model_id=model_id, user_api_key_dict=caller)
|
||||
assert owners[model_id] == retrieved["owned_by"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("scope", [None, "expand"])
|
||||
@pytest.mark.parametrize("prefix", ["anthropic", "public"])
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_list_expanded_names_use_wildcard_provider(
|
||||
monkeypatch: pytest.MonkeyPatch, scope: str | None, prefix: str
|
||||
) -> None:
|
||||
exact_name: Final = f"{prefix}/configured-model"
|
||||
router: Final = litellm.Router(
|
||||
model_list=[
|
||||
{"model_name": f"{prefix}/*", "litellm_params": {"model": "anthropic/*", "api_key": "sk-fake"}},
|
||||
{"model_name": exact_name, "litellm_params": {"model": "openai/configured-model", "api_key": "sk-fake"}},
|
||||
]
|
||||
)
|
||||
monkeypatch.setattr(litellm.proxy.proxy_server, "llm_router", router)
|
||||
monkeypatch.setattr(litellm.proxy.proxy_server, "llm_model_list", router.model_list)
|
||||
monkeypatch.setattr(litellm.proxy.proxy_server, "prisma_client", None)
|
||||
monkeypatch.setattr(litellm.proxy.proxy_server, "user_model", None)
|
||||
monkeypatch.setattr(litellm.proxy.proxy_server, "general_settings", {})
|
||||
|
||||
listing: Final = await litellm.proxy.proxy_server.model_list(
|
||||
user_api_key_dict=UserAPIKeyAuth(api_key="sk-test", user_role=LitellmUserRoles.PROXY_ADMIN),
|
||||
scope=scope,
|
||||
)
|
||||
|
||||
owners: Final = {row["id"]: row["owned_by"] for row in listing["data"]}
|
||||
expanded_owners: Final = {owner for name, owner in owners.items() if name != exact_name}
|
||||
assert expanded_owners == {"anthropic"}
|
||||
assert all(name.startswith(f"{prefix}/") and "*" not in name for name in owners)
|
||||
assert owners[exact_name] == "openai"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue