# 如何在macOS上设置本地编码代理

- 来源：Hacker News 热门（buzzing.cc 中文翻译）
- 作者：kkm
- 发布时间：2026-06-13 04:18
- AIHOT 分数：70
- AIHOT 标记：精选
- AIHOT 链接：https://aihot.virxact.com/items/cmqbegjf700snslamrczkovyv
- 原文链接：https://ikyle.me/blog/2026/how-to-setup-a-local-coding-agent-on-macos

## 精选理由

这篇文章不是泛泛的「本地跑大模型」，而是给 Mac 开发者一个实测过的、能打的生产环境编码代理方案，尤其 MTP 加速让速度不再鸡肋，可以直接抄作业。

## AI 摘要

来自ikyle.me的教程，指导在macOS上搭建本地编码代理，获Hacker News社区104个点赞。

## 正文

最近我的互联网断了几次，搞得我没法用编码智能体，所以当我看到“Gemma 4 现在通过 MTP 多 Token 预测更新后运行速度快了 2 倍”这个更新时，我决定尝试让它跑起来。

我想要一个本地编码智能体方案，它需要：

足够快，能在我的 Mac 上实际使用

通过兼容 OpenAI 的 API 工作（这样我就可以在其他工具里用它）

最好还能在需要时处理截图/图片，这样我可以把智能体生成的截图喂给它。

而且我做到了！这个视频是实时的。它展示出智能体以完全可用的速度在响应。

经过一番测试，我最终采用的方案是：

在 macOS 上用 Metal 编译的 llama.cpp

GGUF 格式的 Gemma 4 26B-A4B

用于投机解码的 Q8 MTP 草稿模型

Gemma 4 多模态投影器

Pi 作为终端编码智能体

这是在配备 64 GB 统一内存的 Apple M1 Max 上测试的，运行 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。

基准测试的提示词是：

Write a compact Python function that parses a unified diff and returns the changed file paths. Then explain two edge cases.

每次基准测试生成大约 128 个 token。

基线：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 token/秒不算快，但可用；不过对于编码智能体工作来说，你希望它尽可能快，尤其是当智能体需要多次调用工具时。

添加 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 个草稿 token，速度为 69.2 token/秒。不过，Unsloth 的《如何运行 MTP 模型》指南中包含了这条注释：

“我们发现 --spec-draft-n-max 2 是最好的起点，但不要假定 2 是最优值，因为性能取决于硬件。尝试 1 到 6 之间的任意值，使用对您的系统最快的那个。”

在遍历 --spec-draft-n-max 后，最佳结果是 3 个草稿 token 下达到 72.2 token/秒。

设置 提示词 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 上运行模型哪种方式更快：llama.cpp 还是 mlx。

运行时 模型 生成速度（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

我原本以为（针对 Mac 优化的）MLX 会最快。然而，在这个特定配置下，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/llama.cpp repos/llama.cpp

cd repos/llama.cpp
cmake -B build \
-DCMAKE_BUILD_TYPE=Release \
-DGGML_METAL=ON \
-DGGML_ACCELERATE=ON

cmake --build build --config Release -j

我测试的构建版本包含：

GGML_METAL=ON
GGML_ACCELERATE=ON
GGML_BLAS=ON
GGML_BLAS_VENDOR=Apple

下载模型文件

创建一个 Python 环境：

cd ~/Developer/ML-Models/Gemma4
python3.11 -m venv .venv
source .venv/bin/activate
pip install -U huggingface_hub hf_xet

下载文件：

mkdir -p models/unsloth-gemma-4-26B-A4B-it-GGUF

huggingface-cli download unsloth/gemma-4-26B-A4B-it-GGUF \
gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf \
mmproj-BF16.gguf \
MTP/gemma-4-26B-A4B-it-Q8_0-MTP.gguf \
--local-dir models/unsloth-gemma-4-26B-A4B-it-GGUF

最终会得到：

models/unsloth-gemma-4-26B-A4B-it-GGUF/
gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf
mmproj-BF16.gguf
MTP/gemma-4-26B-A4B-it-Q8_0-MTP.gguf

启动本地服务器

这是最终的服务器启动命令：

repos/llama.cpp/build/bin/llama-server \
-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 \
--mmproj models/unsloth-gemma-4-26B-A4B-it-GGUF/mmproj-BF16.gguf \
--spec-type draft-mtp \
--spec-draft-n-max 3 \
-ngl 999 \
-fa on \
-c 65536 \
--parallel 1 \
--host 127.0.0.1 \
--port 8080

OpenAI 兼容的端点地址是：

http://127.0.0.1:8080/v1

我写了一个小的 start_server.sh 包装脚本，这样它可以在 tmux 中运行：

#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SESSION_NAME="${SESSION_NAME:-gemma4-server}"
HOST="${HOST:-127.0.0.1}"
PORT="${PORT:-8080}"
CTX_SIZE="${CTX_SIZE:-65536}"
PARALLEL="${PARALLEL:-1}"

LLAMA_SERVER="$ROOT_DIR/repos/llama.cpp/build/bin/llama-server"
MODEL="$ROOT_DIR/models/unsloth-gemma-4-26B-A4B-it-GGUF/gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf"
DRAFT_MODEL="$ROOT_DIR/models/unsloth-gemma-4-26B-A4B-it-GGUF/MTP/gemma-4-26B-A4B-it-Q8_0-MTP.gguf"
MMPROJ="$ROOT_DIR/models/unsloth-gemma-4-26B-A4B-it-GGUF/mmproj-BF16.gguf"
LOG_FILE="$ROOT_DIR/logs/llama-server-mtp.log"

mkdir -p "$ROOT_DIR/logs"

tmux new-session -d -s "$SESSION_NAME" -c "$ROOT_DIR" \
"$LLAMA_SERVER \
-m '$MODEL' \
--model-draft '$DRAFT_MODEL' \
--mmproj '$MMPROJ' \
--spec-type draft-mtp \
--spec-draft-n-max 3 \
-ngl 999 \
-fa on \
-c '$CTX_SIZE' \
--parallel '$PARALLEL' \
--host '$HOST' \
--port '$PORT' \
2>&1 | tee -a '$LOG_FILE'"

启动它：

chmod +x start_server.sh
./start_server.sh

检查服务器是否在运行：

curl http://127.0.0.1:8080/v1/models

配置 Pi

Pi 从以下位置读取模型提供商：

~/.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",
"reasoning": false,
"input": ["text", "image"],
"contextWindow": 65536,
"maxTokens": 8192,
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
}
}
]
}
}
}

关键部分如下：

baseUrl 指向 llama.cpp 的 OpenAI 兼容服务器。

api 设置为 openai-completions。

authHeader 为 false，因为这是本地服务器。

input 同时包含 text 和 image，否则 Pi 会将其当作纯文本处理。

可选地将其设为默认提供商，在：

~/.pi/agent/settings.json

{
"defaultProvider": "gemma4-local",
"defaultModel": "gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf",
"defaultThinkingLevel": "minimal"
}

然后检查 Pi 能否看到它：

pi --offline --list-models gemma

预期输出：

provider model context max-out thinking images
gemma4-local gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf 65.5K 8.2K no yes

使用本地模型运行 Pi：

pi --provider gemma4-local --model gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf

或者使用非交互模式：

pi -p --provider gemma4-local --model gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf \
"Explain what this repository does"

用于截图：

pi -p @"/path/to/screenshot.png" "Describe this image and point out anything relevant to the UI"

最终配置

最终的本地编程智能体技术栈为：

层 选择

推理运行时 llama.cpp

macOS 加速 Metal + Accelerate

主模型 gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf

草稿模型 gemma-4-26B-A4B-it-Q8_0-MTP.gguf

MTP 参数设置 --spec-draft-n-max 3

多模态投影器 mmproj-BF16.gguf

服务器 运行在 127.0.0.1:8080 上的 llama-server

API OpenAI 兼容的 /v1

编程智能体 Pi

Pi 模型输入 ["text", "image"]

主要结论是 MTP 草稿模型值得使用。在这台机器上，它将 Gemma 4 的推理速度从 58.2 tokens/秒提升到了 72.2 tokens/秒，同时保持了足够简单的配置，可以作为本地 OpenAI 兼容服务器运行。

附言：有人建议使用 Qwen3.6 35B-A3B 而不是 Gemma 4 26B-A4B。根据我能找到的基准测试，Qwen 作为编程智能体的表现远优于 Gemma 4。不过 Qwen 也更慢：Qwen3.6-35B-A3B-UD-Q4_K_XL.gguf + unsloth-Qwen3.6-35B-A3B-MTP-GGUF + mmproj-BF16.gguf 的速度是 55 tk/s，而不是 72 tk/s。当你坐在那里等待时，这个差距相当明显。

下载模型：

mkdir -p models/unsloth-Qwen3.6-35B-A3B-MTP-GGUF

huggingface-cli download unsloth/Qwen3.6-35B-A3B-MTP-GGUF \
Qwen3.6-35B-A3B-UD-Q4_K_XL.gguf \
mmproj-BF16.gguf \
--local-dir models/unsloth-Qwen3.6-35B-A3B-MTP-GGUF

启动服务器：

LLAMA_SERVER=/Users/kylehowells/Developer/ML-Models/Gemma4/repos/llama.cpp/build/bin/llama-server

$LLAMA_SERVER \
-m models/unsloth-Qwen3.6-35B-A3B-MTP-GGUF/Qwen3.6-35B-A3B-UD-Q4_K_XL.gguf \
--mmproj models/unsloth-Qwen3.6-35B-A3B-MTP-GGUF/mmproj-BF16.gguf \
--spec-type draft-mtp \
--spec-draft-n-max 3 \
-ngl 999 \
-fa on \
-c 65536 \
--parallel 1 \
--host 127.0.0.1 \
--port 8081

Pi 配置：

{
"providers": {
"qwen36-local": {
"name": "Qwen3.6 Local",
"baseUrl": "http://127.0.0.1:8081/v1",
"api": "openai-completions",
"apiKey": "local",
"authHeader": false,
"compat": {
"supportsDeveloperRole": false,
"supportsReasoningEffort": false
},
"models": [
{
"id": "Qwen3.6-35B-A3B-UD-Q4_K_XL.gguf",
"name": "Qwen3.6 35B-A3B Q4 + MTP",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 65536,
"maxTokens": 8192,
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
}
}
]
}
}
}

参考资料：

unsloth.ai/docs/models/qwen3.6

unsloth.ai/docs/models/gemma-4

unsloth.ai/docs/models/mtp

github.com/ggml-org/llama.cpp

github.com/earendil-works/pi

介绍 Gemma 4 12B：一个统一的、免编码器的多模态模型

"MTP 使 Google Gemma 4 运行速度提升约 1.4–2.2 倍，且无精度损失"

unsloth/gemma-4-26B-A4B-it-GGUF

unsloth/Qwen3.6-35B-A3B-MTP-GGUF
