diff --git a/litellm/realtime_api/main.py b/litellm/realtime_api/main.py index e88f52b91f9..046665c8f18 100644 --- a/litellm/realtime_api/main.py +++ b/litellm/realtime_api/main.py @@ -356,9 +356,15 @@ async def _arealtime( query_params=query_params, ) elif _custom_llm_provider == "azure": - api_base = dynamic_api_base or litellm_params.api_base or litellm.api_base or get_secret_str("AZURE_API_BASE") + api_base = ( + dynamic_api_base + or api_base + or litellm_params.api_base + or litellm.api_base + or get_secret_str("AZURE_API_BASE") + ) # set API KEY - api_key = dynamic_api_key or litellm.api_key or litellm.openai_key or get_secret_str("AZURE_API_KEY") + api_key = dynamic_api_key or api_key or litellm.api_key or litellm.openai_key or get_secret_str("AZURE_API_KEY") api_version = api_version or litellm_params.api_version or "2024-10-01-preview" @@ -386,9 +392,13 @@ async def _arealtime( litellm_metadata=_build_litellm_metadata(kwargs), ) elif _custom_llm_provider == "openai": - api_base = dynamic_api_base or litellm_params.api_base or litellm.api_base or "https://api.openai.com/" + api_base = ( + dynamic_api_base or api_base or litellm_params.api_base or litellm.api_base or "https://api.openai.com/" + ) # set API KEY - api_key = dynamic_api_key or litellm.api_key or litellm.openai_key or get_secret_str("OPENAI_API_KEY") + api_key = ( + dynamic_api_key or api_key or litellm.api_key or litellm.openai_key or get_secret_str("OPENAI_API_KEY") + ) await openai_realtime.async_realtime( model=model, @@ -590,4 +600,4 @@ async def _realtime_health_check( max_size=REALTIME_WEBSOCKET_MAX_MESSAGE_SIZE_BYTES, ssl=ssl_context, ): - return True + return True \ No newline at end of file diff --git a/tests/test_litellm/realtime_api/test_main.py b/tests/test_litellm/realtime_api/test_main.py index 406f5ef56d9..2c6efa20f5e 100644 --- a/tests/test_litellm/realtime_api/test_main.py +++ b/tests/test_litellm/realtime_api/test_main.py @@ -103,3 +103,51 @@ def test_client_secret_forwards_nested_transcription_model_untouched(monkeypatch session = captured["request_data"]["session"] assert session["model"] == "gpt-4o-realtime-preview" assert session["input_audio_transcription"]["model"] == "whisper-1" + + +def _run_arealtime(monkeypatch, provider, **kwargs): + captured = {} + + async def mock_async_realtime(**call_kwargs): + captured.update(call_kwargs) + + def mock_get_llm_provider(model, api_base, api_key): + return model, provider, None, None + + monkeypatch.setattr(realtime_main, "get_llm_provider", mock_get_llm_provider) + handler = realtime_main.openai_realtime if provider == "openai" else realtime_main.azure_realtime + monkeypatch.setattr(handler, "async_realtime", mock_async_realtime) + + asyncio.run( + realtime_main._arealtime.__wrapped__( + model="gpt-4o-realtime-preview", + websocket=object(), + litellm_logging_obj=FakeLogging(), + **kwargs, + ) + ) + return captured + + +def test_openai_realtime_uses_explicit_api_key(monkeypatch): + """A key resolved from litellm_credential_name arrives as the explicit + api_key argument and must not be discarded.""" + monkeypatch.delenv("OPENAI_API_KEY", raising=False) + monkeypatch.setattr(realtime_main.litellm, "api_key", None) + monkeypatch.setattr(realtime_main.litellm, "openai_key", None) + + captured = _run_arealtime(monkeypatch, "openai", api_key="sk-from-credential", api_base="http://localhost:8799") + assert captured["api_key"] == "sk-from-credential" + assert captured["api_base"] == "http://localhost:8799" + + +def test_azure_realtime_uses_explicit_api_key(monkeypatch): + monkeypatch.delenv("AZURE_API_KEY", raising=False) + monkeypatch.delenv("AZURE_API_BASE", raising=False) + monkeypatch.setattr(realtime_main.litellm, "api_key", None) + monkeypatch.setattr(realtime_main.litellm, "openai_key", None) + + captured = _run_arealtime( + monkeypatch, "azure", api_key="azure-from-credential", api_base="https://my-azure.openai.azure.com" + ) + assert captured["api_key"] == "azure-from-credential" \ No newline at end of file