fix(realtime): bill retained output and route Azure aliases

This commit is contained in:
Emerson Gomes 2026-09-23 03:23:57 -05:00
parent 828707b9f2
commit 8f23d20367
No known key found for this signature in database
GPG key ID: D3DF28AB5D1B5E17
6 changed files with 38 additions and 17 deletions

View file

@ -450,7 +450,17 @@ class RealTimeStreaming:
output_seconds if isinstance(output_seconds, (int, float)) else synthetic_output_seconds
)
if isinstance(input_seconds, (int, float)) or resolved_output_seconds is not None:
if not self._should_store_message(event_obj):
if self._should_store_message(event_obj):
if not isinstance(output_seconds, (int, float)) and synthetic_output_seconds is not None:
self.messages.append(
OpenAIRealtimeTranslationClosedEvent(
type="session.closed",
usage=OpenAIRealtimeTranslationDurationUsage(
type="duration", output_seconds=synthetic_output_seconds
),
)
)
else:
normalized_usage: Final = (
OpenAIRealtimeTranslationDurationUsage(
type="duration",

View file

@ -43,18 +43,8 @@ class AzureAudioTranscription(AzureChatCompletion):
) -> TranscriptionResponse | Coroutine[Any, Any, TranscriptionResponse]:
data: Final = {"model": model, "file": audio_file, **optional_params}
sdk_data: Final = sdk_compatible_transcription_request_data(data)
model_info: Final = (
litellm.get_model_info(model=model, custom_llm_provider="azure")
if f"azure/{model}" in litellm.model_cost
else None
)
provider_specific_entry: Final = model_info.get("provider_specific_entry") if model_info is not None else None
resolved_api_version: Final = (
litellm.AZURE_DEFAULT_API_VERSION
if provider_specific_entry is not None
and provider_specific_entry.get("transcription_deployment_api") == 1
and api_version in ("v1", "latest", "preview")
else api_version
litellm.AZURE_DEFAULT_API_VERSION if api_version in ("v1", "latest", "preview") else api_version
)
if atranscription is True:

View file

@ -234,7 +234,6 @@
"mode": "audio_transcription",
"provider_specific_entry": {
"realtime_ga_only": 1,
"transcription_deployment_api": 1,
"transcription_json_only": 1
},
"source": "https://techcommunity.microsoft.com/blog/azure-ai-foundry-blog/introducing-gpt-transcribe-and-gpt-live-transcribe-in-microsoft-foundry/4541740",

View file

@ -234,7 +234,6 @@
"mode": "audio_transcription",
"provider_specific_entry": {
"realtime_ga_only": 1,
"transcription_deployment_api": 1,
"transcription_json_only": 1
},
"source": "https://techcommunity.microsoft.com/blog/azure-ai-foundry-blog/introducing-gpt-transcribe-and-gpt-live-transcribe-in-microsoft-foundry/4541740",

View file

@ -3027,6 +3027,28 @@ def test_translation_preserves_input_only_provider_usage(
assert closed_events[0]["usage"] == expected_usage
def test_translation_retained_input_only_close_event_bills_captured_output(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(litellm, "logged_real_time_event_types", "*")
streaming = RealTimeStreaming(
websocket=MagicMock(),
backend_ws=MagicMock(),
logging_obj=MagicMock(),
model="gpt-realtime-translate",
translation_session=True,
)
streaming._translation_output_audio_bytes = 48000
close_event: Final = {"type": "session.closed", "usage": {"type": "duration", "input_seconds": 0.25}}
streaming._capture_translation_output_audio(close_event)
streaming.store_message(close_event)
streaming._finalize_translation_usage()
usage_events: Final = tuple(event["usage"] for event in streaming.messages if event.get("type") == "session.closed")
assert len(usage_events) == 2
assert sum(usage.get("input_seconds", 0.0) for usage in usage_events) == 0.25
assert sum(usage.get("output_seconds", 0.0) for usage in usage_events) == 1.0
@pytest.mark.asyncio
async def test_audio_delta_frame_parsed_at_most_once():
client_ws = _beta_client_ws()

View file

@ -261,14 +261,15 @@ def test_gpt_live_transcribe_rejects_file_transcription(local_model_cost_map: No
("2025-04-01-preview", "2025-04-01-preview"),
],
)
def test_azure_gpt_transcribe_resolves_api_version_in_provider(
local_model_cost_map: None, api_version: str | None, expected_api_version: str | None
@pytest.mark.parametrize("model", ["gpt-transcribe", "custom-transcribe-deployment"])
def test_azure_audio_transcription_resolves_api_version_in_provider(
model: str, api_version: str | None, expected_api_version: str | None
) -> None:
handler = AzureAudioTranscription()
handler.async_audio_transcriptions = MagicMock(return_value=MagicMock())
handler.audio_transcriptions(
model="gpt-transcribe",
model=model,
audio_file=io.BytesIO(b"audio"),
optional_params={"stream": True},
logging_obj=MagicMock(),