语音转文字(转录/翻译)支持¶
本文档将引导您通过实现 SupportsTranscription 接口,为 vLLM 的转录和翻译 API 添加对语音转文字 (ASR) 模型的支持。请参阅受支持的模型以获取进一步指导。
更新 vLLM 基础模型¶
假设您已根据基础模型指南在 vLLM 中实现了您的模型。请使用 SupportsTranscription 接口扩展您的模型,并实现以下类属性和方法。
supported_languages 和 supports_transcription_only¶
声明支持的语言和功能
supported_languages映射会在初始化时进行验证。- 如果模型不应提供文本生成服务(例如 Whisper),请设置
supports_transcription_only=True。
supported_languages 和 supports_transcription_only
from typing import ClassVar, Mapping, Literal
import numpy as np
import torch
from torch import nn
from vllm.config import ModelConfig, SpeechToTextConfig
from vllm.inputs import PromptType
from vllm.model_executor.models.interfaces import SupportsTranscription
class YourASRModel(nn.Module, SupportsTranscription):
# Map of ISO 639-1 language codes to language names
supported_languages: ClassVar[Mapping[str, str]] = {
"en": "English",
"it": "Italian",
# ... add more as needed
}
# If your model only supports audio-conditioned generation
# (no text-only generation), enable this flag.
supports_transcription_only: ClassVar[bool] = True
通过 get_speech_to_text_config 提供 ASR 配置。
这用于在服务您的模型时控制 API 的常规行为
get_speech_to_text_config()
class YourASRModel(nn.Module, SupportsTranscription):
...
@classmethod
def get_speech_to_text_config(
cls,
model_config: ModelConfig,
task_type: Literal["transcribe", "translate"],
) -> SpeechToTextConfig:
return SpeechToTextConfig(
sample_rate=16_000,
max_audio_clip_s=30,
# Set to None to disable server-side chunking if your
# model/processor handles it already
min_energy_split_window_size=None,
)
有关每个字段控制内容的说明,请参见音频预处理与分段。
通过 get_generation_prompt 实现提示词构建。服务器会将重采样后的波形数据和任务参数传递给您;您需要返回一个有效的 PromptType。有两种常见的模式:
带音频嵌入的多模态 LLM(例如 Voxtral, Gemma3n)¶
返回一个包含音频 multi_modal_data 以及 prompt 字符串或 prompt_token_ids 的字典
get_generation_prompt()
class YourASRModel(nn.Module, SupportsTranscription):
...
@classmethod
def get_generation_prompt(
cls,
audio: np.ndarray,
stt_config: SpeechToTextConfig,
model_config: ModelConfig,
language: str | None,
task_type: Literal["transcribe", "translate"],
request_prompt: str,
to_language: str | None,
) -> PromptType:
# Example with a free-form instruction prompt
task_word = "Transcribe" if task_type == "transcribe" else "Translate"
prompt = (
"<start_of_turn>user\n"
f"{task_word} this audio: <audio_soft_token>"
"<end_of_turn>\n<start_of_turn>model\n"
)
return {
"multi_modal_data": {"audio": (audio, stt_config.sample_rate)},
"prompt": prompt,
}
关于多模态输入的进一步说明,请参阅多模态输入。
仅音频的编码器-解码器模型(例如 Whisper)¶
返回一个分别带有 encoder_prompt 和 decoder_prompt 条目的字典
get_generation_prompt()
class YourASRModel(nn.Module, SupportsTranscription):
...
@classmethod
def get_generation_prompt(
cls,
audio: np.ndarray,
stt_config: SpeechToTextConfig,
model_config: ModelConfig,
language: str | None,
task_type: Literal["transcribe", "translate"],
request_prompt: str,
to_language: str | None,
) -> PromptType:
if language is None:
raise ValueError("Language must be specified")
prompt = {
"encoder_prompt": {
"prompt": "",
"multi_modal_data": {
"audio": (audio, stt_config.sample_rate),
},
},
"decoder_prompt": (
(f"<|prev|>{request_prompt}" if request_prompt else "")
+ f"<|startoftranscript|><|{language}|>"
+ f"<|{task_type}|><|notimestamps|>"
),
}
return cast(PromptType, prompt)
validate_language (可选)¶
通过 validate_language 进行语言验证
如果您的模型需要指定语言且您希望设置默认值,请重写此方法(参考 Whisper)
validate_language()
@classmethod
def validate_language(cls, language: str | None) -> str | None:
if language is None:
logger.warning(
"Defaulting to language='en'. If you wish to transcribe "
"audio in a different language, pass the `language` field "
"in the TranscriptionRequest."
)
language = "en"
return super().validate_language(language)
get_num_audio_tokens (可选)¶
通过 get_num_audio_tokens 进行流式传输的 Token 计数
提供一个快速的“时长→Token”估算,以改善流式传输的使用统计数据
get_num_audio_tokens()
class YourASRModel(nn.Module, SupportsTranscription):
...
@classmethod
def get_num_audio_tokens(
cls,
audio_duration_s: float,
stt_config: SpeechToTextConfig,
model_config: ModelConfig,
) -> int | None:
# Return None if unknown; otherwise return an estimate.
return int(audio_duration_s * stt_config.sample_rate // 320) # example
音频预处理与分段¶
API 服务器负责在构建提示词之前处理基础音频 I/O 和可选的分段操作
- 重采样:输入音频使用
librosa重采样为SpeechToTextConfig.sample_rate。 - 分段:如果
SpeechToTextConfig.allow_audio_chunking为 True 且时长超过max_audio_clip_s,服务器会将音频分割成重叠的分段,并为每个分段生成提示词。重叠部分由overlap_chunk_second控制。 - 能量感知分割:设置
min_energy_split_window_size后,服务器会寻找低能量区域,以最大限度减少在单词中间进行切割的情况。
相关服务器逻辑
_preprocess_speech_to_text()
# vllm/entrypoints/openai/speech_to_text.py
async def _preprocess_speech_to_text(...):
language = self.model_cls.validate_language(request.language)
...
y, sr = librosa.load(bytes_, sr=self.asr_config.sample_rate)
duration = librosa.get_duration(y=y, sr=sr)
do_split_audio = (self.asr_config.allow_audio_chunking
and duration > self.asr_config.max_audio_clip_s)
chunks = [y] if not do_split_audio else self._split_audio(y, int(sr))
prompts = []
for chunk in chunks:
prompt = self.model_cls.get_generation_prompt(
audio=chunk,
stt_config=self.asr_config,
model_config=self.model_config,
language=language,
task_type=self.task_type,
request_prompt=request.prompt,
to_language=to_language,
)
prompts.append(prompt)
return prompts, duration
自动暴露任务¶
如果您的模型实现了该接口,vLLM 会自动宣告对转录的支持
if supports_transcription(model):
if model.supports_transcription_only:
return ["transcription"]
supported_tasks.append("transcription")
启用后,服务器将初始化转录和翻译处理器
state.openai_serving_transcription = OpenAIServingTranscription(...) if "transcription" in supported_tasks else None
state.openai_serving_translation = OpenAIServingTranslation(...) if "transcription" in supported_tasks else None
除了通过模型注册表使您的模型类可用并实现 SupportsTranscription 外,无需额外的注册步骤。
源码树中的示例¶
- Whisper 编码器-解码器(仅音频): vllm/model_executor/models/whisper.py
- Voxtral 仅解码器(音频嵌入 + LLM): vllm/model_executor/models/voxtral.py。请确保已安装
mistral-common[audio]。 - 带有固定指令提示词的 Gemma3n 仅解码器模型: vllm/model_executor/models/gemma3n_mm.py
- Qwen3-Omni 多模态(带音频嵌入): vllm/model_executor/models/qwen3_omni_moe_thinker.py
使用 API 进行测试¶
一旦您的模型实现了 SupportsTranscription,您就可以测试端点(API 模拟 OpenAI)
-
转录 (ASR)
-
翻译(源语言 → 英语,除非有其他支持)
或者查看 examples/online_serving 中的更多示例。
注意
- 如果您的模型在内部处理分段(例如通过其处理器或编码器),请在返回的
SpeechToTextConfig中设置min_energy_split_window_size=None以禁用服务端分段。 - 实现
get_num_audio_tokens可以提高流式传输使用指标 (prompt_tokens) 的准确性,且无需额外的正向传播。 - 对于多语言行为,请保持
supported_languages与模型的实际能力一致。