Step-Audio2 在线服务部署指南:vLLM-Omni 双阶段 TTS/ASR/S2ST 实践
【免费下载链接】vllm-omniA framework for efficient model inference with omni-modality models项目地址: https://gitcode.com/GitHub_Trending/vl/vllm-omni
导读
本指南以 vLLM-Omni 仓库中 examples/online_serving/step_audio2 目录为核心,系统讲解如何通过 vLLM-Omni 的 OpenAI 兼容在线服务接口部署并调用 Step-Audio-2-mini 模型,覆盖 TTS(文本转语音)、ASR(语音转文本)与 S2ST(语音到语音翻译)三种推理模式。你将掌握两阶段模型的部署拓扑(Thinker → Token2Wav)、Async Chunk 流式模式与顺序模式的性能差异,以及/v1/audio/speech与/v1/chat/completions两种请求路径的完整用法。
Step-Audio2 的模型结构与部署形态
Step-Audio2 是一个典型的两阶段(two-stage)语音模型:
- Stage 0(Thinker / 思考器):负责音频理解与生成,输出「文本 + 音频 token」序列;
- Stage 1(Token2Wav):把 Thinker 产出的音频 token 解码为 24kHz 的波形(WAV)。
该拓扑在 vLLM-Omni 的 pipeline 定义中固化,见 vllm_omni/model_executor/models/step_audio2/pipeline.py:
- Stage 0 使用
step_audio2_thinker模型阶段,执行类型为LLM_AR(自回归),输出latent类型,final_output_type="text",采样约束为detokenize: True; - Stage 1 使用
token2wav模型阶段,执行类型为LLM_GENERATION,输入源为 Stage 0,输出audio类型,采样约束为detokenize: False; - Stage 0 到 Stage 1 的数据桥接函数为
thinker2token2wav(顺序模式)与thinker2token2wav_async_chunk(异步分块模式),实现于vllm_omni.model_executor.stage_input_processors.step_audio2。
仓库为不同推理场景提供了三份可直接使用的部署配置:
| 配置文件 | 拓扑 | 适用场景 |
|---|---|---|
| vllm_omni/deploy/step_audio_2.yaml | Thinker → Token2Wav(顺序) | 完整双阶段推理(TTS / S2ST) |
| vllm_omni/deploy/step_audio_2_async_chunk.yaml | Thinker → Token2Wav(异步分块) | 低首包延迟的 TTS 场景 |
| vllm_omni/deploy/step_audio_2_asr.yaml | 仅 Thinker | 纯 ASR(音频 → 文本) |
安装与前置条件
安装 vLLM-Omni 请参阅仓库根目录的 README.md,按平台选择对应的依赖组合(requirements/目录下提供 cuda、rocm、npu、xpu、cpu、musa 等不同后端的依赖清单)。
部署 Step-Audio-2-mini 还需要:
- 可访问 Hugging Face 或本地已下载的
stepfun-ai/Step-Audio-2-mini权重; - 启动时需携带
--trust-remote-code(模型包含自定义代码); - GPU 环境(参考部署配置默认使用 2 张卡,Thinker 走
tensor_parallel_size=2)。
启动服务
Async Chunk 模式(推荐,TTS 首包延迟更低)
# Async chunk mode (recommended — lower first-packet latency for TTS) vllm serve stepfun-ai/Step-Audio-2-mini --omni --port 8092 \ --deploy-config vllm_omni/deploy/step_audio_2_async_chunk.yaml \ --trust-remote-code --enforce-eager顺序模式(Sequential)
vllm serve stepfun-ai/Step-Audio-2-mini --omni --port 8092 \ --deploy-config vllm_omni/deploy/step_audio_2.yaml \ --trust-remote-code --enforce-eager使用本地模型路径
vllm serve /path/to/Step-Audio-2-mini --omni --port 8092 \ --trust-remote-code --enforce-eager不指定
--deploy-config时,vLLM-Omni 会根据模型架构自动识别 Step-Audio2 并选择默认拓扑;显式指定配置文件则用于控制async_chunk开关、各阶段显存与采样参数。
部署配置详解
以 vllm_omni/deploy/step_audio_2_async_chunk.yaml 为例,逐项说明关键字段:
# Step-Audio2 deploy: thinker -> token2wav with async chunk streaming. async_chunk: true # 开启异步分块流式,音频 token 边生成边送 Token2Wav trust_remote_code: true enable_prefix_caching: false stages: - stage_id: 0 # Thinker 阶段 devices: "0,1" # 使用 GPU 0 和 1 tensor_parallel_size: 2 max_num_seqs: 1 gpu_memory_utilization: 0.7 enforce_eager: true async_scheduling: false max_num_batched_tokens: 1024 default_sampling_params: temperature: 0.7 top_p: 0.9 top_k: -1 # -1 表示不启用 top_k 截断 max_tokens: 1024 seed: 42 repetition_penalty: 1.05 - stage_id: 1 # Token2Wav 阶段 devices: "1" max_num_seqs: 1 gpu_memory_utilization: 0.2 enforce_eager: true async_scheduling: false max_num_batched_tokens: 2048 hf_overrides: architectures: ["StepAudio2Token2WavForConditionalGeneration"] default_sampling_params: temperature: 0.0 # Token2Wav 使用贪心解码 top_p: 1.0 top_k: -1 max_tokens: 1 seed: 42顺序模式配置 vllm_omni/deploy/step_audio_2.yaml 与上述几乎一致,仅async_chunk: false,且 Thinker 的max_num_batched_tokens为 8192、Token2Wav 为 4096——顺序模式需要 Thinker 完整产出后一次性送入 Token2Wav,因此批处理窗口更大。
两份配置均体现了双阶段采样的关键设计:Thinker 阶段使用带温度(0.7)、top_p(0.9)、重复惩罚(1.05)的采样以提升生成自然度;Token2Wav 阶段使用温度 0.0、max_tokens: 1的贪心解码,因为该阶段只负责把音频 token 逐帧解码为波形,不需要随机性。
纯 ASR 部署(Thinker Only)
若只做音频转文本,可部署 vllm_omni/deploy/step_audio_2_asr.yaml:它通过pipeline: step_audio_2_asr显式选择 ASR pipeline,仅保留 Stage 0 的 Thinker,避免双阶段拓扑在音频到文本请求跳过 Token2Wav 时可能出现的死锁问题。CI 配置 vllm_omni/deploy/step_audio2_ci.yaml 同样选用该 ASR pipeline,并额外设置了max_model_len: 1024、skip_mm_profiling: true以及hf_overrides.architectures: ["StepAudio2ThinkerForConditionalGeneration"],便于在较小显存环境(如单卡 24GB)运行。
发送请求
进入示例目录后即可运行客户端:
cd examples/online_serving/step_audio2方式一:TTS 走/v1/audio/speech(推荐)
该端点绕过 chat template,直接触发 TTS 模式,并支持 Async Chunk 流式以获得低首包延迟。
# Python client python openai_speech_client.py --text "你好世界" # With custom system prompt python openai_speech_client.py --text "Hello, how are you?" \ --instructions "You are a friendly assistant." # Save to specific file python openai_speech_client.py --text "你好世界" -o output.wav或直接使用 curl:
curl -X POST http://localhost:8092/v1/audio/speech \ -H "Content-Type: application/json" \ -d '{"model":"stepfun-ai/Step-Audio-2-mini","input":"你好世界","voice":"default"}' \ --output output.wavopenai_speech_client.py的完整参数见 examples/online_serving/step_audio2/openai_speech_client.py:
| 参数 | 默认值 | 说明 |
|---|---|---|
--api-base | http://localhost:8092 | API 基础地址 |
--api-key | EMPTY | API Key(本地服务默认无需鉴权) |
--model,-m | stepfun-ai/Step-Audio-2-mini | 模型名或本地路径 |
--text | 必填 | 待合成的文本 |
--voice | default | 音色名 |
--instructions | 无 | Thinker 阶段的系统提示词(system prompt) |
--response-format | wav | 输出格式,可选wav/pcm |
--output,-o | tts_output.wav | 输出文件路径 |
/v1/audio/speech的底层实现
该端点在 vLLM-Omni 中通过 TTS Adapter 机制实现,Step-Audio2 的适配器位于 vllm_omni/entrypoints/openai/tts_adapters/step_audio2.py。其build方法直接构造一段以<tts_start>结尾的聊天 prompt:
<|im_start|>system {system_prompt}<|im_end|> <|im_start|>user {request.input}<|im_end|> <|im_start|>assistant <tts_start>其中system_prompt取自请求的instructions字段,缺省为"You are a voice assistant. Read the text aloud."。assistant 回合刻意省略<|im_end|>,让 Thinker 在<tts_start>之后继续生成音频 token——这与 chat completions 路径中的continue_final_message语义一致。Adapter 注册的stage_keys为{"step_audio2_thinker"},即 TTS 请求只会路由到 Thinker 阶段,Token2Wav 阶段由 Thinker 的音频 token 输出自动驱动。
注意:说话人的音色由服务端环境变量STEP_AUDIO2_DEFAULT_PROMPT_WAV控制(该变量登记于 vllm_omni/config/environment_variable_inventory.py),客户端voice参数当前接受default。
方式二:Chat Completions(ASR / TTS / S2ST)
# Audio to Text (ASR) python openai_chat_completion_client.py --query-type audio_to_text # Audio to Audio (S2ST) python openai_chat_completion_client.py --query-type audio_to_audio --audio-path /path/to/input.wav客户端 openai_chat_completion_client.py 的参数:
| 参数 | 说明 |
|---|---|
--query-type,-q | 查询类型:audio_to_text、text_to_audio、audio_to_audio |
--audio-path,-a | 输入音频路径(本地文件或 URL,缺省使用内置的 mary_had_lamb 测试音频) |
--text,-t | 待合成的文本(TTS 模式使用) |
--prompt,-p | 自定义提示词/问题 |
--model,-m | 模型名(默认stepfun-ai/Step-Audio-2-mini) |
--max-tokens | Thinker 阶段最大 token 数(默认 1024) |
--output-dir,-o | 音频输出目录(默认output_online) |
--api-base | API 地址(默认http://localhost:8092/v1) |
双阶段采样参数:sampling_params_list
Chat Completions 路径的核心机制是sampling_params_list——按阶段顺序指定各自的采样参数,客户端会将其作为extra_body发送:
thinker_sampling_params = { "temperature": 0.7, "top_p": 0.9, "top_k": -1, "max_tokens": args.max_tokens, "seed": SEED, "detokenize": True, "repetition_penalty": 1.1 if args.query_type != "audio_to_text" else 1.05, } # ASR 模式下在 EOS 处停止 if args.query_type == "audio_to_text": thinker_sampling_params["stop_token_ids"] = [151645] token2wav_sampling_params = { "temperature": 0.0, "top_p": 1.0, "top_k": -1, "max_tokens": 1, "seed": SEED, "detokenize": False, } sampling_params_list = [thinker_sampling_params, token2wav_sampling_params]要点:
- ASR 场景为 Thinker 设置
stop_token_ids: [151645],让模型在文本转录完成后立即停止; - TTS / S2ST 场景需要额外设置
continue_final_message=True与add_generation_prompt=False,确保 assistant 回合中的<tts_start>不会被追加<|im_end|>,Thinker 得以继续生成音频 token; - 音频输入以 data URL(base64)形式编码进
audio_url,支持本地文件(自动按扩展名识别 wav/mp3/ogg/flac)或 HTTP(S) 直链。
Curl 方式(Chat Completions)
# Audio to Text bash run_curl.sh audio_to_text # Text to Audio bash run_curl.sh text_to_audio # Audio to Audio bash run_curl.sh audio_to_audiorun_curl.sh 内置了与 Python 客户端一致的采样参数(Thinker:温度 0.7 / top_p 0.9 / repetition_penalty 1.05 或 1.1;Token2Wav:温度 0.0 /max_tokens: 1),并用jq解析响应中的文本与 base64 音频数据。文本转语音时需在文本末尾追加<tts_start>标记以触发 TTS。
三种查询类型
1. Audio to Text(ASR,语音转文本)
python openai_chat_completion_client.py \ --query-type audio_to_text \ --audio-path /path/to/speech.wav \ --prompt "Transcribe this audio."Thinker 直接输出转录文本,响应中不包含音频。系统提示词为"You are a speech recognition assistant. Transcribe the audio accurately."。
2. Text to Audio(TTS,文本转语音)
# Via speech endpoint (recommended, returns WAV directly) python openai_speech_client.py --text "Hello, welcome to Step-Audio2." # Via chat completions python openai_chat_completion_client.py \ --query-type text_to_audio \ --text "Hello, welcome to Step-Audio2."Chat Completions 路径会构造「user 文本消息 + assistant<tts_start>消息」,Thinker 在<tts_start>后生成音频 token,Token2Wav 解码为波形。
3. Audio to Audio(S2ST,语音到语音)
python openai_chat_completion_client.py \ --query-type audio_to_audio \ --audio-path /path/to/source.wav输入音频经过 Thinker 理解后生成文本转录与音频输出,适用于语音复述、翻译或音色转换场景。
输出说明
- 文本输出:打印到控制台(
choice.message.content); - 音频输出:保存为
output_online/audio_0.wav,24kHz WAV 格式(来自choice.message.audio.data的 base64 解码); - 若 TTS/S2ST 请求未收到音频,客户端会打印
No audio output received警告,此时应检查服务端日志。
API 格式
Step-Audio2 使用 OpenAI 兼容的 chat completions API:
{ "model": "stepfun-ai/Step-Audio-2-mini", "messages": [ { "role": "system", "content": [{"type": "text", "text": "Transcribe the audio."}] }, { "role": "user", "content": [ {"type": "audio_url", "audio_url": {"url": "..."}}, {"type": "text", "text": "Please transcribe."} ] } ], "sampling_params_list": [ {"temperature": 0.7, "max_tokens": 1024}, {"temperature": 0.0, "max_tokens": 1} ] }messages中的audio_url支持公网 URL 与data:base64 data URL 两种形式;sampling_params_list按阶段顺序对应 Thinker 与 Token2Wav。
性能对比:Async Chunk vs Sequential
通过/v1/audio/speech端点的基准测试(4x RTX 3090、10 条提示、并发=1,数据来自示例目录 README):
| 模式 | Mean TTFP | Mean E2E | Mean RTF |
|---|---|---|---|
| Sequential(顺序) | 4316ms | 4316ms | 0.938 |
| Async Chunk(异步分块) | 1437ms | 4362ms | 0.949 |
- Async Chunk 通过把 Thinker 边生成边产出的音频 token分块流式送入 Token2Wav,将首包延迟(TTFP)降低67%(4316ms → 1437ms),端到端耗时(E2E)基本持平;
- 两种模式的 RTF(实时率,Real-Time Factor)均小于 1,说明都能满足实时推理要求;
- 从 pipeline 定义看,Async Chunk 的核心是 Stage 0 的
async_chunk_process_next_stage_input_func=thinker2token2wav_async_chunk,它替代了顺序模式下 Stage 1 的sync_process_input_func=thinker2token2wav,使 Stage 1 无需等待 Thinker 全部输出即可开始解码。
故障排查
服务无响应
# 检查服务是否存活 curl http://localhost:8092/v1/models并核对端口号是否与启动参数--port一致。
FileNotFoundError: prompt_wav file not found
- 确保
{model_dir}/assets/default_female.wav文件存在; - 或在启动服务时设置
STEP_AUDIO2_DEFAULT_PROMPT_WAV环境变量指定说话人提示音频的路径。
音频未生成
- TTS 场景优先使用
/v1/audio/speech端点或openai_speech_client.py; - 走 chat completions 的 TTS 时,确保提示词以
<tts_start>结尾(或使用客户端自动追加机制); - 检查服务端日志中的报错信息。
显存不足(Out of Memory)
- 在部署配置中降低
gpu_memory_utilization(默认 Thinker 0.7 / Token2Wav 0.2,可按实际显存调整); - 减小批大小(
max_num_seqs)或max_num_batched_tokens。
参考资源
- 示例目录:examples/online_serving/step_audio2(客户端脚本、curl 脚本与本指南)
- 部署配置:vllm_omni/deploy/step_audio_2.yaml、vllm_omni/deploy/step_audio_2_async_chunk.yaml、vllm_omni/deploy/step_audio_2_asr.yaml
- Pipeline 拓扑定义:vllm_omni/model_executor/models/step_audio2/pipeline.py
- TTS Adapter 实现:vllm_omni/entrypoints/openai/tts_adapters/step_audio2.py
- 环境变量清单:vllm_omni/config/environment_variable_inventory.py
- 模型实现:
vllm_omni/model_executor/models/step_audio2/(thinker、token2wav、constants 等)
【免费下载链接】vllm-omniA framework for efficient model inference with omni-modality models项目地址: https://gitcode.com/GitHub_Trending/vl/vllm-omni
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考