跳到主要內容
Lab Grimoire
TW EN
請喝咖啡
🔬 AI 研究

一台 Mac 上的本地 LLM,等級約當雲端哪一代?五個模型的實測與踩雷

一個週末,一台 M4 Pro、48GB 記憶體,五個 4-bit 量化的本地模型,八項 benchmark。我想搞清楚:把重複性任務搬離雲端、省 token,離線可用到底要犧牲多少品質?這篇是完整的實測、選型,加上一路踩到的三個 speculative decoding 地雷。

起點:為什麼要把模型搬回本機

用雲端旗艦寫文章、做複雜推理,沒什麼好猶豫的。但真正吃掉帳單的,往往是那些重複、機械、又碰不得隱私的苦力活:結構化 JSON 萃取、命名實體辨識(NER)、分類、敏感資料去識別、文獻初篩。這些任務不需要旗艦的腦力,量大卻持續燒錢,而且個資類資料本來就不該離開本機。

所以方向很明確:一隻高階 + 兩隻小模型併發的離線本地棧,重複性任務全搬回來,只有真正需要腦力的定稿與推理才回雲端。

硬體是一台 M4 Pro、48GB 統一記憶體;推理引擎用 oMLX 掛在本機 :8090。受測的五顆模型(皆為 MLX 量化):

  • Qwen3.6-27B(4-bit,~15GB):品質天花板候選
  • Qwen3.6-35B-A3B(4-bit MoE,~20GB,每次約 3B active):速度候選
  • Qwen3.5-9B(4-bit,5.82GB):萃取主力候選
  • gemma-4-12b-coder(8-bit):coding 特化
  • gemma-4-E4B(4-bit,~5GB):輕量工兵

帳面成績單:八項 benchmark 交叉對照

每項 benchmark 抽測約 30 題,未開推理(thinking),僅供相對排序。免責聲明放前面:30 題的樣本,分數顆粒大概是 1/30 ≈ 3.3%,±10% 內的差距都是雜訊,這張表拿來「分級」可以,拿來「排名」不行。

Benchmark gemma-12b-coder gemma-E4B Qwen3.5-9B Qwen3.6-27B Qwen3.6-35B-A3B
arc_challenge 0.867 0.800 0.867 0.900 0.867
cmmlu(中文) 0.433 0.533 0.633 0.800 0.733
hellaswag 0.800 0.667 0.867 0.833 0.833
humaneval 0.900 0.733 0.833 0.933 0.900
livecodebench 0.167 0.333 0.133 0.467 0.500
mathqa 0.200 0.167 0.433 0.567 0.633
mbpp 0.633 0.700 0.567 0.867 0.767
mmlu 0.667 0.567 0.733 0.700 0.633
綜合平均 0.583 0.563 0.633 0.758 0.733
八項總耗時 1257s 1725s 2277s 3266s 824s

看一眼就能抓到的東西:

  1. Qwen3.6-27B 是品質天花板:綜合 0.758 最高,中文(0.80)與 coding(mbpp 0.867 / humaneval 0.933)都居冠,但也最慢,光 livecodebench 單項就跑了 2138 秒。
  2. Qwen3.6-35B-A3B 是速度和品質的甜蜜點:MoE 架構,每次只啟用約 3B 參數,綜合 0.733 逼近 27B,卻是全場最快(824s,比 27B 快將近四倍)。難 coding(livecodebench 0.50)和數學(0.633)還反超 27B。
  3. 小模型各有位置:9B 格式最穩、中文與 mmlu 佳;gemma-E4B 屬輕量 fallback;gemma-12b-coder 的 humaneval 很強,但一碰難題(livecodebench 0.167)就掉。

那,等級約當雲端哪一代?

先講兩個前提:(一)benchmark 帳面分不等於實戰體感;(二)靜態選擇題最容易被中小模型追平,真實的長上下文與 agentic 差距通常比帳面大得多。 有這兩層打折,我的校準大概是這樣:

本地模型 帳面 benchmark 約當 實戰體感約當(含推理/agentic)
Qwen3.6-35B-A3B(主力) GPT-4o/Claude 3.5 Sonnet(2024 版) GPT-4o-mini ~ Claude 3.5 Haiku 之間,程式碼題可摸到 GPT-4o 下緣
Qwen3.6-27B(備援) 略勝 35B,帳面 ≈ GPT-4o 同上,稍強但慢
Qwen3.5-9B(萃取) GPT-4o-mini ~ 早期 GPT-4-turbo 的知識面 GPT-3.5-turbo 加強版/Llama-3-8B 之上,強在中文知識與穩定 JSON
gemma-4-E4B(工兵) GPT-3.5-turbo/Claude 3 Haiku 級 同級,價值在吞吐不在聰明

說白了,本地棧的天花板帳面約當 2024 年的 GPT-4o;但任務一變成真正的長文與 agentic,體感更像 GPT-4o-mini,離現役旗艦還差一到兩個世代。 但這不是壞事,它剛好卡在「隱私鐵律下的高速苦力」這個位置,夠用。

為什麼日常主力是 35B-A3B,而不是分數最高的 27B

互動式討論回應速度就是一切。35B-A3B 綜合分只差 27B 0.025,卻快將近四倍;27B 唯一能救速度的招式是 MTP(Multi-Token Prediction),在這版 oMLX 已經確認不能用(下一節會講)。所以定案:35B-A3B 當日常主力,27B 降級為「不計時間、要中文或 coding 極致品質時」的 on-demand 備援。

兩顆小模型的實測併發(合計約 11GB)是真並行:循序 11.6 秒,併發 4.02 秒,加速比 2.89 倍。Qwen3.5-9B 設 is_pinned 開機即熱載,重複任務零冷啟;gemma-E4B 當第二併發槽保溫。重複性萃取的延遲被壓到幾乎感覺不到。

三個 speculative decoding 地雷(省你一個週末)

想再壓速度,自然會想到 speculative decoding:小模型先猜、大模型驗證。我把三條路都接了,結果三條全踩雷。記在這裡,省你自己摸索。這版是 oMLX 0.4.4

地雷一:原生 MTP 是 no-op

Qwen3.6-27B-MLX-4bit 的 config 宣告了 mtp heads,但 4-bit 檔根本沒附 mtp.* 權重,MTPModule 被靜默跳過,加速為零(實測 +0.8%,純雜訊)。

地雷二:VLM-MTP 直接崩潰

改走 draft 路徑後,27B 被判為 vlm 引擎,撞上 mlx_vlm 的 bug:

AttributeError: 'tuple' object has no attribute 'hidden_states'
  at mlx_vlm/speculative/mtp.py:170

純文字 LLM 被塞進 VLM 版 MTP 路徑,直接 500。

地雷三:dflash 載入器缺參

下載了專用 draft 模型後接 dflash,log 一句話就說穿了:

DFlashDraftModelArgs.__init__() missing 12 required positional arguments
  → Falling back to vlm engine.

oMLX 0.4.4 的 DFlashDraftModelArgs 載入器沒從 draft config 填必要欄位。E4B 接上去直接 500 崩潰;35B-A3B 則靜默 fallback,回傳 HTTP 200 但沒有任何加速。這種失敗最陰險:它看起來成功了。

教訓一:log 是唯一真相,別信 HTTP 200。 35B 那個「200」其實是 dflash 靜默退回,不看 log 會誤以為加速生效。

specprefill:同一個旋鈕,2.4 倍加速或 6 倍拖累

三條路裡唯一能用的是 specprefill。但它不是萬用加速,是「批次長文件專用旋鈕」。對 35B-A3B 做 ON/OFF A/B(長 prompt):

情境 OFF ON 判讀
cache-miss(每次不同的新長 prompt,16450 tok) 27.57s 11.68s ✅ 快 2.36 倍
cache-hit(同一長 prompt 反覆,8310 tok) 0.81s 4.78s ❌ 反慢 約 6 倍

機制:specprefill 會繞過 oMLX 的 prefix/session KV 快取,每次全量重算 prefill。所以:

  • 新長輸入、無共享前綴(一次性長全文分析、批次消化)→ 開,大勝。
  • 互動式 agent(固定 system + tools prefix、session 累積上下文,多為 cache-hit)→ 關,開了會把每輪從 0.8 秒拖成 4.8 秒。

這直接推翻了我前一步「主模型接 specprefill」的決定。互動主模型(Hermes)定案改回 specprefill OFF,這顆旋鈕重新定位成「跑批次長文件時才臨時開」。

教訓二:加速旋鈕要看工作負載形狀,不是一鍵全開。 同一個 specprefill,在 cache-miss 是 2.4 倍加速,在 cache-hit 是 6 倍拖累。

最終棧與路由

模型 specprefill 角色
Qwen3.6-35B-A3B OFF 互動主模型,吃 prefix 快取
Qwen3.5-9B on(短輸入 no-op) 萃取主力,pinned 熱載
gemma-4-E4B off 第二併發槽,高吞吐預處理
Qwen3.6-27B on(互動宜關) on-demand 高品質備援

任務路由收斂成:敏感資料去識別/結構化萃取/文獻初篩 → 9B(併發溢流給 E4B);離線討論與 coding → 35B-A3B;要中文或 coding 極致品質且不計時間 → 27B。 需要真正腦力的定稿與複雜推理,仍然回雲端旗艦。

還順手清掉了沒有任何路由引用的孤兒模型(歷史 benchmark 殘留、壞掉的 draft),hub 從 60GB 瘦到 33GB,實回收 27GB。

帶得走的東西

  1. log 是唯一真相,別信 HTTP 200。 靜默 fallback 會偽裝成成功。
  2. 加速旋鈕看負載形狀,不是一鍵全開。 cache-miss 與 cache-hit 可以讓同一個旋鈕從救星變累贅。
  3. 敢推翻自己。 接了 specprefill、量完數據發現對互動主模型是淨負向,就該收回。證據大於面子。

常見問題

一台 M4 Mac 上的本地模型,約當雲端哪一代?

帳面最強的 35B-A3B 和 27B,靜態 benchmark 分數落在 2024 年 GPT-4o、Claude 3.5 Sonnet 附近。但實際跑長上下文和 agentic 工具鏈時,體感比較接近 GPT-4o-mini 或 Claude 3.5 Haiku,跟現役旗艦還差一到兩個世代。9B 大概在 GPT-4o-mini 等級,E4B 約當 GPT-3.5-turbo。

分數最高的是 27B,為什麼日常主力選 35B-A3B?

35B-A3B 是 MoE,每次只啟用約 3B 參數,綜合分 0.733 跟 27B 的 0.758 差距很小,但跑完八項 benchmark 只花 824 秒,27B 要 3266 秒,快將近四倍。難 coding 跟數學甚至反超 27B。互動討論回應速度就是一切,而 27B 唯一能救速度的 MTP 在這版 oMLX 是壞的,所以 27B 只留給不趕時間的場合。

specprefill 這種加速旋鈕該不該全開?

不該。specprefill 繞過 prefix 和 session KV 快取,每次從頭算 prefill。新的長輸入(批次長文件)可以快 2.36 倍,但固定 system prefix、反覆命中快取的互動式 agent 反而慢約六倍。開不開要看工作負載長什麼樣子。

這些 benchmark 分數可以拿來精確排名嗎?

不太行。每項只抽了約 30 題,±10% 的雜訊很大,拿來分級可以,拿來排名不行。靜態選擇題也是小模型最容易追分的地方,真實世界的推理和 agentic 差距通常比帳面數字大得多。

覺得這篇有幫助?

追蹤以收到新的 AI × 生醫研究筆記:

或請我喝杯咖啡,讓新內容持續產出。

☕ 請我喝杯咖啡