fix(audio): pass stream, languages and keywords through unchecked for non-OpenAI transcription providers

Providers without a streaming transcription handler got UnsupportedParamsError
for stream=True, languages and keywords, where the merge base forwarded them as
provider-specific params. Only openai and azure validate them now.
This commit is contained in:
mateo-berri 2026-10-20 02:32:55 -07:00 • committed by Emerson Gomes
parent 2501523ecd
commit 572bf65013
No known key found for this signature in database
GPG key ID: D3DF28AB5D1B5E17
2 changed files with 31 additions and 11 deletions

View file

@ -4033,6 +4033,9 @@ def _get_non_default_params(passed_params: dict, default_params: dict, additiona
return non_default_params
_OPENAI_SDK_ONLY_TRANSCRIPTION_PARAMS: Final = frozenset(("languages", "keywords", "stream"))
def get_optional_params_transcription(
model: str,
custom_llm_provider: str,
@ -4060,16 +4063,13 @@ def get_optional_params_transcription(
for k, v in special_params.items():
passed_params[k] = v
default_params: Final = {
"language": None,
"languages": None,
"keywords": None,
"prompt": None,
"response_format": None,
"temperature": None, # openai defaults this to 0
"timestamp_granularities": None,
"stream": None,
}
sends_through_openai_sdk: Final = custom_llm_provider in ("openai", "azure")
transcription_params: Final = (
OPENAI_TRANSCRIPTION_PARAMS
if sends_through_openai_sdk
else [param for param in OPENAI_TRANSCRIPTION_PARAMS if param not in _OPENAI_SDK_ONLY_TRANSCRIPTION_PARAMS]
)
default_params: Final = {param: None for param in (*transcription_params, "prompt", "temperature")}
non_default_params = {k: v for k, v in passed_params.items() if (k in default_params and v != default_params[k])}
optional_params = {}
@ -4122,7 +4122,7 @@ def get_optional_params_transcription(
optional_params=optional_params,
passed_params=passed_params,
custom_llm_provider=custom_llm_provider,
openai_params=OPENAI_TRANSCRIPTION_PARAMS,
openai_params=transcription_params,
additional_drop_params=kwargs.get("additional_drop_params", None),
)
extra_body: Final = optional_params.get("extra_body")

View file

@ -103,6 +103,7 @@ from litellm.utils import (
client,
get_non_default_completion_params,
get_optional_params_image_gen,
get_optional_params_transcription,
get_prompt_cache_min_tokens,
get_supported_openai_params,
get_token_count,
@ -10498,6 +10499,25 @@ def test_get_provider_audio_transcription_config_resolves_for_every_provider() -
assert isinstance(configs[LlmProviders.OPENAI], litellm.OpenAIWhisperAudioTranscriptionConfig)
@pytest.mark.parametrize(
("custom_llm_provider", "model"),
[
("groq", "whisper-large-v3"),
("deepgram", "nova-3"),
("mistral", "voxtral-mini-latest"),
("elevenlabs", "scribe_v1"),
("fireworks_ai", "whisper-v3"),
],
)
def test_openai_sdk_transcription_params_pass_through_to_other_providers(custom_llm_provider: str, model: str) -> None:
hints: Final = {"stream": True, "languages": ["en"], "keywords": ["LiteLLM"]}
params: Final = get_optional_params_transcription(model=model, custom_llm_provider=custom_llm_provider, **hints)
forwarded: Final = {**params.get("extra_body", {}), **params}
assert {key: forwarded.get(key) for key in hints} == hints
@pytest.mark.parametrize(
("model", "optional_params", "expected_response_format"),
[