From 0798b0bf03cb6e7c4dc40ee58fe12ce492ce255f Mon Sep 17 00:00:00 2001 From: Sy03 <1370724210@qq.com> Date: Sun, 5 Jul 2026 01:47:11 +0800 Subject: [PATCH] [Bugfix][Qwen3-TTS] Seed residual MTP sampling (#4869) Signed-off-by: Sy03 <1370724210@qq.com> Co-authored-by: Yueqian Lin --- .../openai_api/test_serving_speech.py | 21 ++++++++++++++ .../deploy/qwen3_tts_high_concurrency.yaml | 2 -- vllm_omni/deploy/voxcpm2.yaml | 29 ++++++++++--------- .../entrypoints/openai/serving_speech.py | 12 ++++++++ 4 files changed, 48 insertions(+), 16 deletions(-) diff --git a/tests/entrypoints/openai_api/test_serving_speech.py b/tests/entrypoints/openai_api/test_serving_speech.py index bed775ee2..8f2797bc7 100644 --- a/tests/entrypoints/openai_api/test_serving_speech.py +++ b/tests/entrypoints/openai_api/test_serving_speech.py @@ -3344,6 +3344,27 @@ class TestTTSAsyncOffloading: qwen3_tts_server._build_tts_params.assert_called_once() qwen3_tts_server._estimate_prompt_len_async.assert_awaited_once() + def test_prepare_speech_generation_qwen3_default_seed_sets_tts_local_seed( + self, qwen3_tts_server, mocker: MockerFixture + ): + """Deploy default seed should seed Qwen3 TTS residual MTP sampling.""" + qwen3_tts_server.engine_client.default_sampling_params_list = [ + SimpleNamespace(max_tokens=2048, seed=42, extra_args=None) + ] + qwen3_tts_server._validate_tts_request = mocker.MagicMock(return_value=None) + qwen3_tts_server._build_tts_params = mocker.MagicMock( + return_value={"text": ["hello"], "task_type": ["CustomVoice"], "speaker": ["Vivian"]} + ) + qwen3_tts_server._estimate_prompt_len_async = mocker.AsyncMock(return_value=512) + request = OpenAICreateSpeechRequest(input="hello") + + asyncio.run(qwen3_tts_server._prepare_speech_generation(request)) + + stage0_params = qwen3_tts_server.engine_client.generate.call_args.kwargs["sampling_params_list"][0] + assert stage0_params.seed == 42 + assert stage0_params.extra_args["tts_local_seed"] == 42 + assert qwen3_tts_server.engine_client.default_sampling_params_list[0].extra_args is None + def test_prepare_speech_generation_uses_adapter_model_type_label( self, voxtral_server, diff --git a/vllm_omni/deploy/qwen3_tts_high_concurrency.yaml b/vllm_omni/deploy/qwen3_tts_high_concurrency.yaml index 9c6ec19fe..4fb6f9894 100644 --- a/vllm_omni/deploy/qwen3_tts_high_concurrency.yaml +++ b/vllm_omni/deploy/qwen3_tts_high_concurrency.yaml @@ -60,7 +60,6 @@ stages: temperature: 0.9 top_k: 50 max_tokens: 4096 - seed: 42 repetition_penalty: 1.05 subtalker_sampling_params: do_sample: true @@ -85,7 +84,6 @@ stages: top_p: 1.0 top_k: -1 max_tokens: 65536 - seed: 42 repetition_penalty: 1.0 platforms: diff --git a/vllm_omni/deploy/voxcpm2.yaml b/vllm_omni/deploy/voxcpm2.yaml index d534a41c1..63996f1b7 100644 --- a/vllm_omni/deploy/voxcpm2.yaml +++ b/vllm_omni/deploy/voxcpm2.yaml @@ -28,20 +28,21 @@ stages: max_num_batched_tokens: 4096 max_model_len: 4096 devices: "0" - hf_overrides: - voxcpm2_runtime_config: - audio_emit_every: 1 - vae_decode_every: 3 - enable_batched_cfm: true - enable_batched_vae_decode: true - coalesce_audio_d2h: true - enable_loc_dit_fused_qkv: true - enable_loc_dit_fused_mlp: true - enable_loc_dit_zero_dt_cache: true - enable_loc_dit_skip_qkv_contig: true - enable_loc_dit_reduce_overhead_no_cg: true - enable_unified_decode_graph: true - unified_decode_graph_max_batch_size: 8 + engine_extras: + hf_overrides: + voxcpm2_runtime_config: + audio_emit_every: 1 + vae_decode_every: 3 + enable_batched_cfm: true + enable_batched_vae_decode: true + coalesce_audio_d2h: true + enable_loc_dit_fused_qkv: true + enable_loc_dit_fused_mlp: true + enable_loc_dit_zero_dt_cache: true + enable_loc_dit_skip_qkv_contig: true + enable_loc_dit_reduce_overhead_no_cg: true + enable_unified_decode_graph: true + unified_decode_graph_max_batch_size: 8 default_sampling_params: temperature: 0.0 top_p: 1.0 diff --git a/vllm_omni/entrypoints/openai/serving_speech.py b/vllm_omni/entrypoints/openai/serving_speech.py index 6f8f1e6dc..ae1a7c1fd 100644 --- a/vllm_omni/entrypoints/openai/serving_speech.py +++ b/vllm_omni/entrypoints/openai/serving_speech.py @@ -3687,6 +3687,18 @@ class OmniOpenAIServingSpeech(OpenAIServing, AudioMixin): stage0_params.extra_args = {} stage0_params.extra_args["tts_local_seed"] = request.seed + if self._tts_model_type == "qwen3_tts" and sampling_params_list: + stage0_params = sampling_params_list[0] + default_seed = getattr(stage0_params, "seed", None) + if default_seed is not None: + import copy + + sampling_params_list = copy.deepcopy(sampling_params_list) + stage0_params = sampling_params_list[0] + if stage0_params.extra_args is None: + stage0_params.extra_args = {} + stage0_params.extra_args.setdefault("tts_local_seed", int(default_seed)) + generator = self.engine_client.generate( prompt=prompt, request_id=request_id,