diff --git a/litellm/router.py b/litellm/router.py index aa2a98d5c23..876d161e227 100644 --- a/litellm/router.py +++ b/litellm/router.py @@ -4594,6 +4594,16 @@ class Router: if custom_llm_provider is not None: response_kwargs["custom_llm_provider"] = custom_llm_provider + # kwargs["session"] (e.g. realtime client_secrets) still has whatever + # model string the caller/proxy originally sent (a model_name/alias), + # not model_name resolved above. acreate_realtime_client_secret + # prioritizes session.model over the model kwarg, so leaving it + # unresolved would silently route with the alias instead of the + # deployment litellm picked. See BerriAI/litellm#36742. + session = response_kwargs.get("session") + if isinstance(session, dict) and session.get("model"): + response_kwargs["session"] = {**session, "model": model_name} + response = original_generic_function(**response_kwargs) rpm_semaphore: Final = self._get_client( diff --git a/tests/router_unit_tests/test_router_endpoints.py b/tests/router_unit_tests/test_router_endpoints.py index 658ad4f3b5c..a6ed1388e24 100644 --- a/tests/router_unit_tests/test_router_endpoints.py +++ b/tests/router_unit_tests/test_router_endpoints.py @@ -524,6 +524,42 @@ def test_generic_api_call_with_fallbacks_basic(sync_mode): assert response == mock_response +@pytest.mark.asyncio +async def test_ageneric_api_call_with_fallbacks_resolves_session_model(): + """ + Regression test for https://github.com/BerriAI/litellm/issues/36742: when a + call has a nested session.model (realtime client_secrets), it must be + rewritten to the deployment litellm actually picked for the model_group, + not left as the caller's original alias. + """ + mock_function = AsyncMock() + mock_function.__name__ = "acreate_realtime_client_secret" + mock_function.return_value = {"value": "ek_test"} + + router = Router( + model_list=[ + { + "model_name": "gpt-realtime-2-1-mini", + "litellm_params": { + "model": "azure/gpt-realtime-2-1-mini-deployment", + "api_key": "fake-api-key", + "api_base": "https://fake.openai.azure.com", + }, + } + ] + ) + + await router._ageneric_api_call_with_fallbacks( + model="gpt-realtime-2-1-mini", + original_function=mock_function, + session={"type": "realtime", "model": "gpt-realtime-2-1-mini"}, + ) + + call_kwargs = mock_function.call_args.kwargs + assert call_kwargs["model"] == "azure/gpt-realtime-2-1-mini-deployment" + assert call_kwargs["session"]["model"] == "azure/gpt-realtime-2-1-mini-deployment" + + @pytest.mark.asyncio async def test_aadapter_completion(): """