本地模型:llama.cpp 与离线运行
本教程共 30 篇 · 第 23 篇 · 更新于 2026-08-10 · 约 14 分钟阅读
本节目标:理解为什么有时候宁愿用慢一点的本地模型;学会在 pi 中配置 llama.cpp、下载和加载模型、在本地和云端模型间自由切换——同时清醒认识本地模型的真实能力边界。
前面所有章节都假设你有网络、有 API Key、在调用云端模型。但现实并不总是这样。你可能在飞机上、在公司内网、处理敏感代码、或者只是不想付 API 账单。
pi 内置了对 llama.cpp 的支持——一个高性能的本地 LLM 推理引擎。这一章就讲怎么把大模型跑在你自己的硬件上。
本章基于 pi v0.84.1。
为什么要折腾本地模型
云端模型(像 Claude Sonnet、GPT-4o)确实强。但在某些场景下,本地模型是不可替代的:
隐私:代码留在你的机器上,不经过任何第三方服务器。如果你在开发涉及商业秘密、医疗数据或未公开算法的项目,这一点足以让你选择本地模型。
离线:飞机上、高铁过隧道时、公司内网没开外网许可——这些情况下云端模型直接罢工,本地模型照常工作。
成本:API 按 token 计费。如果你一天问 pi 几百个问题、跑大量工具调用,月底账单可能让你倒吸一口凉气。本地模型跑起来只用交电费。当然你也得先有一块能跑得动的显卡。
延迟:网络往返一次 100-500ms。本地推理没有网络延迟,响应体感更干脆。
但代价也是实实在在的——本地模型的能力、速度和上下文长度都明显弱于顶级云端模型。这不是”差距正在缩小”的问题,是真实存在的差距。后面会展开讲。
llama.cpp 是什么
llama.cpp 是一个 C++ 写的高性能 LLM 推理引擎,核心卖点是在消费级硬件上跑大模型。
它主要通过量化技术实现这一点——把模型权重从 16 位浮点数(FP16)压缩到 4 位甚至 2 位整数,大幅降低内存需求。一个 7B 参数的模型,FP16 需要约 14GB 显存,Q4 量化后只需要约 4GB——刚好能塞进一块普通游戏显卡。
llama.cpp 支持多种后端:
| 后端 | 适用硬件 | 说明 |
|---|---|---|
| CPU | 任何 x86/ARM | 纯 CPU 推理,速度慢但不需要显卡 |
| CUDA | NVIDIA GPU | 大部分人的选择 |
| Metal | Apple Silicon (M1/M2/M3) | Mac 用户的最佳路径 |
| Vulkan | AMD GPU、Intel Arc | 跨平台 GPU 加速 |
pi 和 llama.cpp 的通信方式是通过 llama.cpp 的路由服务器(router server)。这个服务器管理多个 GGUF 模型文件,按需加载/卸载模型,pi 通过 OpenAI 兼容的 HTTP API 调用它。
Note路由服务器模式和单模型模式是两回事。启动时不传
--model或-m参数就是路由模式,传了就是单模型模式。pi 需要路由模式来动态管理多个模型。
第一步:安装并启动 llama.cpp 服务器
安装 llama.cpp
去 llama.cpp Releases 下载对应平台的预编译包,或者从源码编译。macOS 用户可以直接:
brew install llama.cpp
准备模型目录
创建一个目录专门放 GGUF 模型文件:
mkdir -p ~/models
模型文件的结构是这样的:
~/models/
├── qwen2.5-coder-7b-q4_k_m.gguf # 单文件模型
├── gemma-3-4b-it-Q4_K_M/ # 多模态模型放子目录
│ ├── gemma-3-4b-it-Q4_K_M.gguf
│ └── mmproj-F16.gguf
└── deepseek-coder-33b-Q4_K_M/ # 分片模型也放子目录
├── deepseek-coder-33b-Q4_K_M-00001-of-00003.gguf
├── deepseek-coder-33b-Q4_K_M-00002-of-00003.gguf
└── deepseek-coder-33b-Q4_K_M-00003-of-00003.gguf
要点:单文件 GGUF 直接放 ~/models/,多模态和分片模型各放在自己的子目录里。
启动路由服务器
llama-server \
--models-dir ~/models \
--no-models-autoload \
--jinja \
--host 127.0.0.1 \
--port 8080 \
-ngl 999 \
-c 32768
参数逐个解释:
--models-dir ~/models:告诉服务器去哪找 GGUF 文件--no-models-autoload:不让服务器自动加载所有模型——你的内存和显存放不下。手动控制谁上场--jinja:启用兼容的对话模板,这对工具调用(tool calling)至关重要--host 127.0.0.1:只监听本地,不暴露给网络--port 8080:服务端口-ngl 999:尽可能把模型层放到 GPU。999 是”全部”的意思——实际有上限的层都能被 offload-c 32768:上下文窗口大小。不设的话会用模型的默认值,可能非常大,吃掉大量内存
Note
-c 32768是给 32K 上下文窗口用的。如果你的模型原生支持 128K 但你内存不够,用-c限制它能救你一命。反之,如果模型只有 8K 上下文,设到 32768 也没意义——llama.cpp 会以实际模型能力为准。
如果服务器加了 API Key 保护(--api-key),起 pi 前设好环境变量:
export LLAMA_API_KEY=your-key
服务器跑起来后,验证一下:
curl http://127.0.0.1:8080/health
curl http://127.0.0.1:8080/models
两个都返回正常结果,说明服务器就绪。
第二步:在 pi 里配置 llama.cpp
登录提供商
在 pi 交互模式下:
/login llama.cpp
输入路由服务器地址(默认 http://127.0.0.1:8080),如果服务器有 API Key 也一起填。
或者直接用环境变量跳过这一步:
export LLAMA_BASE_URL=http://127.0.0.1:8080
export LLAMA_API_KEY=***
pi
pi 启动后自动识别这些环境变量,不需要手动 /login。
管理模型
pi 提供了 /llama 指令面板来管理本地模型:
/llama
打开后会看到:
- 当前路由服务器上已发现的模型列表
- 哪些已加载(loaded)、哪些未加载(unloaded)
- 选择未加载的模型来加载它,选择已加载的来卸载
- 还有一项 Download model…,可以直接搜 Hugging Face 下载模型
下载模型很有意思——你在 pi 里搜索 Hugging Face 仓库名,选一个量化版本(比如 Q4_K_M),pi 会通知 llama.cpp 服务器执行下载。下载过程中可以按 Escape 取消。
TipHugging Face 的搜索默认不需要登录,但限流较严。设了
HF_TOKEN环境变量可以提升速率限制,也能下载需要登录才能访问的门控仓库。
切换到本地模型
模型加载后,用 /model 或 Ctrl+L 打开模型选择器。已加载的本地模型会出现在列表里,选中即切换。
如果加载新模型时显存不够,pi 会问你:先卸载当前已加载的模型,还是保持两个都加载。pi 不会悄悄卸载模型,也不会删你的模型文件。
硬件要求和模型选择
本地模型要跑得动,硬件是硬门槛。
显存/内存估算
一个简单的口诀:参数量 × 量化等级 = 大约需要的显存。
比如 7B 参数的模型:
| 量化等级 | 每参数位数 | 7B 大约需要 | 14B 大约需要 |
|---|---|---|---|
| Q2_K | ~2.5 bit | ~3 GB | ~5 GB |
| Q4_K_M | ~4.5 bit | ~4 GB | ~8 GB |
| Q5_K_M | ~5.5 bit | ~5 GB | ~10 GB |
| Q8_0 | ~8.5 bit | ~8 GB | ~15 GB |
| F16 | 16 bit | ~14 GB | ~28 GB |
这只是模型权重。实际运行还有 KV 缓存(上下文越长越大)、操作系统开销——在估算值基础上再加 2-4 GB 比较安全。
适合编码的开源模型
| 模型 | 参数量 | 最低需求 | 编码能力评价 |
|---|---|---|---|
| Qwen 2.5 Coder | 7B / 14B / 32B | 4-8 GB / 8-16 GB / 16-32 GB | 开源编码模型的顶流,多语言支持好 |
| DeepSeek Coder V2 | 16B | 8-16 GB | 复杂编程任务表现不错 |
| CodeLlama | 7B / 13B / 34B | 4-8 GB / 8-16 GB / 18-32 GB | Meta 出品,代码补全场景靠谱 |
| Gemma 3 (Google) | 4B | ~3 GB | 轻量,适合简单问答和代码解释 |
| Mistral | 7B | ~4 GB | 轻量级编码助手,响应快 |
我的建议:如果你有一块 8GB 显存的显卡,从 Qwen 2.5 Coder 7B Q4_K_M 开始。模型小、下载快、配置简单,足以让你感受本地模型的真实体验。满意了再折腾大的。
CPU 推理
没有独显也能跑——纯 CPU 推理。llama.cpp 的 CPU 后端优化很到位,现代 CPU(特别是 Apple Silicon)上的速度不是不能用。
但预期要管理好:7B 模型在 M2 Mac 上用 Metal 加速,每秒能出 20-30 个 token——打字速度级别的流畅。同款模型在 x86 CPU 上可能每秒只有 3-8 个 token,你会看到字一个个蹦出来。
本地模型 vs 云端模型:真实差距
不是泼冷水,但你要有清醒的预期。
能力差距
工具调用:这是最大的差距。Claude 和 GPT-4o 已经有非常成熟的函数调用能力,pi 的 read、write、edit、bash 等工具它们用得很娴熟。大部分开源模型在工具调用上稳定性差得多——有时候格式不对、有时候参数填错、有时候干脆忽略工具。
指令跟随:云端模型基本能做到”你说什么它做什么”。本地模型经常”你说什么它做一半”,或者在长对话中慢慢偏离你的原始意图。
编程能力:简单函数、单文件修改、代码解释——本地模型基本够用。但涉及多文件重构、复杂逻辑推理、跨模块 bug 排查——差距会很明显。
速度差距
云端模型跑在顶配数据中心 GPU 集群上,7B 到 70B+ 参数、大 batch size,一秒几百个 token。你的家用显卡或 CPU,即使 llama.cpp 优化拉满,能跑多少要看硬件。
上下文长度
很多开源模型宣称支持 128K 上下文,但实际在长上下文末尾的表现会明显退化——“看到但看不懂”。而 Claude Sonnet 在 200K 上下文中依然能精确定位信息。
推理能力
大部分开源模型不支持推理模式(reasoning)。你在 pi 里按 Shift+Tab 切换推理等级,本地模型通常只能跑 off 档——它没有”思考过程”这个概念。
什么时候本地模型够用
别被我上面说的吓到。以下场景用本地模型是非常合适的:
- 简单代码问答:“这个函数是干什么的?”
- 单文件小修改:“把这个 for 循环改成 map”
- 离线环境:飞机上、内网里
- 敏感项目:代码不能上传第三方
- 日常快速查询:不值得为一个小问题花 API 费用
Tip推荐的混合策略:日常简单任务用本地模型(省钱、快),复杂任务切回云端模型(能力强)。
Ctrl+P一键切换,不用退出 pi。把这个习惯养起来,你在乎成本和在乎质量之间就有了一个平滑的滑动条。
自定义 llama.cpp 提供商
如果你的 llama.cpp 服务器跑在另一台机器上,或者你有特殊的配置需求,可以通过扩展注册自定义提供商:
pi.registerProvider("llama.cpp", {
name: "我的本地 llama.cpp",
baseUrl: "http://192.168.1.100:8080/v1",
apiKey: "local",
api: "openai-completions",
async refreshModels({ signal }) {
const response = await fetch("http://192.168.1.100:8080/v1/models", { signal });
const { data } = await response.json();
return data.map(({ id }) => ({
id,
name: id,
reasoning: false,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 128000,
maxTokens: 16384,
}));
},
});
refreshModels 是动态模型发现的关键——它实时查询 llama.cpp 服务器当前加载了哪些模型,pi 的 /model 菜单会自动更新。cost 全部设 0 是合理的,本地模型确实不按 token 收费。
排错手册
服务器连不上
curl http://127.0.0.1:8080/health
没反应就是服务器没起来。检查端口、确认没加 --model 参数(加了就是单模型模式,pi 的路由功能用不了)。
/llama 里看不到模型
确认 --models-dir 路径正确、目录里有 GGUF 文件、服务器重启过(加新文件后需要重启才能发现)。
模型加载失败或内存爆了
降 -c 值(上下文窗口),或者先卸载其他已加载模型。llama.cpp 服务器会把模型全部加载到内存/显存,多模型叠加很容易超。
/model 里看不到已加载的模型
加载后要稍微等一下让服务器完成初始化。如果一直不出现,用 /llama 确认加载状态,然后重试 /model。
工具调用不工作
不是你的配置问题。大部分本地模型的工具调用能力本身就弱。确认你用的模型支持 function calling 并且 llama.cpp 服务器开了 --jinja 参数。即便如此,体验和 Claude 比会有落差——这是本地模型的现实,不是 bug。
Note本地模型这条路,硬件到位、预期管理好,体验不会差。但如果你期望本地模型能完全替代 Claude Sonnet 做复杂开发——趁早打消这个念头。把本地模型当”备胎”用,该切云端时果断切,这是目前最务实的策略。
下一章讨论一个更底层的机制:当你的对话越来越长、上下文窗口快要撑爆时,pi 是怎么压缩历史消息的。