feat: add GA protocol as litellm_params for realtime api on azure provider

This commit is contained in:
abi_jey
2025-11-25 19:18:41 +00:00
parent 3249f6dd2d
commit aec0ab777b
2 changed files with 105 additions and 5 deletions
+49 -5
View File
@@ -28,16 +28,60 @@ async def forward_messages(client_ws: Any, backend_ws: Any):
class AzureOpenAIRealtime(AzureChatCompletion):
def _construct_url(self, api_base: str, model: str, api_version: str) -> str:
def _get_realtime_protocol(self) -> str:
"""Return the configured realtime protocol.
Supported values (case-insensitive):
- "beta" -> use legacy `/openai/realtime` (current default)
- "v1" -> use `/openai/v1/realtime`
- "ga" -> alias for "v1" (GA path is v1)
If the parameter is missing or invalid, we fall back to the current
behavior for full backwards compatibility.
"""
Example output:
# `litellm_params` is the standard place to configure provider-specific
# behavior. We keep this defensive in case the attribute isn't set.
params: Any = getattr(self, "litellm_params", None)
if not isinstance(params, dict):
return "beta"
value = params.get("realtime_protocol")
if not isinstance(value, str):
return "beta"
value_normalized = value.lower()
if value_normalized in {"v1", "ga"}:
return "v1"
# Treat anything else (including explicit "beta") as current default
return "beta"
def _construct_url(
self,
api_base: str,
model: str,
api_version: str,
) -> str:
"""Construct the websocket URL for Azure OpenAI realtime.
Example default output (beta / legacy behavior):
"wss://my-endpoint-sweden-berri992.openai.azure.com/openai/realtime?api-version=2024-10-01-preview&deployment=gpt-4o-realtime-preview";
When `realtime_protocol` is set to "v1" or "GA" via `litellm_params`,
this switches to `/openai/v1/realtime`.
"""
api_base = api_base.replace("https://", "wss://")
return (
f"{api_base}/openai/realtime?api-version={api_version}&deployment={model}"
)
protocol = self._get_realtime_protocol()
if protocol == "v1":
path = "/openai/v1/realtime"
else:
# default / beta behavior
path = "/openai/realtime"
return f"{api_base}{path}?api-version={api_version}&deployment={model}"
async def async_realtime(
self,
@@ -71,3 +71,59 @@ async def test_async_realtime_uses_max_size_parameter():
mock_realtime_streaming.assert_called_once()
mock_streaming_instance.bidirectional_forward.assert_awaited_once()
@pytest.mark.asyncio
async def test_construct_url_uses_legacy_realtime_by_default():
"""By default we should keep using `/openai/realtime` (beta behavior)."""
from litellm.llms.azure.realtime.handler import AzureOpenAIRealtime
handler = AzureOpenAIRealtime()
api_base = "https://my-endpoint.openai.azure.com"
api_version = "2024-10-01-preview"
model = "gpt-4o-realtime-preview"
url = handler._construct_url(api_base=api_base, model=model, api_version=api_version)
assert url.startswith("wss://my-endpoint.openai.azure.com")
assert "/openai/realtime" in url
assert "/openai/v1/realtime" not in url
@pytest.mark.asyncio
async def test_construct_url_uses_v1_when_realtime_protocol_v1_or_ga():
"""Setting `realtime_protocol` to v1/GA should switch to `/openai/v1/realtime`."""
from litellm.llms.azure.realtime.handler import AzureOpenAIRealtime
api_base = "https://my-endpoint.openai.azure.com"
api_version = "2024-10-01-preview"
model = "gpt-4o-realtime-preview"
# Helper to construct handler URL with a specific realtime_protocol.
# We avoid mutating handler attributes directly since type checkers don't
# know about `litellm_params` on this class. Instead, we patch the
# `_get_realtime_protocol` helper which is what `_construct_url` uses.
# v1 -> /openai/v1/realtime
handler_v1 = AzureOpenAIRealtime()
with patch.object(handler_v1, "_get_realtime_protocol", return_value="v1"):
url_v1 = handler_v1._construct_url(api_base=api_base, model=model, api_version=api_version)
assert "/openai/v1/realtime" in url_v1
assert "/openai/realtime" not in url_v1
# GA (case-insensitive) -> /openai/v1/realtime
handler_ga = AzureOpenAIRealtime()
with patch.object(handler_ga, "_get_realtime_protocol", return_value="v1"):
url_ga = handler_ga._construct_url(api_base=api_base, model=model, api_version=api_version)
assert "/openai/v1/realtime" in url_ga
assert "/openai/realtime" not in url_ga
# beta or any other value keeps legacy path
handler_beta = AzureOpenAIRealtime()
with patch.object(handler_beta, "_get_realtime_protocol", return_value="beta"):
url_beta = handler_beta._construct_url(api_base=api_base, model=model, api_version=api_version)
assert "/openai/realtime" in url_beta
assert "/openai/v1/realtime" not in url_beta