From 35b328c46c6a88290b4be59e75dc284a4c35261d Mon Sep 17 00:00:00 2001 From: Mubashir Osmani Date: Sat, 18 Jul 2026 22:24:42 +0000 Subject: [PATCH] fix(dashscope): route qwen3-tts-vc tts to dashscope handler and cover speech dispatch Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- litellm/main.py | 4 ++- ...dashscope_text_to_speech_transformation.py | 27 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/litellm/main.py b/litellm/main.py index e1ea631a4eb..db78d4453a0 100644 --- a/litellm/main.py +++ b/litellm/main.py @@ -7857,7 +7857,9 @@ def speech( Coroutine[Any, Any, HttpxBinaryResponseContent], None, ] = None - if custom_llm_provider == "openai" or custom_llm_provider in litellm.openai_compatible_providers: + if ( + custom_llm_provider == "openai" or custom_llm_provider in litellm.openai_compatible_providers + ) and custom_llm_provider != "dashscope": if voice is None or not (isinstance(voice, str)): raise litellm.BadRequestError( message="'voice' is required to be passed as a string for OpenAI TTS", diff --git a/tests/test_litellm/llms/dashscope/test_dashscope_text_to_speech_transformation.py b/tests/test_litellm/llms/dashscope/test_dashscope_text_to_speech_transformation.py index ad7c5b9c7c5..8c62b74a748 100644 --- a/tests/test_litellm/llms/dashscope/test_dashscope_text_to_speech_transformation.py +++ b/tests/test_litellm/llms/dashscope/test_dashscope_text_to_speech_transformation.py @@ -102,3 +102,30 @@ def test_transform_response_raises_without_audio_url(config: DashScopeTextToSpee config.transform_text_to_speech_response( model="qwen3-tts-vc", raw_response=raw, logging_obj=MagicMock() ) + + +def test_speech_dispatches_to_dashscope_handler(): + import litellm + + fake_audio = MagicMock() + + with patch.object( + litellm.main.base_llm_http_handler, + "text_to_speech_handler", + return_value=fake_audio, + ) as mock_handler: + result = litellm.speech( + model="dashscope/qwen3-tts-vc", + input="hello world", + voice="my-cloned-voice", + api_key="sk-test", + ) + + assert result is fake_audio + mock_handler.assert_called_once() + kwargs = mock_handler.call_args.kwargs + assert kwargs["custom_llm_provider"] == "dashscope" + assert kwargs["model"] == "qwen3-tts-vc" + assert kwargs["voice"] == "my-cloned-voice" + assert isinstance(kwargs["text_to_speech_provider_config"], DashScopeTextToSpeechConfig) + assert kwargs["litellm_params"]["api_key"] == "sk-test"