一、官方支持矩阵
整理自 vLLM-MUSA v0.28.0 Release 与各模型 recipe:
| 模型 | 精度 | 硬件 / 并行 | 最大上下文 / 并发序列 |
|---|---|---|---|
| Qwen3-VL-8B-Instruct | BF16 / FP8 | 1× S5000,TP1 | 8,192 / 256 |
| Qwen3-VL-30B-A3B-Instruct(MoE) | BF16 / FP8 | 4× S5000,TP4 | 8,192 / 64 |
| Qwen3-VL-32B-Instruct | BF16 / FP8 | 4× S5000,TP4 | 8,192 / 64 |
| DeepSeek-OCR、MinerU2.5-Pro-2605-1.2B、OvisOCR2、PaddleOCR-VL-1.6 | BF16 | 1× S5000,TP1 | 见各 OCR recipe |
本课后文的启动参数与差异表均取自 BF16 recipe。8B 与 30B-A3B 的 FP8 recipe 与 BF16 基本一致;32B 的 FP8 recipe 差异较大(例如 --gpu-memory-utilization 0.90、--generation-config vllm、FULL_AND_PIECEWISE 图模式与不同的捕获尺寸),请以 Qwen3-VL-32B-Instruct-FP8 recipe 原文为准。
所有 Qwen3-VL recipe 均关闭推测解码。这些配置按约 4K 输入 / 1K 输出的负载调优,官方要求整体照搬,换负载时重新调参;FP8、MTP 与图捕获路径对模型版本敏感,recipe 中固定了 ModelScope 上的权重提交号。
二、准备环境
- 宿主机按第 2 模块装好 Driver 5.2.0,并配置 MUSA 容器运行时(第 2 模块第 4 课)。
- 拉取发布镜像(vLLM-MUSA v0.28.0 docker/README):
export VLLM_MUSA_IMAGE=registry.mthreads.com/mcconline/inference/vllm/vllm-openai:v0.28.0
docker pull "${VLLM_MUSA_IMAGE}"
docker/build_image.sh 从源码构建。另外,默认分支 v0.32.0-dev 的 README 提到了 v0.32.0 镜像,但 GitHub 上还没有对应的 Release / tag;本课仍以有 Release 的 v0.28.0 为准。pip install modelscope
modelscope download --model Qwen/Qwen3-VL-8B-Instruct --local_dir /models/Qwen3-VL-8B-Instruct
# 严格复现时,按 recipe 中记录的提交号下载对应版本
三、启动 Qwen3-VL-8B-Instruct(单卡)
以下命令与 Qwen3-VL-8B-Instruct recipe 一致,在已安装 vllm-musa 的环境(如容器内的 shell)中执行:
export VLLM_PLUGINS=musa,musa_custom_ops
export VLLM_WORKER_MULTIPROC_METHOD=spawn
export PYTHONUNBUFFERED=1
export VLLM_MUSA_QWEN3_VL_VISION_CUDAGRAPH=1
export SAFETENSORS_FAST_GPU=1
CAPTURE_SIZES="$(seq -s, 1 256)"
vllm serve /models/Qwen3-VL-8B-Instruct \
--trust-remote-code \
--tensor-parallel-size 1 \
--served-model-name Qwen3-VL-8B-Instruct \
--max-model-len 8192 \
--max-num-seqs 256 \
--max-num-batched-tokens 8192 \
--gpu-memory-utilization 0.9 \
--mamba-ssm-cache-dtype float32 \
--mm-processor-cache-gb 0 \
--limit-mm-per-prompt '{"image":1,"video":0}' \
--no-enable-prefix-caching \
--no-enable-chunked-prefill \
--attention-backend FLASH_ATTN \
--mm-encoder-attn-backend FLASH_ATTN \
--compilation-config "{\"mode\":\"NONE\",\"cudagraph_mode\":\"FULL_DECODE_ONLY\",\"cudagraph_capture_sizes\":[${CAPTURE_SIZES}]}"
用 Docker 直接启动时,发布镜像的入口是 vllm serve,把模型路径和参数接在镜像名后面,环境变量用 --env 传入(本站整理,基于 docker/README 的示例形式):
MODEL_PATH=/models/Qwen3-VL-8B-Instruct
CAPTURE_SIZES="$(seq -s, 1 256)"
docker run --rm --privileged --ipc=host --network=host \
--env MUSA_VISIBLE_DEVICES=0 --env MTHREADS_VISIBLE_DEVICES=0 \
--env VLLM_PLUGINS=musa,musa_custom_ops \
--env VLLM_WORKER_MULTIPROC_METHOD=spawn \
--env VLLM_MUSA_QWEN3_VL_VISION_CUDAGRAPH=1 \
--env SAFETENSORS_FAST_GPU=1 \
-v "${MODEL_PATH}:${MODEL_PATH}:ro" \
"${VLLM_MUSA_IMAGE}" "${MODEL_PATH}" --host 0.0.0.0 \
--trust-remote-code --tensor-parallel-size 1 \
--served-model-name Qwen3-VL-8B-Instruct \
--max-model-len 8192 --max-num-seqs 256 --max-num-batched-tokens 8192 \
--gpu-memory-utilization 0.9 --mamba-ssm-cache-dtype float32 \
--mm-processor-cache-gb 0 --limit-mm-per-prompt '{"image":1,"video":0}' \
--no-enable-prefix-caching --no-enable-chunked-prefill \
--attention-backend FLASH_ATTN --mm-encoder-attn-backend FLASH_ATTN \
--compilation-config "{\"mode\":\"NONE\",\"cudagraph_mode\":\"FULL_DECODE_ONLY\",\"cudagraph_capture_sizes\":[${CAPTURE_SIZES}]}"
--privileged 只用于隔离的测试主机。生产环境请改用平台的最小权限 MUSA 设备策略;可见设备变量只限定 vLLM 看到的逻辑设备,不会降低 Docker 权限。对 vLLM-MUSA 来说,MUSA_VISIBLE_DEVICES 是决定可见设备的变量。关键参数说明
| 参数 | 作用 |
|---|---|
--limit-mm-per-prompt '{"image":1,"video":0}' | 每个请求最多 1 张图片、0 个视频(8B 与 30B-A3B recipe 显式设置) |
--mm-encoder-attn-backend FLASH_ATTN | 视觉编码器走 FlashAttention(v0.28.0 新增的 Qwen3-VL 路由) |
VLLM_MUSA_QWEN3_VL_VISION_CUDAGRAPH=1 | 可选的视觉模块图捕获(8B recipe 中开启) |
--mm-processor-cache-gb 0 | 关闭多模态预处理缓存,不影响视觉编码器和图捕获 |
--no-enable-prefix-caching / --no-enable-chunked-prefill | 8B / 30B-A3B recipe 中都关闭 |
--gpu-memory-utilization 0.9 | 8B 为 0.9;30B-A3B 与 32B 为 0.85 |
四、30B-A3B 与 32B(4 卡 TP4)的差异
| 项目 | Qwen3-VL-30B-A3B-Instruct | Qwen3-VL-32B-Instruct |
|---|---|---|
--tensor-parallel-size | 4 | 4 |
--max-num-seqs | 64 | 64 |
--gpu-memory-utilization | 0.85 | 0.85 |
| Chunked prefill | 关闭 | 开启(--enable-chunked-prefill) |
| 注意力后端 / 编译配置 | FLASH_ATTN;图捕获尺寸 1–32 与 64 | recipe 未显式指定 |
--max-num-batched-tokens | 8192 | recipe 未设置 |
--limit-mm-per-prompt | {"image":1,"video":0} | recipe 未设置 |
请分别按两份 recipe 原样复制,不要把 8B 的参数套到大模型上。
五、发送图片请求
服务提供 OpenAI 兼容的 chat completions 接口。下面的写法参考官方 PaddleOCR-VL recipe 的客户端示例,改为调用 Qwen3-VL(本站整理):
import base64, mimetypes
from pathlib import Path
from openai import OpenAI
image_path = Path("demo.jpg")
mime = mimetypes.guess_type(image_path.name)[0] or "image/jpeg"
data = base64.b64encode(image_path.read_bytes()).decode("ascii")
client = OpenAI(api_key="EMPTY", base_url="http://localhost:8000/v1", timeout=600)
resp = client.chat.completions.create(
model="Qwen3-VL-8B-Instruct",
messages=[{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": f"data:{mime};base64,{data}"}},
{"type": "text", "text": "请描述这张图片,并列出图中的文字。"},
],
}],
temperature=0.0,
max_tokens=512,
)
print(resp.choices[0].message.content)
六、OCR 类模型
vLLM-MUSA v0.28.0 OCR cookbook 提供四个单卡 BF16 配置。以 PaddleOCR-VL-1.6 recipe 为例:
export MODEL_PATH="<MODEL_PATH>"
export VLLM_WORKER_MULTIPROC_METHOD=spawn
vllm serve "${MODEL_PATH}" \
--trust-remote-code --tensor-parallel-size 1 \
--served-model-name PaddleOCR-VL-1.6-0.9B \
--host 0.0.0.0 --port 8000 --dtype bfloat16 \
--max-model-len 8192 --max-num-seqs 512 --max-num-batched-tokens 16384 \
--gpu-memory-utilization 0.80 --no-enable-prefix-caching --mm-processor-cache-gb 0
- 任务通过提示词选择:
OCR:、Table Recognition:、Formula Recognition:、Chart Recognition:、Spotting:、Seal Recognition:。 - 该 recipe 要求保持默认编译与图捕获设置,不要添加
--enforce-eager;ViT 路径会自动选择 FLASH_ATTN。 - 版面分析与页面拼装由客户端负责。
- 该 recipe 的前置条件写的是“vLLM-MUSA v0.28.0-dev”,与发布镜像 v0.28.0 不完全对应,使用发布镜像时请先核对包版本。
- MinerU2.5-Pro 需要在推理引擎与客户端两侧都安装
mineru-vl-utils。
七、验证
# 1. 服务是否就绪
curl -s http://localhost:8000/v1/models
# 2. 单图语义检查:用答案明确的图片(如含固定文字的截图)对比输出
# 3. 小并发冒烟:并发发送 8–16 个请求,观察是否出现超时或显存错误
正式压测请参照 recipe 中的负载形态(2K/1K 到 4K/1.5K、每组 500 条),并记录驱动、镜像与权重提交号,方便对比。
八、已知限制
- 8B 与 30B-A3B recipe 显式限制为每请求 1 张图、0 个视频;32B recipe 未设该限制,但调优负载同样以单图为主。官方未给出视频输入的调优参数。
- 没有 InternVL3 的官方配置。
- FP8 与图捕获路径对模型版本敏感,请固定权重版本。
- Recipe 以约 4K 输入 / 1K 输出调优,长图文混合场景需要重新调参。
九、回滚
服务无状态,回滚只需换回上一版镜像标签和对应的启动参数。升级前保留旧的启动脚本与镜像,并记录 pip list 中 vllm 与 vllm-musa 的版本。