上周家里的网断了几次,我盯着终端里转圈的 Cursor,第一次认真问自己:AI 编程助手为什么非要依赖云端?
这个问题把我推进了一个周末的折腾。结果还行——我在一台 M1 Max 上跑起了 26B 参数的 Gemma 4,生成速度从 58 tok/s 提到了 72 tok/s,支持截图输入,用 Pi 做终端编程代理。整个过程踩了不少坑,也搞清楚了一些之前没深究过的性能细节。
这篇文章是个实战记录。不聊「要不要用 AI 写代码」这种大话题,只讲怎么把一个大模型塞进本地机器里,并且让它快得能用。
为什么选本地模型
理由其实很朴素:
首先是可用性。网络断了,或者 API 限流了,你就完了。Claude Code 上周重置了周限额,Meta 也开始限制 AI 使用量——云端模型的服务质量比很多人以为的更脆弱。
其次是速度。云端 API 的延迟在 200-500ms 之间波动,加上网络往返,交互体验明显不如本地。当你频繁做小修改——改一行代码、写个注释、补全函数名——云端延迟累积起来很折磨人。
第三是成本。不是说 API 贵,而是说你可以用闲置的硬件资源换免费的推理。M1 Max 的 GPU 平时根本用不满,跑模型刚好。
技术栈:llama.cpp + Gemma 4 + MTP + Pi
最终选定的组合是这样的:
| 层级 | 选择 | 为什么 |
|---|---|---|
| 推理运行时 | llama.cpp | Metal 后端优化好,支持 MTP |
| 主模型 | Gemma 4 26B-A4B Q4_K_XL | 26B 参数,实际激活约 4B,推理快 |
| 投机解码 | Q8 MTP draft model | 提升 24% 生成速度 |
| 多模态 | mmproj-BF16.gguf | 支持截图输入 |
| 代理框架 | Pi | 终端原生,配置简单 |
全部跑在本地,通过 OpenAI 兼容 API(http://127.0.0.1:8080/v1)暴露,跟调用云端 API 一样的体验。
MTP 投机解码:24% 提速是怎么来的
这是整个方案里最有意思的部分。
投机解码(Speculative Decoding) 的原理不复杂:用一个小型「草案模型」快速生成几个候选 token,然后主模型一次性验证它们。如果草案猜对了,主模型一次能接受多个 token——理论上,一次前向传播产出 N 个 token,速度最多提升 N 倍。
MTP(Multi-Token Prediction) 是 Gemma 4 特有的变体。它不是一个独立的草案模型,而是主模型的一个额外「预测头」——和主模型共享大部分权重,只在最后几层分叉出来预测后续 token。好处是:
- 不需要额外加载一个完整的草案模型
- 草案质量和主模型高度对齐(共享表示)
- 显存开销极小(Q8 版本只有几百 MB)
实际测试数据:
配置 | 生成速度 (tok/s) | 加速比
----------------------------------|-----------------|-------
Gemma 4 Q4 (基础) | 58.2 | 1.00x
Gemma 4 Q4 + MTP draft (n=2) | 72.0 | 1.24x
Gemma 4 Q4 + MTP draft (n=3) | 72.2 | 1.24x
Gemma 4 Q4 + MTP draft (n=6) | 61.2 | 1.05x
关键发现:--spec-draft-n-max 不是越大越好。M1 Max 上的最优值是 3,设太大反而变慢。为什么?因为草案模型猜错时,主模型需要回退重算——猜得越多,猜错的概率越大,浪费的计算也越多。
这个 24% 的提升不是数字游戏。从 58 到 72 tok/s 意味着 AI 生成响应的时间从 ~3 秒降到 ~2 秒——刚好跨过「可以接受」到「感觉流畅」的阈值。
量化选型:Q4 够不够用
26B 参数的 Gemma 4,Q4_K_XL 量化后是 16GB。加上 MTP draft 和多模态投影器,总共约 17GB。
Q4 听起来很低,但实际编码质量损失不大。A4B(4B 活跃参数)架构本身就是稀疏激活的——大部分参数在推理时不参与计算。所以量化对输出质量的影响比全激活模型小得多。
对于代码生成这种场景,速度和质量的权衡是明确的:你宁愿要一个快 40% 的 Q4 模型,还是一个慢吞吞的 Q8 模型?在交互式编程中,响应速度直接决定了你是否愿意继续用。
如果你显存充裕(64GB+),可以试试 Qwen 3.6 35B-A3B:
- 编码能力比 Gemma 4 强一档
- 但生成速度降到 55 tok/s
- 3B 活跃参数比 Gemma 的 4B 更少
选择其实很简单:够快就用强的,不够快就用快的。
配置 Pi:让本地模型接上终端
Pi 是最近冒出来的一个终端 AI 编程代理,配合本地模型用起来很顺手。
核心配置在 ~/.pi/agent/models.json:
{
"providers": {
"gemma4-local": {
"name": "Gemma 4 Local",
"baseUrl": "http://127.0.0.1:8080/v1",
"api": "openai-completions",
"apiKey": "local",
"authHeader": false,
"compat": {
"supportsDeveloperRole": false,
"supportsReasoningEffort": false
},
"models": [{
"id": "gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf",
"name": "Gemma 4 26B-A4B Q4 + MTP",
"input": ["text", "image"],
"contextWindow": 65536,
"maxTokens": 8192
}]
}
}
}
注意两个坑:
"input": ["text", "image"]——如果不加"image",Pi 会把模型当纯文本处理,截图功能完全失效。这个地方文档不够醒目,我折腾了半天。"authHeader": false——本地模型不需要认证,但有些代理框架默认会带Authorization头,llama.cpp 的 server 会直接拒绝。
启动服务器:
llama-server \
-m gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf \
--model-draft gemma-4-26B-A4B-it-Q8_0-MTP.gguf \
--mmproj mmproj-BF16.gguf \
--spec-type draft-mtp --spec-draft-n-max 3 \
-ngl 999 -fa on -c 65536 \
--host 127.0.0.1 --port 8080
然后 pi --offline --provider gemma4-local,就跟用云端模型一样了。
几个实测数据
做完这套配置后,我跑了一些实际使用场景的对比:
场景 1:写一个解析 unified diff 的函数
- 云端 Claude:~1.5 秒首 token + 流式输出
- 本地 Gemma 4 + MTP:~2 秒首 token + 连续输出
- 体感差异:几乎无感
场景 2:重构一个 200 行的 Python 文件
- 本地模型在逻辑完整性上稍弱,需要多给一轮反馈
- 但因为是本地,你不会心疼 token——随便重试
场景 3:截图 → 描述 UI 布局
- 多模态投影器工作正常,能识别按钮、表单、布局结构
- 代码级别的视觉细节(像素对齐、颜色值)不如 GPT-4o,但够用
MLX vs llama.cpp:意外但清晰的结论
很多人(包括我)直觉上认为:Mac 上的 MLX(Apple 官方优化框架)应该更快——它专门为 Apple Silicon 设计。实际测试打了脸:
运行时 | 生成速度 (tok/s)
------------------------|-----------------
llama.cpp + MTP draft | 72.2
llama.cpp (纯模型) | 58.2
MLX-LM (Unsloth 4-bit) | 45.8
MLX-LM (社区 4-bit) | 43.9
MLX-LM (OptiQ 4-bit) | 38.1
llama.cpp 比最快的 MLX 配置快了 58%。为什么?llama.cpp 是社区驱动的项目,几年迭代下来针对 Metal 的算子优化非常深入——flash attention、KV cache 量化、连续批处理这些优化都是几千个 commit 堆出来的。MLX 作为较新的框架,生态和优化深度暂时还追不上。
这个结果也提醒了一件事:在 AI 推理领域,「官方推荐」不等于「最快」。社区驱动的项目往往因为更残酷的竞争而优化得更狠。
内存管理的几个细节
跑本地模型最怕的就是 OOM(Out of Memory)。几个省显存的技巧:
KV Cache 量化。llama.cpp 支持 KV cache 的 8-bit 甚至 4-bit 量化(--cache-type-k q8_0 --cache-type-v q8_0),对长上下文场景影响明显。65536 的 context window 如果用全精度 KV cache,光缓存就要占十几 GB。
MLock 的取舍。--mlock 会把模型权重锁在内存里防止 swap,代价是启动时强制吃满显存。对于 64GB 的 M1 Max 来说 17GB 完全扛得住,锁上没坏处。但如果你只有 32GB 而且还要跑浏览器和 IDE,建议别锁——让 OS 自己管理 swap 更灵活。
并行度陷阱。--parallel 控制并发请求数。对于单人编程助手场景,设 1 就够了。设高了会让 KV cache 按倍数膨胀,反而拖慢速度。
多模态投影器的惊喜。加载 mmproj 投影器后,文本生成速度从 71.4 tok/s 变成 72.2 tok/s——几乎没影响。这和很多人的直觉相反:多模态能力几乎是「免费」的,没有理由不带上。
我的做法
这套方案我用了快一周,最大的感受不是「省了 API 钱」,而是「AI 变成了一种本地能力」。
以前用云端 API,总觉得 AI 是个外部服务——用的时候调用,不用的时候它不存在。现在本地常驻一个 26B 的模型,空闲时 0 功耗(GPU 自动降频),需要时秒回。这种体验的改变比省几块钱 API 费用重要得多。
我的建议是:如果你有一台 32GB 以上统一内存的 Mac,或者一张 24GB 以上的 NVIDIA 卡,花一个下午搭一套本地编程助手是值得的。不要指望它完全替代云端——它在复杂任务上不如 Opus 或 Fable——但作为「日常 80% 工作量」的处理器,它绰绰有余。
更重要的是,这种本地 AI 能力正在快速普及。Gemma 4 的 MTP 加速、llama.cpp 的 Metal/ROCm 优化、Qwen 系列的开源——每个季度本地推理都在变快变好。六个月后,本地 72 tok/s 的上限可能会翻倍。
一个我自己的 checklist,供参考:
- 选模型时优先看「实际激活参数」而非总参数量——A4B/A3B 架构在这个场景下是真正的优势
- MTP draft n_max 要针对自己的硬件调,不要照搬文档里的建议值
- 本地模型优先 Q4_K_XL 量化——质量损失最小、速度提升最大
- 多模态投影器几乎不影响生成速度,建议带上
- 用 tmux 管理 llama-server,开机自启,省去每次手动启动
浙公网安备 33010602011771号