* qwen3_tts_talker_only pipeline (single terminal LLM_AR stage, final_output_type "latent") + vllm_omni/deploy/qwen3_tts_talker_only.yaml; a terminal talker publishes its per-step codes.audio rows to the client (omni_client_multimodal_output_keys). * /v1/audio/speech/stream: session.config.output_mode="codec_tokens" streams codec.start (JSON) + binary frames (<IHB seq/n_frames/flags + int16 rows, vllm_omni/entrypoints/openai/codec_stream.py) + codec.done; new input.cancel message aborts an in-flight generation for both codec and PCM sessions (single reader task + session inbox replaces direct socket reads); optional session.config.seed; audio.done gains "cancelled" only when it happened. * serving_speech._generate_codec_chunks aligns the cumulative code tensor to output token ids (drops prefill placeholder/EOS rows) and emits deltas. * TTS adapters: supports_codec_stream / codec_stream_spec (Qwen3-TTS: 16 codebooks, 2048 ids, 12.5 Hz, 24 kHz, decoder qwen3_tts_tokenizer_v2_12hz). * examples/online_serving/text_to_speech/qwen3_tts/edge_decoder_client.py decodes locally with Qwen3TTSTokenizerV2Decoder (ramp schedule, 72-frame context, cancel/reset), codec_parity_check.py and benchmarks/tts/codec_stream_e2e.py compare against the two-stage server. * docs/serving/codec_token_streaming.md; CPU unit tests for the wire format, alignment, session config and handler (frames, unsupported adapter, cancel); L3 e2e tests/e2e/online_serving/test_qwen3_tts_codec_stream.py. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
39 lines
1.8 KiB
Python
39 lines
1.8 KiB
Python
"""Talker-only Qwen3-TTS pipeline registration (CPU)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from vllm_omni.config.pipeline_registry import OMNI_PIPELINES
|
|
from vllm_omni.config.stage_config import _DEPLOY_DIR, StageExecutionType, load_deploy_config, merge_pipeline_deploy
|
|
from vllm_omni.model_executor.models.qwen3_tts.pipeline import QWEN3_TTS_PIPELINE, QWEN3_TTS_TALKER_ONLY_PIPELINE
|
|
|
|
pytestmark = [pytest.mark.core_model, pytest.mark.cpu]
|
|
|
|
|
|
def test_registered_single_terminal_stage():
|
|
assert OMNI_PIPELINES["qwen3_tts_talker_only"] is QWEN3_TTS_TALKER_ONLY_PIPELINE
|
|
p = QWEN3_TTS_TALKER_ONLY_PIPELINE
|
|
assert len(p.stages) == 1
|
|
s = p.stages[0]
|
|
assert s.execution_type is StageExecutionType.LLM_AR
|
|
assert s.final_output is True and s.final_output_type == "latent" and s.engine_output_type == "latent"
|
|
assert s.model_stage == QWEN3_TTS_PIPELINE.stages[0].model_stage == "qwen3_tts"
|
|
assert s.custom_process_next_stage_input_func is None
|
|
assert s.async_chunk_process_next_stage_input_func is None
|
|
assert s.sampling_constraints["stop_token_ids"] == [2150]
|
|
|
|
|
|
def test_deploy_yaml_merges_to_one_stage_config():
|
|
deploy_path = _DEPLOY_DIR / "qwen3_tts_talker_only.yaml"
|
|
assert deploy_path.exists()
|
|
deploy = load_deploy_config(deploy_path)
|
|
assert len(deploy.stages) == 1 and deploy.stages[0].devices == "0"
|
|
merged = merge_pipeline_deploy(QWEN3_TTS_TALKER_ONLY_PIPELINE, deploy)
|
|
stage_configs = merged if isinstance(merged, list) else getattr(merged, "stages", merged)
|
|
assert len(stage_configs) == 1
|
|
cfg = stage_configs[0]
|
|
engine_args = getattr(cfg, "engine_args", cfg)
|
|
assert bool(getattr(engine_args, "async_chunk", False)) is False
|
|
assert getattr(engine_args, "custom_process_next_stage_input_func", None) is None
|