名称: llm-serving-patterns
描述: LLM推理基础设施、服务框架(vLLM、TGI、TensorRT-LLM)、量化技术、批处理策略和流式响应模式。适用于设计LLM服务基础设施、优化推理延迟或扩展LLM部署。
允许工具: 读取、全局搜索、模式匹配
LLM服务模式
何时使用此技能
在以下情况下使用此技能:
- 设计LLM推理基础设施
- 选择服务框架(vLLM、TGI、TensorRT-LLM)
- 实现量化用于生产部署
- 优化批处理和吞吐量
- 构建流式响应系统
- 经济高效地扩展LLM部署
关键词: LLM服务、推理、vLLM、TGI、TensorRT-LLM、量化、INT8、INT4、FP16、批处理、连续批处理、流式、SSE、WebSocket、KV缓存、分页注意力、推测解码
LLM服务架构概述
┌─────────────────────────────────────────────────────────────────────┐
│ LLM服务堆栈 │
├─────────────────────────────────────────────────────────────────────┤
│ 客户端(API、聊天界面、智能体) │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 负载均衡器 / API网关 │ │
│ │ • 速率限制 • 身份验证 • 请求路由 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 推理服务器 │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ │
│ │ │ 请求队列 │ │ 批处理引擎 │ │ KV缓存管理 │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────────────┘ │ │
│ │ │ │ │ │
│ │ ▼ ▼ │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ 模型执行引擎 │ │ │
│ │ │ • 张量操作 • 注意力机制 • 令牌采样 │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ GPU/TPU集群 │ │
│ │ • 模型分片 • 张量并行 • 流水线并行 │ │
│ └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
服务框架比较
| 框架 |
优势 |
最佳适用场景 |
注意事项 |
| vLLM |
分页注意力、高吞吐量、连续批处理 |
通用LLM服务、高并发 |
Python原生、活跃社区 |
| TGI(文本生成推理) |
生产就绪、Hugging Face集成 |
企业部署、HF模型 |
Rust后端、Docker优先 |
| TensorRT-LLM |
NVIDIA优化、最低延迟 |
NVIDIA GPU、延迟关键 |
仅限NVIDIA、设置复杂 |
| Triton推理服务器 |
多模型、多框架 |
异构模型服务 |
企业级复杂度 |
| Ollama |
简单本地部署 |
开发、边缘部署 |
有限扩展功能 |
| llama.cpp |
CPU推理、量化 |
资源受限、边缘 |
需要C++集成 |
框架选择决策树
需要在NVIDIA GPU上最低延迟?
├── 是 → TensorRT-LLM
└── 否
└── 需要高吞吐量与多并发用户?
├── 是 → vLLM(分页注意力)
└── 否
└── 需要企业功能 + HF集成?
├── 是 → TGI
└── 否
└── 简单本地/边缘部署?
├── 是 → Ollama 或 llama.cpp
└── 否 → vLLM(通用目的)
量化技术
精度级别
| 精度 |
比特数 |
内存减少 |
质量影响 |
用例 |
| FP32 |
32 |
基线 |
无 |
训练、参考 |
| FP16/BF16 |
16 |
2倍 |
最小 |
标准服务 |
| INT8 |
8 |
4倍 |
低 |
生产服务 |
| INT4 |
4 |
8倍 |
中等 |
资源受限 |
| INT2 |
2 |
16倍 |
显著 |
实验性 |
量化方法
| 方法 |
描述 |
质量 |
速度 |
| PTQ(后训练量化) |
训练后量化,无再训练 |
良好 |
应用快 |
| QAT(量化感知训练) |
训练期间模拟量化 |
更好 |
需要训练 |
| GPTQ |
一次性权重量化 |
非常好 |
中等 |
| AWQ(激活感知权重量化) |
保留重要权重 |
优秀 |
中等 |
| GGUF/GGML |
llama.cpp格式、CPU优化 |
良好 |
推理非常快 |
| SmoothQuant |
将难度迁移到权重 |
优秀 |
中等 |
量化选择
质量 vs. 效率权衡:
质量 ────────────────────────────────────────────▶ 效率
│ │
│ FP32 FP16 INT8+AWQ INT8+GPTQ INT4 INT2 │
│ ○───────○────────○──────────○──────────○──────○ │
│ │ │ │ │ │ │ │
│ 最佳 优秀 良好 良好 一般 差 │
│ │
批处理策略
静态批处理
请求1:[令牌: 100] ─┐
请求2:[令牌: 50] ─┼──▶ [批处理: 填充到100] ──▶ 处理 ──▶ 全部完成
请求3:[令牌: 80] ─┘
问题:短请求等待长请求(队头阻塞)
连续批处理(首选)
时间 ──────────────────────────────────────────────────────────▶
请求1:[████████████████████████████████] ──▶ 完成
请求2:[████████████] ──▶ 完成 ──▶ 请求4开始 [████████████████]
请求3:[████████████████████] ──▶ 完成 ──▶ 请求5开始 [████████]
• 新请求在其它请求完成时加入批处理
• 无填充浪费
• 最优GPU利用率
批处理参数
| 参数 |
描述 |
权衡 |
max_batch_size |
最大并发请求数 |
内存 vs. 吞吐量 |
max_waiting_tokens |
强制批处理前的令牌数 |
延迟 vs. 吞吐量 |
max_num_seqs |
批处理中最大序列数 |
内存 vs. 并发性 |
KV缓存管理
KV缓存问题
注意力:Q × K^T × V
对于生成的每个令牌:
• 必须用所有先前令牌重新计算注意力
• K和V张量随序列长度增长
• 内存:O(批处理大小 × 序列长度 × 层数 × 隐藏维度)
示例(70B模型,4K上下文):
• 每个请求的KV缓存:~8GB
• 10个并发请求:~80GB GPU内存
分页注意力(vLLM创新)
传统KV缓存:
┌──────────────────────────────────────────┐
│ 请求1 KV缓存(连续、固定) │ ← 浪费内存
├──────────────────────────────────────────┤
│ 请求2 KV缓存(连续、固定) │
├──────────────────────────────────────────┤
│ 碎片化/浪费空间 │
└──────────────────────────────────────────┘
分页注意力:
┌────┬────┬────┬────┬────┬────┬────┬────┐
│ R1 │ R2 │ R1 │ R3 │ R2 │ R1 │ R3 │ R2 │ ← 按需分配页面
└────┴────┴────┴────┴────┴────┴────┴────┘
• 非连续内存分配
• 接近零内存浪费
• 2-4倍更高吞吐量
KV缓存优化策略
| 策略 |
描述 |
内存节省 |
| 分页注意力 |
KV缓存的虚拟内存 |
~50% 减少 |
| 前缀缓存 |
重用公共前缀的KV缓存 |
系统提示:100% |
| 量化KV缓存 |
KV值的INT8/FP8量化 |
50-75% 减少 |
| 滑动窗口 |
有限的注意力上下文 |
线性内存 |
| MQA/GQA |
分组查询注意力 |
架构依赖 |
流式响应模式
服务器发送事件(SSE)
客户端 服务器
│ │
│──── GET /v1/chat/completions ──────▶│
│ (流式: true) │
│ │
│◀──── HTTP 200 OK ───────────────────│
│ Content-Type: text/event-stream│
│ │
│◀──── data: {"token": "Hello"} ──────│
│◀──── data: {"token": " world"} ─────│
│◀──── data: {"token": "!"} ──────────│
│◀──── data: [DONE] ──────────────────│
│ │
SSE优点:
- HTTP/1.1兼容
- 自动重连支持
- 简单实现
- 广泛客户端支持
WebSocket流式
客户端 服务器
│ │
│──── WebSocket 升级 ────────────────▶│
│◀──── 101 切换协议 ───────────────────│
│ │
│──── {"prompt": "Hello"} ───────────▶│
│ │
│◀──── {"token": "Hi"} ───────────────│
│◀──── {"token": " there"} ───────────│
│◀──── {"token": "!"} ────────────────│
│◀──── {"done": true} ────────────────│
│ │
WebSocket优点:
流式实现考虑因素
| 方面 |
SSE |
WebSocket |
| 重连 |
内置 |
手动 |
| 可扩展性 |
每请求 |
连接池 |
| 负载均衡 |
标准HTTP |
粘性会话 |
| 防火墙/代理 |
通常工作 |
可能需要配置 |
| 最佳适用 |
单向流式 |
交互式聊天 |
推测解码
概念
标准解码:
大模型:[T1] → [T2] → [T3] → [T4] → [T5]
10ms 10ms 10ms 10ms 10ms = 50ms总计
推测解码:
草稿模型:[T1, T2, T3, T4, T5](并行,5ms)
│
▼
大模型:[一次性验证T1-T5](15ms)
接受:T1, T2, T3 ✓ 拒绝:T4, T5 ✗
│
▼
[正确生成T4, T5]
总计:~25ms(如果60%接受率,速度提升2倍)
推测解码权衡
| 因素 |
影响 |
| 草稿模型质量 |
更高匹配率 = 更大速度提升 |
| 草稿模型大小 |
更大 = 更好质量、更慢 |
| 推测深度 |
更多令牌 = 更高风险/回报 |
| 验证成本 |
必须小于顺序生成 |
扩展策略
水平扩展
┌─────────────────────────────────────────────────────────┐
│ 负载均衡器 │
│ (轮询、最少连接) │
└─────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ vLLM │ │ vLLM │ │ vLLM │
│ 节点1 │ │ 节点2 │ │ 节点3 │
│ (GPU×4)│ │ (GPU×4)│ │ (GPU×4)│
└─────────┘ └─────────┘ └─────────┘
模型并行
| 策略 |
描述 |
用例 |
| 张量并行 |
跨GPU分割层 |
单个大模型 |
| 流水线并行 |
不同层在不同GPU上 |
非常大模型 |
| 数据并行 |
相同模型、不同批处理 |
高吞吐量 |
张量并行(TP=4):
┌─────────────────────────────────────────┐
│ 层 N │
│ GPU0 │ GPU1 │ GPU2 │ GPU3 │
│ 25% │ 25% │ 25% │ 25% │
└─────────────────────────────────────────┘
流水线并行(PP=4):
GPU0: 层 0-7
GPU1: 层 8-15
GPU2: 层 16-23
GPU3: 层 24-31
延迟优化清单
部署前
- [ ] 选择适当量化(生产用INT8)
- [ ] 启用连续批处理
- [ ] 配置适当KV缓存大小
- [ ] 为硬件设置最优批处理大小
- [ ] 为系统提示启用前缀缓存
运行时
- [ ] 监控GPU内存利用率
- [ ] 跟踪p50/p95/p99延迟
- [ ] 测量首令牌时间(TTFT)
- [ ] 监控每秒令牌数(TPS)
- [ ] 设置适当超时
基础设施
- [ ] 使用最快可用互联(NVLink、InfiniBand)
- [ ] 最小化网络跳数
- [ ] 将推理靠近用户(边缘)
- [ ] 考虑专用推理硬件
成本优化
成本驱动因素
| 因素 |
影响 |
优化 |
| GPU小时 |
最高 |
量化、批处理 |
| 内存 |
高 |
分页注意力、KV缓存优化 |
| 网络 |
中等 |
响应压缩、边缘部署 |
| 存储 |
低 |
模型去重 |
成本估算公式
月成本 =
(每月请求数) × (平均令牌/请求) × (GPU秒/令牌) × ($/GPU小时)
─────────────────────────────────────────────────────────────────────────────
3600
示例:
• 1000万请求/月
• 500令牌平均
• 0.001 GPU秒/令牌(优化后)
• $2/GPU小时
成本 = (10M × 500 × 0.001 × 2) / 3600 = $2,778/月
常见模式
多模型路由
┌─────────────────────────────────────────────────────────┐
│ 路由器 │
│ • 分类请求复杂度 │
│ • 路由到适当模型 │
└─────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 小模型 │ │ 中模型 │ │ 大模型 │
│ (7B) │ │ (13B) │ │ (70B) │
│ 快 │ │ 平衡 │ │ 质量 │
└─────────┘ └─────────┘ └─────────┘
缓存策略
| 缓存类型 |
缓存什么 |
TTL |
| 提示缓存 |
常见系统提示 |
长 |
| KV缓存 |
前缀令牌 |
会话 |
| 响应缓存 |
精确查询匹配 |
可变 |
| 嵌入缓存 |
文档嵌入 |
长 |
相关技能
ml-system-design - 端到端ML管道设计
rag-architecture - 检索增强生成模式
vector-databases - LLM上下文的向量搜索
ml-inference-optimization - 通用推理优化
estimation-techniques - LLM系统的容量规划
版本历史
- v1.0.0(2025-12-26):初始版本 - 系统设计面试的LLM服务模式
最后更新
日期: 2025-12-26