用 Python 部署本地大模型:Ollama、显存预算与可用接口
本地模型是一个有内存预算、有延迟曲线的进程,不是黑盒。这篇实录讲清决定它能不能撑过一下午的几件事:量化、显存算术、一个 HTTP 接口、降级链,以及上线后该看的数字。
拉模型之前先看懂标签
模型名后缀就是量化等级。q4_K_M 表示主权重 4 bit、敏感张量用 K 分组缩放,实际约每参数 4.5 bit。位数越低显存越省、精度略降,所以从 Q4_K_M 起步,只有自己的评测说不够时才往上换。
params_b = 7
bits_per_weight = 4.5 # Q4_K_M,并不是整 4 bit
weights_gb = params_b * 1e9 * bits_per_weight / 8 / 1024**3
print(round(weights_gb, 2))先算权重,再谈效果
KV 缓存也要算进去
权重只是账单的一半。上下文里每个 token 都要在每一层留一份 key 和 value 向量,8k 上下文往往又是 2 到 4 GB。权重加缓存装不下时,模型会溢到 CPU,吞吐直接掉一个数量级。
def kv_cache_gb(layers, hidden, ctx, bytes_per=2):
# K 和 V 两个张量,默认 fp16
return 2 * layers * hidden * ctx * bytes_per / 1024**3
print(round(kv_cache_gb(32, 4096, 8192), 2))上下文不是免费的
起服务,然后当普通接口调用
ollama serve 在 11434 端口暴露 HTTP 接口。向 /api/generate 发一个 stream 为 false 的阻塞 POST,返回一个 JSON 对象。超时要设得比最慢的一次生成更长——默认那几秒足够把正常回答截断。
import requests
payload = {
"model": "qwen2.5:7b-instruct-q4_K_M",
"prompt": "Say hi in five words.",
"stream": False,
}
resp = requests.post("http://127.0.0.1:11434/api/generate", json=payload, timeout=120)
resp.raise_for_status()
print(resp.json()["response"])一个接口,一个超时
有人在等的时候用流式
stream 为 true 时响应体是逐行 JSON:每行的 response 带一个片段,最后一行的 done 为 true。按行解析、跳过空行、边收边打印,用户不到一秒就能看到字,而不是盯着转圈。
import json, requests
with requests.post(url, json=payload, stream=True, timeout=120) as resp:
for line in resp.iter_lines():
if not line:
continue
chunk = json.loads(line)
print(chunk.get("response", ""), end="", flush=True)
if chunk.get("done"):
breakNDJSON,一行一个片段
降级到小模型,而不是抛 500
笔记本上显存溢出、守护进程报 500 都是常态。准备一条有序的模型链,逐级回退,并把「最后是谁答的」记下来,日志才能在以后解释质量为什么掉了。答得慢总好过抛栈。
MODELS = ["qwen2.5:7b-instruct-q4_K_M", "qwen2.5:3b-instruct-q4_K_M"]
def generate(prompt):
for name in MODELS:
try:
return name, call(name, prompt)
except (TimeoutError, RuntimeError):
continue
raise RuntimeError("all local models failed")可记录的降级链
盯首字延迟、吞吐与失败率
首字延迟是用户的体感,每秒 token 数是硬件的产出。两个都记,再按模型记失败率;告警看中位数而不是平均数,否则一个 30 秒的离群值就能半夜叫人。
import statistics
first_token_ms = [820, 910, 780, 2400, 860]
print(round(statistics.median(first_token_ms)), max(first_token_ms))看中位数,不看平均数
你的练习清单
- 拉模型之前就写明标签与量化等级。
- 权重加 KV 缓存装得进显存,并且留有余量。
- 接口显式设了超时,比最慢的一次回答更长。
- 流式输出按行解析,能容忍空行与半行。
- 大模型显存不足时有小模型接管。
- 首字延迟、每秒 token 数与失败率都有记录。
常见问题
7B 模型 Q4 要多少显存?
权重约 4 GB,上下文缓存按长度再加 1 到 4 GB。8 GB 卡比较从容;6 GB 要缩短上下文。
只有 CPU 能跑吗?
能,每秒几个 token。跑通宵批处理没问题,对话体验会很差。
用 Ollama 还是直接用 llama.cpp?
要模型管理和稳定 HTTP 接口就用 Ollama;要调采样参数或跑特殊硬件再上 llama.cpp。
本地模型和云上模型怎么选?
数据不能出内网、或量大且质量够用,选本地;要最强推理或弹性扩容,选云上。
练一练模型监控
覆盖漂移、延迟、小样本评估与决策阈值的题目。
继续阅读: