vLLM 本地部署配置
高吞吐量的 LLM 推理引擎,支持连续批处理和 PagedAttention,适合生产环境
系统要求
| 项目 |
最低要求 |
推荐 |
| Python |
3.8+ |
3.10+ |
| GPU |
NVIDIA (CUDA 11.6+) |
NVIDIA A100/H100/RTX 4090 |
| GPU 显存 |
16 GB |
24 GB+ |
| CUDA |
11.6+ |
12.x |
| 操作系统 |
Linux |
Ubuntu 22.04 |
⚠️ vLLM 目前仅支持 NVIDIA GPU,不支持纯 CPU 推理
安装
pip 安装
| Bash |
|---|
| # 基础安装
pip install vllm
# 指定 CUDA 版本
pip install vllm --extra-index-url https://download.pytorch.org/whl/cu121
|
从源码安装
| Bash |
|---|
| git clone https://github.com/vllm-project/vllm
cd vllm
pip install -e .
|
Docker
| Bash |
|---|
| # 基础镜像
docker run --runtime=nvidia --gpus all \
-v ~/.cache/huggingface:/root/.cache/huggingface \
-p 8000:8000 \
--ipc=host \
vllm/vllm-openai:latest \
--model Qwen/Qwen2.5-7B-Instruct
# 自定义构建
docker build -f Dockerfile -t vllm:custom .
|
Python API 使用
离线批量推理
| Python |
|---|
| from vllm import LLM, SamplingParams
# 初始化模型
llm = LLM(
model="Qwen/Qwen2.5-7B-Instruct",
tensor_parallel_size=1, # GPU 数量
gpu_memory_utilization=0.9,
max_model_len=4096,
)
# 采样参数
params = SamplingParams(
temperature=0.7,
top_p=0.9,
max_tokens=512,
stop=["<|im_end|>"],
)
# 批量生成
prompts = [
"你好,请自我介绍",
"用 Python 写一个快排",
"解释什么是 Transformer",
]
outputs = llm.generate(prompts, sampling_params=params)
for output in outputs:
print(f"Prompt: {output.prompt!r}")
print(f"Output: {output.outputs[0].text!r}")
print()
|
Chat 接口
| Python |
|---|
| from vllm import LLM, SamplingParams
llm = LLM(model="Qwen/Qwen2.5-7B-Instruct")
# Chat 格式
from vllm.entrypoints.openai.protocol import ChatCompletionRequest
conversation = [
{"role": "system", "content": "你是Python助手"},
{"role": "user", "content": "写一个快排"},
]
params = SamplingParams(temperature=0.7, max_tokens=512)
outputs = llm.chat(messages=conversation, sampling_params=params)
print(outputs[0].outputs[0].text)
|
OpenAI 兼容 API 服务
启动服务
| Bash |
|---|
| python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct \
--host 0.0.0.0 \
--port 8000 \
--gpu-memory-utilization 0.9 \
--max-model-len 4096 \
--dtype auto
|
关键启动参数
| 参数 |
说明 |
默认值 |
建议值 |
--model |
模型名称或路径 |
必填 |
— |
--host |
监听地址 |
127.0.0.1 |
0.0.0.0 |
--port |
端口 |
8000 |
— |
--gpu-memory-utilization |
GPU 显存利用率 |
0.9 |
0.85~0.95 |
--max-model-len |
最大上下文长度 |
模型默认 |
按需设小省显存 |
--dtype |
数据类型 |
auto |
auto / float16 / bfloat16 |
--quantization |
量化方法 |
— |
awq / gptq / fp8 / bitsandbytes |
--tensor-parallel-size |
张量并行 GPU 数 |
1 |
按 GPU 数 |
--pipeline-parallel-size |
流水线并行数 |
1 |
多机部署 |
--enable-prefix-caching |
前缀缓存 |
false |
开启可加速 |
--enable-chunked-prefill |
分块预填充 |
false |
开启提升吞吐 |
--swap-space |
CPU swap 空间(GB) |
4 |
4~16 |
--served-model-name |
服务模型名 |
原模型名 |
自定义 |
--chat-template |
聊天模板路径 |
自动检测 |
自定义时指定 |
API 调用示例
| Bash |
|---|
| # Chat Completions
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-7B-Instruct",
"messages": [
{"role": "system", "content": "你是Python助手"},
{"role": "user", "content": "写一个快排"}
],
"temperature": 0.7,
"max_tokens": 1024,
"stream": true
}'
# Completions
curl http://localhost:8000/v1/completions -d '{
"model": "Qwen/Qwen2.5-7B-Instruct",
"prompt": "Python快排:",
"max_tokens": 512
}'
# Embeddings
curl http://localhost:8000/v1/embeddings -d '{
"model": "Qwen/Qwen2.5-7B-Instruct",
"input": "你好世界"
}'
|
Python SDK 调用
| Python |
|---|
| import openai
client = openai.OpenAI(
base_url="http://localhost:8000/v1",
api_key="EMPTY"
)
# 流式对话
stream = client.chat.completions.create(
model="Qwen/Qwen2.5-7B-Instruct",
messages=[{"role": "user", "content": "你好"}],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
|
量化模型部署
AWQ 量化
| Bash |
|---|
| # 启动 AWQ 量化模型
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct-AWQ \
--quantization awq \
--gpu-memory-utilization 0.9
|
GPTQ 量化
| Bash |
|---|
| python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct-GPTQ-Int4 \
--quantization gptq \
--gpu-memory-utilization 0.9
|
FP8 量化
| Bash |
|---|
| python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct \
--quantization fp8 \
--gpu-memory-utilization 0.9
|
BitsAndBytes (NF4)
| Bash |
|---|
| python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct \
--quantization bitsandbytes \
--load-format bitsandbytes \
--gpu-memory-utilization 0.9
|
多 GPU 部署
张量并行(单机多卡)
| Bash |
|---|
| # 2 GPU
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-72B-Instruct \
--tensor-parallel-size 2 \
--gpu-memory-utilization 0.9
# 4 GPU
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-72B-Instruct \
--tensor-parallel-size 4
|
流水线并行(多机部署)
| Bash |
|---|
| # 节点 0(主节点)
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-72B-Instruct \
--tensor-parallel-size 2 \
--pipeline-parallel-size 2 \
--distributed-executor-backend ray
# 节点 1(工作节点)
python -m vllm.worker.worker \
--model Qwen/Qwen2.5-72B-Instruct \
--tensor-parallel-size 2 \
--pipeline-parallel-size 2
|
性能优化
关键优化选项
| 选项 |
说明 |
效果 |
--enable-prefix-caching |
自动缓存相同前缀 |
重复 Prompt 大幅加速 |
--enable-chunked-prefill |
分块预填充 |
提升首 Token 速度 |
--speculative-decoding |
投机解码 |
小模型+大模型加速 |
--swap-space 16 |
CPU swap |
超出显存时不 OOM |
Speculative Decoding 配置
| Bash |
|---|
| python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-14B-Instruct \
--speculative-model Qwen/Qwen2.5-7B-Instruct \
--num-speculative-tokens 5 \
--speculative-max-tokens 32
|
Benchmark
| Bash |
|---|
| # vLLM 自带 benchmark
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct --port 8000 &
# 使用 benchmark 脚本
python benchmarks/benchmark_serving.py \
--backend vllm \
--model Qwen/Qwen2.5-7B-Instruct \
--dataset-name sharegpt \
--num-prompts 100
|
自定义聊天模板
| Bash |
|---|
| # 指定 chat template 文件
python -m vllm.entrypoints.openai.api_server \
--model /path/to/model \
--chat-template /path/to/chat_template.jinja
|
chat_template.jinja 示例(Qwen 格式):
| Django/Jinja |
|---|
| {% for message in messages %}
{{'<|im_start|>' + message['role'] + '\n' + message['content'] + '<|im_end|>' + '\n'}}
{% endfor %}
{% if add_generation_prompt %}
{{ '<|im_start|>assistant\n' }}
{% endif %}
|
常见问题
Q: CUDA Out of Memory?
- 降低
--gpu-memory-utilization(如 0.8)
- 减小
--max-model-len(如 2048)
- 使用量化模型(AWQ/GPTQ)
- 增大
--swap-space(CPU swap 兜底)
- 使用张量并行分到多卡
Q: 首次加载很慢?
首次需要下载模型并加载到 GPU,后续请求会很快。使用 --enable-prefix-caching 可缓存系统 Prompt。
Q: 如何限制并发?
--max-num-seqs 控制最大并发序列数。
练习清单