[Bugfix][Qwen3-TTS] Ignore voice labels for inline Base cloning (#6974)

Signed-off-by: sc-hua <sc_hua@qq.com>
This commit is contained in:
Sicheng Hua authored and GitHub committed 2026-09-22 16:19:37 -07:00
1 parent 7d6e2ade6c
commit d2aa07159c
3 files changed
+39 -2

No files matched your search

@@ -152,3 +152,23 @@ def test_xvector_then_icl_same_ref_audio_keeps_engine_alive(omni_server, online_
online_client.send_audio_speech_request({**base_request, "x_vector_only_mode": True})
online_client.send_audio_speech_request({**base_request, "x_vector_only_mode": False, "ref_text": REF_TEXT})
online_client.send_audio_speech_request({**base_request, "x_vector_only_mode": True})
@hardware_test(res={"cuda": "L4"}, num_cards=1)
@pytest.mark.parametrize("omni_server", tts_async_chunk_server_params, indirect=True)
def test_inline_ref_audio_cache_ignores_openai_voice_label(omni_server, online_client) -> None:
"""An OpenAI voice label must not identify an inline Base voice clone."""
base_request = {
"model": omni_server.model,
"input": get_prompt(),
"stream": False,
"timeout": DEFAULT_AUDIO_SPEECH_TIMEOUT_S,
"response_format": "wav",
"task_type": "Base",
"ref_audio": REF_AUDIO_URL,
"ref_text": REF_TEXT,
"min_audio_bytes": 1,
}
online_client.send_audio_speech_request({**base_request, "voice": "voice-a"})
online_client.send_audio_speech_request({**base_request, "voice": "voice-b"})
@@ -5507,8 +5507,9 @@ class TestTTSAsyncOffloading:
assert prompt["additional_information"]["non_streaming_mode"] == [True]
assert "full_utterance_decode" not in prompt["additional_information"]
def test_qwen3_repeated_ref_audio_hot_path_sends_cache_key_without_waveform(self, qwen3_tts_server):
"""After a ref artifact is marked ready, repeated requests avoid ref_audio payload IPC."""
def test_qwen3_inline_ref_audio_hot_path_does_not_use_named_speaker_cache(self, qwen3_tts_server, mocker):
"""An OpenAI-compatible voice does not identify an inline voice clone."""
ignored_voice_log = mocker.patch("vllm_omni.entrypoints.openai.tts_adapters.qwen3_tts.logger.info")
wav_list = [0.0] * 48000
artifact_key = "a" * 40
ref_audio = "data:audio/wav;base64,same"
@@ -5531,6 +5532,7 @@ class TestTTSAsyncOffloading:
request = OpenAICreateSpeechRequest(
input="hello",
voice="voice-a",
task_type="Base",
ref_audio=ref_audio,
ref_text="reference",
@@ -5540,7 +5542,14 @@ class TestTTSAsyncOffloading:
)
assert request_id == "req-hot"
assert request.voice == "voice-a"
ignored_voice_log.assert_called_once_with(
"Ignoring voice=%r for Qwen3-TTS Base request because inline ref_audio takes precedence",
"voice-a",
)
assert "ref_audio" not in tts_params
assert "speaker" not in tts_params
assert "voice_created_at" not in tts_params
assert tts_params["_qwen3_tts_ref_audio_cache_key"] == [artifact_key]
assert tts_params["ref_code_length"] == [50]
prompt = qwen3_tts_server.engine_client.generate.call_args.kwargs["prompt"]
@@ -431,6 +431,14 @@ class Qwen3TTSAdapter(ARTTSAdapter):
Qwen3-TTS ref-audio artifact tracked after ``generate()``.
"""
server = self.ctx.server
# Inline Base cloning derives its voice from ref_audio, not the
# OpenAI-compatible voice label.
if has_inline_ref_audio and request.task_type == "Base" and request.voice is not None:
logger.info(
"Ignoring voice=%r for Qwen3-TTS Base request because inline ref_audio takes precedence",
request.voice,
)
request = request.model_copy(update={"voice": None})
qwen3_ref_audio_warmup_artifact_key: str | None = None
tts_params = self._build_tts_params(request)
# Resolve ref_audio (explicit or auto-set for uploaded voices)