前言:推理的瓶颈在哪里?
你训练好了一个大模型,部署上线,结果发现:
- 单次请求延迟 5 秒
- 并发 10 个用户就卡死
- GPU 利用率只有 30%
- 每天的 GPU 费用让你肉疼
问题出在哪?
大模型推理有两个阶段:
- Prefill(预填充):处理用户输入,计算密集型
- Decode(解码):逐个生成 token,内存密集型
graph LR
subgraph 推理过程
A[用户输入
100 tokens] --> B[Prefill
并行处理] B --> C[生成 token 1] C --> D[生成 token 2] D --> E[...] E --> F[生成 token N] end subgraph 时间占比 B2[Prefill: 10%] C2[Decode: 90%] end style C2 fill:#ff6b6b
100 tokens] --> B[Prefill
并行处理] B --> C[生成 token 1] C --> D[生成 token 2] D --> E[...] E --> F[生成 token N] end subgraph 时间占比 B2[Prefill: 10%] C2[Decode: 90%] end style C2 fill:#ff6b6b
Decode 阶段是瓶颈! 每生成一个 token 都要:
- 读取整个 KV Cache
- 做一次完整的前向传播
- 只产出一个 token
GPU 的计算能力被浪费了,大部分时间在等待内存读写。
vLLM 的使命:让 GPU 不再"摸鱼"。
一、LLM 推理为什么慢?
1.1 自回归生成的本质
LLM 生成文本是自回归的——每次只能生成一个 token:
def naive_generate(model, prompt, max_tokens):
"""朴素的生成方式"""
tokens = tokenize(prompt)
for _ in range(max_tokens):
# 每次都要处理所有已有的 tokens
logits = model.forward(tokens) # O(n) 复杂度
next_token = sample(logits[-1])
tokens.append(next_token)
if next_token == EOS:
break
return tokens生成 100 个 token 需要 100 次前向传播!
1.2 KV Cache:用空间换时间
为了避免重复计算,使用 KV Cache 缓存历史的 Key 和 Value:
graph TB
subgraph 没有KVCache
A1[Token 1] --> C1[计算 K1, V1]
A2[Token 1,2] --> C2[计算 K1,K2, V1,V2]
A3[Token 1,2,3] --> C3[计算 K1,K2,K3, V1,V2,V3]
end
subgraph 有KVCache
B1[Token 1] --> D1[计算 K1,V1 → 缓存]
B2[Token 2] --> D2[计算 K2,V2 → 缓存
复用 K1,V1] B3[Token 3] --> D3[计算 K3,V3 → 缓存
复用 K1,K2,V1,V2] end style D1 fill:#4ecdc4 style D2 fill:#4ecdc4 style D3 fill:#4ecdc4
复用 K1,V1] B3[Token 3] --> D3[计算 K3,V3 → 缓存
复用 K1,K2,V1,V2] end style D1 fill:#4ecdc4 style D2 fill:#4ecdc4 style D3 fill:#4ecdc4
KV Cache 大小计算:
def calculate_kv_cache_size(
batch_size: int,
seq_len: int,
num_layers: int,
num_heads: int,
head_dim: int,
dtype_bytes: int = 2, # FP16
):
"""计算 KV Cache 大小"""
# 每层需要存储 K 和 V
# 形状: [batch, num_heads, seq_len, head_dim]
per_layer = 2 * batch_size * num_heads * seq_len * head_dim * dtype_bytes
total = per_layer * num_layers
return total / (1024 ** 3) # GB
# LLaMA-7B 的 KV Cache
kv_cache_gb = calculate_kv_cache_size(
batch_size=1,
seq_len=4096,
num_layers=32,
num_heads=32,
head_dim=128,
)
print(f"KV Cache 大小: {kv_cache_gb:.2f} GB")
# 输出: KV Cache 大小: 2.00 GB问题:KV Cache 随序列长度线性增长,显存很快就不够了!
1.3 内存碎片问题
传统的 KV Cache 管理方式会产生大量内存碎片:
graph TB
subgraph 显存布局问题
M1["请求1 KV Cache
[已用 1000] [预留 3096]"] M2["请求2 KV Cache
[已用 500] [预留 3596]"] M3["请求3 KV Cache
[已用 2000] [预留 2096]"] M4["碎片
[浪费的空间]"] end style M4 fill:#ff6b6b
[已用 1000] [预留 3096]"] M2["请求2 KV Cache
[已用 500] [预留 3596]"] M3["请求3 KV Cache
[已用 2000] [预留 2096]"] M4["碎片
[浪费的空间]"] end style M4 fill:#ff6b6b
问题:
- 必须预先分配最大长度的空间
- 短请求浪费大量显存
- 无法高效批处理
二、vLLM 的核心创新:PagedAttention
2.1 灵感来源:操作系统的虚拟内存
操作系统如何管理内存?分页(Paging)!
- 内存被划分为固定大小的"页"
- 不需要连续分配
- 按需分配,用完释放
vLLM 把这个思想用到了 KV Cache 管理上。
2.2 PagedAttention 原理
graph TB
subgraph 传统方式
T1[请求1] --> TC1["连续内存块
[K1,K2,K3,...,K4096]"] T2[请求2] --> TC2["连续内存块
[K1,K2,K3,...,K4096]"] end subgraph PagedAttention P1[请求1] --> PT1["逻辑块表"] P2[请求2] --> PT2["逻辑块表"] PT1 --> PH1["物理块 0"] PT1 --> PH2["物理块 3"] PT1 --> PH3["物理块 7"] PT2 --> PH4["物理块 1"] PT2 --> PH2 PT2 --> PH5["物理块 5"] end style PH2 fill:#4ecdc4
[K1,K2,K3,...,K4096]"] T2[请求2] --> TC2["连续内存块
[K1,K2,K3,...,K4096]"] end subgraph PagedAttention P1[请求1] --> PT1["逻辑块表"] P2[请求2] --> PT2["逻辑块表"] PT1 --> PH1["物理块 0"] PT1 --> PH2["物理块 3"] PT1 --> PH3["物理块 7"] PT2 --> PH4["物理块 1"] PT2 --> PH2 PT2 --> PH5["物理块 5"] end style PH2 fill:#4ecdc4
关键创新:
- 分块存储:KV Cache 被分成固定大小的块(如 16 tokens)
- 非连续分配:块可以在显存中任意位置
- 动态分配:用多少分配多少,用完释放
- 共享机制:相同的前缀可以共享 KV Cache(如 PH2)
2.3 内存利用率对比
pie showData
title 传统方式显存利用
"实际使用" : 30
"预留浪费" : 50
"碎片" : 20
pie showData
title PagedAttention显存利用
"实际使用" : 90
"管理开销" : 5
"碎片" : 5
效果:显存利用率从 30% 提升到 90%+!
2.4 PagedAttention 代码示意
class PagedAttention:
"""PagedAttention 简化示意"""
def __init__(self, block_size=16, num_blocks=1000):
self.block_size = block_size
self.num_blocks = num_blocks
# 物理块池
self.physical_blocks = torch.zeros(
num_blocks, block_size, hidden_size
)
# 空闲块列表
self.free_blocks = list(range(num_blocks))
# 每个请求的块表
self.block_tables = {} # request_id -> [block_ids]
def allocate_block(self, request_id):
"""为请求分配一个新块"""
if not self.free_blocks:
raise MemoryError("显存不足")
block_id = self.free_blocks.pop()
if request_id not in self.block_tables:
self.block_tables[request_id] = []
self.block_tables[request_id].append(block_id)
return block_id
def free_request(self, request_id):
"""释放请求的所有块"""
if request_id in self.block_tables:
self.free_blocks.extend(self.block_tables[request_id])
del self.block_tables[request_id]
def get_kv_cache(self, request_id, position):
"""获取指定位置的 KV Cache"""
block_idx = position // self.block_size
offset = position % self.block_size
block_id = self.block_tables[request_id][block_idx]
return self.physical_blocks[block_id, offset]
def attention(self, query, request_id, seq_len):
"""执行分页注意力"""
# 收集所有相关的 KV Cache 块
block_ids = self.block_tables[request_id]
# 重组为连续张量(或使用 CUDA kernel 直接处理)
keys = []
values = []
for i, block_id in enumerate(block_ids):
start = i * self.block_size
end = min(start + self.block_size, seq_len)
actual_len = end - start
keys.append(self.physical_blocks[block_id, :actual_len, :hidden//2])
values.append(self.physical_blocks[block_id, :actual_len, hidden//2:])
k = torch.cat(keys, dim=0)
v = torch.cat(values, dim=0)
# 标准注意力计算
attn = torch.softmax(query @ k.T / sqrt(d), dim=-1)
output = attn @ v
return output三、vLLM 的其他优化
3.1 Continuous Batching(连续批处理)
传统批处理的问题:
sequenceDiagram
participant R1 as 请求1 (生成100个token)
participant R2 as 请求2 (生成10个token)
participant R3 as 请求3 (生成50个token)
Note over R1,R3: 传统批处理:等最长的完成
R1->>R1: 生成中...
R2->>R2: 生成完成,等待中...
R3->>R3: 生成完成,等待中...
R1->>R1: 还在生成...
Note over R1,R3: R2, R3 白白等待!
Continuous Batching:
sequenceDiagram
participant R1 as 请求1
participant R2 as 请求2
participant R3 as 请求3
participant R4 as 请求4
Note over R1,R4: 连续批处理:动态调度
R1->>R1: 生成中...
R2->>R2: 完成!
Note over R2: 立即返回
R4->>R4: 新请求加入
R3->>R3: 完成!
Note over R3: 立即返回
R1->>R1: 完成!
效果:
- 短请求不用等长请求
- GPU 始终满载
- 吞吐量大幅提升
3.2 Prefix Caching(前缀缓存)
很多请求有相同的前缀(如 system prompt):
# 请求 1
messages = [
{"role": "system", "content": "You are a helpful assistant."}, # 相同
{"role": "user", "content": "What is AI?"}
]
# 请求 2
messages = [
{"role": "system", "content": "You are a helpful assistant."}, # 相同
{"role": "user", "content": "Tell me a joke."}
]Prefix Caching:共享相同前缀的 KV Cache!
graph TB
subgraph 无前缀缓存
R1[请求1] --> K1[计算 system prompt KV]
R2[请求2] --> K2[计算 system prompt KV]
R3[请求3] --> K3[计算 system prompt KV]
end
subgraph 有前缀缓存
P[System Prompt] --> PK[共享 KV Cache]
R4[请求1] --> PK
R5[请求2] --> PK
R6[请求3] --> PK
end
style PK fill:#4ecdc4
3.3 Speculative Decoding(投机解码)
用小模型"猜测"多个 token,大模型验证:
sequenceDiagram
participant Small as 小模型 (Draft)
participant Large as 大模型 (Target)
Small->>Small: 快速生成 5 个候选 token
Small->>Large: 发送候选 tokens
Large->>Large: 并行验证 5 个 token
Large->>Large: 接受前 3 个,拒绝后 2 个
Note over Small,Large: 一次验证 = 生成 3 个 token!
加速原理:
- 小模型快,多生成几个猜测
- 大模型并行验证(比逐个生成快)
- 猜对的直接用,猜错的重新生成
3.4 Tensor Parallelism(张量并行)
单卡装不下?多卡并行!
graph LR
subgraph 张量并行
Input[输入] --> GPU0[GPU 0: 前半部分]
Input --> GPU1[GPU 1: 后半部分]
GPU0 --> Sync[AllReduce 同步]
GPU1 --> Sync
Sync --> Output[输出]
end
vLLM 支持多种并行策略:
- Tensor Parallel:切分矩阵
- Pipeline Parallel:切分层
四、vLLM 实战
4.1 安装
# 安装 vLLM
pip install vllm
# 或者从源码安装(最新特性)
pip install git+https://github.com/vllm-project/vllm.git4.2 离线推理
from vllm import LLM, SamplingParams
def offline_inference():
"""离线批量推理"""
# 加载模型
llm = LLM(
model="meta-llama/Llama-2-7b-chat-hf",
tensor_parallel_size=1, # GPU 数量
dtype="half", # FP16
max_model_len=4096, # 最大序列长度
)
# 采样参数
sampling_params = SamplingParams(
temperature=0.7,
top_p=0.9,
max_tokens=256,
stop=["</s>", "[INST]"],
)
# 批量请求
prompts = [
"[INST] What is machine learning? [/INST]",
"[INST] Write a Python function to sort a list. [/INST]",
"[INST] Explain quantum computing in simple terms. [/INST]",
]
# 生成
outputs = llm.generate(prompts, sampling_params)
# 处理结果
for output in outputs:
prompt = output.prompt
generated = output.outputs[0].text
print(f"Prompt: {prompt[:50]}...")
print(f"Generated: {generated[:100]}...")
print("-" * 50)
if __name__ == "__main__":
offline_inference()4.3 在线服务(OpenAI 兼容 API)
# 启动服务
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-2-7b-chat-hf \
--host 0.0.0.0 \
--port 8000 \
--tensor-parallel-size 1# 客户端调用
import openai
client = openai.OpenAI(
base_url="http://localhost:8000/v1",
api_key="not-needed", # vLLM 不需要 API key
)
# Chat Completion
response = client.chat.completions.create(
model="meta-llama/Llama-2-7b-chat-hf",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is deep learning?"},
],
temperature=0.7,
max_tokens=256,
)
print(response.choices[0].message.content)
# 流式输出
stream = client.chat.completions.create(
model="meta-llama/Llama-2-7b-chat-hf",
messages=[{"role": "user", "content": "Tell me a story."}],
stream=True,
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)4.4 使用量化模型
from vllm import LLM, SamplingParams
def use_quantized_model():
"""使用量化模型"""
# AWQ 量化模型
llm_awq = LLM(
model="TheBloke/Llama-2-7B-AWQ",
quantization="awq",
dtype="half",
)
# GPTQ 量化模型
llm_gptq = LLM(
model="TheBloke/Llama-2-7B-GPTQ",
quantization="gptq",
dtype="half",
)
# 使用
sampling_params = SamplingParams(temperature=0.7, max_tokens=100)
outputs = llm_awq.generate(["Hello, how are you?"], sampling_params)
return outputs4.5 多 GPU 部署
from vllm import LLM, SamplingParams
def multi_gpu_inference():
"""多 GPU 推理"""
# 自动使用多张 GPU
llm = LLM(
model="meta-llama/Llama-2-70b-chat-hf",
tensor_parallel_size=4, # 使用 4 张 GPU
dtype="half",
)
# 70B 模型需要 ~140GB 显存 (FP16)
# 4 张 A100 40GB 刚好够用
sampling_params = SamplingParams(temperature=0.7, max_tokens=256)
outputs = llm.generate(["What is the meaning of life?"], sampling_params)
return outputs
# 或者使用命令行
# python -m vllm.entrypoints.openai.api_server \
# --model meta-llama/Llama-2-70b-chat-hf \
# --tensor-parallel-size 4 \
# --port 80004.6 高级配置
from vllm import LLM, SamplingParams
from vllm.engine.arg_utils import EngineArgs
def advanced_config():
"""高级配置示例"""
llm = LLM(
model="meta-llama/Llama-2-7b-chat-hf",
# 显存管理
gpu_memory_utilization=0.9, # GPU 显存利用率
max_model_len=8192, # 最大序列长度
# 批处理
max_num_batched_tokens=8192, # 批处理最大 token 数
max_num_seqs=256, # 最大并发序列数
# 量化
quantization=None, # "awq", "gptq", "squeezellm"
# 并行
tensor_parallel_size=1,
pipeline_parallel_size=1,
# 精度
dtype="auto", # "half", "float16", "bfloat16", "float"
# 优化
enforce_eager=False, # 禁用 CUDA Graph(调试用)
enable_prefix_caching=True, # 启用前缀缓存
# 投机解码
speculative_model=None, # 小模型路径
num_speculative_tokens=5, # 投机生成的 token 数
)
return llm
# 采样参数详解
sampling_params = SamplingParams(
# 基础参数
temperature=0.7, # 温度,越高越随机
top_p=0.9, # nucleus sampling
top_k=50, # top-k sampling
max_tokens=256, # 最大生成长度
# 停止条件
stop=["</s>", "\n\n"], # 停止词
stop_token_ids=[2], # 停止 token ID
# 高级参数
presence_penalty=0.0, # 存在惩罚
frequency_penalty=0.0, # 频率惩罚
repetition_penalty=1.0, # 重复惩罚
# 输出控制
n=1, # 生成几个候选
best_of=1, # 从几个中选最好的
use_beam_search=False, # 是否使用 beam search
# Logprobs
logprobs=None, # 返回 top-k logprobs
prompt_logprobs=None, # 返回 prompt 的 logprobs
)五、性能调优
5.1 关键性能指标
def benchmark_vllm(llm, prompts, sampling_params):
"""性能基准测试"""
import time
start = time.time()
outputs = llm.generate(prompts, sampling_params)
end = time.time()
# 统计
total_time = end - start
num_prompts = len(prompts)
total_tokens = sum(len(o.outputs[0].token_ids) for o in outputs)
# 指标
throughput = total_tokens / total_time # tokens/秒
latency = total_time / num_prompts # 秒/请求
print(f"总时间: {total_time:.2f}s")
print(f"吞吐量: {throughput:.1f} tokens/s")
print(f"平均延迟: {latency:.3f}s/request")
print(f"总生成 tokens: {total_tokens}")
return throughput, latency5.2 性能优化清单
mindmap
root((vLLM 性能优化))
显存优化
gpu_memory_utilization 调高
使用量化模型
减少 max_model_len
吞吐优化
增加 max_num_seqs
增加 batch size
启用 prefix caching
延迟优化
使用 speculative decoding
减少 max_tokens
使用更快的模型
多卡优化
Tensor Parallel
Pipeline Parallel
5.3 常见问题排查
def troubleshoot_vllm():
"""常见问题排查"""
# 问题 1: CUDA OOM
# 解决: 减少显存使用
llm = LLM(
model="...",
gpu_memory_utilization=0.8, # 降低利用率
max_model_len=2048, # 减少最大长度
)
# 问题 2: 吞吐量低
# 解决: 增加并发
llm = LLM(
model="...",
max_num_seqs=512, # 增加并发数
max_num_batched_tokens=16384, # 增加批处理大小
)
# 问题 3: 首次推理慢
# 原因: CUDA Graph 编译
# 解决: 预热或禁用
llm = LLM(
model="...",
enforce_eager=True, # 禁用 CUDA Graph(会降低性能)
)
# 问题 4: 内存泄漏
# 解决: 显式清理
import gc
import torch
del llm
gc.collect()
torch.cuda.empty_cache()5.4 性能对比
以 LLaMA-2-7B 为例,单张 A100 40GB:
| 框架 | 吞吐量 (tokens/s) | 延迟 (ms/token) |
|---|---|---|
| HuggingFace | 30-50 | 20-30 |
| vLLM | 500-1000 | 1-2 |
| TGI | 300-600 | 2-5 |
| TensorRT-LLM | 800-1200 | 0.8-1.5 |
vLLM 比原生 HuggingFace 快 10-20 倍!
六、生产部署最佳实践
6.1 Docker 部署
# Dockerfile
FROM vllm/vllm-openai:latest
# 复制模型(可选,也可以运行时下载)
# COPY ./model /model
# 启动服务
CMD ["--model", "meta-llama/Llama-2-7b-chat-hf", \
"--port", "8000", \
"--host", "0.0.0.0"]# 构建和运行
docker build -t my-vllm .
docker run --gpus all -p 8000:8000 my-vllm
# 或者直接使用官方镜像
docker run --gpus all \
-v ~/.cache/huggingface:/root/.cache/huggingface \
-p 8000:8000 \
vllm/vllm-openai:latest \
--model meta-llama/Llama-2-7b-chat-hf6.2 Kubernetes 部署
# vllm-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-server
spec:
replicas: 1
selector:
matchLabels:
app: vllm
template:
metadata:
labels:
app: vllm
spec:
containers:
- name: vllm
image: vllm/vllm-openai:latest
args:
- "--model"
- "meta-llama/Llama-2-7b-chat-hf"
- "--port"
- "8000"
resources:
limits:
nvidia.com/gpu: 1
ports:
- containerPort: 8000
volumeMounts:
- name: model-cache
mountPath: /root/.cache/huggingface
volumes:
- name: model-cache
persistentVolumeClaim:
claimName: model-cache-pvc
---
apiVersion: v1
kind: Service
metadata:
name: vllm-service
spec:
selector:
app: vllm
ports:
- port: 80
targetPort: 8000
type: LoadBalancer6.3 负载均衡
# 使用 FastAPI 做负载均衡
from fastapi import FastAPI
import httpx
import random
app = FastAPI()
# vLLM 实例列表
VLLM_SERVERS = [
"http://vllm-1:8000",
"http://vllm-2:8000",
"http://vllm-3:8000",
]
@app.post("/v1/chat/completions")
async def chat_completions(request: dict):
"""负载均衡转发"""
# 简单的随机负载均衡
server = random.choice(VLLM_SERVERS)
async with httpx.AsyncClient() as client:
response = await client.post(
f"{server}/v1/chat/completions",
json=request,
timeout=60.0,
)
return response.json()
@app.get("/health")
async def health_check():
"""健康检查"""
healthy_servers = []
async with httpx.AsyncClient() as client:
for server in VLLM_SERVERS:
try:
resp = await client.get(f"{server}/health", timeout=5.0)
if resp.status_code == 200:
healthy_servers.append(server)
except:
pass
return {
"healthy": len(healthy_servers),
"total": len(VLLM_SERVERS),
"servers": healthy_servers,
}6.4 监控和告警
# 使用 Prometheus 监控
from prometheus_client import Counter, Histogram, start_http_server
import time
# 定义指标
REQUEST_COUNT = Counter('vllm_requests_total', 'Total requests')
REQUEST_LATENCY = Histogram('vllm_request_latency_seconds', 'Request latency')
TOKENS_GENERATED = Counter('vllm_tokens_generated_total', 'Total tokens generated')
def monitored_generate(llm, prompts, sampling_params):
"""带监控的生成"""
REQUEST_COUNT.inc(len(prompts))
start = time.time()
outputs = llm.generate(prompts, sampling_params)
latency = time.time() - start
REQUEST_LATENCY.observe(latency)
total_tokens = sum(len(o.outputs[0].token_ids) for o in outputs)
TOKENS_GENERATED.inc(total_tokens)
return outputs
# 启动 Prometheus 指标服务
start_http_server(9090)七、vLLM vs 其他框架
7.1 主流推理框架对比
graph TB
subgraph 推理框架
vLLM["vLLM
PagedAttention
高吞吐"] TGI["TGI
HuggingFace 出品
易用"] TRT["TensorRT-LLM
NVIDIA 出品
极致性能"] Ollama["Ollama
本地部署
最简单"] end
PagedAttention
高吞吐"] TGI["TGI
HuggingFace 出品
易用"] TRT["TensorRT-LLM
NVIDIA 出品
极致性能"] Ollama["Ollama
本地部署
最简单"] end
| 框架 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|
| vLLM | 高吞吐、易用 | 功能较少 | 通用服务部署 |
| TGI | HF 生态、功能全 | 性能略低 | HF 模型部署 |
| TensorRT-LLM | 极致性能 | 配置复杂 | 超大规模 |
| Ollama | 最简单 | 性能一般 | 本地/开发 |
7.2 何时选择 vLLM?
flowchart TB
A[选择推理框架] --> B{需求是什么?}
B -->|高吞吐服务| C[vLLM ✓]
B -->|本地快速体验| D[Ollama ✓]
B -->|极致性能| E[TensorRT-LLM]
B -->|HF 生态集成| F[TGI]
C --> G[适合大多数场景]
style C fill:#4ecdc4
style G fill:#4ecdc4
选择 vLLM 的理由:
- 开箱即用,配置简单
- 性能足够好(90% 场景够用)
- 社区活跃,更新快
- OpenAI 兼容 API
八、总结
vLLM 核心要点
mindmap
root((vLLM))
核心创新
PagedAttention
Continuous Batching
Prefix Caching
性能优势
10-20倍吞吐提升
90%+显存利用率
低延迟
使用方式
离线推理
在线服务
OpenAI兼容API
部署
单机
多GPU
Kubernetes
关键 Takeaway
- PagedAttention 是核心:借鉴操作系统分页,解决 KV Cache 内存管理问题
- 性能提升显著:比原生 HuggingFace 快 10-20 倍
- 使用简单:几行代码就能用,API 兼容 OpenAI
- 生产就绪:支持量化、多 GPU、Docker/K8s 部署
- 持续进化:社区活跃,新功能不断加入
快速开始模板
# 最简单的 vLLM 使用
from vllm import LLM, SamplingParams
llm = LLM(model="meta-llama/Llama-2-7b-chat-hf")
outputs = llm.generate(
["Hello, how are you?"],
SamplingParams(temperature=0.7, max_tokens=100)
)
print(outputs[0].outputs[0].text)# 最简单的 API 服务
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-2-7b-chat-hf \
--port 8000下一步学习
- [ ] RAG:检索增强生成
- [ ] Agent:让大模型自己干活
- [ ] 多模态:不只是文本
参考资料
- vLLM Paper - Efficient Memory Management for LLM Serving with PagedAttention
- vLLM GitHub - 官方仓库
- vLLM Documentation - 官方文档
- Continuous Batching - Anyscale 博客
- Speculative Decoding - 投机解码论文