vLLM 使用实践

此处使用 NVIDIA GeForce RTX 3060 12 GiB 进行实践。


前提条件

  • GPU 节点已安装与 vLLM 兼容的 NVIDIA 驱动,可通过 nvidia-smi 确认 GPU 能被正常识别。
  • 本文使用 uv 创建 Python 虚拟环境和安装依赖,因此 Python 安装方式需要预先安装 uv:https://docs.astral.sh/uv/#installation
  • 通过官方预编译 Python wheel 安装 vLLM 时,通常不需要单独安装完整的 CUDA Toolkit;如果需要从源码编译 vLLM、编译自定义 CUDA 扩展,或者运行过程中明确出现需要 nvcc 的 JIT 编译错误,再安装与当前环境兼容的 CUDA Toolkit。
  • 使用容器方式运行 vLLM 时,GPU 节点需要安装 Docker 和 NVIDIA Container Toolkit,并确保容器能够访问 NVIDIA GPU。

运行 vLLM


通过 Python 运行

安装 vLLM:

1
2
3
4
5
6
7
8
9
uv venv --python 3.12 --seed --managed-python

source .venv/bin/activate

# --torch-backend=auto 会根据 NVIDIA 驱动选择合适的 PyTorch CUDA 构建
uv pip install "vllm==0.24.0" --torch-backend=auto

# 后续从魔搭社区获取大模型
uv pip install "modelscope==1.37.1"

环境验证:

1
2
3
4
5
6
7
python -c '
import torch, vllm
print("vLLM:", vllm.__version__)
print("GPU:", torch.cuda.get_device_name())
print("Capability:", torch.cuda.get_device_capability())
print("VRAM GiB:", torch.cuda.get_device_properties(0).total_memory / 1024**3)
'

示例输出:

1
2
3
4
vLLM: 0.24.0
GPU: NVIDIA GeForce RTX 3060
Capability: (8, 6)
VRAM GiB: 11.63262939453125

以 FP16 加载 Qwen2.5-1.5B-Instruct,将单请求最大上下文限制为 8192 token,每次调度最多处理 16 个序列,允许 vLLM 使用约 90% 的 GPU 显存,启用公共前缀 KV Cache 复用,并忽略模型自带的生成配置,统一使用 vLLM 默认采样参数:

1
2
3
4
5
6
7
8
9
10
# 从魔搭社区获取大模型
export VLLM_USE_MODELSCOPE=True

vllm serve Qwen/Qwen2.5-1.5B-Instruct \
--dtype half \
--max-model-len 8192 \
--max-num-seqs 16 \
--gpu-memory-utilization 0.90 \
--enable-prefix-caching \
--generation-config vllm

通过预编译 wheel 安装 vLLM 时,通常不需要因为使用 FlashInfer 采样器而单独安装 CUDA Toolkit。如果运行时明确出现 FlashInfer 采样器的编译或兼容性错误,可以检查 PyTorch、CUDA 和 FlashInfer 的版本是否匹配,也可以临时回退到其他 Top-K / Top-P 采样实现:

1
2
3
4
5
6
7
8
VLLM_USE_FLASHINFER_SAMPLER=0 \
vllm serve Qwen/Qwen2.5-1.5B-Instruct \
--dtype half \
--max-model-len 8192 \
--max-num-seqs 16 \
--gpu-memory-utilization 0.90 \
--enable-prefix-caching \
--generation-config vllm

VLLM_USE_FLASHINFER_SAMPLER=0 只控制 Top-K / Top-P 采样器后端,并不会禁用 vLLM 中所有可能使用 FlashInfer 的功能,因此应将其作为针对具体错误的排查手段,而不是默认配置。

运行成功后,会监听 8000 端口,此时可以调用 OpenAI 兼容接口:

1
2
3
4
5
6
7
8
9
10
11
curl http://localhost:8000/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model": "Qwen/Qwen2.5-1.5B-Instruct",
"messages": [
{"role": "system", "content": "你是一名 Linux 和 Kubernetes 助手。"},
{"role": "user", "content": "解释一下 Kubernetes Service 的 ClusterIP。"}
],
"temperature": 0,
"max_tokens": 256
}'


通过 Docker 运行

vLLM 官方提供了镜像,可以直接通过 Docker 运行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
docker run --rm \
--name vllm \
--runtime nvidia \
--gpus all \
-v ~/.cache/huggingface:/root/.cache/huggingface \
-p 8000:8000 \
--ipc=host \
vllm/vllm-openai:v0.24.0 \
--model Qwen/Qwen2.5-1.5B-Instruct \
--dtype half \
--max-model-len 8192 \
--max-num-seqs 16 \
--gpu-memory-utilization 0.90 \
--enable-prefix-caching \
--generation-config vllm

也可以通过魔搭社区获取大模型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
docker run --rm \
--name vllm \
--runtime nvidia \
--gpus all \
-e VLLM_USE_MODELSCOPE=True \
-e MODELSCOPE_CACHE=/modelscope_cache \
-v /data/modelscope:/modelscope_cache \
-p 8000:8000 \
--ipc=host \
vllm/vllm-openai:v0.24.0 \
--model Qwen/Qwen2.5-1.5B-Instruct \
--dtype half \
--max-model-len 8192 \
--max-num-seqs 16 \
--gpu-memory-utilization 0.90 \
--enable-prefix-caching \
--generation-config vllm

运行成功后,同样可以通过 8000 端口调用大模型。


请求级参数

通过在请求中调整 Temperature、Top-K、Top-P 参数,应用于不同场景。

  • 回答太随机、幻觉多:降低 Temperature
  • 回答太单调:提高 Temperature
  • 偶尔出现非常离谱的词:降低 Top-P 或 Top-K
  • 候选范围太窄、表达重复:提高 Top-P 或 Top-K

场景一:事实问答

要求答案稳定、可重复:

1
2
3
4
5
{
"temperature": 0,
"top_p": 1,
"top_k": 0
}

temperature=0 时,vLLM 使用贪心解码,top_ptop_k 实际上不再发挥筛选作用,并在内部设置 top_p=1top_k=0min_p=0。这里显式写出 top_p=1top_k=0,主要是为了让配置含义更加直观。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
curl http://localhost:8000/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model": "Qwen/Qwen2.5-1.5B-Instruct",
"messages": [
{"role": "user", "content": "Kubernetes Service 有哪些类型?"}
],
"temperature": 0,
"top_p": 1,
"top_k": 0,
"max_tokens": 256
}'

场景二:代码生成

希望稳定,但不要完全僵化:

1
2
3
4
5
{
"temperature": 0.2,
"top_p": 0.9,
"top_k": 20
}

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
curl http://localhost:8000/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model": "Qwen/Qwen2.5-1.5B-Instruct",
"messages": [
{
"role": "user",
"content": "编写一个 Bash 脚本,检查 8000 端口是否正在监听。"
}
],
"temperature": 0.2,
"top_p": 0.9,
"top_k": 20,
"max_tokens": 256
}'

场景三:通用聊天

在稳定性和多样性之间取得平衡:

1
2
3
4
5
{
"temperature": 0.7,
"top_p": 0.9,
"top_k": 40
}

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
curl http://localhost:8000/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model": "Qwen/Qwen2.5-1.5B-Instruct",
"messages": [
{
"role": "user",
"content": "用通俗的例子解释 vLLM 的 Continuous Batching。"
}
],
"temperature": 0.7,
"top_p": 0.9,
"top_k": 40,
"max_tokens": 512
}'

场景四:创意、头脑风暴

提高随机性和候选范围:

1
2
3
4
5
{
"temperature": 1.0,
"top_p": 0.95,
"top_k": 50
}

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
curl http://localhost:8000/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model": "Qwen/Qwen2.5-1.5B-Instruct",
"messages": [
{
"role": "user",
"content": "给一个云原生技术博客起十个有创意的名字。"
}
],
"temperature": 1.0,
"top_p": 0.95,
"top_k": 50,
"max_tokens": 512
}'

服务级参数

常见参数:

参数 作用 RTX 3060 测试起点
--dtype 权重和计算精度 half
--gpu-memory-utilization 当前 vLLM 实例可使用的显存比例 0.85~0.90
--max-model-len 输入 Token 与输出 Token 的总长度上限 4096/8192
--max-num-seqs 单轮最多处理的序列数 4~16
--max-num-batched-tokens 单轮最多调度的 Token 数 先保持自动
--enable-prefix-caching 复用完全相同的公共 Token 前缀对应的 KV Cache 存在重复长前缀时开启
--generation-config vllm 使用 vLLM 默认采样参数 调参测试推荐
--served-model-name API 中暴露的模型名 可以设置简短名称
--api-key API 鉴权 对外提供服务时使用
--enforce-eager 禁用 CUDA Graph CUDA Graph 或 OOM 排查时测试
--cpu-offload-gb 将部分权重放入 CPU 显存不足时用于功能验证
--trust-remote-code 执行模型仓库中的自定义代码 仅在模型明确需要时开启

表中的数值是 Qwen2.5-1.5B-Instruct 与 RTX 3060 12 GiB 环境下的测试起点,不是所有模型和负载下的固定最佳配置。


场景一:低并发、本地交互

适合本地聊天和代码助手,可以从以下配置开始测试:

1
2
3
4
5
--dtype half \
--gpu-memory-utilization 0.85 \
--max-model-len 4096 \
--max-num-seqs 4 \
--generation-config vllm

特点:

  • 不追求大量并发。
  • 较小的 max-model-len 可以降低 KV Cache 容量压力。
  • 较小的 max-num-seqs 可能减少 CUDA Graph 捕获规模和相关显存占用。
  • 是否能够降低首 Token 延迟,需要通过实际基准测试确认。

gpu-memory-utilization=0.85 主要用于保留显存余量,不应直接理解为低延迟优化。设置过低会减少 KV Cache 容量,在高负载下可能增加抢占。


场景二:多用户并发

适合多个客户端同时调用短文本请求:

1
2
3
4
5
--dtype half \
--gpu-memory-utilization 0.90 \
--max-model-len 4096 \
--max-num-seqs 16 \
--generation-config vllm

如果不同请求包含相同的长 System Prompt、few-shot 示例或其他公共 Token 前缀,可以额外开启:

1
--enable-prefix-caching

多用户并发本身不意味着 Prefix Caching 一定有效,是否有效取决于不同请求之间是否具有完全相同的 Token 前缀。


场景三:长上下文

适合长文档总结、日志分析和代码问答:

1
2
3
4
5
--dtype half \
--gpu-memory-utilization 0.90 \
--max-model-len 8192 \
--max-num-seqs 4 \
--generation-config vllm

上下文长度增加会提高单个请求的 KV Cache 占用,因此通常需要降低并发数量。在实际请求没有公共长前缀时,不需要为了长上下文单独开启 Prefix Caching。


场景四:相同长文档的多次问答

重点开启 Prefix Caching:

1
2
3
4
--max-model-len 8192 \
--max-num-seqs 8 \
--enable-prefix-caching \
--generation-config vllm

适合以下请求模式:

1
2
3
长文档 + 问题 A
长文档 + 问题 B
长文档 + 问题 C

公共长文档必须位于请求的相同 Token 前缀位置。命中缓存后,可以复用已经计算好的 KV Cache,减少后续请求的 Prefill 计算和首 Token 延迟。

Prefix Caching 不会缓存模型最终生成的回答,也不会直接加速输出阶段的 Decode。如果每次 RAG 检索出来的文档块或文档顺序不同,缓存命中率可能很低。

Author

Warner Chen

Posted on

2026-07-16

Updated on

2026-07-16

Licensed under

You need to set install_url to use ShareThis. Please set it in _config.yml.
You forgot to set the business or currency_code for Paypal. Please set it in _config.yml.

Comments

You forgot to set the shortname for Disqus. Please set it in _config.yml.