refactor(audio-transcription): extract proxy stream helpers; drop unused imports

- proxy_server: extract `_coerce_stream_form_field` and `_wrap_audio_streaming_response` so the `audio_transcriptions` handler stays under PLR0915 (50-statement) limit.
- base transformation: remove unused `AsyncIterator` / `Iterator` imports flagged by F401.
- test: switch `TestProxyStreamCoercion` to import the new helper directly instead of mirroring the inline logic.

Signed-off-by: WaelRabah11 <wael.rabah@multiversecomputing.com>
This commit is contained in:
WaelRabah11 2026-04-29 02:10:44 +02:00
parent 935e580b0d
commit 55a9d308a2
3 changed files with 24 additions and 19 deletions

View file

@ -3,8 +3,6 @@ from dataclasses import dataclass
from typing import (
TYPE_CHECKING,
Any,
AsyncIterator,
Iterator,
List,
Optional,
Union,

View file

@ -8028,6 +8028,25 @@ async def audio_speech(
raise e
def _coerce_stream_form_field(data: Dict) -> None:
"""Form fields arrive as strings; coerce `stream` to a real bool in-place."""
raw = data.get("stream")
if isinstance(raw, str):
data["stream"] = raw.strip().lower() == "true"
def _wrap_audio_streaming_response(response: Any, fastapi_response: Response) -> Any:
"""Wrap a TranscriptionStreamingResponse iterator in FastAPI StreamingResponse
so SSE chunks flush directly instead of being JSON-serialized."""
if isinstance(response, TranscriptionStreamingResponse):
return StreamingResponse(
content=response,
media_type="text/event-stream",
headers=dict(fastapi_response.headers),
)
return response
@router.post(
"/v1/audio/transcriptions",
dependencies=[Depends(user_api_key_auth)],
@ -8056,10 +8075,7 @@ async def audio_transcriptions(
form_data = await get_form_data(request)
data = {key: value for key, value in form_data.items() if key != "file"}
# Form fields arrive as strings; coerce `stream` to bool so downstream
# provider transformation sees a real boolean.
if "stream" in data and isinstance(data["stream"], str):
data["stream"] = data["stream"].strip().lower() == "true"
_coerce_stream_form_field(data)
# Include original request and headers in the data
data = await add_litellm_data_to_request(
@ -8167,16 +8183,7 @@ async def audio_transcriptions(
if callback_headers:
fastapi_response.headers.update(callback_headers)
# Streaming transcription: wrap raw-byte iterator in StreamingResponse
# so FastAPI flushes SSE chunks instead of trying to JSON-serialize.
if isinstance(response, TranscriptionStreamingResponse):
return StreamingResponse(
content=response,
media_type="text/event-stream",
headers=dict(fastapi_response.headers),
)
return response
return _wrap_audio_streaming_response(response, fastapi_response)
except Exception as e:
await proxy_logging_obj.post_call_failure_hook(
user_api_key_dict=user_api_key_dict, original_exception=e, request_data=data

View file

@ -221,8 +221,8 @@ class TestProxyStreamCoercion:
],
)
def test_stream_coercion_logic(self, raw, expected):
# Mirror the inline coercion in proxy_server.audio_transcriptions
from litellm.proxy.proxy_server import _coerce_stream_form_field
data = {"stream": raw}
if "stream" in data and isinstance(data["stream"], str):
data["stream"] = data["stream"].strip().lower() == "true"
_coerce_stream_form_field(data)
assert data["stream"] is expected