Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 54 additions & 2 deletions litellm/proxy/auth/model_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from litellm._logging import verbose_proxy_logger
from litellm.proxy._types import SpecialModelNames, UserAPIKeyAuth
from litellm.router import Router
from litellm.router_utils.fallback_event_handlers import get_fallback_model_group
from litellm.types.router import LiteLLM_Params
from litellm.utils import get_valid_models

Expand Down Expand Up @@ -52,7 +53,7 @@ def _get_models_from_access_groups(
if model in model_access_groups:
if (
not include_model_access_groups
): # remove access group, unless requested - e.g. when creating a key and trying to see list of models
): # remove access group, unless requested - e.g. when creating a key
idx_to_remove.append(idx)
new_models.extend(model_access_groups[model])

Expand Down Expand Up @@ -104,7 +105,8 @@ def get_key_models(
- List of model name strings
- Empty list if no models set
- If model_access_groups is provided, only return models that are in the access groups
- If include_model_access_groups is True, it includes the 'keys' of the model_access_groups in the response - {"beta-models": ["gpt-4", "claude-v1"]} -> returns 'beta-models'
- If include_model_access_groups is True, it includes the 'keys' of the model_access_groups
in the response - {"beta-models": ["gpt-4", "claude-v1"]} -> returns 'beta-models'
"""
all_models: List[str] = []
if len(user_api_key_dict.models) > 0:
Expand Down Expand Up @@ -287,3 +289,53 @@ def _get_wildcard_models(
unique_models.remove(model)

return all_wildcard_models


def get_all_fallbacks(
model: str,
llm_router: Optional[Router] = None,
fallback_type: str = "general",
) -> List[str]:
"""
Get all fallbacks for a given model from the router's fallback configuration.

Args:
model: The model name to get fallbacks for
llm_router: The LiteLLM router instance
fallback_type: Type of fallback ("general", "context_window", "content_policy")

Returns:
List of fallback model names. Empty list if no fallbacks found.
"""
if llm_router is None:
return []

# Get the appropriate fallback list based on type
fallbacks_config: list = []
if fallback_type == "general":
fallbacks_config = getattr(llm_router, "fallbacks", [])
elif fallback_type == "context_window":
fallbacks_config = getattr(llm_router, "context_window_fallbacks", [])
elif fallback_type == "content_policy":
fallbacks_config = getattr(llm_router, "content_policy_fallbacks", [])
else:
verbose_proxy_logger.warning(f"Unknown fallback_type: {fallback_type}")
return []

if not fallbacks_config:
return []

try:
# Use existing function to get fallback model group
fallback_model_group, _ = get_fallback_model_group(
fallbacks=fallbacks_config,
model_group=model
)

if fallback_model_group is None:
return []

return fallback_model_group
except Exception as e:
verbose_proxy_logger.error(f"Error getting fallbacks for model {model}: {e}")
return []
54 changes: 45 additions & 9 deletions litellm/proxy/proxy_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ def generate_feedback_box():
from litellm.proxy.auth.handle_jwt import JWTHandler
from litellm.proxy.auth.litellm_license import LicenseCheck
from litellm.proxy.auth.model_checks import (
get_all_fallbacks,
get_complete_model_list,
get_key_models,
get_mcp_server_ids,
Expand Down Expand Up @@ -3657,11 +3658,18 @@ async def model_list(
team_id: Optional[str] = None,
include_model_access_groups: Optional[bool] = False,
only_model_access_groups: Optional[bool] = False,
include_metadata: Optional[bool] = False,
fallback_type: Optional[str] = None,
):
"""
Use `/model/info` - to get detailed model information, example - pricing, mode, etc.

This is just for compatibility with openai projects like aider.

Query Parameters:
- include_metadata: Include additional metadata in the response with fallback information
- fallback_type: Type of fallbacks to include ("general", "context_window", "content_policy")
Defaults to "general" when include_metadata=true
"""
global llm_model_list, general_settings, llm_router, prisma_client, user_api_key_cache, proxy_logging_obj
all_models = []
Expand Down Expand Up @@ -3722,16 +3730,44 @@ async def model_list(
only_model_access_groups=only_model_access_groups,
)

# Build response data
model_data = []
for model in all_models:
model_info = {
"id": model,
"object": "model",
"created": DEFAULT_MODEL_CREATED_AT_TIME,
"owned_by": "openai",
}

# Add metadata if requested
if include_metadata:
metadata = {}

# Default fallback_type to "general" if include_metadata is true
effective_fallback_type = fallback_type if fallback_type is not None else "general"

# Validate fallback_type
valid_fallback_types = ["general", "context_window", "content_policy"]
if effective_fallback_type not in valid_fallback_types:
raise HTTPException(
status_code=400,
detail=f"Invalid fallback_type. Must be one of: {valid_fallback_types}"
)

fallbacks = get_all_fallbacks(
model=model,
llm_router=llm_router,
fallback_type=effective_fallback_type
)
metadata["fallbacks"] = fallbacks

model_info["metadata"] = metadata

model_data.append(model_info)

return dict(
data=[
{
"id": model,
"object": "model",
"created": DEFAULT_MODEL_CREATED_AT_TIME,
"owned_by": "openai",
}
for model in all_models
],
data=model_data,
object="list",
)

Expand Down
Loading