Skip to main content

01 vLLM 快速部署入门

info

参考文献

版权:CC BY-SA 4.0(署名—相同方式共享)

1 什么是 vLLM?

vLLM 是一个高效、易用的大语言模型(LLM)推理和服务框架,专注于优化推理速度和吞吐量,尤其适合高并发的生产环境。它由加州大学伯克利分校的研究团队开发,并因其出色的性能成为当前最受欢迎的 LLM 推理引擎之一。

vLLM 同时支持在 GPU 和 CPU 上运行,本文将会分别介绍 vLLM 使用 GPU 和 CPU 作为后端时的安装与运行方法。

2 前提准备

2.1 购买虚拟机

如果本地不具备 GPU 环境,可考虑通过云服务提供商(如阿里云、腾讯云等)购买 GPU 服务器。

操作系统建议选择 Ubuntu 22.04,GPU 型号可根据实际需求进行选择。由于大语言模型通常占用较多磁盘空间,建议适当增加磁盘容量。

2.2 虚拟环境

推荐使用 uv 来管理 python 虚拟环境,执行以下命令安装 uv:

curl -LsSf https://astral.sh/uv/install.sh | sh
source $HOME/.local/bin/env

# or uv 也可以 pip 装(虽然官方推荐使用二进制)国内源比较快
pip install uv --index-url https://pypi.tuna.tsinghua.edu.cn/simple

# Installing collected packages: uv
# Successfully installed uv-0.9.11

3 安装

3.1 使用 GPU 作为 vLLM 后端

3.1.1 系统要求

vLLM 包含预编译的 C++ 和 CUDA (12.6) 二进制文件,需满足以下条件:

  • 操作系统:Linux
  • Python 版本:3.9 ~ 3.12
  • GPU:计算能力 7.0 或更高(如 V100、T4、RTX20xx、A10、A100、L4、H100 等)

注:计算能力(Compute capability)定义了每个 NVIDIA GPU 架构的硬件特性和支持的指令。计算能力决定你是否可以使用某些 CUDA 或 Tensor 核心功能(如 Unified Memory、Tensor Core、动态并行等),并不直接代表 GPU 的计算性能。

3.1.2 安装和配置 GPU 依赖

可以使用以下命令一键安装相关依赖,该脚本会安装 NVIDIA GPU Driver,NVIDIA Container Toolkit,以及配置 NVIDIA Container Runtime(后续通过 Docker 运行 vLLM 时需要)。

curl -sS https://raw.githubusercontent.com/cr7258/hands-on-lab/refs/heads/main/ai/gpu/setup/docker-only-install.sh | bash

3.1.3 安装 vLLM

创建 Python 虚拟环境

# (Recommended) Create a new uv environment. Use `--seed` to install `pip` and `setuptools` in the environment.
uv venv --python 3.12 --seed
source .venv/bin/activate

# output
# Using CPython 3.12.3 interpreter at: miniconda3/bin/python3.12
# Creating virtual environment with seed packages at: .venv

安装 vLLM

uv pip install vllm

# or 国内镜像源
uv pip install vllm -i https://pypi.tuna.tsinghua.edu.cn/simple

# 验证
python3 -c "import vllm; print(vllm.__version__)"
# 0.11.2

4 离线推理 vs 在线推理

离线推理(offline inference)和在线推理(online inference)的主要区别在于使用场景、延迟要求、资源调度方式等方面,简单总结如下。

4.1 离线推理

对一批输入数据进行集中处理,通常不要求实时返回结果。特点如下

  • 批处理:常用于处理大量输入,如日志分析、推荐系统预计算。
  • 低延迟要求:结果可以晚些返回,不影响用户体验。
  • 资源利用高:系统可以在空闲时充分利用 GPU/CPU 资源。
  • 示例场景:每天夜间跑用户兴趣画像、预生成广告文案等。

4.2 在线推理

针对用户实时请求进行推理,立即返回结果。特点如下

  • 实时响应:响应时间通常要求在几百毫秒以内。
  • 延迟敏感:高并发、低延迟是核心指标。
  • 资源分配稳定:服务需长时间在线、资源预留固定。
  • 示例场景:聊天机器人、搜索联想、智能客服等。

5 离线推理

安装好 vLLM 后,你可以开始对一系列输入提示词进行文本生成(即离线批量推理)。以下代码是 vLLM 官网提供的示例:

# basic.py
# https://github.com/vllm-project/vllm/blob/main/examples/offline_inference/basic/basic.py

from vllm import LLM, SamplingParams

# Sample prompts.
prompts = [
"Hello, my name is",
"The president of the United States is",
"The capital of France is",
"The future of AI is",
]

sampling_params = SamplingParams(temperature=0.8, top_p=0.95)

def main():
# 使用 Qwen/Qwen2.5-1.5B-Instruct
# Qwen/Qwen2.5-0.5B-Instruct
llm = LLM(
model="Qwen/Qwen2.5-0.5B-Instruct",
gpu_memory_utilization=0.75,)

outputs = llm.generate(prompts, sampling_params)

print("\nGenerated Outputs:\n" + "-" * 60)
for output in outputs:
prompt = output.prompt
generated_text = output.outputs[0].text
print(f"Prompt: {prompt!r}")
print(f"Output: {generated_text!r}")
print("-" * 60)

if __name__ == "__main__":
main()

在上面的代码中,使用了 SamplingParams 来指定采样过程的参数。采样温度设置为 0.8,核采样概率设置为 0.95。下面解释一下这两个参数的用途:

Sampling Temperature(采样温度) 和 Nucleus Sampling Probability(核采样概率/Top-p) 是大语言模型生成文本时常用的两个采样参数,用于控制输出文本的多样性和质量。

  • 采样温度(Sampling Temperature)
    • 作用:控制生成文本的“随机性”或“创造性”。
    • 原理:温度会对模型输出的概率分布进行缩放。温度越低(如 0.5),高概率的词更容易被选中,生成结果更确定、重复性更高;温度越高(如 1.2),低概率的词被选中的机会增加,文本更有多样性但可能更混乱。
    • 具体来说,temperature=0.8 表示在概率分布上做了一定程度的“平滑”,比默认的 1.0 更偏向于选择高概率词,但仍保留一定的多样性。
  • 核采样概率(Nucleus Sampling Probability / Top-p)
    • 作用:控制每一步生成时考虑的候选词集合大小,动态平衡文本的多样性和合理性。
    • 原理:Top-p(核采样)会将所有词按概率从高到低排序,累加概率,直到总和首次超过 0.95 为止,只在这部分“核心”词中随机采样。

这里用一个例子来解释这两个采样参数之间的关系,假设模型下一步可以说 “猫 狗 老虎 大象 猴子 乌龟 老鹰 鳄鱼 蚂蚁 ...”(有上万个词):

  • Temperature 是调整每个词出现的概率(“猫”的概率是 30%,你可以把它调得更大或更小);
  • Top-p 是把所有词排序后,只保留累计概率达到 95% 的前几个词,比如前 7 个,然后从中挑一个。

输出是通过 llm.generate 方法生成的。该方法会将输入提示加入 vLLM 引擎的等待队列,并调用 vLLM 引擎以高吞吐量生成输出。最终输出会以 RequestOutput 对象列表的形式返回,每个对象包含完整的输出 token。

执行以下代码运行程序:

mkdir -p llm && vim llm/01basic.py
cd llm
python 01basic.py

# Debug1 会报错连接不上 HuggingFace,可以设置环境变量
export HF_ENDPOINT=https://hf-mirror.com

# 验证
curl -I https://hf-mirror.com/
# 如果能返回 200 → 就可以下载模型了。

# 再次运行
python 01basic.py

# 清空文件内容并重新复制代码
: > 01basic.py

Debug 常见问题

# Debug2 你这块显卡总共 31.36 GiB,启动时只有 27.09 GiB 空闲,
# 但 vLLM 想按 gpu_memory_utilization=0.9 预留 28.22 GiB,所以它觉得空闲显存不够,直接报错退出了。

nvidia-smi

# GPU: RTX 5090
# 总显存: 约 32 GB
# 当前占用: 3.7 GB
# 空闲显存: 约 28.3 GB

# 手动释放显存
sudo kill -9 <PID> # 杀掉占 GPU 的进程

6 在线推理

vLLM 可以部署为实现 OpenAI API 协议的服务器。默认情况下,服务器在 http://localhost:8000 启动。你可以通过 --host--port 参数指定地址。服务器目前一次只能托管一个模型,实现了 list modelscreate chat completion 等端点。

运行以下命令以启动 vLLM 服务器,并使用 Qwen/Qwen2.5-1.5B-Instruct 模型:

vllm serve Qwen/Qwen2.5-1.5B-Instruct

启动后的输出如下

这个服务器可以像 OpenAI API 一样以相同的格式进行请求。例如,要列出模型

curl -sS http://localhost:8000/v1/models | jq

# Debug3 如果没有安装 jq,可以直接运行下面的命令
sudo apt update
sudo apt install -y jq

# output
{
"object": "list",
"data": [
{
"id": "Qwen/Qwen2.5-1.5B-Instruct",
"object": "model",
"created": 1763896843,
"owned_by": "vllm",
"root": "Qwen/Qwen2.5-1.5B-Instruct",
"parent": null,
"max_model_len": 32768,
"permission": [
{
"id": "modelperm-3d933d4ac16042f5966ecd690be3b5da",
"object": "model_permission",
"created": 1763896843,
"allow_create_engine": false,
"allow_sampling": true,
"allow_logprobs": true,
"allow_search_indices": false,
"allow_view": true,
"allow_fine_tuning": false,
"organization": "*",
"group": null,
"is_blocking": false
}
]
}
]
}

6.1 使用 vLLM 的 OpenAI Completions API

你可以使用输入提示词查询模型

curl -sS http://localhost:8000/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-1.5B-Instruct",
"prompt": "北京是一个"
}' | jq

# output
{
"id": "cmpl-c1c6332d810243f3a10227c1dac38cb6",
"object": "text_completion",
"created": 1763896879,
"model": "Qwen/Qwen2.5-1.5B-Instruct",
"choices": [
{
"index": 0,
"text": "历史悠久的城市,有许多历史遗迹和文化景点。以下是一些值得一看的",
"logprobs": null,
"finish_reason": "length",
"stop_reason": null,
"token_ids": null,
"prompt_logprobs": null,
"prompt_token_ids": null
}
],
"service_tier": null,
"system_fingerprint": null,
"usage": {
"prompt_tokens": 2,
"total_tokens": 18,
"completion_tokens": 16,
"prompt_tokens_details": null
},
"kv_transfer_params": null
}

7 vLLM GPU 性能测试

当前进行测试的 GPU 服务器配置参数如下

  • GPU: NVIDIA GeForce RTX 5090
  • 显存: 大约 32 GB(Memory-Usage: xxxx MiB / 32607 MiB)
  • 驱动版本: Driver Version: 580.76.05
  • CUDA 版本: CUDA Version: 13.0

以下是一个简单的单机压测脚本 顺序 100 次请求

#!/usr/bin/env bash
set -euo pipefail

########################################
# 配置区:根据需要修改
########################################

# vLLM 服务地址
URL="http://localhost:8000/v1/chat/completions"

# 模型名称(和 vLLM 启动时一致)
MODEL="Qwen/Qwen2.5-1.5B-Instruct"

# 压测请求内容
PROMPT="Tell me a joke"

# 默认请求次数,可在命令行传参数覆盖,比如:./bench_vllm.sh 200
N=${1:-100}

########################################
# 压测开始
########################################

# 临时文件用于存放每次请求的延迟(毫秒)
tmp_file=$(mktemp)

echo "====== vLLM 单机压测 ======"
echo "目标 URL : $URL"
echo "模型 : $MODEL"
echo "请求内容 : $PROMPT"
echo "请求总数 : $N 次"
echo

# 记录整体开始时间(毫秒)
start_all=$(date +%s%3N)

for ((i=1;i<=N;i++)); do
t0=$(date +%s%3N)

# 发送请求(丢弃响应体,只测性能)
curl -sS "$URL" \
-H "Content-Type: application/json" \
-d "{
\"model\": \"$MODEL\",
\"messages\": [
{\"role\": \"user\", \"content\": \"$PROMPT\"}
]
}" > /dev/null

t1=$(date +%s%3N)
latency=$((t1 - t0)) # 单次请求耗时(毫秒)

echo "$latency" >> "$tmp_file"
echo "请求 $i 延迟: ${latency} ms"
done

end_all=$(date +%s%3N)
total_ms=$((end_all - start_all))

echo
echo "==== 性能统计 ===="

awk -v total_ms="$total_ms" '
{
s+=$1; a[NR]=$1
}
END{
n=NR
if (n == 0) {
print "没有采集到任何延迟数据"
exit 1
}

# 需要 gawk 支持 asort
asort(a)

avg = s/n
p50 = a[int(0.5*n)]
p95 = a[int(0.95*n)]
max = a[n]

printf "请求总数 : %d 次\n", n
printf "总耗时 : %.2f 秒\n", total_ms/1000
printf "吞吐量(QPS) : %.2f 请求/秒\n", n/(total_ms/1000)
printf "延迟(毫秒)\n"
printf " 平均延迟 : %.2f ms\n", avg
printf " P50 延迟 : %.2f ms\n", p50
printf " P95 延迟 : %.2f ms\n", p95
printf " 最大延迟 : %.2f ms\n", max
}' "$tmp_file"

# 清理临时文件
rm -f "$tmp_file"
# 安装必备依赖
# Ubuntu 镜像里默认是 mawk
# 不是 gawk,所以没有 asort 函数(asort 只有 GNU awk 才支持)
sudo apt update
sudo apt install -y gawk

vim single_bench.sh
chmod +x single_bench.sh

# 运行压测
./single_bench.sh

# output
====== vLLM 单机压测 ======
==== 性能统计 ====
请求总数 : 100
总耗时 : 13.10
吞吐量(QPS) : 7.63 请求/秒
延迟(毫秒)
平均延迟 : 128.67 ms
P50 延迟 : 118.00 ms
P95 延迟 : 192.00 ms
最大延迟 : 389.00 ms