From 5fc0bfe01eeff89e70befd01eac046f783a71072 Mon Sep 17 00:00:00 2001 From: Nick Cao Date: Mon, 4 May 2026 10:17:25 -0400 Subject: [PATCH] [Cleanup] Use tokens_input() for TTS prompt construction (#3227) Signed-off-by: Nick Cao Co-authored-by: Claude --- .../openai_api/test_serving_speech_voxcpm.py | 2 ++ .../entrypoints/openai/serving_speech.py | 35 +++++++++---------- .../models/voxcpm2/voxcpm2_talker.py | 5 ++- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/tests/entrypoints/openai_api/test_serving_speech_voxcpm.py b/tests/entrypoints/openai_api/test_serving_speech_voxcpm.py index 48660b6d1..ebd4ef1ab 100644 --- a/tests/entrypoints/openai_api/test_serving_speech_voxcpm.py +++ b/tests/entrypoints/openai_api/test_serving_speech_voxcpm.py @@ -109,6 +109,7 @@ class TestVoxCPMServing: assert call.kwargs["prompt"] == { "prompt_token_ids": [1], "additional_information": tts_params, + "type": "token", } assert call.kwargs["output_modalities"] == ["audio"] @@ -140,4 +141,5 @@ class TestVoxCPMServing: assert call.kwargs["prompt"] == { "prompt_token_ids": [1], "additional_information": tts_params, + "type": "token", } diff --git a/vllm_omni/entrypoints/openai/serving_speech.py b/vllm_omni/entrypoints/openai/serving_speech.py index 15579e4e0..2fc55ebb4 100644 --- a/vllm_omni/entrypoints/openai/serving_speech.py +++ b/vllm_omni/entrypoints/openai/serving_speech.py @@ -24,6 +24,7 @@ from vllm.entrypoints.openai.engine.protocol import ( RequestResponseMetadata, ) from vllm.entrypoints.openai.engine.serving import OpenAIServing +from vllm.inputs import tokens_input from vllm.logger import init_logger from vllm.multimodal.media import MediaConnector from vllm.utils import random_uuid @@ -1537,10 +1538,9 @@ class OmniOpenAIServingSpeech(OpenAIServing, AudioMixin): self._tts_tokenizer = mistral_tokenizer.instruct if voice is not None: tokens = self._tts_tokenizer.encode_speech_request(SpeechRequest(input=text, voice=voice)).tokens - return { - "prompt_token_ids": tokens, - "additional_information": {"voice": [voice]}, - } + prompt = tokens_input(prompt_token_ids=tokens) + prompt["additional_information"] = {"voice": [voice]} + return prompt else: tokenized = self._tts_tokenizer.encode_speech_request(SpeechRequest(input=text, ref_audio=ref_audio)) audio = tokenized.audios[0] @@ -1586,10 +1586,9 @@ class OmniOpenAIServingSpeech(OpenAIServing, AudioMixin): } if request.max_new_tokens is not None: additional_information["max_new_tokens"] = [request.max_new_tokens] - return { - "prompt_token_ids": prompt_ids, - "additional_information": additional_information, - } + prompt = tokens_input(prompt_token_ids=prompt_ids) + prompt["additional_information"] = additional_information + return prompt wav_samples, sr = ref_audio_data normalized_text, normalized_ref_text = normalize_fish_voice_clone_texts(request.input, request.ref_text) @@ -1612,10 +1611,9 @@ class OmniOpenAIServingSpeech(OpenAIServing, AudioMixin): additional_information["voice_created_at"] = self.uploaded_speakers[voice_lower].get("created_at", 0) if request.max_new_tokens is not None: additional_information["max_new_tokens"] = request.max_new_tokens - return { - "prompt_token_ids": [1] * ph_len, - "additional_information": additional_information, - } + prompt = tokens_input(prompt_token_ids=[1] * ph_len) + prompt["additional_information"] = additional_information + return prompt # ---- CosyVoice3 helpers ---- @@ -1685,10 +1683,9 @@ class OmniOpenAIServingSpeech(OpenAIServing, AudioMixin): if has_spk_emb: # Passed as plain float list additional_information["spk_emb"] = list(request.speaker_embedding) - return { - "prompt_token_ids": [0], - "additional_information": additional_information, - } + prompt = tokens_input(prompt_token_ids=[0]) + prompt["additional_information"] = additional_information + return prompt # ---- Common speech generation helpers ---- @@ -1764,7 +1761,8 @@ class OmniOpenAIServingSpeech(OpenAIServing, AudioMixin): tts_params = {} elif self._tts_model_type == "moss_tts_nano": tts_params = await self._build_moss_tts_params(request) - prompt = {"prompt_token_ids": [1], "additional_information": tts_params} + prompt = tokens_input(prompt_token_ids=[1]) + prompt["additional_information"] = tts_params else: tts_params = self._build_tts_params(request) # Resolve ref_audio (explicit or auto-set for uploaded voices) @@ -1778,7 +1776,8 @@ class OmniOpenAIServingSpeech(OpenAIServing, AudioMixin): tts_params["ref_audio"] = [[wav_list, sr]] ph_len = await self._estimate_prompt_len_async(tts_params) - prompt = {"prompt_token_ids": [1] * ph_len, "additional_information": tts_params} + prompt = tokens_input(prompt_token_ids=[1] * ph_len) + prompt["additional_information"] = tts_params else: # Qwen omni models (Qwen3-Omni, Qwen2.5-Omni) use a "talker" # stage whose preprocess requires chat-templated tokens. The diff --git a/vllm_omni/model_executor/models/voxcpm2/voxcpm2_talker.py b/vllm_omni/model_executor/models/voxcpm2/voxcpm2_talker.py index 40cf68181..05f7df9c9 100644 --- a/vllm_omni/model_executor/models/voxcpm2/voxcpm2_talker.py +++ b/vllm_omni/model_executor/models/voxcpm2/voxcpm2_talker.py @@ -23,6 +23,7 @@ import torch import torch.nn as nn from vllm.config import VllmConfig from vllm.forward_context import get_forward_context, override_forward_context +from vllm.inputs import tokens_input from vllm.logger import init_logger from vllm.model_executor.models.utils import ( AutoWeightsLoader, @@ -121,7 +122,9 @@ def build_voxcpm2_prompt( else: additional["reference_audio"] = [[ref_audio, ref_sr]] prefill_len += ref_len + 2 # ref_start / ref_end - return {"prompt_token_ids": [1] * prefill_len, "additional_information": additional} + prompt = tokens_input(prompt_token_ids=[1] * prefill_len) + prompt["additional_information"] = additional + return prompt def _encode_raw_audio(