diff --git a/tests/model_executor/models/qwen3_tts/test_qwen3_tts_code2wav.py b/tests/model_executor/models/qwen3_tts/test_qwen3_tts_code2wav.py index 581eb977e..d4ac126cb 100644 --- a/tests/model_executor/models/qwen3_tts/test_qwen3_tts_code2wav.py +++ b/tests/model_executor/models/qwen3_tts/test_qwen3_tts_code2wav.py @@ -25,6 +25,7 @@ class _FakeDecoder(nn.Module): self.total_upsample = total_upsample self.decode_calls: list[dict[str, object]] = [] self.batched_decode_calls: list[dict[str, object]] = [] + self.batched_decode_codes: list[torch.Tensor] = [] self.decode_codes: list[torch.Tensor] = [] self.cudagraph_calls: list[dict[str, int | torch.device]] = [] @@ -64,6 +65,7 @@ class _FakeDecoder(nn.Module): left_context_size: int = 25, max_batch_size: int = 0, ) -> list[torch.Tensor]: + self.batched_decode_codes.append(codes.detach().cpu().clone()) self.batched_decode_calls.append( { "chunk_size": chunk_size, @@ -203,6 +205,26 @@ def test_forward_uses_decoder_audio_contract_without_context(): torch.testing.assert_close(audio, expected) +def test_forward_reads_current_model_intermediate_buffer_for_full_payload(): + """Full-payload sync mode must decode connector codec ids, not placeholders.""" + model = _make_model() + placeholder_ids = torch.zeros(12, dtype=torch.long) + payload_codes = torch.arange(12, dtype=torch.long) + 17 + + model.forward( + input_ids=placeholder_ids, + runtime_additional_information=[], + model_intermediate_buffer=[ + { + "codes": {"audio": payload_codes}, + "meta": {"left_context_size": 0}, + } + ], + ) + + torch.testing.assert_close(model.decoder.batched_decode_codes[-1], payload_codes.reshape(1, _NUM_QUANTIZERS, 6)) + + @pytest.mark.parametrize("skipped_length", [0, 1], ids=["empty", "malformed"]) def test_stateless_batch_uses_original_request_index_for_left_context(skipped_length): model = _make_model() diff --git a/vllm_omni/model_executor/models/qwen3_tts/qwen3_tts_code2wav.py b/vllm_omni/model_executor/models/qwen3_tts/qwen3_tts_code2wav.py index 8bb9e30d5..2701520b2 100644 --- a/vllm_omni/model_executor/models/qwen3_tts/qwen3_tts_code2wav.py +++ b/vllm_omni/model_executor/models/qwen3_tts/qwen3_tts_code2wav.py @@ -260,6 +260,7 @@ class Qwen3TTSCode2Wav(nn.Module): intermediate_tensors: Any = None, inputs_embeds: torch.Tensor | None = None, runtime_additional_information: list[dict[str, Any]] | None = None, + model_intermediate_buffer: list[dict[str, Any]] | None = None, **kwargs: Any, ) -> OmniOutput: """Decode codec codes into audio waveform. @@ -285,6 +286,13 @@ class Qwen3TTSCode2Wav(nn.Module): multimodal_outputs={"model_outputs": [empty], "sr": [sr_tensor]}, ) + # vLLM's runner renamed this per-request side channel to + # ``model_intermediate_buffer``. Keep accepting the old explicit + # argument for older runners, and use the new name when it is empty. + # Without this fallback, the non-async-chunk/full-payload path decodes + # placeholder input_ids instead of the codec payload from Stage 0. + if not runtime_additional_information: + runtime_additional_information = model_intermediate_buffer runtime_infos = runtime_additional_information or [] ids = input_ids.reshape(-1).to(dtype=torch.long) request_ids_list = self._split_request_ids(ids, kwargs.get("seq_token_counts"))