如何在 macOS 上设置本地编码代理
如何在 macOS 上设置本地编码代理
使用 llama.cpp 在本地运行 Gemma 4 26B-A4B 和 Qwen3.6 35B-A3B,支持 MTP 投机解码、多模态,并以 PI 作为编码代理(coding agent)。
我最近几次互联网故障让我失去了编码代理,因此当我看到针对 Gemma 4 的 “Gemma 4 现在通过 MTP 运行速度提升 2 倍” 多令牌预测(Multi-Token Prediction, MTP)更新时,我决定尝试让它在本地运行。
我想要一个本地编码代理设置:
- 能在我的 Mac 上足够快地使用
- 通过 OpenAI 兼容的 API 工作(这样我可以在其他工具中使用它)
- 并且最好能在需要时处理屏幕截图/图像,这样我可以将生成内容的截图喂给它。
我做到了!这段视频是实时录制的。展示了代理以完全可用的速度响应。
经过一些测试,我最终确定的设置是:
llama.cpp 在 macOS 上使用 Metal 构建
- Gemma 4 26B-A4B 的 GGUF 格式
- 用于投机解码的 Q8 MTP 草稿模型
- Gemma 4 多模态投影器
- Pi 作为终端编码代理
该测试在 Apple M1 Max 上运行,配备 64 GB 统一内存,系统为 macOS 15.7.7。
模型
主模型:gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf。
Huggingface 链接:models/unsloth-gemma-4-26B-A4B-it-GGUF/gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf
该文件约为 16 GB。加上 MTP 草稿头和多模态投影器后,模型文件夹约为 17 GB。
基准测试提示为:
编写一个紧凑的 Python 函数,用于解析统一差异(unified diff)并返回更改的文件路径。然后解释两个边界情况。
每个基准测试生成约 128 个令牌。
基线:llama.cpp + Metal
首先,我直接通过 llama.cpp 和 Metal 加速运行主模型:
repos/llama.cpp/build/bin/llama-cli \
-m models/unsloth-gemma-4-26B-A4B-it-GGUF/gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf \
-ngl 999 \
-fa on \
-c 4096 \
-n 128
结果:
| 设置 | 提示 tok/s | 生成 tok/s |
|---|---|---|
| Gemma 4 26B-A4B Q4, llama.cpp Metal | 298.0 | 58.2 |
58 tokens/秒并不快,但可用,但对于编码代理工作,你需要尽可能快的速度,尤其是当代理进行多次工具调用时。
添加 MTP 草稿模型
Gemma 4 现在有 MTP 草稿模型可用:
MTP/gemma-4-26B-A4B-it-Q8_0-MTP.gguf
可以通过 llama.cpp 作为投机草稿模型加载:
repos/llama.cpp/build/bin/llama-cli \
-m models/unsloth-gemma-4-26B-A4B-it-GGUF/gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf \
--model-draft models/unsloth-gemma-4-26B-A4B-it-GGUF/MTP/gemma-4-26B-A4B-it-Q8_0-MTP.gguf \
--spec-type draft-mtp \
--spec-draft-n-max 3 \
-ngl 999 \
-fa on \
-c 4096 \
-n 128
首次运行 MTP,使用 4 个草稿令牌时速度为 69.2 tokens/秒。不过,Unsloth 的 如何运行 MTP 模型 指南中包含以下说明:
“我们发现
--spec-draft-n-max 2是很好的起点,但不要假定 2 是最优的,因为性能依赖于硬件。尝试 1 到 6 之间的任何值,并在你的系统上使用最快的一个。”
在遍历 --spec-draft-n-max 后,最佳结果是使用 3 个草稿令牌达到 72.2 tokens/秒。
| 设置 | 提示 tok/s | 生成 tok/s | 加速比 |
|---|---|---|---|
| 仅主模型 | 298.0 | 58.2 | 1.00x |
| 主模型 + Q8 MTP 草稿 | 295.6 | 72.2 | 1.24x |
有用的是,提示处理基本保持不变,而生成速度提升了约 24%。
调优 MTP
我测试了 --spec-draft-n-max 从 1 到 6 的值。
| --spec-draft-n-max | 提示 tok/s | 生成 tok/s |
|---|---|---|
| 1 | 295.5 | 68.4 |
| 2 | 299.1 | 72.0 |
| 3 | 295.6 | 72.2 |
| 4 | 297.3 | 70.7 |
| 5 | 297.9 | 63.7 |
| 6 | 296.3 | 61.2 |
在我的 M1 Max 机器上,3 是最快的,2 也非常接近,两者都可以。更高的值会变慢。
MLX 对比
我还通过 mlx-lm 测试了 MLX 模型,以找出在 Mac 上运行模型的更快方式。
| 运行时 | 模型 | 生成 tok/s |
|---|---|---|
| llama.cpp Metal + MTP | Unsloth GGUF Q4 + Q8 MTP | 72.2 |
| llama.cpp Metal | Unsloth GGUF Q4 | 58.2 |
| MLX-LM | Unsloth UD MLX 4-bit | 45.8 |
| MLX-LM | mlx-community 4-bit | 43.9 |
| MLX-LM | mlx-community OptiQ 4-bit | 38.1 |
我原以为 MLX(为 Mac 优化)会是最快的。然而,对于这个特定设置,llama.cpp 比 MLX 更快,而带 MTP 的 llama.cpp 明显是最佳选择。我想,llama.cpp 长期以来的优化工作使得它尽管跨平台,但在 macOS 上也有很好的表现。
我还尝试过通过 gemma-4-swift-mlx 运行 Gemma 4 MTP,但测试的 26B 4-bit MLX 检查点与加载器的预期权重键不匹配,而且我已经进行了之前的 MLX 测试,所以继续推进,而不是重新下载新模型并尝试调整以匹配。
添加图像支持
对于 Pi,我还希望能够附加截图。我最初为它设置的本地模型条目将该模型声明为纯文本:
"input": ["text"]
这意味着 Pi 没有正确地将图像工具输出发送给模型。
llama.cpp 服务器还需要 Gemma 4 多模态投影器才能让多模态部分工作(只有 12B 是原生多模态):
mmproj-BF16.gguf
当加载了 --mmproj 时,llama.cpp 会宣传多模态支持,而且 Pi 可以发送图像。
我重新运行了文本基准测试,加载了投影器,以检查它是否改变了速度:
| 设置 | 投影器 | 提示 tok/s | 生成 tok/s |
|---|---|---|---|
| llama.cpp Metal + MTP | 无 | 120.3 | 71.4 |
| llama.cpp Metal + MTP | mmproj-BF16.gguf | 297.4 | 72.2 |
最终运行带上投影器后,文本生成速度没有下降。
设置说明
安装 llama.cpp
安装依赖项:
brew install cmake git tmux python@3.11
克隆并构建 llama.cpp:
```
mkdir -p ~/Developer/ML-Models/Gemma4/repos
cd ~/Developer/ML-Models/Gemma4
git clone https://github.com/ggml-org/ll