fix: add ModelsLab TTS dispatch in main.py and handle poll errors

Two issues addressed based on Greptile review:

1. **Critical - missing dispatch handler**: Add 'modelslab' elif branch in
   litellm/main.py speech() function so litellm.speech(model='modelslab/...')
   is routable. Uses base_llm_http_handler.text_to_speech_handler() following
   the same pattern as minimax and other providers.

2. **Poll error handling**: When _poll_tts_sync() returns status='error',
   raise BaseLLMException with the actual error message instead of falling
   through to the confusing 'no audio URL' error.
This commit is contained in:
adhikjoshi 2026-03-02 06:05:46 +05:30
parent 1de97cf2e1
commit 239abc14ae
2 changed files with 40 additions and 0 deletions

View file

@ -177,6 +177,13 @@ class ModelsLabTextToSpeechConfig(BaseTextToSpeechConfig):
if status == "processing":
response_data = self._poll_tts_sync(request_id)
# Re-check status from polled response
if response_data.get("status") == "error":
raise BaseLLMException(
status_code=500,
message=response_data.get("message", "ModelsLab TTS failed"),
headers={},
)
audio_url = response_data.get("output", "")
if not audio_url:

View file

@ -6976,6 +6976,39 @@ def speech( # noqa: PLR0915
**kwargs,
)
elif custom_llm_provider == "modelslab":
from litellm.llms.modelslab.text_to_speech.transformation import (
ModelsLabTextToSpeechConfig,
)
# ModelsLab Text-to-Speech
if text_to_speech_provider_config is None:
text_to_speech_provider_config = ModelsLabTextToSpeechConfig()
modelslab_tts_config = cast(ModelsLabTextToSpeechConfig, text_to_speech_provider_config)
# Convert voice to string if it is a dict
modelslab_voice_str: Optional[str] = None
if isinstance(voice, str):
modelslab_voice_str = voice
elif isinstance(voice, dict):
modelslab_voice_str = voice.get("voice_id") or voice.get("id") or voice.get("name")
response = base_llm_http_handler.text_to_speech_handler(
model=model,
input=input,
voice=modelslab_voice_str,
text_to_speech_provider_config=modelslab_tts_config,
text_to_speech_optional_params=optional_params,
custom_llm_provider=custom_llm_provider,
litellm_params=litellm_params_dict,
logging_obj=logging_obj,
timeout=timeout,
extra_headers=extra_headers,
client=client,
_is_async=aspeech or False,
)
if response is None:
raise Exception(
"Unable to map the custom llm provider={} to a known provider={}.".format(