fix(realtime): azure Foundry realtime endpoints + self-provision e2e realtime suite - #32558
Conversation
…endpoints The azure realtime handler appended the realtime path to api_base verbatim, so a Foundry base carrying a project path (.../api/projects/<name>) produced an invalid realtime URL and the websocket handshake hung. Normalize api_base to scheme and host before building the realtime path so both Azure OpenAI and Foundry bases connect Point the e2e realtime azure deployment at the GA gpt-realtime model and stop passing the os.environ refs the realtime path never unwraps, resolving them from the gateway env by name instead. Drop the local docker-compose scaffolding from the tree
Greptile SummaryThis PR fixes the Azure AI Foundry realtime URL construction (normalizing
Confidence Score: 4/5Safe to merge with one fix: the provisioning fixture can leak partially-created proxy deployments if an early provider raises before the try block is entered. The tests/e2e/llm_translation/realtime/conftest.py — provisioning loop sits outside the try/finally guard.
|
| Filename | Overview |
|---|---|
| litellm/ocr/main.py | Adds _is_doc_intelligence guard so that dynamic_api_base no longer overwrites a doc-intelligence endpoint with a generic Azure AI base; _rust_bridge_api_base then correctly falls through to AZURE_DOCUMENT_INTELLIGENCE_ENDPOINT when api_base is None. |
| tests/e2e/llm_translation/realtime/conftest.py | New fixture provisions realtime deployments via /model/new; partial provisioning failure before the try block leaves already-created models undeleted on the proxy. |
| tests/e2e/llm_translation/realtime/realtime_client.py | Replaces static skip_if_unconfigured + configured_models() pattern with self-provisioning via /model/new; RealtimeProvider gains litellm_params for deployment creation and PROVIDERS is updated with concrete model specs. |
| tests/e2e/llm_translation/realtime/test_realtime_e2e.py | Tests updated to use provisioned model names from realtime_models fixture instead of static aliases; otherwise unchanged. |
| tests/e2e/llm_translation/realtime/test_realtime_pipecat_audio_e2e.py | WAV fixture skip converted to assert (hard-fail); fixture path is correctly relative to the new location; tests updated to use provisioned model names. |
| tests/e2e/llm_translation/test_ocr_rust_e2e.py | Removes vertex_project/vertex_credentials os.environ refs from VertexOcr.litellm_params (the OCR path doesn't unwrap them); removes the vertex-deepseek test case; updates Azure AI model to mistral-document-ai-2512. |
| tests/e2e/models.py | Adds `realtime_protocol: str |
| tests/e2e/e2e_gateway.py | Adds list_files and list_fine_tuning_jobs gateway helpers; unrelated to the realtime/OCR fix but straightforward. |
Reviews (2): Last reviewed commit: "fix(ocr): route azure_ai doc-intelligenc..." | Re-trigger Greptile
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
ishaan-berri
left a comment
There was a problem hiding this comment.
small changes requested
…iscovery suite The discovery endpoints suite calls client.gateway.list_files and list_fine_tuning_jobs, which did not exist on Gateway, so both tests errored with AttributeError before reaching the proxy. Add the two GET wrappers using the existing FileListResponse / FineTuningJobsResponse models
The azure realtime handshake failure was a config issue, not a litellm bug: the realtime base was set to the Azure AI Foundry project endpoint (.../api/projects/<p>), but the OpenAI-compatible realtime route lives at the resource root. litellm correctly appends the realtime path to whatever base it is given, so pointing the realtime deployment at the resource root is the fix and no core change is needed
…source get_llm_provider inherits AZURE_AI_API_BASE into api_base for every azure_ai/* OCR model, but Azure Document Intelligence is a separate resource reached via AZURE_DOCUMENT_INTELLIGENCE_ENDPOINT, so doc-intelligence requests went to the wrong host. Stop inheriting the azure_ai base for doc-intelligence models so api_base stays unset and both the rust bridge and the python get_complete_url fall back to the document-intelligence endpoint. This drops the earlier _rust_bridge_api_base reorder, which only covered the rust path and let the env silently override an explicit api_base
|
closing in favor of #32577 to run CI |
Relevant issues
Linear ticket
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
Delays in PR merge?
If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).
Screenshots / Proof of Fix
Verified against a live proxy on
localhost:4000driving the real provider realtime APIs (OpenAI, Azure AI Foundry, Gemini AI Studio, Vertex AI), no mocks, real spendBefore the fix (branch at
a239ab1), the Azure realtime deployment pointed at an Azure AI Foundry base that carries a project path. The handler appended the realtime path to it verbatim, producing an invalid URL, so the websocket handshake hung and the client never got a session:After the fix (
23e608a),api_baseis normalized to scheme+host, the URL is correct, and the session establishes against real Azure:Full realtime raw-websocket suite, all four providers (text conversation and tool-call round-trip), every request reaching the real provider:
Gemini and Vertex need
LITELLM_GEMINI_LIVE_DEFER_SETUP=trueon the gateway so the deferred-setup path emitssession.updatedand the full Live to GA flow normalizes; Azure Foundry needsAZURE_API_BASE/AZURE_API_KEYset to the Foundry resourceType
🐛 Bug Fix
✅ Test
Changes
litellm/llms/azure/realtime/handler.py: the realtime URL builder appended the realtime path ontoapi_baseas given, so an Azure AI Foundry base likehttps://<resource>.services.ai.azure.com/api/projects/<project>yielded a URL with the project path in front of/openai/v1/realtimeand the handshake hung._construct_urlnow reducesapi_baseto scheme and host before appending the realtime path, which leaves a plain Azure OpenAI base unchanged and makes Foundry bases workThe e2e realtime suite now provisions each provider's deployment through
/model/newat session start instead of depending on a statically configured gateway model_list, so it is self-contained. The provider configs were corrected to the models that are actually served (Azuregpt-realtime, OpenAIgpt-realtime-2) and stopped passingos.environ/*references forapi_baseandvertex_project, which the realtime path does not unwrap; the gateway resolves those from its own environment by name.models.pygains arealtime_protocolfield on the deployment bodyThis branch also carries the earlier rust OCR fix:
litellm/ocr/main.pyrouted Azure Document Intelligence OCR through the genericazure_aibase because the doc-intelligence branch in_rust_bridge_api_basesat after an early return that always matched, so it now resolvesAZURE_DOCUMENT_INTELLIGENCE_ENDPOINTfirst, and the rust OCR e2e cases were pointed at the correct regions and env resolution