Skip to content

实操 03 模型本地部署与推理优化

所属:AI 知识图谱实操系列(practice/)。正文的经济账与产业格局见 07 篇 · 算力与硬件底座,本篇解决"我要自部署,用什么工具、需要什么硬件、怎么跑起来"。

速览卡

内容
一句话定位从零把一个开源模型跑在自己机器上(或服务器上),并搞懂量化、显存、并发这些决定"能不能用"的硬约束
核心内容Ollama / vLLM / llama.cpp 选型、显存估算公式、量化实测、API 服务化、并发与 KV Cache、压测方法
前置知识会用命令行;00 篇(知道什么是参数量、量化)
读完能做到根据手头硬件选出正确工具,把 7B~70B 级模型跑起来并对外提供 OpenAI 兼容 API;能估算"我的显存能跑多大模型"
配套正文自部署 vs API 的经济账见 07 篇;何时该自部署的临界点见 01 篇

版本约定:工具版本与模型名均标 [易变],以官方文档为准。本篇讲的是不变的判断方法与操作骨架


一、三大工具选型:一张表定下来

工具定位一句话用它当你……
Ollama个人开发/体验一条命令跑模型,自动管显存在自己电脑上玩、做原型、离线使用
vLLM生产服务高吞吐并发服务,PagedAttention要给多人/多业务提供 API 服务
llama.cpp端侧/极限压缩纯 CPU 也能跑,GGUF 量化格式没有像样显卡、要塞进笔记本/手机/树莓派

决策路径:先问"给谁用"——

自己一个人用? ──▶ Ollama
多人调用 / 要 SLA? ──▶ vLLM(GPU 服务器)
没有 GPU / 端侧设备? ──▶ llama.cpp

三者不互斥:Ollama 底层就是 llama.cpp;原型用 Ollama、上线换 vLLM 是常见路径。


二、显存估算:先算账再下载(最值钱的一节)

下载 30GB 的模型才发现显存只有 24GB——用这个公式提前算:

显存需求 ≈ 参数量 × 每参数字节数(量化) × 1.2 (框架开销)

   FP16: 2 字节 | INT8: 1 字节 | INT4: 0.5 字节

速查表(含 1.2 开销系数,单位 GB):

参数量FP16INT8 (Q8)INT4 (Q4)
1.5B3.61.80.9
7B16.88.44.2
14B33.616.88.4
32B76.838.419.2
70B1688442

再叠加 KV Cache(上下文越多占越多,长上下文场景不可忽略):

KV Cache ≈ 2 × 层数 × KV头数 × 头维度 × 上下文长度 × 精度字节数 × 批大小

不必手算精确值,记住量级:7B 模型 FP16、8K 上下文、单并发,KV Cache 约 1~2GB;上下文翻倍它翻倍,并发数翻倍它翻倍。

例:32B 模型 INT4 ≈ 19.2GB 权重 + 2GB KV Cache ≈ 22GB → 一张 24GB 显卡(RTX 4090 级)勉强可跑。这与 07 篇端侧分析的结论一致:消费级显卡的甜点区是 7B~32B 的 INT4 量化


三、路径 A:Ollama(个人开发首选)

bash
# 1. 安装后(官网下载安装包),一条命令拉起模型
ollama run qwen2.5:7b          # [易变] 模型名以 ollama library 为准

# 2. 就直接能聊了。退出后模型常驻本地
ollama list                    # 查看已下载模型
ollama ps                      # 查看当前加载与显存占用

对外提供 OpenAI 兼容 API

Ollama 自带兼容层,你为云端 API 写的代码几乎零修改迁到本地

python
from openai import OpenAI

client = OpenAI(
    api_key="ollama",                          # 随便填,Ollama 不校验
    base_url="http://localhost:11434/v1",      # 关键:指向本地
)
resp = client.chat.completions.create(
    model="qwen2.5:7b",                        # [易变]
    messages=[{"role": "user", "content": "解释 KV Cache 的作用"}],
    temperature=0,
)
print(resp.choices[0].message.content)

这意味着实操 0102 里的所有代码,把 base_url 一换就能在本地跑——开发/调试不花钱。

常用操作

bash
ollama run qwen2.5:14b --verbose     # 显示每秒 Token 数(TPS),性能基线就看它
ollama rm qwen2.5:7b                 # 删模型释放磁盘

四、路径 B:vLLM(生产服务)

4.1 起服务

bash
pip install vllm

# 单卡启动(以 Qwen 7B 为例 [易变])
vllm serve Qwen/Qwen2.5-7B-Instruct \
  --max-model-len 8192 \        # 限制上下文长度,直接压住 KV Cache 上限
  --gpu-memory-utilization 0.90 # 显存预算占比(留 10% 余量防 OOM)

# 显存不够装 FP16?直接加载官方 GPTQ/AWQ 量化版(模型名以 HF 为准 [易变])
vllm serve Qwen/Qwen2.5-7B-Instruct-AWQ --max-model-len 8192

启动后自动提供 OpenAI 兼容 API(默认 :8000),与 Ollama 同理换 base_url 即用。

4.2 vLLM 为什么快:三个不变的机制

机制解决什么问题一句话原理
PagedAttentionKV Cache 碎片浪费像操作系统分页管理内存一样管理 KV Cache,碎片近乎为零
Continuous Batching请求排队等待整批完成新请求随到随插入当前批,不等下一轮
Prefix Caching相同前缀重复计算相同 system prompt / 少样本前缀只算一次

这就是 07 篇说的"推理优化决定自部署成本"的落地层。同样的卡,vLLM 比裸跑 HuggingFace generate() 吞吐高一个量级

4.3 并发调参直觉

  • --max-num-seqs:最大并发批大小,默认 256,按业务峰值调
  • 显存 OOM → 先降 --max-model-len,再降 --gpu-memory-utilization
  • 吞吐不够 → 优先确认 Prefix Caching 生效(system prompt 是否统一前缀),再考虑加卡

五、量化实测:省显存的钱,付质量的账

5.1 量化档位怎么选

档位体积/显存质量损失适用
FP16 / BF16基准无(训练精度)显存管够的生产环境
INT8 (Q8)½几乎无损显存紧一档、质量敏感
INT4 (Q4_K_M 等)¼轻微(日常任务可感知度低)消费级显卡跑大模型的主流选择
低于 INT4更小明显劣化仅端侧极限压缩,需评测兜底

5.2 量化前后必须自己测(5 分钟的对比实验)

同一批问题跑两遍,人工对比。用一个可脚本化的最小对照:

python
QUESTIONS = [
    "解释什么是温度参数",
    "把这段话翻译成英文:大模型的幻觉无法根除,只能缓解。",
    "9.11 和 9.9 哪个大?",                # 经典陷阱题,量化劣化容易在这暴露
    "写一个二分查找的 Python 实现",
]

def compare(model_a: str, model_b: str, client):
    for q in QUESTIONS:
        print(f"\n=== {q} ===")
        for name in (model_a, model_b):
            r = client.chat.completions.create(
                model=name,
                messages=[{"role": "user", "content": q}],
                temperature=0,
            )
            print(f"--- {name} ---\n{r.choices[0].message.content[:200]}")

正式评测要用评测集而非肉眼——方法见实操 02 第八节05 篇


六、压测:知道你的服务的真实容量

上线前必做。用 vllm bench(vLLM 自带)或任何 HTTP 压测工具,关注三个指标:

指标含义经验参考
TTFT 首 Token 延迟用户按下回车到看到第一个字交互式 < 1s 为佳
TPS 每 Token 生成速度打字机速度单流 > 20 tok/s 体验尚可
吞吐 tokens/s(总)整机的钱花得值不值并发上去后应远大于单流 TPS
bash
# vLLM 自带压测( shareGPT 格式数据集 [易变])
python -m vllm.entrypoints.openai.api_server ...   # 先起服务
python benchmarks/benchmark_serving.py \
  --backend vllm --model Qwen/Qwen2.5-7B-Instruct \
  --num-prompts 100 --request-rate 5               # 100 个请求、每秒 5 个

压测后回答两个问题:目标并发下 TTFT 是否达标?峰值 2 倍时是变慢还是崩?(变慢可接受,崩要加熔断——见 05 篇稳定性设计


七、端侧与 CPU 路径(llama.cpp 速览)

没有 GPU 时的可行路径:

bash
# llama.cpp:GGUF 格式模型,纯 CPU 推理
git clone https://github.com/ggerganov/llama.cpp && cd llama.cpp
cmake -B build && cmake --build build -j

./build/bin/llama-cli -m qwen2.5-7b-q4_k_m.gguf -p "解释 RAG" -n 256

预期管理(对照 07 篇端侧分析):

  • 纯 CPU 跑 7B Q4:普通笔记本约 3~8 tok/s——能用,但不流畅;3B 以下模型 + CPU 才有接近实时的体验
  • Apple Silicon(M 系统一内存):GPU/CPU 共享内存,Ollama 在 Mac 上体验最佳,是个人端侧开发的主战场
  • 小内存设备选 1.5B~3B 级模型,先做单一任务(如摘要、分类),别贪全能力

八、自部署决策复盘(对照正文)

跑完全流程后回看 07 篇经济账的临界点公式,你现在能填上数字了:

自部署月成本 ≈ 显卡折旧/租用 + 电费 + 运维人力
API 月成本    ≈ 实操 01 第六节算出的用量 × 单价

经验判断:个人学习/原型 → API 或 Ollama 免费档足够;日均百万级请求、数据不出域、或需要深度定制(微调+私有化一体)→ 自部署开始划算。两边都搭一遍再决定,成本已经有了量级感。


九、动手任务

  • [ ] 任务 1:用显存公式估算"我的设备最大能跑多大的 INT4 模型",再用 Ollama 实际拉起验证,记录 ollama ps 显示的实际占用与估算的偏差
  • [ ] 任务 2:跑 ollama run--verbose 记录 TPS;换一个更小的模型(7B→3B)对比速度,体会"参数量 vs 速度"的取舍
  • [ ] 任务 3:把实操 02 的 RAG 问答切到本地模型(只改 base_url),对比云端模型与本地 7B 的回答质量差距,写下 3 个可感知的差异点
  • [ ] 任务 4(有 GPU/服务器):vLLM 起 7B AWQ 量化版,benchmark_serving 压出 TTFT/吞吐曲线,找到 TTFT < 1s 的最大并发数
  • [ ] 自检:能不看资料说出——Ollama/vLLM/llama.cpp 各自什么时候用?显存估算公式?为什么 RAG 的 Embedding 也占显存要算进去?TTFT 和吞吐为什么是两个指标?

延伸方向