From 05a9d313ac6c7556071de726f3a12ecafa0b4b35 Mon Sep 17 00:00:00 2001 From: songkuan-zheng <252822057+songkuan-zheng@users.noreply.github.com> Date: Wed, 17 Jun 2026 11:24:19 +0000 Subject: [PATCH] perf(proxy): drop dead proxy_model_list fetch on the /v1/models user-filter hot path Greptile P2 thread on #29748 flagged that `proxy_model_list` flows into `_apply_user_models_filter` only to be passed through to `get_user_models`, where it is consumed exclusively on the `all-proxy-models` branch. `_apply_user_models_filter` already short-circuits and returns `all_models` unchanged when `all-proxy-models` is in the user's models list, so the parameter is never read on any reachable code path. Concrete cost: `apply_user_models_filter_to_deployments` (called on every `/v2/model/info` and the by-id branch of `/v1/model/info`) materializes the full router model-name list via `llm_router.get_model_names()` on each call, then threads it through three layers down to a function that always ignores it. Fix: - Drop `proxy_model_list` from `_apply_user_models_filter` signature. - Update both callers (`get_available_models_for_user`, `apply_user_models_filter_to_deployments`) to stop passing it. The former still computes `proxy_model_list` for legitimate downstream consumers (`get_complete_model_list`, `get_key_models`, etc.); the latter no longer needs `llm_router.get_model_names()` at all and drops the call. - Inside `_apply_user_models_filter`, pass `[]` to the surviving `get_user_models(...)` call with an inline comment naming the dead branch, so the structural contract of `get_user_models` is preserved for hypothetical future callers that do hit the `all-proxy-models` path. Local verification: - 59/59 tests/test_litellm/proxy/discovery_endpoints/ - 87/87 across discovery_endpoints + proxy_server/test_routes_model_info + proxy_server/test_team_model_name_translation --- litellm/proxy/utils.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/litellm/proxy/utils.py b/litellm/proxy/utils.py index c8ffb869c8f..beddf498dbd 100644 --- a/litellm/proxy/utils.py +++ b/litellm/proxy/utils.py @@ -6444,7 +6444,6 @@ async def get_available_models_for_user( all_models = await _apply_user_models_filter( all_models=all_models, user_api_key_dict=user_api_key_dict, - proxy_model_list=proxy_model_list, model_access_groups=model_access_groups, prisma_client=prisma_client, proxy_logging_obj=proxy_logging_obj, @@ -6457,7 +6456,6 @@ async def get_available_models_for_user( async def _apply_user_models_filter( all_models: List[str], user_api_key_dict: "UserAPIKeyAuth", - proxy_model_list: List[str], model_access_groups: Dict[str, List[str]], prisma_client: Optional["PrismaClient"], proxy_logging_obj: Optional["ProxyLogging"], @@ -6534,9 +6532,14 @@ async def _apply_user_models_filter( if SpecialModelNames.all_proxy_models.value in user_models: return all_models + # The `all-proxy-models` short-circuit above returned already, so + # `user_models` here never contains it; `get_user_models` reads + # `proxy_model_list` only on that branch, so passing [] is a no-op + # here and lets the caller skip a `llm_router.get_model_names()` call + # on every /v1/models and /v2/model/info request. user_allowed = get_user_models( user_models=user_models, - proxy_model_list=proxy_model_list, + proxy_model_list=[], model_access_groups=model_access_groups, ) return filter_models_by_user_access( @@ -6579,10 +6582,8 @@ async def apply_user_models_filter_to_deployments( return deployments if llm_router is None: - proxy_model_list: List[str] = [] model_access_groups: Dict[str, List[str]] = {} else: - proxy_model_list = llm_router.get_model_names() model_access_groups = llm_router.get_model_access_groups() distinct_model_names = list( @@ -6591,7 +6592,6 @@ async def apply_user_models_filter_to_deployments( allowed_model_names = await _apply_user_models_filter( all_models=distinct_model_names, user_api_key_dict=user_api_key_dict, - proxy_model_list=proxy_model_list, model_access_groups=model_access_groups, prisma_client=prisma_client, proxy_logging_obj=proxy_logging_obj,