本篇文章更新時間:2026/06/14
如有資訊過時或語誤之處,歡迎使用 Contact 功能通知或向一介資男的 LINE 社群反應。
如果本站內容對你有幫助,歡迎贊助支持 。
內容目錄
前言:當網路斷了,你的 Coding Agent 還在嗎?
現代開發者越來越依賴 AI Coding Agent — Claude Code、Cursor、Kiro、Copilot。但這些工具有一個共同的致命弱點:它們全部依賴網路。
網路斷了、API 額度用完了、飛機上想寫 code、或者你單純不想把私人專案的程式碼送到別人的伺服器 — 這些情境都會讓你的 AI 助手瞬間消失。
這篇文章記錄的是:如何在你的 Mac 上建立一個完全離線、速度可用、免費的 AI Coding Agent。不是玩具等級的「跑個模型回答問題」,而是一個真的能讀寫檔案、執行命令、處理多檔案任務的完整 coding agent。
最終成果:在 Apple M5 Pro 64GB 上,達到 84.9 tokens/sec 的生成速度,搭配一個支援工具呼叫、截圖輸入、128K context 的本地 coding agent。
技術堆疊總覽
| 層級 | 選擇 | 角色 |
|---|---|---|
| 推論引擎 | llama.cpp | 在 Mac 上跑 GGUF 模型,提供 OpenAI 相容 API |
| 硬體加速 | Metal + Accelerate | Apple GPU + 矩陣運算加速 |
| 主模型 | Qwen3.6-35B-A3B (Q5_K_XL) | 35B 參數 MoE,每次只啟用 3B,coding 能力極強 |
| 加速技術 | MTP (Multi-Token Prediction) | 模型內建的投機解碼,加速 1.3-1.7x |
| 多模態 | mmproj-BF16.gguf | 支援圖片/截圖輸入 |
| Coding Agent | Pi | 終端機 coding agent,支援工具呼叫、檔案讀寫 |
為什麼選 Qwen3.6 而不是 Gemma 4?
2026 年中,能在 Mac 上本地跑的 coding-capable 模型主要有兩個選擇:Google 的 Gemma 4 26B-A4B 和阿里巴巴的 Qwen3.6 35B-A3B。兩者都是 Mixture-of-Experts 架構,都能在 64GB Mac 上順跑。
但 coding 能力差距巨大:
| Benchmark | Qwen3.6 35B-A3B | Gemma 4 26B-A4B |
|---|---|---|
| SWE-bench Verified(真實 GitHub issue) | 73.4% | 17.4%* |
| SWE-bench Multilingual | 78.9% | 74.3% |
| 每次推論啟用參數 | 3B | 4B |
* Gemma 4 26B-A4B 在 SWE-bench Verified 上僅 17.4%,而同系列 dense 架構的 Gemma 4 31B 為 52.0%。數據來源為 Qwen 官方 benchmark。
Qwen3.6 在真實軟體工程任務上碾壓 Gemma 4。啟用的參數還更少,理論上推論更快。唯一的缺點是:因為總參數量較大(35B vs 26B),模型檔案稍大,在記憶體頻寬受限的情境下會稍慢一些。
Gemma 4 的優勢在哪?速度。在同一台 M1 Max 上,Gemma 4 搭配 MTP 可以跑到 72 tok/s,而 Qwen3.6 是 55 tok/s。如果你追求極致回應速度且 coding 品質要求不那麼高,Gemma 4 是合理的選擇。但如果你要的是一個真正能解決問題的 coding agent,Qwen3.6 是目前的最佳本地選擇。
為什麼用 llama.cpp 而不是 MLX?
這個問題在 2026 年中的答案比你想像的複雜。簡單版:因為 MTP 加速在 llama.cpp 上最成熟穩定,且 llama-server 原生提供 coding agent 需要的 OpenAI 相容 API。但完整的技術脈絡值得講清楚。
先講結論不對的部分:MLX 不慢
Apple 的 MLX 框架在 Apple Silicon 上的基礎推論速度其實比 llama.cpp 快。多份獨立測試都證實了這點:
- vllm-mlx 論文顯示 MLX 在文字模型上比 llama.cpp 快 21-87%
- Codersera 2026 對比中,Mac mini M4 Pro 跑 Qwen3-Coder-30B-A3B(MoE 模型),MLX 達 ~130 tok/s,raw llama.cpp Metal 約 ~89 tok/s
- Ollama 自 0.19 版(2026 年 3 月)起,在 Apple Silicon 上已改用 MLX 作為底層引擎,decode 速度從 58 提升到 112 tok/s(93% 加速)
MLX 是 Apple 專為自家晶片設計的機器學習框架,在 Apple Silicon 上的推論速度優於 llama.cpp 的 Metal 後端。具體原因可參考 vllm-mlx 論文的分析。
那為什麼不用 MLX?三個具體原因
1. MTP 支援成熟度
MTP 是這套方案的速度關鍵(後面會詳細解釋)。到 2026 年 6 月的狀態是:
- llama.cpp:MTP 支援穩定,
--spec-type draft-mtp直接讀取 GGUF 內建的 MTP heads,無需額外設定。社群已有大量實測數據和最佳化參數。 - MLX:
mlx-lm 0.21(2026 年 5 月)加入了 speculative decoding 支援,mlx-community/Qwen3.6-35B-A3B-MTP-4bit也已上架 HuggingFace。但相較 llama.cpp 的 MTP 實作,這是較新的功能,可參考的實測數據和設定範例明顯較少。
一份 Kyle Howells 的實測(M1 Max 64GB, Gemma 4 26B-A4B)顯示,llama.cpp + MTP 達到 72.2 tok/s,而同期的 MLX(無 MTP)僅 43-46 tok/s:
| Runtime | 生成速度 (tok/s) | 備註 |
|---|---|---|
| llama.cpp + MTP | 72.2 | MTP 接受率帶來 1.24x 加速 |
| llama.cpp(無 MTP) | 58.2 | 純 Metal 推論 |
| MLX (Unsloth UD 4-bit) | 45.8 | 無 MTP |
| MLX (mlx-community 4-bit) | 43.9 | 無 MTP |
注意這個對比的前提:MLX 端沒有啟用 MTP。如果 MLX 也啟用 MTP,理論上應該比 llama.cpp + MTP 更快(因為 MLX 的基礎速度更高)。但在撰文時,MLX + MTP + Qwen3.6 這個具體組合尚未有可靠的第三方 benchmark 數據佐證其穩定性。
2. Serving 架構
Coding agent 需要一個 OpenAI 相容的 HTTP API endpoint。llama.cpp 的 llama-server 原生提供 /v1/chat/completions,支援 function calling、multimodal(圖片輸入)、streaming — 這些都是 Pi 等 agent 工具的硬需求。
MLX 端的 mlx_lm.server 也有 OpenAI 相容 API,但在工具呼叫格式(tool_choice、parallel tool calls)和多模態(mmproj 載入方式)上,與 llama-server 的成熟度仍有差距。Kyle Howells 的教學和 HuggingFace 上的 Pi 整合範例(如 DuoNeural)均使用 llama-server 作為 Pi 的後端。
3. GGUF 生態系的量化選擇
GGUF 格式提供從 Q2 到 Q8 的完整量化光譜,Unsloth 的 UD 動態量化更能精細地對每層 tensor 分配位元數。MLX 格式的量化選項較少(常見為 3-bit、4-bit、8-bit),且不支援 Unsloth UD 這種 per-tensor 動態位元分配。Q5_K_XL 這種介於 Q4 和 Q6 之間的「甜蜜點」量化,目前僅存在於 GGUF 生態系。
對 64 GB Mac 來說,Q5_K_XL 是最佳平衡點。這個量化等級只在 GGUF 生態系中有。
什麼時候該改用 MLX?
這個技術決策不是永恆的。以下情況出現時,值得重新評估:
- MLX + MTP + Qwen3.6 組合有穩定的第三方 benchmark 證實其速度和穩定性
mlx_lm.server的 tool calling 和 multimodal 支援追上 llama-server- Pi 或你使用的 coding agent 原生支援 MLX serving
- 你需要在同一台 Mac 上做 LoRA 微調(MLX 的訓練工具鏈遠勝 llama.cpp)
技術選擇的核心原則:選穩定可用的方案,而不是理論最快的方案。 2026 年中,llama.cpp + MTP 是 coding agent 場景下經過最多實戰驗證的路線。
量化等級怎麼選?
什麼是量化?
原始模型用 16-bit 浮點數儲存權重,一個 35B 參數的模型需要約 70GB。量化是把精度降低(例如 4-bit、5-bit),用更少的空間存放模型,換取可以在消費級硬體上跑。
Unsloth 的 UD(Unsloth Dynamic)量化特別之處在於:它不是全部用同一個精度,而是對每層的每個 tensor 分析重要度,動態分配不同的位元數。重要的 tensor 保留高精度,不重要的壓更低。這讓同樣的檔案大小能保留更多品質。
選擇建議
| 量化等級 | 檔案大小 | 適合硬體 | 品質 |
|---|---|---|---|
| Q4_K_XL | ~21 GB | 24 GB VRAM / 32 GB Mac | 日常夠用 |
| Q5_K_XL | ~25 GB | 64 GB Mac(推薦) | 品質甜蜜點 |
| Q6_K_XL | ~33 GB | 64 GB+ Mac | 接近無損但速度降 |
| Q8_K_XL | ~39 GB | 雙 GPU / 96 GB Mac | 近乎無損 |
如果你有 64 GB 統一記憶體,Q5_K_XL 是最佳選擇。比 Q4 在長推理鏈和複雜程式碼生成上更穩定,但只多佔 4 GB。Q6 以上的品質提升在 coding 任務中已不明顯,卻要付出更多的速度代價。
MTP 是什麼?為什麼重要?
傳統的語言模型生成是「一次一個 token」— 生成一個、確認一個、再生成下一個。瓶頸不在計算,而在記憶體頻寬:每生成一個 token 都要把整個模型的權重從記憶體讀一遍。
MTP(Multi-Token Prediction)的做法是:在模型中額外訓練幾個小型「draft head」(草稿頭),它們會在主模型生成一個 token 的同時,預測接下來的 2-3 個 token。然後主模型驗證這些預測是否正確 — 正確的直接接受,不正確的從第一個錯誤處重新生成。
因為驗證比生成快(可以平行化),只要預測的接受率夠高,就能顯著加速。在我們的實測中:
- 接受率:72.1%(每 366 個 draft token,264 個被接受)
- 實際加速:依硬體而異,第三方測試報告 1.24x(Gemma 4, M1 Max)至 1.49x(Qwen3.6, A100)。我們的 M5 Pro 實測 84.9 tok/s,相較無 MTP 的預估基線約有 30-50% 提升。
而且 MTP 不影響輸出品質 — 被接受的 token 和主模型自己生成的完全一致。
Context Window 與記憶體的關係
Context window 決定模型一次能「看到」多少文字。對 coding agent 來說,這包括:系統提示詞 + 對話歷史 + 程式碼檔案內容 + 工具呼叫結果。
更大的 context 需要更多的 KV cache(Key-Value cache)記憶體。不過 Qwen3.6 的混合架構讓這個成本出奇地低:
Qwen3.6 的 40 層中,只有 10 層使用傳統的注意力機制(需要 KV cache),其餘 30 層使用 DeltaNet(線性遞歸架構,其 state 大小固定,不隨 context 長度增長)。因此,隨 context 線性增長的 KV cache 記憶體僅來自 10/40 = 1/4 的層。
實測數據(M5 Pro 64GB):
| Context 大小 | KV cache 佔用 | Server 總記憶體 | 剩餘給系統 |
|---|---|---|---|
| 65K | ~2.7 GB | ~28 GB | ~36 GB |
| 128K(推薦) | ~5.4 GB | ~30 GB | ~34 GB |
| 262K(模型上限) | ~11 GB | ~36 GB | ~28 GB |
128K context 涵蓋了 99% 的 coding agent 使用情境(大型 repo 上下文、長對話歷史),且在 64 GB Mac 上完全不構成壓力。
完整安裝步驟
前置需求
- Apple Silicon Mac(M1 以上,建議 32 GB 以上統一記憶體)
- macOS 14 以上
- Homebrew 已安裝
- 約 30 GB 磁碟空間
Step 1:安裝依賴
brew install cmake tmux
cmake 用來編譯 llama.cpp,tmux 用來讓伺服器在背景跑。
Step 2:編譯 llama.cpp
mkdir -p ~/Developer/ML-Models/Qwen36/repos
cd ~/Developer/ML-Models/Qwen36
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
關鍵 flag 說明:
DGGML_METAL=ON— 啟用 Apple GPU 加速DGGML_ACCELERATE=ON— 啟用 Apple Accelerate 框架(BLAS 矩陣運算)-j— 平行編譯,用滿所有 CPU 核心
編譯完成後,build/bin/llama-server 就是我們需要的推論伺服器。
Step 3:下載模型
cd ~/Developer/ML-Models/Qwen36
python3 -m venv .venv
source .venv/bin/activate
pip install -U huggingface_hub hf_xet
mkdir -p models/unsloth-Qwen3.6-35B-A3B-MTP-GGUF
hf download unsloth/Qwen3.6-35B-A3B-MTP-GGUF \
Qwen3.6-35B-A3B-UD-Q5_K_XL.gguf \
mmproj-BF16.gguf \
--local-dir models/unsloth-Qwen3.6-35B-A3B-MTP-GGUF
會下載兩個檔案:
Qwen3.6-35B-A3B-UD-Q5_K_XL.gguf(25 GB)— 主模型,內建 MTP headsmmproj-BF16.gguf(861 MB)— 多模態投影器,讓模型能理解圖片
注意: repo 名稱中的 -MTP-GGUF 表示 MTP 已經嫁接在 GGUF 檔案中,不需要額外下載 draft model。
Step 4:建立啟動腳本
建立 ~/Developer/ML-Models/Qwen36/start_server.sh:
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SESSION_NAME="${SESSION_NAME:-qwen36-server}"
HOST="${HOST:-127.0.0.1}"
PORT="${PORT:-8081}"
CTX_SIZE="${CTX_SIZE:-131072}"
PARALLEL="${PARALLEL:-1}"
LLAMA_SERVER="$ROOT_DIR/repos/llama.cpp/build/bin/llama-server"
MODEL="$ROOT_DIR/models/unsloth-Qwen3.6-35B-A3B-MTP-GGUF/Qwen3.6-35B-A3B-UD-Q5_K_XL.gguf"
MMPROJ="$ROOT_DIR/models/unsloth-Qwen3.6-35B-A3B-MTP-GGUF/mmproj-BF16.gguf"
LOG_FILE="$ROOT_DIR/logs/llama-server.log"
mkdir -p "$ROOT_DIR/logs"
if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
echo "Session '$SESSION_NAME' already running. Attach with: tmux attach -t $SESSION_NAME"
exit 0
fi
tmux new-session -d -s "$SESSION_NAME" -c "$ROOT_DIR" \
"$LLAMA_SERVER \
-m '$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'"
echo "Server started in tmux session '$SESSION_NAME'"
echo " Endpoint: http://$HOST:$PORT/v1"
echo " Attach: tmux attach -t $SESSION_NAME"
echo " Stop: tmux kill-session -t $SESSION_NAME"
chmod +x ~/Developer/ML-Models/Qwen36/start_server.sh
關鍵參數說明:
--spec-type draft-mtp— 啟用 MTP 投機解碼(使用 GGUF 內建的 draft heads)--spec-draft-n-max 3— 每步最多預測 3 個 draft token(需要自己 benchmark,2-3 通常最佳)-ngl 999— 把所有模型層放到 GPU(Metal)上-fa on— 啟用 Flash Attention-c 131072— 128K context window--parallel 1— 單一 slot(個人使用不需要多人並行)
Step 5:安裝並設定 Pi Coding Agent
Pi 是一個終端機 coding agent,支援 OpenAI 相容 API、工具呼叫、檔案讀寫和截圖輸入。
npm install -g @earendil-works/pi-coding-agent
建立 ~/.pi/agent/models.json:
{
"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-Q5_K_XL.gguf",
"name": "Qwen3.6 35B-A3B Q5 + MTP",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 131072,
"maxTokens": 8192,
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
}
}
]
}
}
}
重要設定說明:
"input": ["text", "image"]— 告訴 Pi 這個模型支援圖片,否則 Pi 不會傳送截圖"reasoning": true— 啟用 thinking mode,模型會先在<think>區塊推理再回答"authHeader": false— 本地伺服器不需要認證"cost"全設 0 — 本地推論免費
Step 6:驗證
# 啟動伺服器
~/Developer/ML-Models/Qwen36/start_server.sh
# 等待載入完成(約 15 秒)
curl http://127.0.0.1:8081/v1/models
# 確認 Pi 看到本地模型
pi --list-models qwen
# 測試推論
pi -p --provider qwen36-local "Write a Python function to reverse a string"
實測效能
測試環境:Apple M5 Pro, 18 CPU cores, 20 GPU cores, 64 GB 統一記憶體, macOS 26.4
| 指標 | 數據 |
|---|---|
| Token 生成速度 | 84.9 tok/s |
| Prompt 處理速度 | 92.5 tok/s |
| MTP 接受率 | 72.1%(264/366) |
| 模型記憶體佔用 | ~30 GB(含 128K KV cache) |
| 首次載入時間 | ~15 秒 |
84.9 tok/s 意味著每秒輸出約 60-70 個字元,大約半行程式碼。在實際使用中,回應速度與使用雲端 API 的體感差異不大。
對比 Kyle Howells 在 M1 Max 64GB 上的 55 tok/s(同模型 Q4 量化),M5 Pro 的記憶體頻寬提升相當明顯。
日常使用方式
基本工作流程
# 開機後啟動伺服器(只需一次)
~/Developer/ML-Models/Qwen36/start_server.sh
# 進入專案目錄,啟動本地 agent
cd ~/Projects/my-app
pi --provider qwen36-local
模型切換
Pi 支援多個 provider 共存。如果你同時設定了雲端 API,可以隨時切換:
# 用本地 Qwen(離線可用、免費)
pi --provider qwen36-local
# 用雲端 OpenAI(需網路、更強但收費)
pi --provider openai-codex
# 不加 --provider 就用預設
pi
截圖輸入
# 讓 agent 看截圖來調整 UI
pi -p --provider qwen36-local @"~/Desktop/screenshot.png" "這個按鈕的對齊有問題,幫我修正 CSS"
伺服器管理
# 查看伺服器狀態
curl -s http://127.0.0.1:8081/v1/models | head -3
# 查看即時 log
tmux attach -t qwen36-server
# (Ctrl+B, D 脫離)
# 關閉伺服器(釋放記憶體)
tmux kill-session -t qwen36-server
實戰示範:用本地 Agent 修一個 Bug
以下是一個真實的操作紀錄,展示 Pi + 本地 Qwen3.6 如何在完全離線的情況下完成一個開發任務。
情境
你有一個 utils.py,裡面的 parse_csv function 在遇到欄位不齊的 CSV 時會 crash:
def parse_csv(filepath):
results = []
with open(filepath, 'r') as f:
headers = f.readline().strip().split(',')
for line in f:
values = line.strip().split(',')
row = {}
for i in range(len(headers)):
row[headers[i]] = values[i] # IndexError if row is short
results.append(row)
return results
指令
cd ~/Projects/my-app
pi -p --provider qwen36-local \
"Look at utils.py. This parse_csv function crashes when a row has fewer columns than the header. Fix it to handle mismatched row lengths gracefully."
結果
Pi 讀取了檔案、定位了問題(values[i] 在 row 較短時觸發 IndexError)、直接修改了程式碼:
def parse_csv(filepath):
results = []
with open(filepath, 'r') as f:
headers = f.readline().strip().split(',')
for line in f:
values = line.strip().split(',')
row = {}
for i in range(len(headers)):
row[headers[i]] = values[i] if i < len(values) else None
results.append(row)
return results
整個過程約 3 秒完成。Pi 自動讀取檔案、生成修正、寫回磁碟 — 不需要網路,不需要 API key,不產生費用。
這就是本地 coding agent 的核心價值:一個隨時可用、零成本、能直接動你程式碼的 AI 助手。
補充:Gemma 4 的雙模型方案
如果你想同時擁有「快速回應」和「高品質 coding」兩種選擇,可以額外設定 Gemma 4:
# 下載 Gemma 4(額外 17 GB)
mkdir -p ~/Developer/ML-Models/Gemma4/models/unsloth-gemma-4-26B-A4B-it-GGUF
hf 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 ~/Developer/ML-Models/Gemma4/models/unsloth-gemma-4-26B-A4B-it-GGUF
Gemma 4 的 MTP 是獨立檔案(不是嫁接在主模型中),所以啟動時需要額外指定 --model-draft:
llama-server \
-m gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf \
--model-draft MTP/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
然後在 models.json 中加入第二個 provider,用不同的 port 區分。根據任務複雜度選擇:簡單問題用 Gemma 4(快),複雜 coding 用 Qwen3.6(強)。
注意:兩個模型不建議同時跑在同一台 64GB Mac 上(記憶體會不夠)。需要時關掉一個再開另一個。
已知限制
- 品質仍不及頂級雲端模型 — Qwen3.6 35B-A3B 在 SWE-bench 73.4% 很強,但 Claude Opus 4.8 和 GPT-5.5 等閉源模型仍有明顯優勢。本地模型適合中等複雜度的任務。
- 記憶體限制 — 16 GB Mac 只能跑 Q3/Q4 量化且 context 受限。32 GB 是起步,64 GB 最舒適。
- 首次 prompt 較慢 — 如果一次餵入大量 context(例如整個大型檔案),prompt processing 會需要幾秒。後續對話因為有 cache 會快很多。
- 工具呼叫偶有失誤 — 本地模型在複雜的多步驟工具呼叫中,偶爾會格式錯誤。比雲端模型的穩定性稍差。
結語
2026 年中,本地 AI Coding Agent 已經從「堪用」進入「好用」的階段。84.9 tok/s 的速度、128K 的 context、72% 的 MTP 接受率 — 這些數字代表的是一個真正可以日常使用的開發工具,而不只是技術展示。
更重要的是:它完全免費、完全離線、完全在你的控制之下。你的程式碼不會離開你的電腦。
如果你有一台 64 GB 的 Apple Silicon Mac,這套方案值得嘗試。最壞的結果不過是多佔 30 GB 硬碟空間;最好的結果是你多了一個永遠在線、不收費、不斷網的 coding 夥伴。
參考資源
- How to Setup a Local Coding Agent on macOS — Kyle Howells(本文靈感來源)
- llama.cpp — 跨平台 LLM 推論引擎
- Pi — 終端機 coding agent
- unsloth/Qwen3.6-35B-A3B-MTP-GGUF — 模型下載
- Unsloth MTP Guide — MTP 使用指南
- Qwen3.6 官方 Blog
