vLLM 推理框架—Qwen2.5-VL token数分析
在使用 vLLM 部署 Qwen2.5-VL-32B 模型时,一张图片被编码成的 token 数量并不是一个固定的值,它会主要取决于输入图片的分辨率。模型会根据图片的分辨率动态地生成不同数量的视觉 token。可以通过以下方式进行部署:
1 | python3 -m vllm.entrypoints.openai.api_server --served-model-name Qwen2.5-VL-32B-Instruct --port 8080 --model /data/modelRepository/qwen-vl-model/qwen-vl-model_2-5-32b --tensor-parallel-size 2 --max-model-len 65536 --gpu-memory-utilization 0.85 --disable-log-stats --limit_mm_per_prompt image=10,video=1 --api-key <YOUR_API_KEY> --host 0.0.0.0 --enable-auto-tool-choice --tool-call-parser hermes --trust-remote-code |
或者
1 | sudo docker run -itd --gpus '"device=3, 4"' \ |
🔢 Token数量计算方法
Qwen2.5-VL 模型会通过视觉编码器(ViT)将图像分割成 patches(图像块),并进一步处理这些 patches 来生成视觉 token。其计算可大致表示为:
单图 Token 数 ≈ (图像高度 / Patch步长) × (图像宽度 / Patch步长) / (空间合并因子)²
其中:
- Patch步长(Patch Stride):通常为 14 像素。这意味着图像会被划分成一系列 14x14 像素的块(但最终 token 数并非简单等同于块的数量)。
- 空间合并因子(Spatial Merge Size, M):在视觉编码过程中,相邻的 2x2 个空间 patch 特征会被合并成一个 token。该因子默认为 2。
- 图像的高度和宽度在预处理时通常会被调整为 28 的倍数,以满足模型架构的要求。
📊 常见分辨率下的Token估算
根据上述规则,一些常见分辨率下的图片大致会产生如下数量的视觉 token:
| 图像分辨率 | 预估 Token 数量 | 说明 |
|---|---|---|
| 224x224 | ~ 256 tokens | 较低分辨率,处理速度快 |
| 448x448 | ~ 1024 tokens | 中等分辨率,细节和计算量的平衡 |
| 672x672 | ~ 2304 tokens | 较高分辨率,能保留更多细节 |
| 896x896 | ~ 4096 tokens | 高分辨率,需要更多计算资源 |
请注意,表中的 token 数量是估算值。实际 token 数量可能会因模型的具体预处理步骤(如调整图像尺寸以符合模型要求)而略有波动。
💡 注意事项
- 动态分辨率:Qwen2.5-VL 支持动态分辨率处理。这意味着不同大小、不同比例的图片产生的 token 数量是不同的。较高分辨率的图像会产生更多的视觉 token,从而保留更多的细节信息,但也会增加计算开销和内存占用。
- 上下文长度:Qwen2.5-VL-32B 模型支持长达 128K 的上下文长度。单张图片产生的视觉 token(通常几百到几千)会与文本 token 共同占用这个上下文窗口。你需要确保图片 token 加上文本 token 的总和不超过模型的最大上下文限制。
- 实际测试:要获取精确的 token 数量,最可靠的方法是在你的 vLLM 部署环境中实际处理一张图片,并通过模型的 API 或日志输出查看实际消耗的 token 数。
💎 高分辨率图片示例
如果是一张 2550*3300 和一张 1920×1280 的图片呢,分别有多少 token?
Qwen2.5-VL 模型在处理图像前,会先将其分辨率调整(Resize)为 28 的倍数,以满足其视觉编码器(ViT)的架构要求。这是计算的关键第一步。
其 Token 数量的计算公式可以简化为:
Token数量 ≈ (调整后的图像高度 / 28) × (调整后的图像宽度 / 28)
1. 对于 2550 × 3300 的图片
这张图片非常高,类似于一张海报或传单。
- 调整分辨率:
- 模型需要将尺寸调整为 28 的倍数。
- 2550 ÷ 28 ≈ 91.07 -> 向下取整为 91 倍 -> 91 * 28 = 2548
- 3300 ÷ 28 ≈ 117.86 -> 向上取整为 118 倍 -> 118 * 28 = 3304
- 因此,调整后的分辨率大约为 2548 × 3304。
- 计算Token数量:
- Token数 = (2548 / 28) × (3304 / 28) = 91 × 118 = 10,738 tokens
结论:这张 2550 × 3300 的图片经过预处理后,大约会产生 10,738 个视觉 Token。
2. 对于 1920 × 1280 的图片
这张图片是接近 16:10 的宽屏比例。
- 调整分辨率:
- 1920 ÷ 28 ≈ 68.57 -> 通常向下取整为 68 倍 -> 68 * 28 = 1904
- 1280 ÷ 28 ≈ 45.71 -> 通常向下取整为 45 倍?但 4528=1260,与 1280 相差较大。更合理的做法是寻找最接近的倍数。1288 (4628) 比 1260 更接近 1280。
- 因此,调整后的分辨率可能为 1904 × 1288。
- 计算Token数量:
- Token数 = (1904 / 28) × (1288 / 28) = 68 × 46 = 3,128 tokens
结论:这张 1920 × 1280 的图片经过预处理后,大约会产生 3,128 个视觉 Token。
测试验证的代码如下。
1 | import requests |
💎 高分辨率视频示例
如果是一条长度为 106 秒、12 帧每秒、分辨率为 2504*1390 的视频,以及一条长度为 106 秒,30 帧每秒,分辨率为 1280×720 的视频呢,分别有多少 token?
1. 对于长度为 106 秒、12 帧每秒、分辨率为 2504*1390 的视频
- Token数 = 71000
2. 对于长度为 106 秒,30 帧每秒,分辨率为 1280*720 的视频
- Token数 = 19163 『其中(25041390/(1280720))*19163约等于71000』
3. 对于一张 1280*720 的图片,对应的 token 为 1223,视频约采样 15~16 帧图片

