2026-03-30 13:02:28 +08:00
|
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
|
|
|
|
"""
|
|
|
|
|
E2E offline tests for Qwen3-TTS Base model with text input and audio output.
|
|
|
|
|
|
|
|
|
|
Async_chunk disable, cuda_graph disabled (no_async_chunk stage config).
|
|
|
|
|
CUDA graph is disabled by setting engine_args.enforce_eager=true via modify_stage_config().
|
|
|
|
|
Same structure as test_qwen3_omni (models, stage_configs, test_params, parametrize omni_runner).
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
|
|
os.environ["VLLM_WORKER_MULTIPROC_METHOD"] = "spawn"
|
|
|
|
|
os.environ["VLLM_TEST_CLEAN_GPU_MEMORY"] = "0"
|
|
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
|
2026-04-20 14:23:42 +08:00
|
|
|
from tests.helpers.mark import hardware_test
|
2026-04-29 20:44:05 -04:00
|
|
|
from tests.helpers.media import load_test_audio_data_url
|
2026-04-20 14:23:42 +08:00
|
|
|
from tests.helpers.stage_config import get_deploy_config_path, modify_stage_config
|
2026-03-30 13:02:28 +08:00
|
|
|
|
|
|
|
|
MODEL = "Qwen/Qwen3-TTS-12Hz-0.6B-Base"
|
2026-04-29 20:44:05 -04:00
|
|
|
# See tests/e2e/online_serving/test_qwen3_tts_base.py for the vendored-asset rationale.
|
|
|
|
|
REF_AUDIO_URL = load_test_audio_data_url("qwen3_tts/clone_2.wav")
|
2026-03-30 13:02:28 +08:00
|
|
|
REF_TEXT = "Okay. Yeah. I resent you. I love you. I respect you. But you know what? You blew it! And thanks to you."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_cuda_graph_config():
|
2026-04-19 10:36:00 +08:00
|
|
|
"""Build a temp deploy yaml mirroring the deleted qwen3_tts_no_async_chunk.yaml.
|
|
|
|
|
|
|
|
|
|
Composes the synchronous (no-async-chunk) variant on top of the bundled
|
|
|
|
|
qwen3_tts.yaml prod default, with cudagraphs disabled. Replaces the deleted
|
|
|
|
|
standalone variant yaml; same effective config, no checked-in file needed.
|
|
|
|
|
"""
|
|
|
|
|
return modify_stage_config(
|
|
|
|
|
get_deploy_config_path("qwen3_tts.yaml"),
|
2026-03-30 13:02:28 +08:00
|
|
|
updates={
|
2026-04-19 10:36:00 +08:00
|
|
|
"async_chunk": False,
|
|
|
|
|
"stages": {
|
2026-03-30 13:02:28 +08:00
|
|
|
0: {
|
2026-04-19 10:36:00 +08:00
|
|
|
"max_num_seqs": 1,
|
|
|
|
|
"gpu_memory_utilization": 0.2,
|
|
|
|
|
"enforce_eager": True,
|
|
|
|
|
"async_scheduling": False,
|
|
|
|
|
},
|
|
|
|
|
1: {
|
|
|
|
|
"gpu_memory_utilization": 0.2,
|
|
|
|
|
"enforce_eager": True,
|
|
|
|
|
"async_scheduling": False,
|
2026-03-30 13:02:28 +08:00
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Same structure as test_qwen3_omni: models, stage_configs, test_params
|
|
|
|
|
tts_server_params = [
|
|
|
|
|
pytest.param(
|
|
|
|
|
(MODEL, get_cuda_graph_config()),
|
|
|
|
|
id="no_cuda_graph",
|
|
|
|
|
)
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_prompt():
|
|
|
|
|
"""Text prompt for text-to-audio (same role as get_question in test_qwen3_omni)."""
|
|
|
|
|
return "Hello, this is a test for text to audio."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.advanced_model
|
|
|
|
|
@pytest.mark.omni
|
|
|
|
|
@hardware_test(res={"cuda": "L4"}, num_cards=1)
|
|
|
|
|
@pytest.mark.parametrize("omni_runner", tts_server_params, indirect=True)
|
|
|
|
|
def test_text_to_audio_001(omni_runner, omni_runner_handler) -> None:
|
|
|
|
|
"""
|
|
|
|
|
Test text input processing and audio output via offline Omni runner.
|
|
|
|
|
Deploy Setting: qwen3_tts_no_async_chunk.yaml + enforce_eager=true
|
|
|
|
|
Input Modal: text
|
|
|
|
|
Output Modal: audio
|
|
|
|
|
Input Setting: stream=False
|
|
|
|
|
Extra Setting: task_type=Base, voice=clone, ref_audio/ref_text provided
|
|
|
|
|
Datasets: few requests
|
|
|
|
|
"""
|
|
|
|
|
request_config = {
|
|
|
|
|
"input": get_prompt(),
|
|
|
|
|
"task_type": "Base",
|
|
|
|
|
"voice": "clone",
|
|
|
|
|
"ref_audio": REF_AUDIO_URL,
|
|
|
|
|
"ref_text": REF_TEXT,
|
|
|
|
|
}
|
|
|
|
|
omni_runner_handler.send_audio_speech_request(request_config)
|