docs: add comprehensive vLLM guide (Chinese)

Complete documentation covering:
- Model support matrix (which models can/cannot use vLLM and why)
- Quick start for AutoModelVLLM, offline, and streaming inference
- Architecture diagrams and streaming design explanation
- Performance benchmarks
- API reference
- FAQ
This commit is contained in:
游雁
2026-05-23 13:30:46 +08:00
parent bdcb315109
commit d0e3235fa3
+235
View File
@@ -0,0 +1,235 @@
# FunASR vLLM Inference Guide
本文档介绍如何使用 vLLM 加速 FunASR 中 LLM-based ASR 模型的推理。
## 概览
vLLM 是一个高吞吐量 LLM 推理引擎,支持 PagedAttention、Tensor Parallelism 等优化。FunASR 集成 vLLM 用于加速 LLM 解码部分,实现 **2-3x** 推理加速。
### 适用模型
| 模型 | vLLM 支持 | 说明 |
|------|-----------|------|
| **FunASRNano** | ✓ | Qwen3-0.6B LLM,支持离线和流式 |
| **LLMASR** | ✓ | Whisper + Qwen/Vicuna/LLaMA |
| **GLMASR** | ✓ | GLM-ASR-Nano |
| **QwenAudioWarp** | ✓ | Qwen-Audio |
| Paraformer | ✗ | 非自回归模型(CIF predictor),无 LLM 解码 |
| SenseVoice | ✗ | Whisper-like encoder-decoder,非 LLM |
| Conformer/Transformer | ✗ | CTC/attention 解码,非 LLM |
| Qwen3-ASR | ✗ | 使用外部 qwen-asr 包自带优化 |
### 为什么 Paraformer 不能用 vLLM?
Paraformer 使用 CIF (Continuous Integrate-and-Fire) predictor 实现**非自回归**并行解码。所有 token 同时生成,不需要 KV-cache。vLLM 的优化(PagedAttention、KV-cache 管理)只对**自回归** LLM 有效。
## 安装
```bash
pip install funasr>=1.3.0
pip install vllm>=0.11.0
pip install safetensors tiktoken
```
## 快速开始
### 通用接口 (AutoModelVLLM)
```python
from funasr.auto.auto_model_vllm import AutoModelVLLM
# 自动检测模型类型,使用 vLLM 加速
model = AutoModelVLLM(
model="FunAudioLLM/Fun-ASR-Nano-2512",
hub="ms",
tensor_parallel_size=2, # 2卡并行
gpu_memory_utilization=0.8,
)
results = model.generate(["audio.wav"], language="中文")
print(results[0]["text"])
```
### 离线批量推理 (FunASRNanoVLLM)
```python
from funasr.models.fun_asr_nano.inference_vllm import FunASRNanoVLLM
engine = FunASRNanoVLLM.from_pretrained(
model="FunAudioLLM/Fun-ASR-Nano-2512",
tensor_parallel_size=4, # 4卡并行
)
# 批量处理
results = engine.generate(
inputs=["audio1.wav", "audio2.wav", "audio3.wav"],
hotwords=["开放时间"],
language="中文",
)
for r in results:
print(f"[{r['key']}] {r['text']}")
if "timestamps" in r:
print(f" timestamps: {r['timestamps'][:3]}")
```
### 流式推理 (FunASRNanoStreamingVLLM)
```python
from funasr.models.fun_asr_nano.inference_vllm_streaming import FunASRNanoStreamingVLLM
engine = FunASRNanoStreamingVLLM.from_pretrained(
model="FunAudioLLM/Fun-ASR-Nano-2512",
chunk_ms=720, # 每720ms一个chunk
rollback_chars=8, # 回退8个字符
)
for result in engine.streaming_generate("audio.wav", language="中文"):
if result["is_final"]:
print(f"最终结果: {result['text']}")
else:
print(f"[{result['audio_duration_ms']:.0f}ms] {result['text']}")
print(f" 确认区: {result['fixed_text']}")
```
## 命令行 Demo
```bash
cd examples/industrial_data_pretraining/fun_asr_nano
# 单卡推理
python demo_vllm.py --input audio.wav --language 中文
# 多卡并行 + 批量
python demo_vllm.py --input wav.scp --tensor-parallel-size 4 --batch-size 32
# 带热词
python demo_vllm.py --input audio.wav --hotwords 开放时间 周一 --language 中文
```
## 架构说明
```
┌───────────────────────────────────────────────────────────┐
│ FunASR + vLLM │
├───────────────────────────────────────────────────────────┤
│ │
│ Audio ──→ Frontend ──→ Audio Encoder ──→ Audio Adaptor │
│ (fbank) (SenseVoice/ (Linear/ │
│ Whisper) Transformer) │
│ │ │
│ ▼ │
│ Audio Embeddings │
│ │ │
│ Text Prompt ──→ Tokenize ──→ Embed ──→ [Concat] │
│ (system/user/ │ │
│ assistant) ▼ │
│ ┌─────────────┐ │
│ │ vLLM │ │
│ │ (Qwen3/etc) │ │
│ │ TP并行加速 │ │
│ └──────┬──────┘ │
│ ▼ │
│ Generated Text │
│ │
│ (可选) CTC Forced Alignment ──→ 字级别时间戳 │
│ │
└───────────────────────────────────────────────────────────┘
```
### 流式推理设计
```
音频流(每720ms一个chunk)
│
▼ 累计音频重新编码
┌──────────────────────┐
│ Stage 1: 前10个chunk │ ← 批量生成,无 prev_text
│ 找到稳定输出 │
└──────────┬───────────┘
▼
┌──────────────────────┐
│ Stage 2: 后续chunk │ ← 用稳定输出作为 prev_text prefill
│ 带 prev_text 生成 │
└──────────┬───────────┘
▼
每个 chunk 输出: [fixed 区域] + [8字 unfixed 区域]
(不会变) (可能在下一chunk改变)
```
## 性能对比
### 离线推理(5.6s 中文音频)
| 配置 | 延迟 | 相对加速 |
|------|------|----------|
| Torch (baseline) | 0.89s | 1x |
| vLLM 1-GPU | 0.30s | **3.0x** |
| vLLM 2-GPU TP | ~0.20s | **4.5x** |
### 流式推理(17s 中文音频,25 chunks)
| 配置 | 总时间 | 加速 |
|------|--------|------|
| Torch sequential | 5.1s | 1x |
| vLLM batch | 2.8s | **1.8x** |
### 批量推理吞吐
| Batch Size | 1-GPU | 2-GPU | 4-GPU |
|-----------|-------|-------|-------|
| 1 | ~1.5x | ~2x | ~2.5x |
| 16 | ~4x | ~7x | ~12x |
| 32 | ~5x | ~9x | ~15x |
## API 参考
### `AutoModelVLLM(model, ...)`
通用入口,自动检测模型类型。
| 参数 | 默认值 | 说明 |
|------|--------|------|
| `model` | - | 模型名或本地路径 |
| `hub` | `"ms"` | `"ms"` (ModelScope) 或 `"hf"` (HuggingFace) |
| `tensor_parallel_size` | `1` | GPU 并行数 |
| `gpu_memory_utilization` | `0.8` | vLLM KV-cache 显存比例 |
| `max_model_len` | `4096` | 最大序列长度 |
| `dtype` | `"bf16"` | 计算精度 |
### `engine.generate(inputs, ...)`
| 参数 | 说明 |
|------|------|
| `inputs` | 音频路径列表、numpy array、torch Tensor |
| `language` | 语言提示:"中文"、"英文"、"日文" 等 |
| `hotwords` | 热词列表,提升识别准确率 |
| `itn` | 逆文本正则化(默认 True) |
| `max_new_tokens` | 最大生成 token 数(默认 512) |
**返回**: `[{"key": str, "text": str, "timestamps": [...]}]`
### `streaming_engine.streaming_generate(audio, ...)`
| 参数 | 说明 |
|------|------|
| `audio_input` | 音频路径或数据 |
| `chunk_ms` | chunk 大小(默认 720ms) |
| `rollback_chars` | 回退字符数(默认 8) |
**Yields**: `{"text", "fixed_text", "is_final", "chunk_idx", "audio_duration_ms"}`
## 常见问题
### Q: 为什么前几个 chunk 输出为空?
模型需要约 3 秒音频才能产生有意义的输出,这是模型本身的特性。
### Q: CUDA OOM 怎么办?
- 减小 `gpu_memory_utilization`(如 0.6)
- 增加 `tensor_parallel_size`
- 减小 `max_model_len`
### Q: 流式和离线结果略有不同?
正常现象。流式每个 chunk 独立生成,离线看到完整音频。最终 chunk 的结果与离线基本一致。
### Q: 支持哪些音频格式?
wav、mp3、flac 等主流格式,采样率会自动转为 16kHz。