Skip to content

大模型推理服务部署

从零搭建本地大模型推理服务——vLLM、TGI、Ollama 三大框架对比实战,涵盖模型选型、量化压缩、API 服务化、并发优化、GPU 资源管理、生产部署与监控,一套方案让你摆脱 API 依赖。


1. 为什么要自己部署推理服务

1.1 API 调用的四大痛点:成本、隐私、延迟、依赖

如果你的 AI 应用完全依赖 OpenAI / Claude 等 API,迟早会遇到这些问题:

API 调用的四大痛点:

  ① 成本失控 ─── 日均 10 万次调用 × $0.03/次 = $3,000/月 = $36,000/年
     │            规模越大越贵,没有边际成本递减

  ② 数据隐私 ─── 用户数据发送到第三方服务器
     │            金融/医疗/政务场景不合规

  ③ 延迟不可控 ── 跨境网络延迟 200-500ms + 排队等待
     │            国内访问 OpenAI 需要代理,稳定性差

  ④ 供应商依赖 ── API 限流、价格调整、服务下线
                  2024 年 GPT-4 涨价 50%,用户无能为力

用一个真实的例子量化成本差异:

维度API 调用(GPT-4o)自部署(Qwen2.5-32B)
单次成本~$0.03~$0.001(已摊设备成本)
日均 10 万次/月$90,000$5,000(GPU 租用)
数据传输出境到美国本地内网
延迟(P50)3-8s1-3s
最大并发受限于 Rate Limit受限于 GPU 显存
模型定制不支持可微调

1.2 自部署的优势与门槛

自部署不是银弹,它有明确的优势门槛

自部署的优势:

  ✅ 成本可预测 ── GPU 是固定成本,不随调用量线性增长
  ✅ 数据不出域 ── 完全本地化,满足合规要求
  ✅ 低延迟 ────── 内网部署,无网络开销
  ✅ 可定制 ────── 微调、量化、推理参数完全可控
  ✅ 无限流 ────── 并发上限取决于硬件,不受 API 限制

自部署的门槛:

  ⚠️ 硬件投入 ── 至少需要 1 张 A10(24GB)或 RTX 4090
  ⚠️ 运维成本 ── GPU 驱动、CUDA、模型更新都要自己管
  ⚠️ 模型质量 ── 开源模型整体弱于 GPT-4o / Claude 3.5 Sonnet
  ⚠️ 工程复杂度 ── 需要掌握推理框架、量化、并发优化

💡 自部署的核心逻辑是"用工程能力换运营成本"——如果你的团队有 GPU 资源和运维能力,日均调用量超过 1 万次时,自部署几乎一定比 API 更划算。

1.3 什么时候该自己部署:决策树

用这个决策树快速判断你的场景是否适合自部署:

自部署决策树:

  你的场景需要数据不出域吗?
    ├── YES → ✅ 必须自部署(金融/医疗/政务)

    └── NO → 你的日均 LLM 调用量是多少?

                ├── < 1,000 次 → ❌ 用 API,自部署不划算

                ├── 1,000 - 10,000 次 → 需要看场景:
                │     │
                │     ├── 延迟敏感? → ✅ 自部署(内网秒级响应)
                │     ├── 需要微调? → ✅ 自部署(API 不支持微调)
                │     └── 都不需要? → ❌ 继续用 API

                └── > 10,000 次 → ✅ 自部署几乎一定更划算
                                   月成本可降低 5-10 倍

不同场景的推荐方案:

场景推荐方案理由
个人开发/原型验证Ollama 本地零成本,笔记本就能跑
小团队内部工具vLLM + 1×A10性价比最高
B 端 SaaS 产品vLLM + 多 GPU高并发,数据隔离
金融/医疗合规TGI/vLLM + 私有云数据不出域
大规模 to C 产品自部署 + API 混合基线自部署,峰值用 API

1.4 硬件需求速览:不同模型需要多少 GPU 显存

一张速查表,帮你快速评估需要什么硬件:

模型显存需求速查(推理阶段,不含 KV Cache):

  模型参数量    FP16 显存    INT8 显存    INT4 显存
  ──────────  ──────────  ──────────  ──────────
  7B           14 GB       7 GB        4 GB
  14B          28 GB       14 GB       8 GB
  32B          64 GB       32 GB       18 GB
  72B         144 GB       72 GB       40 GB

  粗算公式:显存(GB) ≈ 参数量(B) × 每参数字节数
    FP16 = 2 字节 → 7B × 2 = 14GB
    INT8 = 1 字节 → 7B × 1 = 7GB
    INT4 = 0.5 字节 → 7B × 0.5 = 3.5GB(实际约 4GB)

常用 GPU 的显存与适配模型:

GPU显存价格(租用/月)推荐模型
RTX 409024 GB~$3007B FP16 / 14B INT8 / 32B INT4
A1024 GB~$200同上(数据中心级,更稳定)
A100 40G40 GB~$80032B FP16 / 72B INT4
A100 80G80 GB~$1,50072B FP16 / 72B INT8
H10080 GB~$2,50072B FP16 + 大并发
Mac M2 Ultra192 GB 统一内存一次性 ~$5,00072B(CPU 推理,较慢)

💡 INT4 量化是性价比之王——32B 模型量化到 INT4 只需 18GB 显存,一张 RTX 4090 就能跑。质量损失约 2-5%,但成本降低 60%。对于大多数场景,INT4 的 32B 模型优于 FP16 的 7B 模型。

第 1 章核心知识回顾:

概念一句话解释
四大痛点成本失控、数据隐私、延迟不稳、供应商锁定
核心逻辑用工程能力换运营成本
决策门槛日均 > 1 万次 或 数据合规需求 → 自部署
显存公式显存(GB) ≈ 参数量(B) × 每参数字节数
性价比首选INT4 量化 + RTX 4090 / A10

2. 推理框架选型:vLLM vs TGI vs Ollama

2.1 三大框架一览:定位与差异

三大框架的定位完全不同——选错框架比选错模型影响更大:

维度vLLMTGIOllama
开发者UC BerkeleyHugging FaceOllama Inc
定位高吞吐量推理引擎HF 生态集成方案最简单的本地部署
核心优势PagedAttention + 极致性能生态好 + Docker 一键部署零配置 + 一行命令
API 兼容OpenAI 格式 ✅自有格式 + OpenAI 适配OpenAI 格式 ✅
量化支持AWQ / GPTQ / FP8GPTQ / bitsandbytesGGUF(CPU+GPU 混合)
多 GPUTensor Parallel ✅Tensor Parallel ✅❌ 单 GPU
部署方式pip / DockerDocker 为主独立安装包
适用场景生产环境、高并发HF 生态、快速原型开发调试、个人使用
一句话选型指南:

  生产环境、追求性能 → vLLM
  HF 生态、Docker 优先 → TGI
  个人开发、快速体验 → Ollama

2.2 vLLM:高吞吐量的首选(PagedAttention 原理)

vLLM 是目前性能最强的开源推理引擎,核心创新是 PagedAttention。

为什么 vLLM 快?——PagedAttention 原理:

  传统推理引擎的 KV Cache 管理:
  ┌─────────────────────────────────────────────┐
  │  请求 A:预分配 2048 tokens 的 KV Cache       │
  │  ████████░░░░░░░░░░░░░░░░░░░░░░░░           │
  │  实际只用了 512 tokens → 75% 显存浪费!       │
  └─────────────────────────────────────────────┘

  vLLM 的 PagedAttention:
  ┌─────────────────────────────────────────────┐
  │  KV Cache 按"页"分配(类似操作系统虚拟内存)  │
  │  请求 A:████ ████ ████ (按需分配 3 页)     │
  │  请求 B:████ ████ (按需分配 2 页)          │
  │  空闲页回收 → 显存利用率从 30% 提升到 90%+    │
  └─────────────────────────────────────────────┘

vLLM 的核心特性:

vLLM 特性速览:

  ① PagedAttention ──── KV Cache 按页管理,显存利用率 90%+
  ② Continuous Batching ── 新请求不等待,动态加入批次
  ③ Tensor Parallel ──── 多 GPU 自动拆分模型
  ④ Prefix Caching ──── 相同 System Prompt 共享 KV Cache
  ⑤ OpenAI API 兼容 ─── 无缝替换 OpenAI SDK
  ⑥ 量化支持 ────────── AWQ / GPTQ / FP8 / INT8

💡 vLLM 的 Continuous Batching 比静态 Batching 吞吐量高 2-5 倍——传统框架必须等一批请求都完成才能处理下一批;vLLM 的请求完成一个就释放一个位置,新请求立即填入,GPU 永远不空闲。

2.3 TGI:Hugging Face 官方方案(生态集成优势)

TGI(Text Generation Inference)是 Hugging Face 官方的推理服务,最大的优势是和 HF 生态无缝集成

TGI 的核心特性:

  ① HF Hub 直连 ──── 模型 ID 直接加载,无需手动下载
  ② Flash Attention 2 ── 原生支持,自动启用
  ③ 流式输出 ────── Server-Sent Events,原生流式
  ④ Token 级统计 ── 每个 token 的生成延迟、概率
  ⑤ 多格式量化 ─── GPTQ / bitsandbytes / EETQ
  ⑥ Docker 优先 ── 一行命令启动,镜像预装所有依赖

TGI 的典型用法:

bash
# 一行命令启动 TGI(Docker)
docker run --gpus all \
  -p 8080:80 \
  -v /data/models:/data \
  ghcr.io/huggingface/text-generation-inference:latest \
  --model-id Qwen/Qwen2.5-14B-Instruct \
  --quantize gptq \
  --max-input-tokens 4096 \
  --max-total-tokens 8192

# 调用 API
curl http://localhost:8080/generate \
  -d '{"inputs":"什么是 Transformer?","parameters":{"max_new_tokens":200}}'

💡 TGI 适合已经深度使用 HF 生态的团队——如果你的模型在 HF Hub 上、训练用的 Transformers、数据集用的 Datasets,那 TGI 是最省事的选择。但性能上比 vLLM 低 20-30%。

2.4 Ollama:最简单的本地部署(开发体验优先)

Ollama 的设计哲学是**"像 Docker 管理镜像一样管理模型"**——一行命令下载、运行、切换模型:

bash
# 安装 Ollama(macOS / Linux)
curl -fsSL https://ollama.com/install.sh | sh

# 下载并运行模型(一行命令)
ollama run qwen2.5:32b

# 其他常用命令
ollama list                     # 列出已下载的模型
ollama pull llama3.1:8b         # 只下载不运行
ollama rm mistral:7b            # 删除模型
ollama serve                    # 启动 API 服务

Ollama 的 API 兼容 OpenAI 格式:

python
from openai import OpenAI

# 把 base_url 指向 Ollama,代码零改动
client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")

response = client.chat.completions.create(
    model="qwen2.5:32b",
    messages=[{"role": "user", "content": "什么是 PagedAttention?"}],
)
print(response.choices[0].message.content)
Ollama 的定位:

  ✅ 适合的场景:
    • 本地开发调试(Mac / Linux 笔记本)
    • 快速体验、对比不同模型
    • 个人知识助手、私人 AI 工具

  ❌ 不适合的场景:
    • 生产环境高并发(不支持 Continuous Batching)
    • 多 GPU 部署(不支持 Tensor Parallel)
    • 极致性能优化(无 PagedAttention)

2.5 性能基准对比:吞吐量 / 延迟 / 显存占用

以 Qwen2.5-14B-Instruct(INT4 量化)在单张 A10 (24GB) 上的测试数据:

基准测试条件:
  模型:Qwen2.5-14B-Instruct-AWQ(INT4)
  GPU:NVIDIA A10 24GB
  输入:256 tokens | 输出:512 tokens
  并发:16 个并发请求

┌───────────────────┬──────────┬──────────┬──────────┐
│      指标          │  vLLM    │  TGI     │  Ollama  │
├───────────────────┼──────────┼──────────┼──────────┤
│ 吞吐量(req/s)    │  12.8    │  9.2     │  2.1     │
│ 首 Token 延迟      │  85ms    │  120ms   │  350ms   │
│ 生成速度(tok/s)   │  142     │  108     │  45      │
│ 显存占用           │  11.2 GB │  12.8 GB │  9.4 GB  │
│ P99 延迟           │  4.2s    │  5.8s    │  18.6s   │
└───────────────────┴──────────┴──────────┴──────────┘

  vLLM    ████████████████████████████████  12.8 req/s
  TGI     ███████████████████████           9.2 req/s
  Ollama  █████                             2.1 req/s

关键发现:

性能差异的根本原因:

  vLLM 最快:
    ├── PagedAttention → 显存利用率高 → 能同时处理更多请求
    ├── Continuous Batching → GPU 利用率 95%+
    └── CUDA Graph → 减少 kernel launch 开销

  TGI 中等:
    ├── Flash Attention 2 → 计算效率高
    ├── 有 Continuous Batching,但实现不如 vLLM 优化
    └── Rust 后端 → 稳定但灵活性不如 Python

  Ollama 最慢:
    ├── llama.cpp 后端 → 针对 CPU 优化,GPU 利用率不高
    ├── 无 Continuous Batching → 请求串行处理
    └── 但显存占用最低(GGUF 格式更紧凑)

💡 不要被 Ollama 的低性能吓到——Ollama 虽然并发性能弱,但单请求延迟在个人使用场景已经足够快(首 token 350ms)。选框架要看场景,不是一味追求 benchmark。

第 2 章核心知识回顾:

概念一句话解释
vLLM性能之王,PagedAttention + Continuous Batching
TGIHF 官方,Docker 一键部署,生态集成好
Ollama最简单,一行命令跑模型,适合个人/开发
PagedAttentionKV Cache 按页分配,显存利用率 30% → 90%
选型建议生产→vLLM,HF 生态→TGI,个人→Ollama

3. 模型选型与获取

3.1 主流开源模型对比:Llama 3 / Qwen 2.5 / Mistral / DeepSeek

2024-2025 年开源模型已经能覆盖大部分生产场景。主流选择:

模型可选尺寸中文能力代码能力许可证推荐场景
Llama 3.18B / 70B / 405B⭐⭐⭐⭐⭐⭐Llama License英文为主、代码生成
Qwen 2.57B / 14B / 32B / 72B⭐⭐⭐⭐⭐⭐⭐⭐⭐Apache 2.0中文场景首选
Mistral7B / 8×7B (MoE)⭐⭐⭐⭐⭐Apache 2.0欧洲合规、多语言
DeepSeek V3671B (MoE)⭐⭐⭐⭐⭐⭐⭐⭐⭐MIT代码、数学推理
Yi 1.56B / 9B / 34B⭐⭐⭐⭐⭐⭐⭐Apache 2.0中文通用
GLM-49B⭐⭐⭐⭐⭐⭐⭐自定义中文对话
快速选型指南:

  中文为主?
    ├── YES → Qwen 2.5(中文最强开源模型)
    │          ├── 资源充足 → 72B
    │          └── 资源有限 → 14B / 32B INT4

    └── NO → 英文/代码为主?
              ├── 代码 → DeepSeek Coder / Llama 3.1
              └── 通用 → Llama 3.1 70B / Mistral 8×7B

3.2 模型大小与质量的权衡:7B / 14B / 32B / 72B 怎么选

模型不是越大越好——要在质量和成本之间找到甜蜜点

模型大小 vs 能力 vs 成本:

  能力  ▲
       │                         ● 72B(接近 GPT-4 水平)
       │                    ● 32B(大部分生产场景够用)
       │              ● 14B(性价比最高)
       │        ● 7B(简单任务足够)
       │  ● 3B(嵌入式/边缘设备)
       └──────────────────────────────────→ 成本
         低                              高
尺寸典型质量INT4 显存推荐场景对标 API
7B能完成简单指令~4 GB分类、提取、简单问答GPT-3.5 基础版
14B流畅的多轮对话~8 GB客服、FAQ、翻译GPT-3.5 Turbo
32B复杂推理和创作~18 GB代码生成、分析报告GPT-4o-mini
72B接近 SOTA 水平~40 GB高质量内容、复杂推理GPT-4o(部分场景)

💡 14B INT4 是自部署的甜蜜点——一张 RTX 4090(24GB)就能跑,质量足以覆盖 80% 的生产场景(客服、翻译、提取、问答)。只有在复杂推理和代码生成场景才需要升级到 32B+。

3.3 模型下载:Hugging Face / ModelScope / 镜像加速

模型文件通常几十 GB,下载渠道的选择直接影响效率:

bash
# ── 方法一:Hugging Face CLI(国际最全) ──
pip install huggingface_hub
huggingface-cli download Qwen/Qwen2.5-14B-Instruct-AWQ \
  --local-dir /data/models/qwen2.5-14b-awq

# ── 方法二:ModelScope(国内最快,免翻墙) ──
pip install modelscope
modelscope download --model Qwen/Qwen2.5-14B-Instruct-AWQ \
  --local_dir /data/models/qwen2.5-14b-awq

# ── 方法三:HF 镜像站(国内加速 HF) ──
export HF_ENDPOINT=https://hf-mirror.com
huggingface-cli download Qwen/Qwen2.5-14B-Instruct-AWQ \
  --local-dir /data/models/qwen2.5-14b-awq

# ── 方法四:Ollama 直接下载(最简单) ──
ollama pull qwen2.5:14b  # 自动下载 GGUF 格式
渠道速度(国内)模型数量适用框架
Hugging Face慢(需翻墙)最全(80 万+)vLLM / TGI
HF 镜像站同 HFvLLM / TGI
ModelScope最快较多(10 万+)vLLM / TGI
Ollama RegistryGGUF 为主Ollama

3.4 模型格式:SafeTensors / GGUF / AWQ / GPTQ

不同格式适用于不同推理框架——格式选错直接无法加载

格式精度适用框架特点
SafeTensorsFP16 / BF16vLLM / TGI原始精度,最大显存占用
GPTQINT4 / INT8vLLM / TGI离线量化,需校准数据集
AWQINT4vLLM保护重要权重,质量更好
GGUFQ4_K_M / Q5 等Ollama / llama.cppCPU+GPU 混合推理
FP8FP8vLLM(H100)H100 专属,平衡精度和速度
格式选择流程:

  你用什么推理框架?

    ├── vLLM → 首选 AWQ(质量最好的 INT4)
    │          次选 GPTQ → 再次 SafeTensors(FP16)

    ├── TGI → 首选 GPTQ → 次选 SafeTensors

    └── Ollama → 只能用 GGUF
                 推荐 Q4_K_M(平衡质量和大小)

💡 同一个模型,AWQ 的量化质量通常优于 GPTQ——AWQ 会分析哪些权重对输出影响大,保护这些"重要权重"不被激进量化。在 vLLM 上推荐优先选 AWQ 格式的模型。

第 3 章核心知识回顾:

概念一句话解释
中文首选Qwen 2.5 系列(7B-72B)
代码首选DeepSeek Coder / Llama 3.1
甜蜜点14B INT4,一张 4090 就能跑
国内下载ModelScope 或 HF 镜像站
格式选择vLLM→AWQ,TGI→GPTQ,Ollama→GGUF

4. 模型量化:用更少的显存跑更大的模型

4.1 量化原理:FP16 → INT8 → INT4 的精度与显存变化

量化的本质是用更低精度的数据类型存储模型权重,从而减少显存占用:

不同精度的表示范围与大小:

  FP32(32位浮点)── 每个参数 4 字节
  ████████████████    精度极高,但显存占用最大

  FP16(16位浮点)── 每个参数 2 字节
  ████████            标准推理精度,质量无损

  INT8(8位整数)─── 每个参数 1 字节
  ████                轻微精度损失(~1%),显存减半

  INT4(4位整数)─── 每个参数 0.5 字节
  ██                  可感知精度损失(~3-5%),显存减 75%

以 Qwen2.5-32B 为例的实际效果:

精度显存占用需要的 GPU推理速度质量损失
FP1664 GB1×A100 80G基准0%
INT832 GB1×A100 40G+10%~1%
INT4 (GPTQ)18 GB1×RTX 4090+25%~3%
INT4 (AWQ)18 GB1×RTX 4090+25%~2%

4.2 GPTQ 量化:离线量化的标准方案

GPTQ 是最成熟的离线量化方法——需要一个校准数据集来决定量化参数

GPTQ 的工作原理:

  原始模型(FP16)


  ① 准备校准数据集 ── 128-256 条代表性文本


  ② 逐层量化 ──────── 每一层找到最优的量化参数
    │                   使量化误差最小化(OBQ 算法)

  ③ 输出量化模型 ──── INT4/INT8 权重 + 量化配置


  加载到 vLLM / TGI 推理
bash
# 使用 AutoGPTQ 进行量化
pip install auto-gptq

# Python 量化脚本
python -c "
from transformers import AutoTokenizer
from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig

model_id = 'Qwen/Qwen2.5-14B-Instruct'
quantize_config = BaseQuantizeConfig(bits=4, group_size=128, damp_percent=0.1)

tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoGPTQForCausalLM.from_pretrained(model_id, quantize_config)

# 校准数据集(通常用 C4、WikiText 或你的业务数据)
examples = [tokenizer(t, return_tensors='pt') for t in calibration_texts[:128]]
model.quantize(examples)
model.save_quantized('/data/models/qwen2.5-14b-gptq-int4')
"

💡 大多数情况不需要自己量化——HuggingFace 上已经有大量预量化的模型。搜索 模型名-GPTQ模型名-AWQ 直接下载即可。自己量化只在使用私有微调模型时需要。

4.3 AWQ 量化:保护重要权重的智能量化

AWQ(Activation-aware Weight Quantization)的核心思想是不是所有权重同等重要

AWQ vs GPTQ 的区别:

  GPTQ:所有权重平等对待,统一量化
    权重: [0.12, 0.83, 0.04, 0.91, 0.07]
    量化: [ 0,    1,    0,    1,    0  ]  ← 所有权重都被压缩

  AWQ:分析哪些权重对输出影响大,保护它们
    权重: [0.12, 0.83, 0.04, 0.91, 0.07]
    重要度:[低,   ★高, 低,   ★高,  低  ]
    量化: [ 0,   0.8,  0,   0.9,   0  ]  ← 重要权重保留更高精度
    
  → AWQ 在同样 INT4 下,质量损失比 GPTQ 少 ~30%
bash
# AWQ 量化(使用 autoawq 库)
pip install autoawq

python -c "
from awq import AutoAWQForCausalLM
from transformers import AutoTokenizer

model_id = 'Qwen/Qwen2.5-14B-Instruct'
quant_config = {'zero_point': True, 'q_group_size': 128, 'w_bit': 4, 'version': 'GEMM'}

model = AutoAWQForCausalLM.from_pretrained(model_id)
tokenizer = AutoTokenizer.from_pretrained(model_id)
model.quantize(tokenizer, quant_config=quant_config)
model.save_quantized('/data/models/qwen2.5-14b-awq')
"

4.4 GGUF 量化:CPU + GPU 混合推理(Ollama 专用)

GGUF 是 llama.cpp 生态的量化格式,最大特点是支持 CPU + GPU 混合推理——显存不够时,把一部分层放到 CPU 内存运行:

GGUF 的 CPU + GPU 混合推理:

  72B 模型(INT4 需要 ~40GB)

    ├── GPU 只有 24GB?
    │     │
    │     └── 前 40 层 → GPU(24GB 显存)
    │         后 40 层 → CPU(16GB 内存)
    │         → 速度降低 50%,但至少能跑!

    └── GPU 有 80GB?
          └── 全部 80 层 → GPU
              → 全速运行

GGUF 的量化等级(从高质量到高压缩):

量化等级每参数占用质量损失适用场景
Q8_08.5 bits~0.5%最高质量,显存充足时用
Q6_K6.6 bits~1%高质量 + 适度压缩
Q5_K_M5.7 bits~2%平衡选择
Q4_K_M4.8 bits~3%推荐默认选择
Q3_K_M3.9 bits~5%极致压缩,有感知质量损失
Q2_K3.4 bits~10%不推荐,损失太大
bash
# Ollama 下载特定量化等级
ollama pull qwen2.5:32b-instruct-q4_K_M   # 推荐
ollama pull qwen2.5:72b-instruct-q4_K_M   # 大模型低显存方案

# 手动转换为 GGUF(需要 llama.cpp)
python llama.cpp/convert_hf_to_gguf.py \
  /data/models/qwen2.5-14b \
  --outfile qwen2.5-14b-q4_k_m.gguf \
  --outtype q4_k_m

4.5 量化效果对比:精度损失 vs 速度提升 vs 显存节省

用 Qwen2.5-14B-Instruct 在 A10 (24GB) 上的综合对比:

量化方法综合对比(Qwen2.5-14B-Instruct):

┌───────────┬──────────┬──────────┬──────────┬──────────┐
│  量化方法   │ 显存占用  │ 生成速度  │ 质量得分  │ 推荐度   │
│           │          │ (tok/s)  │ (满分100) │          │
├───────────┼──────────┼──────────┼──────────┼──────────┤
│ FP16      │ 28 GB    │  82      │  100     │ 显存够时用│
│ INT8      │ 14 GB    │  95      │  99      │ ⭐⭐⭐⭐   │
│ GPTQ-INT4 │  8 GB    │  118     │  96      │ ⭐⭐⭐     │
│ AWQ-INT4  │  8 GB    │  120     │  97.5    │ ⭐⭐⭐⭐⭐  │
│ GGUF-Q4KM │  9 GB    │  45*     │  97      │ 个人使用  │
└───────────┴──────────┴──────────┴──────────┴──────────┘

  * GGUF 速度较低因为 Ollama 无 Continuous Batching

  显存节省:FP16(28GB) → AWQ-INT4(8GB) = 节省 71%
  速度提升:FP16(82t/s) → AWQ-INT4(120t/s) = 提升 46%
  质量损失:FP16(100) → AWQ-INT4(97.5) = 仅损失 2.5%

💡 量化不仅省显存,还能加速推理——INT4 模型的数据传输量只有 FP16 的 1/4,而 GPU 推理通常是 memory-bound(显存带宽瓶颈),所以更少的数据量 = 更快的推理速度。

第 4 章核心知识回顾:

概念一句话解释
量化公式显存 ≈ 参数量 × 每参数字节数
GPTQ需校准数据,统一量化,最成熟
AWQ保护重要权重,同精度下质量更好
GGUFOllama 专用,支持 CPU+GPU 混合
推荐方案vLLM 用 AWQ-INT4,Ollama 用 Q4_K_M

5. 部署实战:三大框架的完整搭建

5.1 vLLM 部署:安装 → 启动 → OpenAI 兼容 API

Step 1:安装 vLLM

bash
# 前置要求:CUDA 12.1+, Python 3.9+
pip install vllm

# 验证安装
python -c "import vllm; print(vllm.__version__)"

Step 2:启动 OpenAI 兼容 API 服务

bash
# 最简启动(AWQ 量化模型)
vllm serve Qwen/Qwen2.5-14B-Instruct-AWQ \
  --host 0.0.0.0 \
  --port 8000

# 生产级启动(带关键优化参数)
vllm serve Qwen/Qwen2.5-14B-Instruct-AWQ \
  --host 0.0.0.0 \
  --port 8000 \
  --tensor-parallel-size 1 \
  --gpu-memory-utilization 0.90 \
  --max-model-len 8192 \
  --max-num-seqs 64 \
  --enable-prefix-caching \
  --quantization awq \
  --dtype half

关键参数说明:

参数作用推荐值
--gpu-memory-utilizationGPU 显存使用比例0.90(留 10% 余量)
--max-model-len最大上下文长度按需设置,越短越省显存
--max-num-seqs最大并发请求数32-128
--enable-prefix-caching共享 System Prompt 缓存生产必开
--tensor-parallel-size多 GPU 并行数GPU 数量

Step 3:调用 API(和 OpenAI SDK 完全兼容)

python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="not-needed")

response = client.chat.completions.create(
    model="Qwen/Qwen2.5-14B-Instruct-AWQ",
    messages=[{"role": "user", "content": "用 Python 实现快速排序"}],
    temperature=0.7,
    max_tokens=1000,
    stream=True,  # 支持流式输出
)

for chunk in response:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")

5.2 TGI 部署:Docker 一键启动 → 参数调优

TGI 推荐用 Docker 部署——镜像预装了所有 CUDA 依赖:

bash
# 创建模型目录
mkdir -p /data/models

# 一键启动 TGI
docker run --gpus all -d \
  --name tgi \
  -p 8080:80 \
  -v /data/models:/data \
  -e HUGGING_FACE_HUB_TOKEN=$HF_TOKEN \
  ghcr.io/huggingface/text-generation-inference:latest \
  --model-id Qwen/Qwen2.5-14B-Instruct-GPTQ \
  --quantize gptq \
  --max-input-tokens 4096 \
  --max-total-tokens 8192 \
  --max-batch-prefill-tokens 4096 \
  --max-concurrent-requests 64

TGI 的关键调优参数:

参数作用推荐值
--max-input-tokens最大输入长度按场景设置
--max-total-tokens输入+输出总长度8192
--max-concurrent-requests最大并发64-128
--max-batch-prefill-tokensPrefill 批大小4096
--num-shard多 GPU 分片数GPU 数量
bash
# TGI 的 API 调用
curl http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "tgi",
    "messages": [{"role": "user", "content": "什么是 Transformer?"}],
    "max_tokens": 500,
    "stream": true
  }'

💡 vLLM 和 TGI 都兼容 OpenAI API 格式——只需要把 base_urlapi.openai.com 改成你的服务地址,应用代码零修改。这意味着你可以随时在 API 调用和自部署之间切换。

5.3 Ollama 部署:安装 → 下载模型 → 本地 API

Ollama 的部署流程最简单——三步搞定:

bash
# Step 1:安装
curl -fsSL https://ollama.com/install.sh | sh

# Step 2:下载并启动模型
ollama run qwen2.5:14b

# Step 3:API 已自动启动在 http://localhost:11434
curl http://localhost:11434/v1/chat/completions \
  -d '{
    "model": "qwen2.5:14b",
    "messages": [{"role": "user", "content": "你好"}]
  }'

自定义模型配置——用 Modelfile 控制行为:

dockerfile
# Modelfile - 自定义模型配置
FROM qwen2.5:14b

# 设置默认参数
PARAMETER temperature 0.7
PARAMETER top_p 0.9
PARAMETER num_ctx 8192
PARAMETER num_gpu 99

# 设置系统提示词
SYSTEM """你是一个专业的技术助手,请用中文回答所有问题。
回答要简洁、准确、有代码示例。"""
bash
# 创建自定义模型
ollama create my-tech-assistant -f Modelfile

# 运行自定义模型
ollama run my-tech-assistant

5.4 Docker Compose 编排:一键启动完整推理服务

生产环境推荐用 Docker Compose 编排完整服务栈:

yaml
# docker-compose.yml
version: "3.8"

services:
  # vLLM 推理服务
  vllm:
    image: vllm/vllm-openai:latest
    runtime: nvidia
    environment:
      - NVIDIA_VISIBLE_DEVICES=all
    volumes:
      - /data/models:/models
    command: >
      --model /models/qwen2.5-14b-awq
      --host 0.0.0.0
      --port 8000
      --gpu-memory-utilization 0.90
      --max-model-len 8192
      --max-num-seqs 64
      --enable-prefix-caching
      --quantization awq
    ports:
      - "8000:8000"
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  # Nginx 反向代理
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      vllm:
        condition: service_healthy
nginx
# nginx.conf
upstream vllm_backend {
    server vllm:8000;
}

server {
    listen 80;
    
    location /v1/ {
        proxy_pass http://vllm_backend/v1/;
        proxy_set_header Host $host;
        proxy_read_timeout 300s;  # LLM 生成可能很慢
        proxy_buffering off;     # 流式输出必须关闭缓冲
    }
}
bash
# 一键启动
docker compose up -d

# 查看状态
docker compose ps
docker compose logs -f vllm

💡 Nginx 的 proxy_buffering off 是流式输出的关键——如果不关闭,Nginx 会把 SSE 事件缓存起来一次性返回,用户看到的就不是"逐字打出"而是"等半天突然全出来"。

第 5 章核心知识回顾:

概念一句话解释
vLLMvllm serve + OpenAI 兼容 API,生产首选
TGIDocker 一行命令,HF 生态集成好
Ollama三步搞定,Modelfile 自定义配置
Docker Compose编排 vLLM + Nginx,一键启动
关键配置--gpu-memory-utilization 0.90 + --enable-prefix-caching

6. 并发优化与性能调优

6.1 Continuous Batching:为什么它是吞吐量的关键

传统的静态 Batching 和 vLLM 的 Continuous Batching 差异巨大:

静态 Batching(传统方式):

  时间 →→→→→→→→→→→→→→→→→→→→→→→→→→→
  请求A ████████████████████████████  (完成)
  请求B ████████████████████████████  (完成)
  请求C ████████████                  (完成,但要等 A/B)
  请求D                               █████████████████  (等整个批次完成才能开始)
  
  → 请求 C 早就完成了,但被 A/B 拖住
  → 请求 D 白白等待
  → GPU 利用率 ~50%

Continuous Batching(vLLM/TGI):

  时间 →→→→→→→→→→→→→→→→→→→→→→→→→→→
  请求A ████████████████████████████  (完成)
  请求B ████████████████████████████  (完成)
  请求C ████████████  (完成 → 位置立即让给 D)
  请求D              █████████████████  (C 完成后立即开始)
  请求E                    ████████████████  (B 完成后立即开始)
  
  → 完成一个就填入一个
  → GPU 永远满载
  → GPU 利用率 ~95%

💡 Continuous Batching 是选择 vLLM/TGI 而非 Ollama 的最核心原因——在 16 并发场景下,Continuous Batching 的吞吐量是静态 Batching 的 3-5 倍。

6.2 KV Cache 管理:PagedAttention 与显存分配

KV Cache 是推理阶段最大的显存消耗——模型权重是固定的,但 KV Cache 随并发动态增长

显存的构成:

  总显存 = 模型权重 + KV Cache + 临时计算
  
  以 Qwen2.5-14B-AWQ 在 24GB GPU 上为例:
  ┌──────────────────────────────────────────────┐
  │ 模型权重(AWQ INT4):     8 GB(固定)         │
  │ ██████████████                                │
  │                                               │
  │ KV Cache(动态):          ~14 GB(可配置)    │
  │ ░░░░░░░░░░░░░░░░░░░░░░░░░░                    │
  │                                               │
  │ 临时计算 + 系统:           ~2 GB(固定)       │
  │ ████                                          │
  └──────────────────────────────────────────────┘

  KV Cache 决定了能同时处理多少请求:
  
  每个请求的 KV Cache = 层数 × 2 × 头数 × 头维度 × 序列长度 × 2字节
  14B 模型:40 × 2 × 40 × 128 × 4096 × 2B ≈ 3.3 GB/请求
  
  14 GB 可用 KV Cache ÷ 3.3 GB/请求 ≈ 4 个并发
  
  但 PagedAttention 不预分配全部长度 → 实际可跑 16-32 并发!

6.3 Tensor Parallel:多 GPU 并行推理

当单张 GPU 无法放下模型时,用 Tensor Parallel 把模型拆分到多张 GPU:

Tensor Parallel 的拆分方式:

  单 GPU(72B FP16 需要 144GB → 单卡放不下):
  ┌──────────────────────────────┐
  │  Layer 1-80  → 一张 GPU?     │
  │  ❌ 显存不够                  │
  └──────────────────────────────┘

  2-GPU Tensor Parallel:
  ┌──────────────┐  ┌──────────────┐
  │ GPU 0         │  │ GPU 1         │
  │ 每层的前半部分  │  │ 每层的后半部分  │
  │ 72 GB         │  │ 72 GB         │
  └──────────────┘  └──────────────┘
  
  → 每张 GPU 负担一半参数
  → 需要 GPU 间高速通信(NVLink 最佳)
bash
# vLLM 多 GPU 启动
vllm serve Qwen/Qwen2.5-72B-Instruct \
  --tensor-parallel-size 2 \        # 2 张 GPU
  --gpu-memory-utilization 0.90

# TGI 多 GPU 启动
docker run --gpus all \
  ghcr.io/huggingface/text-generation-inference:latest \
  --model-id Qwen/Qwen2.5-72B-Instruct \
  --num-shard 2                     # 2 张 GPU
GPU 配置推荐模型Tensor Parallel
1× A10 (24G)14B INT4 / 7B FP16不需要
2× A10 (48G)32B FP16 / 72B INT4--tp 2
4× A100 (320G)72B FP16 + 大并发--tp 4
8× H100 (640G)405B FP16--tp 8

💡 Tensor Parallel 的效率取决于 GPU 间通信带宽——2 张通过 PCIe 连接的 GPU,Tensor Parallel 效率约 70-80%;通过 NVLink 连接的效率可达 95%。尽量选 NVLink 互联的服务器。

6.4 请求调度策略:队列管理与优先级

当并发请求超过 GPU 处理能力时,需要请求排队和优先级调度

python
import asyncio
from dataclasses import dataclass, field
from enum import IntEnum

class Priority(IntEnum):
    HIGH = 0      # VIP 用户、付费接口
    NORMAL = 1    # 普通用户
    LOW = 2       # 后台任务、批量处理

@dataclass(order=True)
class InferenceRequest:
    priority: int
    created_at: float = field(compare=False)
    prompt: str = field(compare=False)
    future: asyncio.Future = field(compare=False)

class RequestScheduler:
    """推理请求调度器:优先级队列 + 超时管理"""
    
    def __init__(self, max_queue_size: int = 200, timeout: float = 60.0):
        self.queue = asyncio.PriorityQueue(maxsize=max_queue_size)
        self.timeout = timeout
        self.active_requests = 0
    
    async def submit(self, prompt: str, priority: Priority = Priority.NORMAL) -> str:
        """提交推理请求"""
        if self.queue.full():
            raise Exception("推理队列已满,请稍后重试")
        
        future = asyncio.get_event_loop().create_future()
        request = InferenceRequest(
            priority=priority, created_at=time.time(), 
            prompt=prompt, future=future,
        )
        await self.queue.put(request)
        
        # 等待结果(带超时)
        try:
            return await asyncio.wait_for(future, timeout=self.timeout)
        except asyncio.TimeoutError:
            raise Exception(f"推理超时({self.timeout}s)")

💡 队列深度是重要的监控指标——当队列持续大于 50 时,说明 GPU 处理能力不足。应该考虑扩容(加 GPU)或限流(拒绝低优先级请求)。

6.5 性能调优参数速查表

一张表汇总 vLLM 所有关键调优参数:

参数默认值推荐值说明
--gpu-memory-utilization0.900.85-0.95越高越多并发,但 OOM 风险增大
--max-model-len模型最大值按需降低降到 4096 可多 50% 并发
--max-num-seqs25632-128限制同时处理的请求数
--max-num-batched-tokens自动8192-16384每次 Prefill 的 token 数
--enable-prefix-cachingfalsetrueSystem Prompt 复用,必开
--enable-chunked-prefillfalsetrue长输入分块 Prefill
--swap-space44-16 GBCPU swap 空间
--enforce-eagerfalsefalse关闭 CUDA Graph(调试用)
--dtypeautohalf / bfloat16计算精度
性能调优的优先级(投入产出比从高到低):

  ① 选对量化格式 ──── AWQ INT4 > GPTQ > FP16(ROI 最高)
  ② 开启 Prefix Caching ── 大部分场景 System Prompt 相同
  ③ 调整 max-model-len ─── 不需要 128K 就别设 128K
  ④ 调整 gpu-memory-utilization ── 0.90 通常最佳
  ⑤ Tensor Parallel ────── 多 GPU 线性提升

第 6 章核心知识回顾:

概念一句话解释
Continuous Batching完成一个填入一个,GPU 利用率 95%+
KV Cache随并发增长,PagedAttention 按页管理
Tensor Parallel多 GPU 拆分模型,NVLink 效率最高
请求调度优先级队列 + 超时管理
首要优化选对量化 > Prefix Caching > 调参数

7. GPU 资源管理与多模型部署

7.1 GPU 显存规划:模型大小 × 并发数 × KV Cache

生产环境必须做精确的显存规划——OOM 会导致服务直接崩溃

显存规划公式:

  总显存需求 = 模型权重 + KV Cache + 计算开销 + 系统预留

  模型权重 = 参数量 × 每参数字节数
    14B × 0.5B (INT4) = 7 GB

  KV Cache = 并发数 × 每请求 KV Cache 大小
    每请求 = 层数 × 2 × 头数 × 头维度 × 平均序列长度 × 2B
    14B 模型:≈ 800 MB/请求(平均 2048 tokens)
    16 并发 → 16 × 0.8 GB = 12.8 GB

  计算开销 + 系统 ≈ 2 GB

  总计 = 7 + 12.8 + 2 = 21.8 GB → 需要 24GB GPU ✓
模型精度8 并发16 并发32 并发推荐 GPU
7BINT410 GB13 GB19 GBRTX 4090
14BINT414 GB22 GB36 GBA10 / A100 40G
32BINT426 GB38 GB62 GBA100 80G
72BINT452 GB68 GB100 GB2×A100 80G

7.2 多模型共存:一台机器跑多个模型

多 GPU 服务器可以每张 GPU 跑不同的模型,通过不同端口对外提供服务:

bash
# GPU 0 跑通用模型
CUDA_VISIBLE_DEVICES=0 vllm serve Qwen/Qwen2.5-14B-Instruct-AWQ \
  --port 8000 --gpu-memory-utilization 0.90 &

# GPU 1 跑代码模型
CUDA_VISIBLE_DEVICES=1 vllm serve deepseek-ai/DeepSeek-Coder-V2-Lite-Instruct \
  --port 8001 --gpu-memory-utilization 0.90 &

# Nginx 按路由分发
# /v1/chat → 8000(通用)
# /v1/code → 8001(代码)
nginx
# nginx.conf - 多模型路由
upstream general_model { server localhost:8000; }
upstream code_model    { server localhost:8001; }

server {
    listen 80;
    location /v1/chat/ { proxy_pass http://general_model/v1/; }
    location /v1/code/ { proxy_pass http://code_model/v1/; }
}

7.3 模型热加载与卸载:按需切换节省显存

如果 GPU 资源有限,可以按需加载模型——不用的模型卸载释放显存:

python
class ModelManager:
    """模型热加载管理器"""
    
    def __init__(self, gpu_memory_limit_gb: int = 24):
        self.loaded_models: dict[str, dict] = {}
        self.gpu_memory_limit = gpu_memory_limit_gb
    
    async def get_model(self, model_name: str) -> str:
        """获取模型的 API 地址,自动加载/卸载"""
        if model_name in self.loaded_models:
            self.loaded_models[model_name]["last_used"] = time.time()
            return self.loaded_models[model_name]["url"]
        
        # 显存不够时,卸载最久未使用的模型
        while self._used_memory() + self._model_size(model_name) > self.gpu_memory_limit:
            lru_model = min(self.loaded_models, 
                          key=lambda k: self.loaded_models[k]["last_used"])
            await self._unload(lru_model)
        
        url = await self._load(model_name)
        return url

7.4 CPU 卸载:显存不够时的降级方案

当显存确实不够时,可以把模型的部分层卸载到 CPU 内存

bash
# Ollama 自动 CPU 卸载(GGUF 格式天然支持)
ollama run qwen2.5:72b  # 自动判断:GPU 放不下的层放 CPU

# vLLM CPU 卸载(通过 swap space)
vllm serve Qwen/Qwen2.5-32B-Instruct-AWQ \
  --swap-space 16 \          # 16GB CPU 内存作为 swap
  --gpu-memory-utilization 0.95

💡 CPU 卸载是"能跑"和"跑得快"的折衷——把 20% 的层放到 CPU 会让推理速度下降约 40%。如果预算允许,优先升级 GPU 而不是依赖 CPU 卸载。

第 7 章核心知识回顾:

概念一句话解释
显存公式模型权重 + KV Cache(并发相关)+ 开销
多模型CUDA_VISIBLE_DEVICES 隔离 + Nginx 路由
热加载LRU 策略按需加载/卸载模型
CPU 卸载显存不够的降级方案,速度下降明显

8. 生产部署:从开发到上线

8.1 API 网关:Nginx 反向代理 + 负载均衡

多实例 vLLM 通过 Nginx 做负载均衡:

nginx
upstream llm_cluster {
    least_conn;  # 最少连接数策略(推荐)
    server 10.0.0.1:8000 weight=1;
    server 10.0.0.2:8000 weight=1;
    
    keepalive 32;  # 保持长连接
}

server {
    listen 80;
    
    # API 限流:每秒 100 个请求
    limit_req_zone $binary_remote_addr zone=llm:10m rate=100r/s;
    
    location /v1/ {
        limit_req zone=llm burst=50;
        proxy_pass http://llm_cluster/v1/;
        proxy_read_timeout 300s;
        proxy_buffering off;
        proxy_set_header Connection '';
        proxy_http_version 1.1;
    }
}

8.2 健康检查与自动重启

bash
# systemd 服务配置(自动重启)
# /etc/systemd/system/vllm.service
[Unit]
Description=vLLM Inference Server
After=network.target

[Service]
Type=simple
User=appuser
ExecStart=/usr/bin/vllm serve /models/qwen2.5-14b-awq \
  --host 0.0.0.0 --port 8000 --gpu-memory-utilization 0.90
Restart=always
RestartSec=10
Environment=CUDA_VISIBLE_DEVICES=0

[Install]
WantedBy=multi-user.target
bash
# 启动并设置开机自启
sudo systemctl enable --now vllm
sudo systemctl status vllm

8.3 监控与报警:GPU 利用率 / 推理延迟 / 队列深度

核心监控指标:

指标采集方式报警阈值
GPU 利用率nvidia-smi / DCGM< 50%(浪费)或 > 95%(过载)
GPU 显存nvidia-smi> 90%(OOM 风险)
推理延迟 P99vLLM /metrics> 30s
队列深度vLLM /metrics> 50(需扩容)
请求错误率Nginx 日志> 1%
bash
# vLLM 自带 Prometheus 指标
curl http://localhost:8000/metrics

# 关键指标:
# vllm:num_requests_running     - 正在处理的请求数
# vllm:num_requests_waiting     - 等待队列中的请求数
# vllm:gpu_cache_usage_perc     - KV Cache 使用率
# vllm:avg_generation_throughput_toks_per_s - 生成吞吐量

8.4 日志与调试:请求追踪与错误排查

bash
# vLLM 日志级别调整
VLLM_LOGGING_LEVEL=DEBUG vllm serve ...

# 常见错误排查
# OOM → 降低 --gpu-memory-utilization 或 --max-model-len
# CUDA error → 检查驱动版本,升级到 CUDA 12.1+
# 模型加载慢 → 检查磁盘 IO,模型放 SSD

8.5 自动扩缩容:基于队列深度的弹性伸缩

python
# 简易自动扩缩容脚本
import subprocess, requests, time

def get_queue_depth() -> int:
    metrics = requests.get("http://localhost:8000/metrics").text
    for line in metrics.split("\n"):
        if "num_requests_waiting" in line and not line.startswith("#"):
            return int(float(line.split()[-1]))
    return 0

def scale(replicas: int):
    subprocess.run(["docker", "compose", "up", "-d", 
                    "--scale", f"vllm={replicas}"])

while True:
    depth = get_queue_depth()
    if depth > 50:
        scale(2)   # 扩容到 2 实例
    elif depth < 5:
        scale(1)   # 缩回 1 实例
    time.sleep(30)

💡 GPU 服务的扩缩容比 CPU 服务慢得多——模型加载需要 30-120 秒,冷启动成本高。建议设置较保守的缩容策略(等待 10 分钟低负载才缩容),避免频繁抖动。

第 8 章核心知识回顾:

概念一句话解释
负载均衡Nginx least_conn + proxy_buffering off
自动重启Systemd Restart=always
核心指标GPU 利用率 + 队列深度 + P99 延迟
扩缩容基于队列深度,注意模型加载冷启动耗时

9. 成本分析:自部署 vs API 调用的盈亏平衡点

9.1 GPU 服务器成本:购买 vs 租用 vs 云 GPU

方案代表月成本优势劣势
购买服务器RTX 4090 工作站~$150(折旧)长期最便宜一次性投入大(~$5,000)
GPU 云租用AutoDL / vast.ai$200-800按需使用,灵活数据在别人服务器
云厂商 GPUAWS / 阿里云$800-3,000企业级 SLA最贵
Serverless GPURunPod / Modal按秒计费零运维冷启动慢(30-120s)
各方案的月成本对比(24GB GPU,7×24 运行):

  购买 4090      █████  $150/月(按 3 年折旧)
  AutoDL        ████████  $200/月
  vast.ai       ██████████  $250/月
  阿里云 A10     ████████████████████  $500/月
  AWS A10G      ███████████████████████████  $700/月

9.2 盈亏平衡点计算:多少请求量时自部署更划算

盈亏平衡点计算:

  API 成本 = 日均请求量 × 单次成本 × 30天
  自部署成本 = GPU 月租 + 运维人工(可忽略)

  以 GPT-4o ($0.03/次) vs 自部署 Qwen2.5-14B ($200/月) 为例:

  $0.03 × N × 30 = $200
  N = $200 ÷ ($0.03 × 30)
  N ≈ 222 次/天

  → 日均超过 222 次调用,自部署就比 GPT-4o API 划算!

  更实际的对比(考虑模型质量差异):
  ┌──────────────┬──────────┬──────────┬──────────┐
  │ 日均请求量    │ API 月费  │ 自部署月费 │ 结论     │
  ├──────────────┼──────────┼──────────┼──────────┤
  │ 100 次       │ $90      │ $200     │ API 划算 │
  │ 500 次       │ $450     │ $200     │ 自部署赢 │
  │ 5,000 次     │ $4,500   │ $200     │ 自部署大赢│
  │ 50,000 次    │ $45,000  │ $800     │ 自部署完胜│
  └──────────────┴──────────┴──────────┴──────────┘

9.3 混合策略:自部署兜底 + API 弹性扩展

最优的生产方案是自部署处理基线流量,API 处理峰值溢出

python
class HybridLLMRouter:
    """混合路由:自部署优先,溢出到 API"""
    
    def __init__(self):
        self.local = OpenAI(base_url="http://localhost:8000/v1", api_key="local")
        self.remote = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
        self.local_queue_threshold = 30  # 本地队列超过 30 就溢出
    
    async def chat(self, messages: list, **kwargs) -> str:
        # 检查本地服务队列深度
        if await self._local_queue_depth() < self.local_queue_threshold:
            try:
                return await self._call_local(messages, **kwargs)
            except Exception:
                pass  # 本地失败,降级到 API
        
        # 溢出到 API
        return await self._call_remote(messages, **kwargs)
    
    async def _local_queue_depth(self) -> int:
        metrics = requests.get("http://localhost:8000/metrics").text
        # 解析 num_requests_waiting 指标
        for line in metrics.split("\n"):
            if "num_requests_waiting" in line and not line.startswith("#"):
                return int(float(line.split()[-1]))
        return 0
混合策略的成本优势:

  纯 API(日均 5,000 次):     $4,500/月
  纯自部署(1×A10):           $200/月,但峰值可能排队
  混合策略:
    ├── 自部署处理 80% 请求 → $200/月
    └── API 处理 20% 溢出   → $900/月
    └── 总计 $1,100/月,节省 75%,无排队

💡 混合策略是大多数生产系统的最优解——自部署覆盖日常基线,API 弹性应对峰值。既控制成本(节省 70%+),又保证了服务质量(零排队)。

第 9 章核心知识回顾:

概念一句话解释
性价比最高AutoDL / vast.ai 租用 ~$200/月
盈亏点GPT-4o 替代:日均 >222 次自部署划算
混合策略自部署兜底 + API 溢出,节省 70%+

附录

A. 推理框架选型决策表

你的场景推荐框架推荐模型推荐量化
个人开发 / 体验OllamaQwen2.5:14bGGUF Q4_K_M
小团队内部工具vLLMQwen2.5-14B-AWQAWQ INT4
B 端 SaaS 产品vLLMQwen2.5-32B-AWQAWQ INT4
代码辅助工具vLLMDeepSeek-Coder-V2AWQ INT4
合规场景(金融/医疗)vLLM / TGIQwen2.5-72BFP16 / INT8
最大规模 to CvLLM + API 混合72B + GPT-4oAWQ + API

B. GPU 显存需求速查表

模型FP16INT8INT4推荐 GPU(INT4)
7B14 GB7 GB4 GBRTX 4060 (8G)
14B28 GB14 GB8 GBRTX 4090 (24G)
32B64 GB32 GB18 GBRTX 4090 / A10
72B144 GB72 GB40 GBA100 80G
405B810 GB405 GB220 GB8×A100 / 4×H100

C. 常见问题与排错指南

问题原因解决方案
OOM: CUDA out of memory显存不足降低 --gpu-memory-utilization 或用更小模型
模型加载超级慢磁盘 IO 瓶颈模型放 NVMe SSD
首 Token 延迟很长Prefill 阶段计算量大减少 --max-input-tokens
吞吐量上不去未开启 Continuous Batching升级到 vLLM(自动开启)
输出乱码量化损失或 tokenizer 不匹配换更高精度量化(Q5/Q6)
GPU 利用率低请求不够多增大 --max-num-seqs
CUDA 版本不兼容驱动/CUDA/PyTorch 版本冲突用 Docker(预装所有依赖)

坚持是一种品格