diff --git a/litellm/proxy/route_llm_request.py b/litellm/proxy/route_llm_request.py index 3301c345749..8870aeb9abe 100644 --- a/litellm/proxy/route_llm_request.py +++ b/litellm/proxy/route_llm_request.py @@ -488,13 +488,7 @@ async def _route_request_single_attempt( # noqa: ANN202 # returns unawaited pr has_router_settings_override: Final = "router_settings_override" in data if has_router_settings_override: - # Apply per-request router settings overrides from key/team config - # Instead of creating a new Router (expensive), merge settings into kwargs - # The Router already supports per-request overrides for these settings override_settings: Final = data.pop("router_settings_override") - - # Settings that the Router accepts as per-request kwargs - # These override the global router settings for this specific request per_request_settings: Final = ( "fallbacks", "context_window_fallbacks", @@ -507,7 +501,6 @@ async def _route_request_single_attempt( # noqa: ANN202 # returns unawaited pr ) if isinstance(override_settings, dict): - # Merge override settings into data (only if not already set in request) for key in per_request_settings: if key in override_settings and key not in data: data[key] = override_settings[key] @@ -536,7 +529,6 @@ async def _route_request_single_attempt( # noqa: ANN202 # returns unawaited pr return _route_user_config_request(data, route_type) elif has_router_settings_override: - # Use main router with overridden kwargs if llm_router is not None: return getattr(llm_router, f"{route_type}")(**data) else: diff --git a/tests/test_litellm/proxy/test_route_llm_request.py b/tests/test_litellm/proxy/test_route_llm_request.py index a37ec3858d7..5abbda91b8b 100644 --- a/tests/test_litellm/proxy/test_route_llm_request.py +++ b/tests/test_litellm/proxy/test_route_llm_request.py @@ -511,6 +511,41 @@ async def test_route_request_with_router_settings_override_and_api_key(): assert "model_group_alias" not in call_kwargs +@pytest.mark.asyncio +async def test_route_request_with_router_settings_override_and_api_key_real_router(): + import litellm + + router: Final = litellm.Router( + model_list=[ + { + "model_name": "gpt-3.5-turbo", + "litellm_params": { + "model": "openai/gpt-3.5-turbo", + "api_key": "fake", + "mock_response": "real-router-success", + }, + } + ] + ) + data = { + "model": "gpt-3.5-turbo", + "messages": [{"role": "user", "content": "Hello"}], + "api_key": "sk-user-test-key", + "router_settings_override": { + "num_retries": 3, + "timeout": 15, + }, + } + + coroutine = await route_request(data, router, None, "acompletion") + response = await coroutine + + assert response.choices[0].message.content == "real-router-success" + assert "router_settings_override" not in data + assert data["num_retries"] == 3 + assert data["timeout"] == 15 + + def test_gated_mock_params_cover_mock_router_testing_params(): """``GATED_MOCK_PARAM_NAMES`` is hardcoded to avoid a cyclic import against ``litellm.types.router``. This test guards against drift — if a