[Config Refactor] Migrate 5 TTS models (VoxCPM2 / CosyVoice3 / MiMo Audio / Voxtral TTS / Fish Speech S2 Pro) to Pipeline + Deploy schema (#2958)
Signed-off-by: Yueqian Lin <linyueqian@outlook.com> Co-authored-by: SYLAR <125541396+lishunyang12@users.noreply.github.com>
This commit is contained in:
1 parent
c2578f7131
commit
3f504b45d2
47 files changed
+702
-844
No files matched your search
@@ -22,21 +22,10 @@ vllm serve Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice \
|
||||
--enforce-eager
|
||||
|
||||
# Fish Speech S2 Pro
|
||||
vllm-omni serve fishaudio/s2-pro \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/fish_speech_s2_pro.yaml \
|
||||
--omni \
|
||||
--port 8091 \
|
||||
--trust-remote-code \
|
||||
--enforce-eager \
|
||||
--gpu-memory-utilization 0.9
|
||||
vllm serve fishaudio/s2-pro --omni --port 8091
|
||||
|
||||
# Voxtral TTS
|
||||
vllm serve mistralai/Voxtral-4B-TTS-2603 \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/voxtral_tts.yaml \
|
||||
--omni \
|
||||
--port 8091 \
|
||||
--trust-remote-code \
|
||||
--enforce-eager
|
||||
vllm serve mistralai/Voxtral-4B-TTS-2603 --omni --port 8091
|
||||
```
|
||||
|
||||
### Generate Speech
|
||||
|
||||
@@ -61,10 +61,17 @@ Key components live in `vllm_omni/model_executor/models/cosyvoice3/cosyvoice3.py
|
||||
- Stage 0 uses `CosyVoice3LM` and outputs speech tokens + conditioning features.
|
||||
- Stage 1 runs the flow model (DiT-based CFM) and HiFiGAN to synthesize waveform.
|
||||
|
||||
Stage wiring is configured in `vllm_omni/model_executor/stage_configs/cosyvoice3.yaml`.
|
||||
Pipeline topology lives in `vllm_omni/model_executor/models/cosyvoice3/pipeline.py`;
|
||||
runtime tunables (batch size, memory limits, sampling) live in
|
||||
`vllm_omni/deploy/cosyvoice3.yaml`. The deploy config auto-loads by
|
||||
HF `model_type` and defaults to `async_chunk: true` (shared-memory
|
||||
streaming). Pass `--no-async-chunk` on `vllm serve` to switch to the
|
||||
legacy sync path where stage 1 runs `text2flow` over the full
|
||||
speech-token sequence.
|
||||
|
||||
- Stage 0 emits latent speech tokens.
|
||||
- Stage 1 consumes them via `custom_process_input_func` and outputs audio.
|
||||
- Stage 1 consumes them via `sync_process_input_func` (sync mode) or the
|
||||
shared-memory connector (async-chunk mode) and outputs audio.
|
||||
|
||||
## Example materials
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@ Run a single sample for basic TTS:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type tts_sft
|
||||
```
|
||||
@@ -47,7 +46,6 @@ Run batch samples for basic TTS:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type tts_sft \
|
||||
--num-prompts {batch_size}
|
||||
@@ -65,7 +63,6 @@ Generate speech from text input:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type tts_sft \
|
||||
--text "The weather is so nice today."
|
||||
@@ -77,7 +74,6 @@ Generate speech with explicit voice style instructions:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type tts_sft_with_instruct \
|
||||
--text "The weather is so nice today." \
|
||||
@@ -90,7 +86,6 @@ Generate speech using an audio reference for voice cloning:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type tts_sft_with_audio \
|
||||
--text "The weather is so nice today." \
|
||||
@@ -103,7 +98,6 @@ Generate speech from text containing natural voice descriptions:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type tts_sft_with_natural_instruction \
|
||||
--text "In a panting young male voice, he said: I can't run anymore, wait for me!"
|
||||
@@ -115,7 +109,6 @@ Transcribe audio to text:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type audio_trancribing_sft \
|
||||
--audio-path "./spoken_dialogue_assistant_turn_1.wav"
|
||||
@@ -127,7 +120,6 @@ Understand and analyze audio content with text queries:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type audio_understanding_sft \
|
||||
--text "Summarize the audio." \
|
||||
@@ -140,7 +132,6 @@ Audio understanding with reasoning chain:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type audio_understanding_sft_with_thinking \
|
||||
--text "Summarize the audio." \
|
||||
@@ -153,7 +144,6 @@ Multi-turn dialogue with audio input and output:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type spoken_dialogue_sft_multiturn \
|
||||
--audio-path "./prompt_speech_zh_m.wav"
|
||||
@@ -167,7 +157,6 @@ Multi-turn dialogue converting speech to text:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type speech2text_dialogue_sft_multiturn
|
||||
```
|
||||
@@ -180,7 +169,6 @@ Multi-turn text-only dialogue:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type text_dialogue_sft_multiturn
|
||||
```
|
||||
|
||||
@@ -13,28 +13,24 @@ When `mistral_common` has `SpeechRequest` support, prompt token IDs are built vi
|
||||
```bash
|
||||
# Basic single-prompt with cheerful_female voice preset
|
||||
python3 examples/offline_inference/voxtral_tts/end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/voxtral_tts.yaml \
|
||||
--write-audio --voice cheerful_female \
|
||||
--model mistralai/Voxtral-4B-TTS-2603 \
|
||||
--text "That eerie silence after the first storm was just the calm before another round of chaos, wasn't it?"
|
||||
|
||||
# 32 replicate prompts with cheerful_female voice preset
|
||||
python3 examples/offline_inference/voxtral_tts/end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/voxtral_tts.yaml \
|
||||
--num-prompts 32 --write-audio --voice cheerful_female \
|
||||
--model mistralai/Voxtral-4B-TTS-2603 \
|
||||
--text "That eerie silence after the first storm was just the calm before another round of chaos, wasn't it?"
|
||||
|
||||
# Streaming with neutral_female voice preset
|
||||
python3 examples/offline_inference/voxtral_tts/end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/voxtral_tts.yaml \
|
||||
--streaming --write-audio --voice neutral_female \
|
||||
--model mistralai/Voxtral-4B-TTS-2603 \
|
||||
--text "That eerie silence after the first storm was just the calm before another round of chaos, wasn't it?"
|
||||
|
||||
# 32 prompts, 8 concurrent requests per wave, streaming with neutral_female voice
|
||||
python3 examples/offline_inference/voxtral_tts/end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/voxtral_tts.yaml \
|
||||
--num-prompts 32 --concurrency 8 --streaming --write-audio --voice neutral_female \
|
||||
--model mistralai/Voxtral-4B-TTS-2603 \
|
||||
--text "That eerie silence after the first storm was just the calm before another round of chaos, wasn't it?"
|
||||
@@ -42,7 +38,6 @@ python3 examples/offline_inference/voxtral_tts/end2end.py \
|
||||
# Short debug prompt with reference audio
|
||||
# Note: Reference audio capability is not yet released.
|
||||
python3 examples/offline_inference/voxtral_tts/end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/voxtral_tts.yaml \
|
||||
--write-audio \
|
||||
--model mistralai/Voxtral-4B-TTS-2603 \
|
||||
--text "This is a test message." \
|
||||
@@ -57,7 +52,7 @@ python3 examples/offline_inference/voxtral_tts/end2end.py \
|
||||
| `--text TEXT` | Text to synthesize (default: `"This is a test message."`) |
|
||||
| `--audio-path PATH` | Path to reference audio file for voice cloning |
|
||||
| `--output-dir DIR` | Directory to write output WAV files (default: `output_audio`) |
|
||||
| `--stage-configs-path PATH` | Path to stage configs YAML (currently it must be set for VoxtralTTS) |
|
||||
| `--deploy-config PATH` | Override the deploy config path. If unset, auto-loads `vllm_omni/deploy/voxtral_tts.yaml` from the HF `model_type`. |
|
||||
| `--num-prompts N` | Number of replicate prompts to run for measuring performance (default: 1) |
|
||||
| `--streaming` | Use streaming generation via `AsyncOmni` (default: blocking `Omni`) |
|
||||
| `--concurrency N` | Max concurrent requests per wave (must be used with `--streaming`, must evenly divide `--num-prompts`) |
|
||||
|
||||
@@ -41,15 +41,11 @@ Features:
|
||||
## Launch the Server
|
||||
|
||||
```bash
|
||||
vllm-omni serve fishaudio/s2-pro \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/fish_speech_s2_pro.yaml \
|
||||
--omni \
|
||||
--port 8091 \
|
||||
--trust-remote-code \
|
||||
--enforce-eager \
|
||||
--gpu-memory-utilization 0.9
|
||||
vllm serve fishaudio/s2-pro --omni --port 8091
|
||||
```
|
||||
|
||||
The deploy config is auto-loaded from `vllm_omni/deploy/fish_qwen3_omni.yaml`.
|
||||
|
||||
Or use the convenience script:
|
||||
|
||||
```bash
|
||||
|
||||
@@ -13,10 +13,10 @@ Please refer to [README.md](https://github.com/vllm-project/vllm-omni/tree/main/
|
||||
```bash
|
||||
export MIMO_AUDIO_TOKENIZER_PATH="XiaomiMiMo/MiMo-Audio-Tokenizer"
|
||||
|
||||
vllm-omni serve XiaomiMiMo/MiMo-Audio-7B-Instruct --omni \
|
||||
--served-model-name "MiMo-Audio-7B-Instruct" \
|
||||
--port 18091 --stage-configs-path ./vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--chat-template ./examples/online_serving/mimo_audio/chat_template.jinja
|
||||
vllm serve XiaomiMiMo/MiMo-Audio-7B-Instruct --omni \
|
||||
--served-model-name "MiMo-Audio-7B-Instruct" \
|
||||
--port 18091 \
|
||||
--chat-template ./examples/online_serving/mimo_audio/chat_template.jinja
|
||||
```
|
||||
> ⚠️ **Important**
|
||||
> **MiMo-Audio is not compatible with the default chat template.**
|
||||
|
||||
@@ -58,7 +58,14 @@ Key components live in `vllm_omni/model_executor/models/cosyvoice3/cosyvoice3.py
|
||||
- Stage 0 uses `CosyVoice3LM` and outputs speech tokens + conditioning features.
|
||||
- Stage 1 runs the flow model (DiT-based CFM) and HiFiGAN to synthesize waveform.
|
||||
|
||||
Stage wiring is configured in `vllm_omni/model_executor/stage_configs/cosyvoice3.yaml`.
|
||||
Pipeline topology lives in `vllm_omni/model_executor/models/cosyvoice3/pipeline.py`;
|
||||
runtime tunables (batch size, memory limits, sampling) live in
|
||||
`vllm_omni/deploy/cosyvoice3.yaml`. The deploy config auto-loads by
|
||||
HF `model_type` and defaults to `async_chunk: true` (shared-memory
|
||||
streaming). Pass `--no-async-chunk` on `vllm serve` to switch to the
|
||||
legacy sync path where stage 1 runs `text2flow` over the full
|
||||
speech-token sequence.
|
||||
|
||||
- Stage 0 emits latent speech tokens.
|
||||
- Stage 1 consumes them via `custom_process_input_func` and outputs audio.
|
||||
- Stage 1 consumes them via `sync_process_input_func` (sync mode) or the
|
||||
shared-memory connector (async-chunk mode) and outputs audio.
|
||||
@@ -24,7 +24,13 @@ def run_e2e():
|
||||
required=True,
|
||||
help="Path to CosyVoice3 model directory (e.g., pretrained_models/Fun-CosyVoice3-0.5B/).",
|
||||
)
|
||||
parser.add_argument("--stage-config", type=str, default="vllm_omni/model_executor/stage_configs/cosyvoice3.yaml")
|
||||
parser.add_argument(
|
||||
"--deploy-config",
|
||||
type=str,
|
||||
default=None,
|
||||
help="Override the deploy config path. If unset, auto-loads "
|
||||
"vllm_omni/deploy/cosyvoice3.yaml based on the HF model_type.",
|
||||
)
|
||||
parser.add_argument("--prompt", type=str, default="Hello, this is a test of the CosyVoice system capability.")
|
||||
parser.add_argument(
|
||||
"--prompt-text",
|
||||
@@ -43,18 +49,14 @@ def run_e2e():
|
||||
if not os.path.exists(args.tokenizer):
|
||||
raise FileNotFoundError(f"{args.tokenizer} does not exist!")
|
||||
|
||||
# Ensure stage config exists
|
||||
if not os.path.exists(args.stage_config):
|
||||
raise FileNotFoundError(f"{args.stage_config} does not exist!")
|
||||
if args.deploy_config is not None and not os.path.exists(args.deploy_config):
|
||||
raise FileNotFoundError(f"{args.deploy_config} does not exist!")
|
||||
|
||||
print(f"Initializing cosyvoice E2E with model={args.model}")
|
||||
|
||||
# Initialize Omni
|
||||
# This spins up the engine(s) based on the stage config
|
||||
# We pass trust_remote_code=True same as Qwen examples
|
||||
omni = Omni(
|
||||
model=args.model,
|
||||
stage_configs_path=args.stage_config,
|
||||
deploy_config=args.deploy_config,
|
||||
trust_remote_code=True,
|
||||
tokenizer=args.tokenizer,
|
||||
log_stats=True,
|
||||
|
||||
@@ -39,7 +39,6 @@ Run a single sample for basic TTS:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type tts_sft
|
||||
```
|
||||
@@ -48,7 +47,6 @@ Run batch samples for basic TTS:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type tts_sft \
|
||||
--num-prompts {batch_size}
|
||||
@@ -66,7 +64,6 @@ Generate speech from text input:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type tts_sft \
|
||||
--text "The weather is so nice today."
|
||||
@@ -78,7 +75,6 @@ Generate speech with explicit voice style instructions:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type tts_sft_with_instruct \
|
||||
--text "The weather is so nice today." \
|
||||
@@ -91,7 +87,6 @@ Generate speech using an audio reference for voice cloning:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type tts_sft_with_audio \
|
||||
--text "The weather is so nice today." \
|
||||
@@ -104,7 +99,6 @@ Generate speech from text containing natural voice descriptions:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type tts_sft_with_natural_instruction \
|
||||
--text "In a panting young male voice, he said: I can't run anymore, wait for me!"
|
||||
@@ -116,7 +110,6 @@ Transcribe audio to text:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type audio_trancribing_sft \
|
||||
--audio-path "./spoken_dialogue_assistant_turn_1.wav"
|
||||
@@ -128,7 +121,6 @@ Understand and analyze audio content with text queries:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type audio_understanding_sft \
|
||||
--text "Summarize the audio." \
|
||||
@@ -141,7 +133,6 @@ Audio understanding with reasoning chain:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type audio_understanding_sft_with_thinking \
|
||||
--text "Summarize the audio." \
|
||||
@@ -154,7 +145,6 @@ Multi-turn dialogue with audio input and output:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type spoken_dialogue_sft_multiturn \
|
||||
--audio-path "./prompt_speech_zh_m.wav"
|
||||
@@ -168,7 +158,6 @@ Multi-turn dialogue converting speech to text:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type speech2text_dialogue_sft_multiturn
|
||||
```
|
||||
@@ -181,7 +170,6 @@ Multi-turn text-only dialogue:
|
||||
|
||||
```bash
|
||||
python3 -u end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--model-name XiaomiMiMo/MiMo-Audio-7B-Instruct \
|
||||
--query-type text_dialogue_sft_multiturn
|
||||
```
|
||||
|
||||
@@ -182,7 +182,7 @@ def main(args):
|
||||
|
||||
omni = Omni(
|
||||
model=model_name,
|
||||
stage_configs_path=args.stage_configs_path,
|
||||
deploy_config=args.deploy_config,
|
||||
log_stats=args.enable_stats,
|
||||
log_file=("omni_pipeline.log" if args.enable_stats else None),
|
||||
init_sleep_seconds=args.init_sleep_seconds,
|
||||
@@ -428,10 +428,11 @@ def parse_args():
|
||||
help="Sampling rate for audio.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--stage-configs-path",
|
||||
"--deploy-config",
|
||||
type=str,
|
||||
default="../../../model_executor/stage_configs/mimo_audio.yaml",
|
||||
help="Path to a stage configs file.",
|
||||
default=None,
|
||||
help="Override the deploy config path. If unset, auto-loads "
|
||||
"vllm_omni/deploy/mimo_audio.yaml based on the HF model_type.",
|
||||
)
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
@@ -10,28 +10,24 @@ When `mistral_common` has `SpeechRequest` support, prompt token IDs are built vi
|
||||
```bash
|
||||
# Basic single-prompt with cheerful_female voice preset
|
||||
python3 examples/offline_inference/voxtral_tts/end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/voxtral_tts.yaml \
|
||||
--write-audio --voice cheerful_female \
|
||||
--model mistralai/Voxtral-4B-TTS-2603 \
|
||||
--text "That eerie silence after the first storm was just the calm before another round of chaos, wasn't it?"
|
||||
|
||||
# 32 replicate prompts with cheerful_female voice preset
|
||||
python3 examples/offline_inference/voxtral_tts/end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/voxtral_tts.yaml \
|
||||
--num-prompts 32 --write-audio --voice cheerful_female \
|
||||
--model mistralai/Voxtral-4B-TTS-2603 \
|
||||
--text "That eerie silence after the first storm was just the calm before another round of chaos, wasn't it?"
|
||||
|
||||
# Streaming with neutral_female voice preset
|
||||
python3 examples/offline_inference/voxtral_tts/end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/voxtral_tts.yaml \
|
||||
--streaming --write-audio --voice neutral_female \
|
||||
--model mistralai/Voxtral-4B-TTS-2603 \
|
||||
--text "That eerie silence after the first storm was just the calm before another round of chaos, wasn't it?"
|
||||
|
||||
# 32 prompts, 8 concurrent requests per wave, streaming with neutral_female voice
|
||||
python3 examples/offline_inference/voxtral_tts/end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/voxtral_tts.yaml \
|
||||
--num-prompts 32 --concurrency 8 --streaming --write-audio --voice neutral_female \
|
||||
--model mistralai/Voxtral-4B-TTS-2603 \
|
||||
--text "That eerie silence after the first storm was just the calm before another round of chaos, wasn't it?"
|
||||
@@ -39,7 +35,6 @@ python3 examples/offline_inference/voxtral_tts/end2end.py \
|
||||
# Short debug prompt with reference audio
|
||||
# Note: Reference audio capability is not yet released.
|
||||
python3 examples/offline_inference/voxtral_tts/end2end.py \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/voxtral_tts.yaml \
|
||||
--write-audio \
|
||||
--model mistralai/Voxtral-4B-TTS-2603 \
|
||||
--text "This is a test message." \
|
||||
@@ -54,7 +49,7 @@ python3 examples/offline_inference/voxtral_tts/end2end.py \
|
||||
| `--text TEXT` | Text to synthesize (default: `"This is a test message."`) |
|
||||
| `--audio-path PATH` | Path to reference audio file for voice cloning |
|
||||
| `--output-dir DIR` | Directory to write output WAV files (default: `output_audio`) |
|
||||
| `--stage-configs-path PATH` | Path to stage configs YAML (currently it must be set for VoxtralTTS) |
|
||||
| `--deploy-config PATH` | Override the deploy config path. If unset, auto-loads `vllm_omni/deploy/voxtral_tts.yaml` from the HF `model_type`. |
|
||||
| `--num-prompts N` | Number of replicate prompts to run for measuring performance (default: 1) |
|
||||
| `--streaming` | Use streaming generation via `AsyncOmni` (default: blocking `Omni`) |
|
||||
| `--concurrency N` | Max concurrent requests per wave (must be used with `--streaming`, must evenly divide `--num-prompts`) |
|
||||
|
||||
@@ -39,7 +39,7 @@ logger = logging.getLogger(__name__)
|
||||
async def run_streaming(inputs, sampling_params_list, model_name, args, output_dir):
|
||||
async_omni = AsyncOmni(
|
||||
model=model_name,
|
||||
stage_configs_path=args.stage_configs_path,
|
||||
deploy_config=args.deploy_config,
|
||||
log_stats=args.log_stats,
|
||||
)
|
||||
|
||||
@@ -192,7 +192,7 @@ def run_non_streaming(inputs, sampling_params_list, model_name, args, output_dir
|
||||
llm = Omni(
|
||||
model=model_name,
|
||||
log_stats=args.log_stats,
|
||||
stage_configs_path=args.stage_configs_path,
|
||||
deploy_config=args.deploy_config,
|
||||
)
|
||||
|
||||
if args.profiling_mode:
|
||||
@@ -253,10 +253,11 @@ def parse_args() -> Namespace:
|
||||
help="Directory to write output wav files.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--stage-configs-path",
|
||||
"--deploy-config",
|
||||
type=str,
|
||||
default=None,
|
||||
help="Path to stage configs YAML. Auto-resolved from model if not set.",
|
||||
help="Override the deploy config path. If unset, auto-loads "
|
||||
"vllm_omni/deploy/voxtral_tts.yaml based on the HF model_type.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--num-prompts", type=int, default=1, help="Number of replicate prompts to run for measuring performance"
|
||||
|
||||
@@ -29,15 +29,12 @@ Features:
|
||||
## Launch the Server
|
||||
|
||||
```bash
|
||||
vllm-omni serve fishaudio/s2-pro \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/fish_speech_s2_pro.yaml \
|
||||
--omni \
|
||||
--port 8091 \
|
||||
--trust-remote-code \
|
||||
--enforce-eager \
|
||||
--gpu-memory-utilization 0.9
|
||||
vllm serve fishaudio/s2-pro --omni --port 8091
|
||||
```
|
||||
|
||||
The deploy config is auto-loaded from `vllm_omni/deploy/fish_qwen3_omni.yaml`
|
||||
(the HF `model_type` on the fishaudio checkpoints is `fish_qwen3_omni`).
|
||||
|
||||
Or use the convenience script:
|
||||
|
||||
```bash
|
||||
|
||||
@@ -11,18 +11,13 @@ MODEL="${MODEL:-fishaudio/s2-pro}"
|
||||
PORT="${PORT:-8091}"
|
||||
GRADIO_PORT="${GRADIO_PORT:-7860}"
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
||||
|
||||
echo "Starting Fish Speech S2 Pro server (port $PORT)..."
|
||||
FLASHINFER_DISABLE_VERSION_CHECK=1 \
|
||||
vllm-omni serve "$MODEL" \
|
||||
--stage-configs-path "$REPO_ROOT/vllm_omni/model_executor/stage_configs/fish_speech_s2_pro.yaml" \
|
||||
vllm serve "$MODEL" \
|
||||
--omni \
|
||||
--host 0.0.0.0 \
|
||||
--port "$PORT" \
|
||||
--gpu-memory-utilization 0.9 \
|
||||
--trust-remote-code \
|
||||
--enforce-eager \
|
||||
--omni &
|
||||
--port "$PORT" &
|
||||
SERVER_PID=$!
|
||||
|
||||
cleanup() {
|
||||
|
||||
@@ -13,11 +13,7 @@ PORT="${PORT:-8091}"
|
||||
echo "Starting Fish Speech S2 Pro server with model: $MODEL"
|
||||
|
||||
FLASHINFER_DISABLE_VERSION_CHECK=1 \
|
||||
vllm-omni serve "$MODEL" \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/fish_speech_s2_pro.yaml \
|
||||
vllm serve "$MODEL" \
|
||||
--omni \
|
||||
--host 0.0.0.0 \
|
||||
--port "$PORT" \
|
||||
--gpu-memory-utilization 0.9 \
|
||||
--trust-remote-code \
|
||||
--enforce-eager \
|
||||
--omni
|
||||
--port "$PORT"
|
||||
@@ -13,10 +13,10 @@ Please refer to [README.md](../../../README.md)
|
||||
```bash
|
||||
export MIMO_AUDIO_TOKENIZER_PATH="XiaomiMiMo/MiMo-Audio-Tokenizer"
|
||||
|
||||
vllm-omni serve XiaomiMiMo/MiMo-Audio-7B-Instruct --omni \
|
||||
--served-model-name "MiMo-Audio-7B-Instruct" \
|
||||
--port 18091 --stage-configs-path ./vllm_omni/model_executor/stage_configs/mimo_audio.yaml \
|
||||
--chat-template ./examples/online_serving/mimo_audio/chat_template.jinja
|
||||
vllm serve XiaomiMiMo/MiMo-Audio-7B-Instruct --omni \
|
||||
--served-model-name "MiMo-Audio-7B-Instruct" \
|
||||
--port 18091 \
|
||||
--chat-template ./examples/online_serving/mimo_audio/chat_template.jinja
|
||||
```
|
||||
> ⚠️ **Important**
|
||||
> **MiMo-Audio is not compatible with the default chat template.**
|
||||
|
||||
@@ -5,12 +5,13 @@ Serve VoxCPM2 TTS via the OpenAI-compatible `/v1/audio/speech` endpoint.
|
||||
## Start the Server
|
||||
|
||||
```bash
|
||||
python -m vllm_omni.entrypoints.openai.api_server \
|
||||
--model openbmb/VoxCPM2 \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/voxcpm2.yaml \
|
||||
--host 0.0.0.0 --port 8000
|
||||
vllm serve openbmb/VoxCPM2 --omni --host 0.0.0.0 --port 8000
|
||||
```
|
||||
|
||||
The deploy config is auto-loaded from `vllm_omni/deploy/voxcpm2.yaml`. Pass
|
||||
`--deploy-config <path>` to override, or `--stage-N-<field> <value>` (e.g.
|
||||
`--stage-0-max-num-seqs 8`) for per-stage runtime overrides.
|
||||
|
||||
## Zero-shot Synthesis
|
||||
|
||||
```bash
|
||||
|
||||
@@ -8,10 +8,7 @@ the audio clock rate.
|
||||
|
||||
Usage:
|
||||
# Start the vLLM server first:
|
||||
python -m vllm_omni.entrypoints.openai.api_server \
|
||||
--model openbmb/VoxCPM2 \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/voxcpm2.yaml \
|
||||
--host 0.0.0.0 --port 8000
|
||||
vllm serve openbmb/VoxCPM2 --omni --host 0.0.0.0 --port 8000
|
||||
|
||||
# Then launch the demo:
|
||||
python gradio_demo.py --api-base http://localhost:8000
|
||||
|
||||
@@ -13,10 +13,7 @@ Examples:
|
||||
--ref-audio "https://example.com/reference.wav"
|
||||
|
||||
Server setup:
|
||||
python -m vllm_omni.entrypoints.openai.api_server \
|
||||
--model openbmb/VoxCPM2 \
|
||||
--stage-configs-path vllm_omni/model_executor/stage_configs/voxcpm2.yaml \
|
||||
--host 0.0.0.0 --port 8000
|
||||
vllm serve openbmb/VoxCPM2 --omni --host 0.0.0.0 --port 8000
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -15,19 +15,18 @@ from __future__ import annotations
|
||||
import functools
|
||||
import io
|
||||
import os
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from urllib.request import urlopen
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
import soundfile as sf
|
||||
import yaml
|
||||
from huggingface_hub import snapshot_download
|
||||
from vllm.sampling_params import SamplingParams
|
||||
|
||||
from tests.helpers.mark import hardware_test
|
||||
from tests.helpers.runtime import OmniRunner
|
||||
from tests.helpers.stage_config import get_deploy_config_path
|
||||
from vllm_omni.model_executor.models.cosyvoice3.config import CosyVoice3Config
|
||||
from vllm_omni.model_executor.models.cosyvoice3.tokenizer import get_qwen_tokenizer
|
||||
|
||||
@@ -44,13 +43,9 @@ REFERENCE_STAGE0_TEMPERATURE = 1.0
|
||||
REFERENCE_STAGE0_REPETITION_PENALTY = 2.0
|
||||
|
||||
|
||||
def _stage_config(name: str) -> str:
|
||||
return str(Path(__file__).parent.parent.parent.parent / "vllm_omni" / "model_executor" / "stage_configs" / name)
|
||||
|
||||
|
||||
STAGE_CONFIGS = [
|
||||
_stage_config("cosyvoice3.yaml"),
|
||||
_stage_config("cosyvoice3_async_chunk.yaml"),
|
||||
ASYNC_CHUNK_MODES = [
|
||||
pytest.param(False, id="sync"),
|
||||
pytest.param(True, id="async_chunk"),
|
||||
]
|
||||
|
||||
|
||||
@@ -138,19 +133,6 @@ def _get_stage_engine_outputs(omni_runner: OmniRunner, stage_id: int):
|
||||
raise AttributeError("Unable to locate stage outputs on Omni runner")
|
||||
|
||||
|
||||
def _patched_stage_config(base_stage_config: str, model_dir: Path, tmp_dir: Path) -> str:
|
||||
cfg = yaml.safe_load(Path(base_stage_config).read_text(encoding="utf-8"))
|
||||
tokenizer_path = str(model_dir / "CosyVoice-BlankEN")
|
||||
for stage in cfg.get("stage_args", []):
|
||||
engine_args = stage.setdefault("engine_args", {})
|
||||
engine_args["tokenizer"] = tokenizer_path
|
||||
engine_args["enforce_eager"] = True
|
||||
engine_args["hf_overrides"] = {"architectures": ["CosyVoice3Model"]}
|
||||
out_path = tmp_dir / Path(base_stage_config).name
|
||||
out_path.write_text(yaml.safe_dump(cfg, sort_keys=False), encoding="utf-8")
|
||||
return str(out_path)
|
||||
|
||||
|
||||
def _build_reference_inputs(prompt_audio: tuple[np.ndarray, int]) -> list[dict[str, object]]:
|
||||
return [
|
||||
{
|
||||
@@ -165,54 +147,54 @@ def _build_reference_inputs(prompt_audio: tuple[np.ndarray, int]) -> list[dict[s
|
||||
@pytest.mark.core_model
|
||||
@pytest.mark.omni
|
||||
@hardware_test(res={"cuda": "L4"}, num_cards=1)
|
||||
@pytest.mark.parametrize("base_stage_config", STAGE_CONFIGS)
|
||||
def test_cosyvoice3_offline_reference_zero_shot(base_stage_config: str) -> None:
|
||||
@pytest.mark.parametrize("async_chunk", ASYNC_CHUNK_MODES)
|
||||
def test_cosyvoice3_offline_reference_zero_shot(async_chunk: bool) -> None:
|
||||
"""CosyVoice3 zero-shot reference inference should stop cleanly and produce sane audio."""
|
||||
prompt_audio, prompt_sr = _load_reference_prompt_wav()
|
||||
model_dir = _resolve_model_dir()
|
||||
expected_stop_token = int(CosyVoice3Config().llm["eos_token_id"])
|
||||
|
||||
with tempfile.TemporaryDirectory(prefix="cv3-e2e-") as tmp:
|
||||
stage_config = _patched_stage_config(base_stage_config, model_dir, Path(tmp))
|
||||
with OmniRunner(
|
||||
str(model_dir), seed=42, stage_configs_path=stage_config, stage_init_timeout=300
|
||||
) as omni_runner:
|
||||
sampling_params_list = omni_runner.get_default_sampling_params_list()
|
||||
sampling_params_list[0] = _reference_zero_shot_stage0_sampling(text=REFERENCE_SYNTH_TEXT)
|
||||
with OmniRunner(
|
||||
str(model_dir),
|
||||
seed=42,
|
||||
stage_configs_path=get_deploy_config_path("cosyvoice3.yaml"),
|
||||
async_chunk=async_chunk,
|
||||
stage_init_timeout=300,
|
||||
) as omni_runner:
|
||||
sampling_params_list = omni_runner.get_default_sampling_params_list()
|
||||
sampling_params_list[0] = _reference_zero_shot_stage0_sampling(text=REFERENCE_SYNTH_TEXT)
|
||||
|
||||
outputs = omni_runner.omni.generate(
|
||||
_build_reference_inputs((prompt_audio, prompt_sr)), sampling_params_list
|
||||
outputs = omni_runner.omni.generate(_build_reference_inputs((prompt_audio, prompt_sr)), sampling_params_list)
|
||||
|
||||
assert outputs, "No outputs returned"
|
||||
audio_mm = outputs[0].multimodal_output
|
||||
assert "audio" in audio_mm, "No audio output found"
|
||||
|
||||
audio = _concat_audio(audio_mm["audio"])
|
||||
assert audio.size > 0, "Generated audio is empty"
|
||||
|
||||
sr_val = audio_mm.get("sr", 24000)
|
||||
if isinstance(sr_val, list) and sr_val:
|
||||
sr_val = sr_val[-1]
|
||||
if hasattr(sr_val, "item"):
|
||||
sr_val = sr_val.item()
|
||||
sr = int(sr_val)
|
||||
assert sr == 24000, f"Unexpected sample_rate={sr}"
|
||||
|
||||
duration_s = audio.size / sr
|
||||
assert 2.8 <= duration_s <= 8.8, f"Unexpected duration={duration_s:.3f}s (samples={audio.size}, sr={sr})"
|
||||
|
||||
stage0_outputs = _get_stage_engine_outputs(omni_runner, 0)
|
||||
if stage0_outputs:
|
||||
completion = stage0_outputs[0].outputs[0]
|
||||
finish_reason = getattr(completion, "finish_reason", None)
|
||||
stop_reason = getattr(completion, "stop_reason", None)
|
||||
num_tokens = len(getattr(completion, "token_ids", []) or [])
|
||||
|
||||
assert finish_reason == "stop", f"Stage-0 finish_reason={finish_reason}, expected 'stop'"
|
||||
assert int(stop_reason) == expected_stop_token, (
|
||||
f"Stage-0 stop_reason={stop_reason}, expected {expected_stop_token}"
|
||||
)
|
||||
|
||||
assert outputs, "No outputs returned"
|
||||
audio_mm = outputs[0].multimodal_output
|
||||
assert "audio" in audio_mm, "No audio output found"
|
||||
|
||||
audio = _concat_audio(audio_mm["audio"])
|
||||
assert audio.size > 0, "Generated audio is empty"
|
||||
|
||||
sr_val = audio_mm.get("sr", 24000)
|
||||
if isinstance(sr_val, list) and sr_val:
|
||||
sr_val = sr_val[-1]
|
||||
if hasattr(sr_val, "item"):
|
||||
sr_val = sr_val.item()
|
||||
sr = int(sr_val)
|
||||
assert sr == 24000, f"Unexpected sample_rate={sr}"
|
||||
|
||||
duration_s = audio.size / sr
|
||||
assert 2.8 <= duration_s <= 8.8, f"Unexpected duration={duration_s:.3f}s (samples={audio.size}, sr={sr})"
|
||||
|
||||
stage0_outputs = _get_stage_engine_outputs(omni_runner, 0)
|
||||
if stage0_outputs:
|
||||
completion = stage0_outputs[0].outputs[0]
|
||||
finish_reason = getattr(completion, "finish_reason", None)
|
||||
stop_reason = getattr(completion, "stop_reason", None)
|
||||
num_tokens = len(getattr(completion, "token_ids", []) or [])
|
||||
|
||||
assert finish_reason == "stop", f"Stage-0 finish_reason={finish_reason}, expected 'stop'"
|
||||
assert int(stop_reason) == expected_stop_token, (
|
||||
f"Stage-0 stop_reason={stop_reason}, expected {expected_stop_token}"
|
||||
)
|
||||
assert 80 <= num_tokens <= 220, f"Stage-0 num_tokens={num_tokens}, expected sane stop-bound range"
|
||||
else:
|
||||
assert "async_chunk" in Path(base_stage_config).name, "Stage-0 produced no engine outputs"
|
||||
assert 80 <= num_tokens <= 220, f"Stage-0 num_tokens={num_tokens}, expected sane stop-bound range"
|
||||
else:
|
||||
assert async_chunk, "Stage-0 produced no engine outputs"
|
||||
@@ -7,25 +7,17 @@ import torch
|
||||
|
||||
from tests.helpers.mark import hardware_test
|
||||
from tests.helpers.runtime import OmniRunner
|
||||
from tests.helpers.stage_config import get_deploy_config_path
|
||||
|
||||
VOXCPM2_MODEL = "openbmb/VoxCPM2"
|
||||
STAGE_CONFIG = os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"vllm_omni",
|
||||
"model_executor",
|
||||
"stage_configs",
|
||||
"voxcpm2.yaml",
|
||||
)
|
||||
DEPLOY_CONFIG = get_deploy_config_path("voxcpm2.yaml")
|
||||
SAMPLE_RATE = 48000
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def voxcpm2_engine():
|
||||
"""Create VoxCPM2 engine for testing."""
|
||||
with OmniRunner(VOXCPM2_MODEL, stage_configs_path=STAGE_CONFIG) as runner:
|
||||
with OmniRunner(VOXCPM2_MODEL, stage_configs_path=DEPLOY_CONFIG) as runner:
|
||||
yield runner.omni
|
||||
|
||||
|
||||
|
||||
@@ -31,13 +31,11 @@ from vllm import SamplingParams
|
||||
|
||||
from tests.helpers.mark import hardware_test
|
||||
from tests.helpers.runtime import OmniRunner
|
||||
from tests.helpers.stage_config import modify_stage_config
|
||||
from tests.helpers.stage_config import get_deploy_config_path, modify_stage_config
|
||||
from vllm_omni.entrypoints.async_omni import AsyncOmni
|
||||
|
||||
MODEL = "mistralai/Voxtral-4B-TTS-2603"
|
||||
STAGE_CONFIG = str(
|
||||
Path(__file__).parent.parent.parent.parent / "vllm_omni" / "model_executor" / "stage_configs" / "voxtral_tts.yaml"
|
||||
)
|
||||
STAGE_CONFIG = get_deploy_config_path("voxtral_tts.yaml")
|
||||
SAMPLE_RATE = 24000
|
||||
# Minimum expected audio samples for a short sentence (~0.04s of 24kHz audio)
|
||||
MIN_AUDIO_SAMPLES = 1000
|
||||
@@ -66,9 +64,9 @@ def _resolve_stage_config(run_level: str) -> str:
|
||||
return modify_stage_config(
|
||||
STAGE_CONFIG,
|
||||
deletes={
|
||||
"stage_args": {
|
||||
0: ["engine_args.load_format"],
|
||||
1: ["engine_args.load_format"],
|
||||
"stages": {
|
||||
0: ["load_format"],
|
||||
1: ["load_format"],
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@@ -12,12 +12,11 @@ import os
|
||||
os.environ["VLLM_WORKER_MULTIPROC_METHOD"] = "spawn"
|
||||
os.environ["VLLM_TEST_CLEAN_GPU_MEMORY"] = "0"
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from tests.helpers.mark import hardware_test
|
||||
from tests.helpers.runtime import OmniServerParams
|
||||
from tests.helpers.stage_config import get_deploy_config_path
|
||||
|
||||
MODEL = "FunAudioLLM/Fun-CosyVoice3-0.5B-2512"
|
||||
|
||||
@@ -27,8 +26,8 @@ REF_TEXT = "希望你以后能够做的比我还好呦。"
|
||||
|
||||
|
||||
def get_stage_config(name: str = "cosyvoice3.yaml"):
|
||||
"""Get the stage config path from vllm_omni model_executor stage_configs."""
|
||||
return str(Path(__file__).parent.parent.parent.parent / "vllm_omni" / "model_executor" / "stage_configs" / name)
|
||||
"""Get the deploy config path for CosyVoice3."""
|
||||
return get_deploy_config_path(name)
|
||||
|
||||
|
||||
def get_prompt(prompt_type="zh"):
|
||||
@@ -44,7 +43,7 @@ tts_server_params = [
|
||||
OmniServerParams(
|
||||
model=MODEL,
|
||||
stage_config_path=get_stage_config(),
|
||||
server_args=["--trust-remote-code", "--disable-log-stats"],
|
||||
server_args=["--trust-remote-code", "--disable-log-stats", "--no-async-chunk"],
|
||||
),
|
||||
id="cosyvoice3",
|
||||
)
|
||||
@@ -54,7 +53,7 @@ tts_async_chunk_server_params = [
|
||||
pytest.param(
|
||||
OmniServerParams(
|
||||
model=MODEL,
|
||||
stage_config_path=get_stage_config("cosyvoice3_async_chunk.yaml"),
|
||||
stage_config_path=get_stage_config(),
|
||||
server_args=["--trust-remote-code", "--disable-log-stats"],
|
||||
),
|
||||
id="cosyvoice3_async_chunk",
|
||||
@@ -93,7 +92,7 @@ def test_voice_clone_zh_001(omni_server, openai_client) -> None:
|
||||
def test_voice_clone_zh_002(omni_server, openai_client) -> None:
|
||||
"""
|
||||
Test voice cloning TTS with Chinese text via async_chunk streaming.
|
||||
Deploy Setting: cosyvoice3_async_chunk.yaml
|
||||
Deploy Setting: cosyvoice3.yaml with default ``async_chunk: true``
|
||||
Input Modal: text + ref_audio + ref_text
|
||||
Output Modal: audio (streamed)
|
||||
Input Setting: stream=True
|
||||
|
||||
@@ -12,7 +12,7 @@ import pytest
|
||||
from tests.helpers.mark import hardware_test
|
||||
from tests.helpers.media import generate_synthetic_audio
|
||||
from tests.helpers.runtime import OmniServerParams, dummy_messages_from_mix_data
|
||||
from tests.helpers.stage_config import modify_stage_config
|
||||
from tests.helpers.stage_config import get_deploy_config_path
|
||||
from vllm_omni.model_executor.model_loader.weight_utils import (
|
||||
download_weights_from_hf_specific,
|
||||
)
|
||||
@@ -26,26 +26,6 @@ os.environ["VLLM_WORKER_MULTIPROC_METHOD"] = "spawn"
|
||||
models = ["XiaomiMiMo/MiMo-Audio-7B-Instruct"]
|
||||
|
||||
|
||||
def get_chunk_config():
|
||||
path = modify_stage_config(
|
||||
str(Path(__file__).parent.parent / "stage_configs" / "mimo_audio_ci.yaml"),
|
||||
updates={
|
||||
"async_chunk": True,
|
||||
"stage_args": {
|
||||
0: {
|
||||
"engine_args.custom_process_next_stage_input_func": "vllm_omni.model_executor.stage_input_processors.mimo_audio.llm2code2wav_async_chunk"
|
||||
},
|
||||
1: {
|
||||
"engine_args.max_model_len": 8192,
|
||||
"engine_args.max_num_batched_tokens": 8192,
|
||||
},
|
||||
},
|
||||
},
|
||||
deletes={"stage_args": {1: ["custom_process_input_func"]}},
|
||||
)
|
||||
return path
|
||||
|
||||
|
||||
def download_tokenizer():
|
||||
tokenizer_path = os.environ.get("MIMO_AUDIO_TOKENIZER_PATH", MIMO_AUDIO_TOKENIZER_REPO)
|
||||
if os.path.exists(tokenizer_path):
|
||||
@@ -59,19 +39,21 @@ def download_tokenizer():
|
||||
return local_path
|
||||
|
||||
|
||||
# CI stage config for H100 / MI325
|
||||
# Guard module-level setup so test collection doesn't fail in environments
|
||||
# where the model cache is read-only or models aren't available.
|
||||
try:
|
||||
stage_configs = [get_chunk_config()]
|
||||
stage_configs = [get_deploy_config_path("mimo_audio.yaml")]
|
||||
tokenizer_path = download_tokenizer()
|
||||
os.environ["MIMO_AUDIO_TOKENIZER_PATH"] = tokenizer_path
|
||||
|
||||
# --load-format dummy applies to every stage pipeline-wide, avoiding a
|
||||
# per-stage yaml rewrite (the old approach wrote a tempfile + atexit-unlink
|
||||
# which raced with CI's process lifecycle).
|
||||
test_params = [
|
||||
OmniServerParams(
|
||||
model=model,
|
||||
stage_config_path=stage_config,
|
||||
server_args=["--chat-template", CHAT_TEMPLATE_PATH],
|
||||
server_args=["--chat-template", CHAT_TEMPLATE_PATH, "--load-format", "dummy"],
|
||||
)
|
||||
for model in models
|
||||
for stage_config in stage_configs
|
||||
|
||||
@@ -12,19 +12,16 @@ import os
|
||||
os.environ["VLLM_WORKER_MULTIPROC_METHOD"] = "spawn"
|
||||
os.environ["VLLM_TEST_CLEAN_GPU_MEMORY"] = "0"
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
|
||||
from tests.helpers.mark import hardware_test
|
||||
from tests.helpers.runtime import OmniServerParams
|
||||
from tests.helpers.stage_config import get_deploy_config_path
|
||||
|
||||
MODEL = "mistralai/Voxtral-4B-TTS-2603"
|
||||
|
||||
STAGE_CONFIG = str(
|
||||
Path(__file__).parent.parent.parent.parent / "vllm_omni" / "model_executor" / "stage_configs" / "voxtral_tts.yaml"
|
||||
)
|
||||
STAGE_CONFIG = get_deploy_config_path("voxtral_tts.yaml")
|
||||
EXTRA_ARGS = ["--trust-remote-code", "--enforce-eager", "--disable-log-stats"]
|
||||
TEST_PARAMS = [OmniServerParams(model=MODEL, stage_config_path=STAGE_CONFIG, server_args=EXTRA_ARGS)]
|
||||
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
# CI stage config for running MiMo-Audio in multi-stage omni runtime.
|
||||
# Based on mimo_audio.yaml with load_format: dummy for CI testing.
|
||||
|
||||
async_chunk: false
|
||||
stage_args:
|
||||
- stage_id: 0
|
||||
stage_type: llm
|
||||
runtime:
|
||||
process: true
|
||||
devices: "0"
|
||||
engine_args:
|
||||
dtype: bfloat16
|
||||
max_num_seqs: 1
|
||||
model_stage: fused_thinker_talker
|
||||
model_arch: MiMoAudioForConditionalGeneration
|
||||
worker_type: ar
|
||||
scheduler_cls: vllm_omni.core.sched.omni_ar_scheduler.OmniARScheduler
|
||||
tensor_parallel_size: 1
|
||||
gpu_memory_utilization: 0.5
|
||||
enforce_eager: true
|
||||
trust_remote_code: true
|
||||
enable_prefix_caching: false
|
||||
engine_output_type: latent
|
||||
max_model_len: 8192
|
||||
max_num_batched_tokens: 8192
|
||||
load_format: dummy
|
||||
is_comprehension: true
|
||||
final_output: true
|
||||
final_output_type: text
|
||||
default_sampling_params:
|
||||
temperature: 0.6
|
||||
top_p: 0.95
|
||||
top_k: 50
|
||||
max_tokens: 18192
|
||||
seed: 42
|
||||
detokenize: True
|
||||
repetition_penalty: 1.1
|
||||
|
||||
- stage_id: 1
|
||||
stage_type: llm
|
||||
runtime:
|
||||
process: true
|
||||
devices: "0"
|
||||
engine_args:
|
||||
model_stage: code2wav
|
||||
max_num_seqs: 1
|
||||
model_arch: MiMoAudioForConditionalGeneration
|
||||
worker_type: generation
|
||||
scheduler_cls: vllm_omni.core.sched.omni_generation_scheduler.OmniGenerationScheduler
|
||||
tensor_parallel_size: 1
|
||||
gpu_memory_utilization: 0.2
|
||||
enforce_eager: true
|
||||
trust_remote_code: true
|
||||
enable_prefix_caching: false
|
||||
engine_output_type: audio
|
||||
max_model_len: 18192
|
||||
max_num_batched_tokens: 18192
|
||||
async_scheduling: false
|
||||
load_format: dummy
|
||||
engine_input_source: [ 0 ]
|
||||
is_comprehension: false
|
||||
custom_process_input_func: vllm_omni.model_executor.stage_input_processors.mimo_audio.llm2code2wav
|
||||
final_output: true
|
||||
final_output_type: audio
|
||||
default_sampling_params:
|
||||
temperature: 0.0
|
||||
top_p: 1.0
|
||||
top_k: -1
|
||||
max_tokens: 18192
|
||||
seed: 42
|
||||
detokenize: false
|
||||
@@ -43,6 +43,26 @@ _OMNI_PIPELINES: dict[str, tuple[str, str]] = {
|
||||
"vllm_omni.model_executor.models.qwen3_tts.pipeline",
|
||||
"QWEN3_TTS_PIPELINE",
|
||||
),
|
||||
"voxcpm2": (
|
||||
"vllm_omni.model_executor.models.voxcpm2.pipeline",
|
||||
"VOXCPM2_PIPELINE",
|
||||
),
|
||||
"cosyvoice3": (
|
||||
"vllm_omni.model_executor.models.cosyvoice3.pipeline",
|
||||
"COSYVOICE3_PIPELINE",
|
||||
),
|
||||
"mimo_audio": (
|
||||
"vllm_omni.model_executor.models.mimo_audio.pipeline",
|
||||
"MIMO_AUDIO_PIPELINE",
|
||||
),
|
||||
"voxtral_tts": (
|
||||
"vllm_omni.model_executor.models.voxtral_tts.pipeline",
|
||||
"VOXTRAL_TTS_PIPELINE",
|
||||
),
|
||||
"fish_qwen3_omni": (
|
||||
"vllm_omni.model_executor.models.fish_speech.pipeline",
|
||||
"FISH_SPEECH_PIPELINE",
|
||||
),
|
||||
}
|
||||
|
||||
# --- Single-stage diffusion pipelines (populated in PR 3/N) ---
|
||||
|
||||
@@ -1367,11 +1367,32 @@ class StageConfigFactory:
|
||||
from vllm.transformers_utils.config import get_hf_file_to_dict
|
||||
|
||||
config_dict = get_hf_file_to_dict("config.json", model, revision=None)
|
||||
if config_dict and "model_type" in config_dict:
|
||||
return config_dict["model_type"], None
|
||||
if config_dict:
|
||||
if "model_type" in config_dict:
|
||||
return config_dict["model_type"], None
|
||||
# VoxCPM2-style configs use singular ``architecture`` rather
|
||||
# than HF's standard ``model_type`` / ``architectures``. Accept
|
||||
# it as a fallback so the pipeline registry can still match.
|
||||
if "architecture" in config_dict and isinstance(config_dict["architecture"], str):
|
||||
return config_dict["architecture"], None
|
||||
except Exception as e:
|
||||
logger.debug(f"Failed to auto-detect model type for {model}: {e}")
|
||||
|
||||
# Final fallback: some models (e.g. CosyVoice3) ship an empty
|
||||
# config.json and rely on naming conventions. Match the model path
|
||||
# basename against registered pipeline keys — longest match wins
|
||||
# so "cosyvoice3" (length 10) beats "cosyvoice" (length 9).
|
||||
model_lower = model.lower().replace("-", "").replace("_", "")
|
||||
best: str | None = None
|
||||
best_len = 0
|
||||
for registered_key in _PIPELINE_REGISTRY.keys():
|
||||
candidate = registered_key.lower().replace("-", "").replace("_", "")
|
||||
if candidate and candidate in model_lower and len(candidate) > best_len:
|
||||
best = registered_key
|
||||
best_len = len(candidate)
|
||||
if best is not None:
|
||||
return best, None
|
||||
|
||||
return None, None
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
# CosyVoice3 deploy: 2-stage talker → flow-matching code2wav.
|
||||
#
|
||||
# Default mode is async-chunk streaming through SharedMemoryConnector. Pass
|
||||
# ``--no-async-chunk`` to the serve CLI for the legacy sync path (stage 1
|
||||
# builds flow input from the full speech-token sequence via ``text2flow``).
|
||||
# The shared-memory connector definition and input/output_connectors
|
||||
# references stay in the yaml unconditionally; the runtime only activates
|
||||
# them when ``async_chunk: true``.
|
||||
#
|
||||
# enforce_eager=true everywhere:
|
||||
# * Stage 0 (talker) — cudagraph not verified on this checkpoint.
|
||||
# * Stage 1 (code2wav) — CUDA graphs don't work with dynamic conv shapes.
|
||||
async_chunk: true
|
||||
dtype: float32
|
||||
|
||||
connectors:
|
||||
connector_of_shared_memory:
|
||||
name: SharedMemoryConnector
|
||||
extra:
|
||||
codec_streaming: true
|
||||
connector_get_sleep_s: 0.01
|
||||
connector_get_max_wait_first_chunk: 3000
|
||||
connector_get_max_wait: 300
|
||||
codec_chunk_frames: 25
|
||||
codec_left_context_frames: 25
|
||||
codec_vocab_size: 6561
|
||||
|
||||
stages:
|
||||
- stage_id: 0
|
||||
max_num_seqs: 1
|
||||
gpu_memory_utilization: 0.4
|
||||
enforce_eager: true
|
||||
devices: "0"
|
||||
output_connectors:
|
||||
to_stage_1: connector_of_shared_memory
|
||||
default_sampling_params:
|
||||
max_tokens: 2048
|
||||
top_k: 25
|
||||
top_p: 0.8
|
||||
# near-identity repetition penalty forces vLLM to track
|
||||
# output_token_ids for RAS (stop-token logit logsumexp).
|
||||
repetition_penalty: 1.0001
|
||||
disable_hybrid_kv_cache_manager: true
|
||||
mm_processor_cache_gb: 0
|
||||
skip_mm_profiling: true
|
||||
|
||||
- stage_id: 1
|
||||
max_num_seqs: 1
|
||||
gpu_memory_utilization: 0.2
|
||||
enforce_eager: true
|
||||
max_model_len: 32768
|
||||
devices: "0"
|
||||
input_connectors:
|
||||
from_stage_0: connector_of_shared_memory
|
||||
default_sampling_params:
|
||||
max_tokens: 2048
|
||||
disable_hybrid_kv_cache_manager: true
|
||||
skip_mm_profiling: true
|
||||
@@ -0,0 +1,61 @@
|
||||
# Fish Speech S2 Pro deploy: async-chunk streaming slow_ar → dac_decoder.
|
||||
# Verified on 1× H20.
|
||||
# Registry key and filename use the HF ``model_type=fish_qwen3_omni`` for
|
||||
# auto-detection; human-readable "fish_speech" stays as the source directory.
|
||||
async_chunk: true
|
||||
enable_chunked_prefill: false
|
||||
|
||||
connectors:
|
||||
connector_of_shared_memory:
|
||||
name: SharedMemoryConnector
|
||||
extra:
|
||||
shm_threshold_bytes: 65536
|
||||
codec_streaming: true
|
||||
connector_get_sleep_s: 0.01
|
||||
connector_get_max_wait_first_chunk: 3000
|
||||
connector_get_max_wait: 300
|
||||
# ~21 Hz codec; 25 frames ≈ 1.16s of audio.
|
||||
codec_chunk_frames: 25
|
||||
codec_left_context_frames: 25
|
||||
initial_codec_chunk_frames: 4
|
||||
|
||||
stages:
|
||||
- stage_id: 0
|
||||
max_num_seqs: 4
|
||||
gpu_memory_utilization: 0.6
|
||||
enforce_eager: false
|
||||
async_scheduling: false
|
||||
# vLLM >=0.19 requires max_num_batched_tokens >= max_model_len when
|
||||
# enable_chunked_prefill=false. Bumped from legacy 3072 to match
|
||||
# max_model_len; chunked prefill stays off because the SlowAR decode
|
||||
# loop isn't chunked-prefill-safe.
|
||||
max_num_batched_tokens: 16384
|
||||
max_model_len: 16384
|
||||
devices: "0"
|
||||
output_connectors:
|
||||
to_stage_1: connector_of_shared_memory
|
||||
default_sampling_params:
|
||||
temperature: 0.8
|
||||
top_k: 30
|
||||
top_p: 0.9
|
||||
max_tokens: 2048
|
||||
seed: 42
|
||||
repetition_penalty: 1.0
|
||||
|
||||
- stage_id: 1
|
||||
max_num_seqs: 1
|
||||
gpu_memory_utilization: 0.1
|
||||
enforce_eager: true
|
||||
async_scheduling: false
|
||||
max_num_batched_tokens: 16384
|
||||
max_model_len: 16384
|
||||
devices: "0"
|
||||
input_connectors:
|
||||
from_stage_0: connector_of_shared_memory
|
||||
default_sampling_params:
|
||||
temperature: 0.0
|
||||
top_p: 1.0
|
||||
top_k: -1
|
||||
max_tokens: 65536
|
||||
seed: 42
|
||||
repetition_penalty: 1.0
|
||||
@@ -0,0 +1,56 @@
|
||||
# MiMo Audio deploy: 2-stage thinker+talker → code2wav.
|
||||
#
|
||||
# Default mode is async-chunk streaming on a single GPU (both stages on
|
||||
# device 0) through SharedMemoryConnector. For the legacy 2-GPU sync
|
||||
# pipeline (stage 1 on a second card), pass ``--no-async-chunk
|
||||
# --stage-1-devices 1 --stage-1-max-model-len 18192
|
||||
# --stage-1-max-num-batched-tokens 18192`` to the serve CLI.
|
||||
async_chunk: true
|
||||
dtype: bfloat16
|
||||
|
||||
connectors:
|
||||
connector_of_shared_memory:
|
||||
name: SharedMemoryConnector
|
||||
extra:
|
||||
shm_threshold_bytes: 365536
|
||||
codec_streaming: true
|
||||
connector_get_sleep_s: 0.001
|
||||
connector_get_max_wait_first_chunk: 3000
|
||||
connector_get_max_wait: 300
|
||||
codec_chunk_frames: 3
|
||||
codec_left_context_frames: 3
|
||||
|
||||
stages:
|
||||
- stage_id: 0
|
||||
max_num_seqs: 1
|
||||
gpu_memory_utilization: 0.3
|
||||
enforce_eager: true
|
||||
max_num_batched_tokens: 8192
|
||||
max_model_len: 8192
|
||||
devices: "0"
|
||||
output_connectors:
|
||||
to_stage_1: connector_of_shared_memory
|
||||
default_sampling_params:
|
||||
temperature: 0.6
|
||||
top_p: 0.95
|
||||
top_k: 50
|
||||
max_tokens: 18192
|
||||
seed: 42
|
||||
repetition_penalty: 1.1
|
||||
|
||||
- stage_id: 1
|
||||
max_num_seqs: 1
|
||||
gpu_memory_utilization: 0.2
|
||||
enforce_eager: true
|
||||
async_scheduling: false
|
||||
max_num_batched_tokens: 8192
|
||||
max_model_len: 8192
|
||||
devices: "0"
|
||||
input_connectors:
|
||||
from_stage_0: connector_of_shared_memory
|
||||
default_sampling_params:
|
||||
temperature: 0.0
|
||||
top_p: 1.0
|
||||
top_k: -1
|
||||
max_tokens: 18192
|
||||
seed: 42
|
||||
@@ -0,0 +1,29 @@
|
||||
# VoxCPM2 deploy: single-stage AR pipeline with per-request state batching.
|
||||
# Verified on 1x H20 141GB.
|
||||
#
|
||||
# Fields omitted from a stage fall back to StageDeployConfig defaults (see
|
||||
# vllm_omni/config/stage_config.py). Notable choices:
|
||||
# * enforce_eager=true because the talker's KV-cache save/restore loop is
|
||||
# not cudagraph-compatible (captured separately via voxcpm2_talker's own
|
||||
# _CapturedGraph path).
|
||||
# * max_num_seqs=4 matches the legacy max_batch_size=4 contract: concurrent
|
||||
# requests are supported via per-request StaticKVCache save/restore.
|
||||
async_chunk: false
|
||||
dtype: bfloat16
|
||||
|
||||
stages:
|
||||
- stage_id: 0
|
||||
max_num_seqs: 4
|
||||
gpu_memory_utilization: 0.9
|
||||
enforce_eager: true
|
||||
async_scheduling: true
|
||||
max_num_batched_tokens: 4096
|
||||
max_model_len: 4096
|
||||
devices: "0"
|
||||
default_sampling_params:
|
||||
temperature: 0.0
|
||||
top_p: 1.0
|
||||
top_k: -1
|
||||
max_tokens: 4096
|
||||
seed: 42
|
||||
repetition_penalty: 1.0
|
||||
@@ -0,0 +1,65 @@
|
||||
# Voxtral TTS deploy: async-chunk streaming generator → audio tokenizer.
|
||||
# Verified on 1× H20.
|
||||
#
|
||||
# Mistral tokenizer/config/load flags are declared per-stage here because
|
||||
# DeployConfig does not yet expose them as pipeline-wide fields. They must
|
||||
# match on every stage so the engine args stay consistent across workers.
|
||||
async_chunk: true
|
||||
|
||||
connectors:
|
||||
connector_of_shared_memory:
|
||||
name: SharedMemoryConnector
|
||||
extra:
|
||||
shm_threshold_bytes: 65536
|
||||
codec_streaming: true
|
||||
connector_get_sleep_s: 0.01
|
||||
connector_get_max_wait_first_chunk: 3000
|
||||
connector_get_max_wait: 300
|
||||
codec_chunk_frames: 25
|
||||
codec_chunk_frames_at_begin: 5
|
||||
codec_left_context_frames: 25
|
||||
|
||||
stages:
|
||||
- stage_id: 0
|
||||
max_num_seqs: 32
|
||||
gpu_memory_utilization: 0.8
|
||||
enforce_eager: false
|
||||
async_scheduling: true
|
||||
max_model_len: 4096
|
||||
devices: "0"
|
||||
output_connectors:
|
||||
to_stage_1: connector_of_shared_memory
|
||||
default_sampling_params:
|
||||
temperature: 0.0
|
||||
top_p: 1.0
|
||||
top_k: -1
|
||||
max_tokens: 2048
|
||||
seed: 42
|
||||
repetition_penalty: 1.1
|
||||
tokenizer_mode: mistral
|
||||
config_format: mistral
|
||||
load_format: mistral
|
||||
skip_mm_profiling: true
|
||||
enable_chunked_prefill: false
|
||||
|
||||
- stage_id: 1
|
||||
max_num_seqs: 32
|
||||
gpu_memory_utilization: 0.1
|
||||
enforce_eager: true
|
||||
async_scheduling: false
|
||||
max_num_batched_tokens: 65536
|
||||
max_model_len: 65536
|
||||
devices: "0"
|
||||
input_connectors:
|
||||
from_stage_0: connector_of_shared_memory
|
||||
default_sampling_params:
|
||||
temperature: 0.9
|
||||
top_p: 0.8
|
||||
top_k: 40
|
||||
max_tokens: 2048
|
||||
seed: 42
|
||||
repetition_penalty: 1.05
|
||||
tokenizer_mode: mistral
|
||||
config_format: mistral
|
||||
load_format: mistral
|
||||
skip_mm_profiling: true
|
||||
@@ -247,22 +247,25 @@ def _convert_dataclasses_to_dict(obj: Any) -> Any:
|
||||
def _try_resolve_omni_model_type(model: str) -> str | None:
|
||||
"""Try to resolve model_type for omni models with empty config.json.
|
||||
|
||||
Checks if any registered omni stage config file name matches a substring
|
||||
in the model name (e.g. 'cosyvoice3' in 'FunAudioLLM/Fun-CosyVoice3-0.5B-2512').
|
||||
When multiple configs match, the longest stem wins to avoid ambiguity
|
||||
(e.g. 'bagel_single_stage' over 'bagel').
|
||||
Searches both the legacy ``stage_configs/*.yaml`` directory and the
|
||||
migrated ``deploy/*.yaml`` directory for a stem that substring-matches
|
||||
the model path (e.g. ``cosyvoice3`` in
|
||||
``FunAudioLLM/Fun-CosyVoice3-0.5B-2512``). The longest match wins so
|
||||
``cosyvoice3`` beats ``cosyvoice`` and ``bagel_single_stage`` beats
|
||||
``bagel``.
|
||||
"""
|
||||
stage_configs_dir = PROJECT_ROOT / "vllm_omni" / "model_executor" / "stage_configs"
|
||||
if not stage_configs_dir.exists():
|
||||
return None
|
||||
model_lower = model.lower().replace("-", "").replace("_", "")
|
||||
best_match: str | None = None
|
||||
best_len = 0
|
||||
for config_file in sorted(stage_configs_dir.glob("*.yaml")):
|
||||
candidate = config_file.stem.replace("-", "").replace("_", "")
|
||||
if candidate in model_lower and len(candidate) > best_len:
|
||||
best_match = config_file.stem
|
||||
best_len = len(candidate)
|
||||
for subdir in ("model_executor/stage_configs", "deploy"):
|
||||
config_dir = PROJECT_ROOT / "vllm_omni" / subdir
|
||||
if not config_dir.exists():
|
||||
continue
|
||||
for config_file in sorted(config_dir.glob("*.yaml")):
|
||||
candidate = config_file.stem.replace("-", "").replace("_", "")
|
||||
if candidate and candidate in model_lower and len(candidate) > best_len:
|
||||
best_match = config_file.stem
|
||||
best_len = len(candidate)
|
||||
return best_match
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
"""CosyVoice3 pipeline topology (frozen).
|
||||
|
||||
Stage 0: Talker — text prompt → speech tokens (LLM autoregressive).
|
||||
Stage 1: Code2Wav — flow-matching decoder → acoustic features → waveform.
|
||||
* ``sync_process_input_func`` runs when ``deploy.async_chunk=false``:
|
||||
stage 1 builds full-sequence flow input via ``text2flow``.
|
||||
* ``async_chunk_process_next_stage_input_func`` runs when
|
||||
``deploy.async_chunk=true``: stage 0 streams codec chunks to stage 1
|
||||
through the shared-memory connector.
|
||||
"""
|
||||
|
||||
from vllm_omni.config.stage_config import (
|
||||
PipelineConfig,
|
||||
StageExecutionType,
|
||||
StagePipelineConfig,
|
||||
)
|
||||
|
||||
_PROC = "vllm_omni.model_executor.stage_input_processors.cosyvoice3"
|
||||
|
||||
COSYVOICE3_PIPELINE = PipelineConfig(
|
||||
model_type="cosyvoice3",
|
||||
model_arch="CosyVoice3Model",
|
||||
stages=(
|
||||
StagePipelineConfig(
|
||||
stage_id=0,
|
||||
model_stage="cosyvoice3_talker",
|
||||
execution_type=StageExecutionType.LLM_AR,
|
||||
input_sources=(),
|
||||
owns_tokenizer=True,
|
||||
engine_output_type="latent",
|
||||
async_chunk_process_next_stage_input_func=(f"{_PROC}.talker2code2wav_async_chunk"),
|
||||
sampling_constraints={
|
||||
# merged speech stop token (logsumexp of all 200 stop logits)
|
||||
"stop_token_ids": [6562],
|
||||
},
|
||||
),
|
||||
StagePipelineConfig(
|
||||
stage_id=1,
|
||||
model_stage="cosyvoice3_code2wav",
|
||||
execution_type=StageExecutionType.LLM_GENERATION,
|
||||
input_sources=(0,),
|
||||
final_output=True,
|
||||
final_output_type="audio",
|
||||
engine_output_type="latent",
|
||||
sync_process_input_func=f"{_PROC}.text2flow",
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -0,0 +1,51 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
"""Fish Speech S2 Pro pipeline topology (frozen).
|
||||
|
||||
Stage 0: slow_ar — text → RVQ codec tokens (LLM autoregressive).
|
||||
Stage 1: dac_decoder — RVQ tokens → audio waveform (LLM_GENERATION).
|
||||
|
||||
The HF config top-level reports ``model_type = "fish_qwen3_omni"`` (the
|
||||
OmniConfig that bundles slow-AR and fast-AR sub-configs), which is why the
|
||||
registry key follows the HF name rather than the human-readable "fish_speech".
|
||||
"""
|
||||
|
||||
from vllm_omni.config.stage_config import (
|
||||
PipelineConfig,
|
||||
StageExecutionType,
|
||||
StagePipelineConfig,
|
||||
)
|
||||
|
||||
_PROC = "vllm_omni.model_executor.stage_input_processors.fish_speech"
|
||||
|
||||
FISH_SPEECH_PIPELINE = PipelineConfig(
|
||||
model_type="fish_qwen3_omni",
|
||||
model_arch="FishSpeechSlowARForConditionalGeneration",
|
||||
stages=(
|
||||
StagePipelineConfig(
|
||||
stage_id=0,
|
||||
model_stage="fish_speech_slow_ar",
|
||||
execution_type=StageExecutionType.LLM_AR,
|
||||
input_sources=(),
|
||||
owns_tokenizer=True,
|
||||
engine_output_type="latent",
|
||||
async_chunk_process_next_stage_input_func=(f"{_PROC}.slow_ar_to_dac_decoder_async_chunk"),
|
||||
sampling_constraints={
|
||||
"detokenize": False,
|
||||
# <|im_end|> — stop when the model emits end-of-turn.
|
||||
"stop_token_ids": [151645],
|
||||
},
|
||||
),
|
||||
StagePipelineConfig(
|
||||
stage_id=1,
|
||||
model_stage="dac_decoder",
|
||||
model_arch="FishSpeechDACDecoder",
|
||||
execution_type=StageExecutionType.LLM_GENERATION,
|
||||
input_sources=(0,),
|
||||
final_output=True,
|
||||
final_output_type="audio",
|
||||
engine_output_type="audio",
|
||||
sampling_constraints={"detokenize": True},
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -0,0 +1,54 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
"""MiMo Audio pipeline topology (frozen).
|
||||
|
||||
Stage 0: fused thinker+talker — multimodal understanding + text + RVQ codes.
|
||||
Stage 1: Code2Wav — RVQ codes → waveform.
|
||||
|
||||
MiMoAudioConfig inherits from Qwen2Config, so the HF ``model_type`` field
|
||||
reports ``qwen2`` — the registry's model_type-based auto-detect can't
|
||||
disambiguate. ``hf_architectures`` lets ``StageConfigFactory`` fall back to
|
||||
matching ``hf_config.architectures`` instead.
|
||||
"""
|
||||
|
||||
from vllm_omni.config.stage_config import (
|
||||
PipelineConfig,
|
||||
StageExecutionType,
|
||||
StagePipelineConfig,
|
||||
)
|
||||
|
||||
_PROC = "vllm_omni.model_executor.stage_input_processors.mimo_audio"
|
||||
|
||||
MIMO_AUDIO_PIPELINE = PipelineConfig(
|
||||
model_type="mimo_audio",
|
||||
# HF ``architectures: ["MiMoAudioModel"]`` is also the registry key in
|
||||
# ``model_executor/models/registry.py``; it resolves to the internal
|
||||
# class ``MiMoAudioForConditionalGeneration`` in ``mimo_audio.py``.
|
||||
model_arch="MiMoAudioModel",
|
||||
hf_architectures=("MiMoAudioModel",),
|
||||
stages=(
|
||||
StagePipelineConfig(
|
||||
stage_id=0,
|
||||
model_stage="fused_thinker_talker",
|
||||
execution_type=StageExecutionType.LLM_AR,
|
||||
input_sources=(),
|
||||
final_output=True,
|
||||
final_output_type="text",
|
||||
owns_tokenizer=True,
|
||||
engine_output_type="latent",
|
||||
async_chunk_process_next_stage_input_func=(f"{_PROC}.llm2code2wav_async_chunk"),
|
||||
sampling_constraints={"detokenize": True},
|
||||
),
|
||||
StagePipelineConfig(
|
||||
stage_id=1,
|
||||
model_stage="code2wav",
|
||||
execution_type=StageExecutionType.LLM_GENERATION,
|
||||
input_sources=(0,),
|
||||
final_output=True,
|
||||
final_output_type="audio",
|
||||
engine_output_type="audio",
|
||||
sync_process_input_func=f"{_PROC}.llm2code2wav",
|
||||
sampling_constraints={"detokenize": False},
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -0,0 +1,35 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
"""VoxCPM2 pipeline topology (frozen).
|
||||
|
||||
Single-stage AR TTS: text → speech waveform in one pass.
|
||||
Uses the native MiniCPM4 base_lm with a per-request StaticKVCache that the
|
||||
talker restores into the paged attention layer at step boundaries.
|
||||
"""
|
||||
|
||||
from vllm_omni.config.stage_config import (
|
||||
PipelineConfig,
|
||||
StageExecutionType,
|
||||
StagePipelineConfig,
|
||||
)
|
||||
|
||||
VOXCPM2_PIPELINE = PipelineConfig(
|
||||
model_type="voxcpm2",
|
||||
model_arch="VoxCPM2TalkerForConditionalGeneration",
|
||||
stages=(
|
||||
StagePipelineConfig(
|
||||
stage_id=0,
|
||||
model_stage="latent_generator",
|
||||
execution_type=StageExecutionType.LLM_AR,
|
||||
input_sources=(),
|
||||
final_output=True,
|
||||
final_output_type="audio",
|
||||
owns_tokenizer=True,
|
||||
engine_output_type="audio",
|
||||
sampling_constraints={
|
||||
"detokenize": False,
|
||||
"stop_token_ids": [1],
|
||||
},
|
||||
),
|
||||
),
|
||||
)
|
||||
Whitespace-only changes.
@@ -0,0 +1,45 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
"""Voxtral TTS pipeline topology (frozen).
|
||||
|
||||
Stage 0: audio_generation — text → acoustic latents (LLM_AR, tokenizer owner).
|
||||
Stage 1: audio_tokenizer — acoustic latents → waveform (LLM_GENERATION).
|
||||
"""
|
||||
|
||||
from vllm_omni.config.stage_config import (
|
||||
PipelineConfig,
|
||||
StageExecutionType,
|
||||
StagePipelineConfig,
|
||||
)
|
||||
|
||||
_PROC = "vllm_omni.model_executor.stage_input_processors.voxtral_tts"
|
||||
|
||||
VOXTRAL_TTS_PIPELINE = PipelineConfig(
|
||||
model_type="voxtral_tts",
|
||||
model_arch="VoxtralTTSForConditionalGeneration",
|
||||
stages=(
|
||||
StagePipelineConfig(
|
||||
stage_id=0,
|
||||
model_stage="audio_generation",
|
||||
execution_type=StageExecutionType.LLM_AR,
|
||||
input_sources=(),
|
||||
final_output=False,
|
||||
final_output_type="text",
|
||||
owns_tokenizer=True,
|
||||
engine_output_type="latent",
|
||||
async_chunk_process_next_stage_input_func=(f"{_PROC}.generator2tokenizer_async_chunk"),
|
||||
sampling_constraints={"detokenize": True},
|
||||
),
|
||||
StagePipelineConfig(
|
||||
stage_id=1,
|
||||
model_stage="audio_tokenizer",
|
||||
execution_type=StageExecutionType.LLM_GENERATION,
|
||||
input_sources=(0,),
|
||||
final_output=True,
|
||||
final_output_type="audio",
|
||||
engine_output_type="audio",
|
||||
sampling_constraints={"detokenize": True},
|
||||
extras={"tts_args": {"max_instructions_length": 500}},
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -1,53 +0,0 @@
|
||||
# Stage config for running CosyVoice3 with 2 stage architecture
|
||||
# Stage 0: Talker (text prompt → speech tokens)
|
||||
# Stage 1: Code2Wav (flow matching → acoustic features → waveform)
|
||||
# Right now I have coded up stage 2 in stage 1 only; can be split in future
|
||||
|
||||
stage_args:
|
||||
- stage_id: 0
|
||||
is_comprehension: true
|
||||
runtime:
|
||||
devices: 0
|
||||
engine_args:
|
||||
model_stage: cosyvoice3_talker
|
||||
worker_cls: vllm_omni.worker.gpu_ar_worker.GPUARWorker
|
||||
scheduler_cls: vllm_omni.core.sched.omni_ar_scheduler.OmniARScheduler
|
||||
model_arch: CosyVoice3Model
|
||||
trust_remote_code: true
|
||||
gpu_memory_utilization: 0.2
|
||||
engine_output_type: latent # Output speech tokens for chunk aware flow matching
|
||||
disable_hybrid_kv_cache_manager: true
|
||||
enable_prefix_caching: false
|
||||
enforce_eager: true
|
||||
mm_processor_cache_gb: 0
|
||||
skip_mm_profiling: true
|
||||
dtype: "float32"
|
||||
default_sampling_params:
|
||||
max_tokens: 2048
|
||||
stop_token_ids: [6562] # merged speech stop token (logsumexp of all 200 stop logits)
|
||||
top_k: 25
|
||||
top_p: 0.8
|
||||
repetition_penalty: 1.0001 # near-identity; forces vLLM to track output_token_ids for RAS
|
||||
|
||||
- stage_id: 1
|
||||
runtime:
|
||||
devices: 0
|
||||
engine_args:
|
||||
model_stage: cosyvoice3_code2wav
|
||||
model_arch: CosyVoice3Model
|
||||
trust_remote_code: true
|
||||
worker_cls: vllm_omni.worker.gpu_generation_worker.GPUGenerationWorker
|
||||
scheduler_cls: vllm_omni.core.sched.omni_generation_scheduler.OmniGenerationScheduler
|
||||
engine_output_type: latent
|
||||
gpu_memory_utilization: 0.1
|
||||
enforce_eager: true # CUDA graphs don't work with dynamic conv shapes in code2wav
|
||||
disable_hybrid_kv_cache_manager: true
|
||||
enable_prefix_caching: false
|
||||
skip_mm_profiling: true
|
||||
dtype: "float32"
|
||||
default_sampling_params:
|
||||
max_tokens: 2048
|
||||
engine_input_source: [0]
|
||||
custom_process_input_func: vllm_omni.model_executor.stage_input_processors.cosyvoice3.text2flow
|
||||
final_output: true
|
||||
final_output_type: audio
|
||||
@@ -1,81 +0,0 @@
|
||||
# Stage config for running CosyVoice3 with async_chunk architecture
|
||||
# Stage 0: Talker (text prompt -> speech tokens streamed by chunks)
|
||||
# Stage 1: Code2Wav (flow matching -> acoustic features -> waveform)
|
||||
async_chunk: true
|
||||
|
||||
stage_args:
|
||||
- stage_id: 0
|
||||
is_comprehension: true
|
||||
runtime:
|
||||
devices: 0
|
||||
max_batch_size: 1
|
||||
engine_args:
|
||||
model_stage: cosyvoice3_talker
|
||||
model_arch: CosyVoice3Model
|
||||
worker_type: ar
|
||||
worker_cls: vllm_omni.worker.gpu_ar_worker.GPUARWorker
|
||||
scheduler_cls: vllm_omni.core.sched.omni_ar_scheduler.OmniARScheduler
|
||||
custom_process_next_stage_input_func: vllm_omni.model_executor.stage_input_processors.cosyvoice3.talker2code2wav_async_chunk
|
||||
trust_remote_code: true
|
||||
gpu_memory_utilization: 0.4
|
||||
engine_output_type: latent
|
||||
disable_hybrid_kv_cache_manager: true
|
||||
enable_prefix_caching: false
|
||||
enforce_eager: true
|
||||
mm_processor_cache_gb: 0
|
||||
skip_mm_profiling: true
|
||||
dtype: "float32"
|
||||
default_sampling_params:
|
||||
max_tokens: 2048
|
||||
stop_token_ids: [6562] # merged speech stop token (logsumexp of all 200 stop logits)
|
||||
top_k: 25
|
||||
top_p: 0.8
|
||||
repetition_penalty: 1.0001 # near-identity; forces vLLM to track output_token_ids for RAS
|
||||
output_connectors:
|
||||
to_stage_1: connector_of_shared_memory
|
||||
|
||||
- stage_id: 1
|
||||
runtime:
|
||||
devices: 0
|
||||
max_batch_size: 1
|
||||
engine_args:
|
||||
model_stage: cosyvoice3_code2wav
|
||||
model_arch: CosyVoice3Model
|
||||
worker_type: generation
|
||||
worker_cls: vllm_omni.worker.gpu_generation_worker.GPUGenerationWorker
|
||||
scheduler_cls: vllm_omni.core.sched.omni_generation_scheduler.OmniGenerationScheduler
|
||||
trust_remote_code: true
|
||||
engine_output_type: latent
|
||||
gpu_memory_utilization: 0.2
|
||||
enforce_eager: true
|
||||
disable_hybrid_kv_cache_manager: true
|
||||
enable_prefix_caching: false
|
||||
skip_mm_profiling: true
|
||||
max_model_len: 32768
|
||||
dtype: "float32"
|
||||
default_sampling_params:
|
||||
max_tokens: 2048
|
||||
engine_input_source: [0]
|
||||
final_output: true
|
||||
final_output_type: audio
|
||||
input_connectors:
|
||||
from_stage_0: connector_of_shared_memory
|
||||
|
||||
runtime:
|
||||
enabled: true
|
||||
|
||||
connectors:
|
||||
connector_of_shared_memory:
|
||||
name: SharedMemoryConnector
|
||||
extra:
|
||||
codec_streaming: true
|
||||
connector_get_sleep_s: 0.01
|
||||
connector_get_max_wait_first_chunk: 3000
|
||||
connector_get_max_wait: 300
|
||||
codec_chunk_frames: 25
|
||||
codec_left_context_frames: 25
|
||||
codec_vocab_size: 6561
|
||||
|
||||
edges:
|
||||
- from: 0
|
||||
to: 1
|
||||
@@ -1,91 +0,0 @@
|
||||
async_chunk: true
|
||||
stage_args:
|
||||
- stage_id: 0
|
||||
stage_type: llm
|
||||
is_comprehension: true
|
||||
runtime:
|
||||
devices: "0"
|
||||
max_batch_size: 16
|
||||
engine_args:
|
||||
max_num_seqs: 4
|
||||
model_stage: fish_speech_slow_ar
|
||||
model_arch: FishSpeechSlowARForConditionalGeneration
|
||||
worker_type: ar
|
||||
scheduler_cls: vllm_omni.core.sched.omni_ar_scheduler.OmniARScheduler
|
||||
enforce_eager: false
|
||||
trust_remote_code: true
|
||||
async_scheduling: false
|
||||
enable_prefix_caching: false
|
||||
engine_output_type: latent
|
||||
gpu_memory_utilization: 0.6
|
||||
distributed_executor_backend: "mp"
|
||||
max_num_batched_tokens: 3072
|
||||
max_model_len: 16384
|
||||
custom_process_next_stage_input_func: vllm_omni.model_executor.stage_input_processors.fish_speech.slow_ar_to_dac_decoder_async_chunk
|
||||
output_connectors:
|
||||
to_stage_1: connector_of_shared_memory
|
||||
default_sampling_params:
|
||||
temperature: 0.8
|
||||
top_k: 30
|
||||
top_p: 0.9
|
||||
max_tokens: 2048
|
||||
seed: 42
|
||||
detokenize: false
|
||||
repetition_penalty: 1.0
|
||||
# <|im_end|> token -- stop when model emits end-of-turn.
|
||||
stop_token_ids: [151645]
|
||||
|
||||
- stage_id: 1
|
||||
stage_type: llm
|
||||
runtime:
|
||||
devices: "0"
|
||||
max_batch_size: 16
|
||||
engine_args:
|
||||
max_num_seqs: 1
|
||||
model_stage: dac_decoder
|
||||
model_arch: FishSpeechDACDecoder
|
||||
worker_type: generation
|
||||
scheduler_cls: vllm_omni.core.sched.omni_generation_scheduler.OmniGenerationScheduler
|
||||
enforce_eager: true
|
||||
trust_remote_code: true
|
||||
async_scheduling: false
|
||||
enable_prefix_caching: false
|
||||
engine_output_type: audio
|
||||
gpu_memory_utilization: 0.1
|
||||
distributed_executor_backend: "mp"
|
||||
max_num_batched_tokens: 8192
|
||||
max_model_len: 16384
|
||||
engine_input_source: [0]
|
||||
final_output: true
|
||||
final_output_type: audio
|
||||
input_connectors:
|
||||
from_stage_0: connector_of_shared_memory
|
||||
default_sampling_params:
|
||||
temperature: 0.0
|
||||
top_p: 1.0
|
||||
top_k: -1
|
||||
max_tokens: 65536
|
||||
seed: 42
|
||||
detokenize: true
|
||||
repetition_penalty: 1.0
|
||||
|
||||
runtime:
|
||||
enabled: true
|
||||
connectors:
|
||||
connector_of_shared_memory:
|
||||
name: SharedMemoryConnector
|
||||
extra:
|
||||
shm_threshold_bytes: 65536
|
||||
codec_streaming: true
|
||||
connector_get_sleep_s: 0.01
|
||||
connector_get_max_wait_first_chunk: 3000
|
||||
connector_get_max_wait: 300
|
||||
# Chunk sizes for streaming -- ~21 Hz codec.
|
||||
# 25 frames ≈ 1.16s of audio at 21.5 Hz.
|
||||
codec_chunk_frames: 25
|
||||
codec_left_context_frames: 25
|
||||
initial_codec_chunk_frames: 4
|
||||
|
||||
edges:
|
||||
- from: 0
|
||||
to: 1
|
||||
@@ -1,69 +0,0 @@
|
||||
# stage config for running mimo-audio for multi-stage omni runtime.
|
||||
|
||||
# The following config has been verified on 1x H20-96G GPU.
|
||||
async_chunk: false
|
||||
stage_args:
|
||||
- stage_id: 0
|
||||
stage_type: llm
|
||||
runtime:
|
||||
process: true # Run this stage in a separate process
|
||||
devices: "0" # Visible devices for this stage (CUDA_VISIBLE_DEVICES/torch.cuda.set_device)
|
||||
engine_args:
|
||||
dtype: bfloat16
|
||||
max_num_seqs: 1
|
||||
model_stage: fused_thinker_talker
|
||||
model_arch: MiMoAudioForConditionalGeneration
|
||||
worker_type: ar
|
||||
scheduler_cls: vllm_omni.core.sched.omni_ar_scheduler.OmniARScheduler
|
||||
tensor_parallel_size: 1 # Change to desired TP size for multi-GPU inference (e.g., 4 for 4 GPUs)
|
||||
gpu_memory_utilization: 0.3
|
||||
enforce_eager: true # need to discuss
|
||||
trust_remote_code: true
|
||||
enable_prefix_caching: false
|
||||
engine_output_type: latent # change the param name,such as pooling_output
|
||||
max_model_len: 8192
|
||||
max_num_batched_tokens: 8192
|
||||
is_comprehension: true
|
||||
final_output: true
|
||||
final_output_type: text
|
||||
default_sampling_params:
|
||||
temperature: 0.6
|
||||
top_p: 0.95
|
||||
top_k: 50
|
||||
max_tokens: 18192
|
||||
seed: 42
|
||||
detokenize: True
|
||||
repetition_penalty: 1.1
|
||||
|
||||
- stage_id: 1
|
||||
stage_type: llm
|
||||
runtime:
|
||||
process: true # Run this stage in a separate process
|
||||
devices: "1" # Visible devices for this stage (CUDA_VISIBLE_DEVICES/torch.cuda.set_device)
|
||||
engine_args:
|
||||
model_stage: code2wav
|
||||
max_num_seqs: 1
|
||||
model_arch: MiMoAudioForConditionalGeneration
|
||||
worker_type: generation
|
||||
scheduler_cls: vllm_omni.core.sched.omni_generation_scheduler.OmniGenerationScheduler
|
||||
tensor_parallel_size: 1 # Change to desired TP size for multi-GPU inference (e.g., 4 for 4 GPUs)
|
||||
gpu_memory_utilization: 0.2
|
||||
enforce_eager: true
|
||||
trust_remote_code: true
|
||||
enable_prefix_caching: false
|
||||
engine_output_type: audio
|
||||
max_model_len: 18192
|
||||
max_num_batched_tokens: 18192
|
||||
async_scheduling: false
|
||||
engine_input_source: [ 0 ]
|
||||
is_comprehension: false
|
||||
custom_process_input_func: vllm_omni.model_executor.stage_input_processors.mimo_audio.llm2code2wav
|
||||
final_output: true
|
||||
final_output_type: audio
|
||||
default_sampling_params:
|
||||
temperature: 0.0
|
||||
top_p: 1.0
|
||||
top_k: -1
|
||||
max_tokens: 18192
|
||||
seed: 42
|
||||
detokenize: false
|
||||
@@ -1,91 +0,0 @@
|
||||
# stage config for running mimo-audio for multi-stage omni runtime.
|
||||
|
||||
# The following config has been verified on 1x H20-96G GPU.
|
||||
async_chunk: true
|
||||
stage_args:
|
||||
- stage_id: 0
|
||||
stage_type: llm
|
||||
runtime:
|
||||
process: true # Run this stage in a separate process
|
||||
devices: "0" # Visible devices for this stage (CUDA_VISIBLE_DEVICES/torch.cuda.set_device)
|
||||
engine_args:
|
||||
dtype: bfloat16
|
||||
max_num_seqs: 1
|
||||
model_stage: fused_thinker_talker
|
||||
model_arch: MiMoAudioForConditionalGeneration
|
||||
worker_type: ar
|
||||
scheduler_cls: vllm_omni.core.sched.omni_ar_scheduler.OmniARScheduler
|
||||
tensor_parallel_size: 1 # Change to desired TP size for multi-GPU inference (e.g., 4 for 4 GPUs)
|
||||
gpu_memory_utilization: 0.3
|
||||
enforce_eager: true # need to discuss
|
||||
trust_remote_code: true
|
||||
enable_prefix_caching: false
|
||||
engine_output_type: latent # change the param name,such as pooling_output
|
||||
max_model_len: 8192
|
||||
max_num_batched_tokens: 8192
|
||||
custom_process_next_stage_input_func: vllm_omni.model_executor.stage_input_processors.mimo_audio.llm2code2wav_async_chunk
|
||||
output_connectors:
|
||||
to_stage_1: connector_of_shared_memory
|
||||
is_comprehension: true
|
||||
final_output: true
|
||||
final_output_type: text
|
||||
default_sampling_params:
|
||||
temperature: 0.6
|
||||
top_p: 0.95
|
||||
top_k: 50
|
||||
max_tokens: 18192
|
||||
seed: 42
|
||||
detokenize: True
|
||||
repetition_penalty: 1.1
|
||||
|
||||
- stage_id: 1
|
||||
stage_type: llm
|
||||
runtime:
|
||||
process: true # Run this stage in a separate process
|
||||
devices: "0" # Visible devices for this stage (CUDA_VISIBLE_DEVICES/torch.cuda.set_device)
|
||||
engine_args:
|
||||
model_stage: code2wav
|
||||
max_num_seqs: 1
|
||||
model_arch: MiMoAudioForConditionalGeneration
|
||||
worker_type: generation
|
||||
scheduler_cls: vllm_omni.core.sched.omni_generation_scheduler.OmniGenerationScheduler
|
||||
tensor_parallel_size: 1 # Change to desired TP size for multi-GPU inference (e.g., 4 for 4 GPUs)
|
||||
gpu_memory_utilization: 0.2
|
||||
enforce_eager: true
|
||||
trust_remote_code: true
|
||||
async_scheduling: false
|
||||
enable_prefix_caching: false
|
||||
engine_output_type: audio
|
||||
max_model_len: 8192
|
||||
max_num_batched_tokens: 8192
|
||||
engine_input_source: [ 0 ]
|
||||
input_connectors:
|
||||
from_stage_0: connector_of_shared_memory
|
||||
is_comprehension: false
|
||||
final_output: true
|
||||
final_output_type: audio
|
||||
default_sampling_params:
|
||||
temperature: 0.0
|
||||
top_p: 1.0
|
||||
top_k: -1
|
||||
max_tokens: 18192
|
||||
seed: 42
|
||||
detokenize: false
|
||||
|
||||
runtime:
|
||||
enabled: true
|
||||
connectors:
|
||||
connector_of_shared_memory:
|
||||
name: SharedMemoryConnector
|
||||
extra:
|
||||
shm_threshold_bytes: 365536
|
||||
codec_streaming: true
|
||||
connector_get_sleep_s: 0.001
|
||||
connector_get_max_wait_first_chunk: 3000
|
||||
connector_get_max_wait: 300
|
||||
codec_chunk_frames: 3
|
||||
codec_left_context_frames: 3
|
||||
|
||||
edges:
|
||||
- from: 0
|
||||
to: 1
|
||||
@@ -1,36 +0,0 @@
|
||||
# VoxCPM2 AR pipeline with per-request state batching.
|
||||
# Uses native MiniCPM4 base_lm + per-request StaticKVCache.
|
||||
# max_batch_size > 1 supported via KV cache save/restore.
|
||||
stage_args:
|
||||
- stage_id: 0
|
||||
stage_type: llm
|
||||
is_comprehension: true
|
||||
runtime:
|
||||
devices: "0"
|
||||
max_batch_size: 4
|
||||
engine_args:
|
||||
dtype: bfloat16
|
||||
model_stage: latent_generator
|
||||
model_arch: VoxCPM2TalkerForConditionalGeneration
|
||||
worker_type: ar
|
||||
scheduler_cls: vllm_omni.core.sched.omni_ar_scheduler.OmniARScheduler
|
||||
enforce_eager: true
|
||||
trust_remote_code: true
|
||||
async_scheduling: true
|
||||
enable_prefix_caching: false
|
||||
engine_output_type: audio
|
||||
gpu_memory_utilization: 0.9
|
||||
distributed_executor_backend: "mp"
|
||||
max_num_batched_tokens: 4096
|
||||
max_model_len: 4096
|
||||
default_sampling_params:
|
||||
temperature: 0.0
|
||||
top_p: 1.0
|
||||
top_k: -1
|
||||
max_tokens: 4096
|
||||
seed: 42
|
||||
detokenize: false
|
||||
repetition_penalty: 1.0
|
||||
stop_token_ids: [1]
|
||||
final_output: true
|
||||
final_output_type: audio
|
||||
@@ -1,100 +0,0 @@
|
||||
async_chunk: true
|
||||
stage_args:
|
||||
- stage_id: 0
|
||||
stage_type: llm # Use llm stage type to launch OmniLLM
|
||||
runtime:
|
||||
process: true # Run this stage in a separate process
|
||||
devices: "0" # Visible devices for this stage (CUDA_VISIBLE_DEVICES/torch.cuda.set_device)
|
||||
engine_args:
|
||||
max_num_seqs: 32
|
||||
model_stage: audio_generation
|
||||
model_arch: VoxtralTTSForConditionalGeneration
|
||||
worker_type: ar
|
||||
worker_cls: vllm_omni.worker.gpu_ar_worker.GPUARWorker
|
||||
scheduler_cls: vllm_omni.core.sched.omni_ar_scheduler.OmniARScheduler
|
||||
gpu_memory_utilization: 0.8
|
||||
enforce_eager: false
|
||||
trust_remote_code: true
|
||||
async_scheduling: true
|
||||
engine_output_type: latent
|
||||
enable_prefix_caching: false
|
||||
tokenizer_mode: mistral
|
||||
config_format: mistral
|
||||
load_format: mistral
|
||||
skip_mm_profiling: true
|
||||
enable_chunked_prefill: false
|
||||
max_model_len: 4096
|
||||
custom_process_next_stage_input_func: vllm_omni.model_executor.stage_input_processors.voxtral_tts.generator2tokenizer_async_chunk
|
||||
output_connectors:
|
||||
to_stage_1: connector_of_shared_memory
|
||||
is_comprehension: true
|
||||
final_output: false
|
||||
final_output_type: text
|
||||
default_sampling_params:
|
||||
temperature: 0.0
|
||||
top_p: 1.0
|
||||
top_k: -1
|
||||
max_tokens: 2048
|
||||
seed: 42
|
||||
detokenize: True
|
||||
repetition_penalty: 1.1
|
||||
- stage_id: 1
|
||||
stage_type: llm # Use llm stage type to launch OmniLLM
|
||||
runtime:
|
||||
process: true
|
||||
devices: "0"
|
||||
engine_args:
|
||||
max_num_seqs: 32
|
||||
model_stage: audio_tokenizer
|
||||
model_arch: VoxtralTTSForConditionalGeneration
|
||||
worker_type: generation
|
||||
worker_cls: vllm_omni.worker.gpu_generation_worker.GPUGenerationWorker
|
||||
scheduler_cls: vllm_omni.core.sched.omni_generation_scheduler.OmniGenerationScheduler
|
||||
async_scheduling: false
|
||||
gpu_memory_utilization: 0.1
|
||||
enforce_eager: true
|
||||
trust_remote_code: true
|
||||
enable_prefix_caching: false
|
||||
skip_mm_profiling: true
|
||||
engine_output_type: audio
|
||||
tokenizer_mode: mistral
|
||||
config_format: mistral
|
||||
load_format: mistral
|
||||
max_num_batched_tokens: 65536
|
||||
max_model_len: 65536
|
||||
engine_input_source: [0]
|
||||
is_comprehension: false
|
||||
final_output: true
|
||||
final_output_type: audio
|
||||
input_connectors:
|
||||
from_stage_0: connector_of_shared_memory
|
||||
tts_args:
|
||||
max_instructions_length: 500
|
||||
default_sampling_params:
|
||||
temperature: 0.9
|
||||
top_p: 0.8
|
||||
top_k: 40
|
||||
max_tokens: 2048
|
||||
seed: 42
|
||||
detokenize: True
|
||||
repetition_penalty: 1.05
|
||||
|
||||
# Top-level runtime config (concise): default windows and stage edges
|
||||
runtime:
|
||||
enabled: true
|
||||
connectors:
|
||||
connector_of_shared_memory:
|
||||
name: SharedMemoryConnector
|
||||
extra:
|
||||
shm_threshold_bytes: 65536
|
||||
codec_streaming: true
|
||||
connector_get_sleep_s: 0.01
|
||||
connector_get_max_wait_first_chunk: 3000
|
||||
connector_get_max_wait: 300
|
||||
codec_chunk_frames: 25
|
||||
codec_chunk_frames_at_begin: 5
|
||||
codec_left_context_frames: 25
|
||||
|
||||
edges:
|
||||
- from: 0 # language_model → acoustic_transformer: trigger only after receiving full input (-1)
|
||||
to: 1
|
||||
Reference in new issue
Block a user