16:35:53 offloaded 42/43 layers to GPU(模型開始載入)
16:38:53 llm server not responding
16:38:54 llm server loading model
16:39:02 llm server not responding
16:39:03 llm server loading model
...(反覆了將近 6 分鐘)
16:42:28 llama runner started in 410.58 seconds(終於啟動)
17:04:49 -- Boot --(機器直接重開機)
用同款 gemma4:e4b,在 Mini PC 和 MacBook Air M3 上各跑一輪,看看換硬體能得到什麼。
速度差 6.7 倍,不只是快慢的問題
Mini PC 平均 1.45 tok/s,Mac 平均 9.75 tok/s。這個差距背後的原因是架構:Mini PC 用 x86 CPU 做矩陣運算,效率遠低於 Apple Silicon 的 Neural Engine + 統一記憶體架構。M3 的統一記憶體讓 CPU 和 GPU 共享同一塊 24GB,模型權重可以直接放在 GPU 能讀取的記憶體,不需要搬移。
記憶體夠,輸出才完整
這是硬體差距最直接的體現:Q2 要求生成一個能解析多種日期格式的 Python 函式,Mini PC 在 600 token 限制下就截斷了(回答還在中途),而 Mac 無限制跑出 2218 tokens 的完整函式。
Q4 要求生成帶有 CTE 和 Window Function 的複雜 SQL,Mini PC 截斷,Mac 輸出完整 1043 tokens 含說明。這不是模型能力的差異,是記憶體和 KV Cache 空間的差異。
WITH RecentSpending AS (
SELECT o.customer_id, SUM(o.amount) AS total_spending
FROM orders o
WHERE o.created_at >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
GROUP BY o.customer_id
),
RankedCustomers AS (
SELECT c.name, c.city, rs.total_spending,
RANK() OVER (PARTITION BY c.city ORDER BY rs.total_spending DESC) as city_rank
FROM RecentSpending rs
JOIN customers c ON rs.customer_id = c.id
)
SELECT city, name, total_spending
FROM RankedCustomers
WHERE city_rank <= 3
ORDER BY city, city_rank;
Thinking 版本(1413 tokens)在 SQL 後面額外附上了欄位說明對照表、RANK vs DENSE_RANK 的差異說明、以及在資料量大時建議加索引的備注。這種「自動補充說明」的行為,在程式碼審查或教學場景特別有用。
原則是:不需要記憶 codebase、不需要複雜推理的任務,都可以先試 Mac。速度快、免費、資料不出門。遇到 Mac 答不好的,再升到 Claude。
進階應用二:Mini PC + Mac 混合架構,讓 Agent Team 更有效率
角色定義(固定,不隨任務改變)
Mini PC → 純指揮中心:跑 Claude Code、管理 Agent Team、處理串接邏輯
不跑任何本地模型,資源用在穩定性和協調上
Mac → 推理後端:跑 Ollama + gemma4:e4b
只負責生成,不做決策
Claude API → 審查 + 架構:程式碼審查、複雜邏輯、跨檔案推理
Mini PC 透過網路呼叫,不在本地
規則:Mac 不在線 → fallback 給 Claude API,不是 Mini PC 自己跑
當你用 Claude Code 的 Agent Team 跑自動化程式開發時,會面對一個現實問題:Claude API 的費用隨 token 用量線性增長,而很多任務其實不需要 Claude 的完整推理能力——DTO 生成、CRUD 樣板、SQL migration 這類結構性重複工作,本地的 gemma4:e4b 就能處理。
解法是把 Mac 當成 Agent Team 的「草稿後端」:Claude Agent 負責架構決策和程式碼審查,Mac gemma4 負責產生第一版草稿,再由 Claude 驗證整合。
架構分工
任務類型
交給誰
原因
DTO / model class
Mac gemma4
結構固定,重複性高
CRUD endpoints 樣板
Mac gemma4
Pattern 固定,不需要推理
SQL migration
Mac gemma4
有範本可循
Unit test 骨架
Mac gemma4
快速產出結構,Claude 填邏輯
複雜業務邏輯
Claude sonnet
需要跨檔案理解,Mac 沒有 context
安全相關程式碼
Claude sonnet/opus
不可靠的輸出風險太高
架構決策 / Code Review
Claude opus
需要深度推理與判斷
前置設定:讓 Mac 的 Ollama 對區網開放
Ollama 預設只監聽本機。在 Mac 上把它開放給區網,Mini PC 才能連進來:
# Mac 上執行(停掉 Ollama app 後)
OLLAMA_HOST=0.0.0.0 ollama serve
# 從 Mini PC 驗證是否連得到(換成 Mac 的區網 IP)
curl http://192.168.1.xxx:11434/api/tags
不想暴露 port 的話,用 SSH Tunnel:Mini PC 上執行 ssh -L 11435:localhost:11434 [email protected] -N,之後打 localhost:11435 就等於打 Mac 的 Ollama。
#!/usr/bin/env python3
"""
mac_draft.py — Call Mac's local gemma4 for code draft generation.
Usage:
python3 mac_draft.py "write a SQLAlchemy User model with id, name, email"
python3 mac_draft.py --task "CRUD for User" --context "FastAPI, SQLAlchemy async"
Exit codes:
0 = success, draft printed to stdout
1 = Mac unreachable → fallback: implement with Claude directly
2 = model error
"""
import json, sys, urllib.request, urllib.error, argparse
MAC_HOST = "http://192.168.1.xxx:11434" # 改成 Mac 的實際 IP
MODEL = "gemma4:e4b"
TIMEOUT = 600
SYSTEM_PROMPT = """You are a code generation assistant. Output ONLY code —
no explanations, no markdown fences, no comments unless essential.
The output will be reviewed and integrated by another agent."""
def check_reachable():
try:
with urllib.request.urlopen(f"{MAC_HOST}/api/tags", timeout=5):
return True
except Exception:
return False
def generate(task, context=""):
prompt = f"Context: {context}\n\nTask: {task}" if context else task
payload = {
"model": MODEL,
"messages": [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": prompt},
],
"stream": False, "think": False,
"options": {"num_ctx": 4096, "num_predict": -1},
}
data = json.dumps(payload).encode()
req = urllib.request.Request(
f"{MAC_HOST}/api/chat", data=data,
headers={"Content-Type": "application/json"},
)
with urllib.request.urlopen(req, timeout=TIMEOUT) as r:
return json.loads(r.read())["message"]["content"]
parser = argparse.ArgumentParser()
parser.add_argument("task", nargs="?")
parser.add_argument("--task", dest="task_flag")
parser.add_argument("--context", default="")
args = parser.parse_args()
task = args.task or args.task_flag
if not task:
print("ERROR: no task provided", file=sys.stderr); sys.exit(1)
if not check_reachable():
print(f"MAC_UNREACHABLE: {MAC_HOST}. Fallback: implement with Claude.",
file=sys.stderr); sys.exit(1)
try:
print(generate(task, args.context))
except Exception as e:
print(f"ERROR: {e}", file=sys.stderr); sys.exit(2)
Agent 的實際使用流程
# Agent (sonnet) 在 Bash tool 中這樣呼叫:
# 1. 請 Mac 出草稿
draft=$(python3 ~/llm-benchmark/scripts/mac_draft.py \
--task "generate SQLAlchemy User model" \
--context "PostgreSQL, async, Pydantic v2")
# 2. 檢查是否成功
if [ $? -ne 0 ]; then
echo "Mac unavailable, implementing directly"
# Claude 自己寫
fi
# 3. 草稿給 Claude 審查後整合進 codebase
echo "$draft" # Claude 讀到這裡,決定是否採用、修改哪裡
告訴 Agents 這條規則:寫入 AGENTS.md
Claude Code 的 Agent Team 每個 subagent 啟動時沒有對話歷史。規則要寫進 AGENTS.md,agent 才會在每次任務開始時讀到它。在專案的 AGENTS.md 加上這個區塊:
## Mac Draft Resource (Local LLM Offload)
Mac (gemma4:e4b) is available as a fast code draft generator.
Tool: python3 ~/llm-benchmark/scripts/mac_draft.py
Use Mac draft BEFORE writing code yourself for:
- DTO / model class boilerplate ✅
- CRUD endpoints (standard pattern) ✅
- SQL migration scripts ✅
- Unit test scaffolding ✅
Do NOT use Mac draft for:
- Complex business logic ❌ (no codebase context)
- Security-sensitive code ❌ (unreliable)
- Cross-file refactoring ❌ (no context)
- Architecture decisions ❌ (use opus)
Workflow:
1. Call mac_draft.py with task description
2. exit code 1 (MAC_UNREACHABLE) → implement with Claude directly
3. Review draft: check patterns, imports, logic, security
4. Integrate into codebase
Mac generates the shape. Claude ensures it fits.
這樣每個 subagent 都會知道「遇到樣板類任務先叫 Mac 出草稿」,不需要每次重新交代規則。
結論與推薦
本次測試跨越三個維度,每層都有明確的答案:
Mini PC + Mac 混合架構的定位
Mini PC 的角色是指揮中心,不是推理引擎。它跑 Claude Code、管理 Agent Team、處理串接邏輯,資源用在穩定性和協調上。推理工作全部交給 Mac 的 gemma4:e4b。
日常問答 / 摘要:Mini PC 發問 → Mac gemma4 回答,免費、快速、資料不出門
草稿程式碼:Agent 呼叫 mac_draft.py → Mac 出草稿 → Claude 審查整合
複雜推理 / 架構決策:直接用 Claude API,不走 Mac
Mac 不在線:fallback 給 Claude API,Mini PC 本身不需要跑任何模型
如果你的情境是 Mini PC 獨立運作(沒有 Mac),模型選擇建議:gemma4:e4b 速度最快(1.45 tok/s)、qwen3:14b 完成度最高(7/7 全答)、qwen3:4b 最省記憶體。但這個架構的速度上限就是 CPU 推論,不如 Mac 的 Apple Silicon。
真正的瓶頸不是模型大小,而是硬體架構。同款模型在 Apple Silicon 上跑出的效果,在 x86 CPU 上根本發揮不出來。如果你認真考慮本地 LLM,MacBook Air M3 是目前性價比最高的入門選擇;Mini PC 路線則需要搭配 NVIDIA GPU(VRAM ≥ 8GB)才能真正發揮。
# Python Crawler — Everything That Can Go Wrong
## ROC Date Format
- [source: analyst] "1150309" 被解析成 AD 1150 年,要用 7 位 YYMMDD ROC 格式
- [source: analyst] TPEX 欄位名 TransactionAmount 不是 TradingMoney
## Holiday / Empty Response
- [source: analyst] TWSE API 假日返回空值,必須 guard `if not data: return []`
然後在 CLAUDE.md 裡強制 agent 在開工前讀 brain:
## Domain Brain — MANDATORY before ANY implementation work
Before writing any plan, code, or review, you MUST:
1. Find the `## Domain Brain:` line in the project's CLAUDE.md
2. Read each listed brain file
3. If you skip this step and a bug was documented in brain, that is YOUR failure
# 檔案位置
~/your-project/CLAUDE.md
# Claude 行為
claude
├─ 讀取 CLAUDE.md
├─ 記住所有規則
├─ 每次你輸入 prompt 時遵守
└─ 不再需要你重複告訴它
類比:
傳統方式 = 每次進公司都告訴員工「要穿正式服裝」
CLAUDE.md 方式 = 第一天讀 dress code,以後自動遵守
一人公司應該在 CLAUDE.md 裡寫什麼
第一層:基本信息(不改的東西)
# Project: Taiwan Invoice System
**Stack**: React 18 + Node.js 18 + PostgreSQL
**Language**: TypeScript (strict mode)
**Main concern**: Taiwan tax law compliance
---
## Architecture Decision Log
### Decision 1: Use Strategy Pattern for tax calculation
**Why**: Taiwan tax law changes frequently (new government = new rates)
**Impact**: New tax type can be added in 30 min, not 8 hours
**Done**: ✅
### Decision 2: Keep invoice data immutable once submitted
**Why**: Taiwan tax audit requires unmodifiable records
**Impact**: No delete/edit after submit, only void new ones
**Done**: ✅
好處:
6 個月後你自己看,能快速想起設計邏輯
新人(或外包)接手,有據可查
Claude 理解你的業務優先級
第二層:代碼標準(重複最多的東西)
## Code Standards
### File Structure
```
src/
├── components/ # React components
├── pages/ # Page-level components
├── services/ # API calls & business logic
├── utils/ # Helpers
├── hooks/ # Custom React hooks
├── styles/ # CSS modules
└── __tests__/ # Test files (mirror structure)
```
### Naming Conventions
- Components: PascalCase (e.g., InvoiceForm.tsx)
- Utilities: camelCase (e.g., calculateTax.ts)
- Constants: UPPER_SNAKE_CASE (e.g., MAX_INVOICE_AMOUNT)
- Database tables: snake_case (e.g., c_invoice)
### Code Quality Rules
**MUST HAVE**:
- [ ] TypeScript (no `any` type)
- [ ] Unit tests for all logic (TDD)
- [ ] JSDoc for public functions
- [ ] Error handling (no silent failures)
**NEVER**:
- ❌ Hardcode config values (use .env)
- ❌ Leave console.log() in production code
- ❌ Commit commented-out code
- ❌ Use var (only let/const)
為什麼重要:
Claude 有了標準,自動遵守
省去每個 prompt 都要說「按 TypeScript best practices」
代碼風格一致,review 更快
第三層:業務邏輯(最容易被遺忘的)
## Taiwan-Specific Rules
### Tax Calculation
- Standard VAT: 5% (applies to most goods)
- Zero-rated: 0% (exports, specific items)
- Tax-exempt: 0% (non-profit, some services)
- Input tax can be deducted if invoice dated in same month
### Invoice Rules
- Invoice number format: GUN (Government Uniform Number)
- Sequence must be continuous
- Cannot be modified after submission
- Must include buyer's company ID + name
- QR code is mandatory for official submission
### Compliance
- Must report to MOPS (Ministry system) by 15th of next month
- Annual audit by tax bureau
- Keep records for 10 years
為什麼重要:
Claude 有了背景,不會犯「常見的 bug」
減少審查時需要找的問題
新人學習曲線 ÷ 2
第四層:技術決策(省掉最多討論時間)
## When You Ask Claude to Build Something
### Before Implementation (Planning Phase)
1. Claude enters Plan Mode automatically
2. Claude reads this CLAUDE.md + design docs
3. Claude proposes approach
4. **YOU APPROVE** (or suggest changes)
5. Claude implements
### Testing Strategy
- Unit tests: Must cover edge cases
- Integration tests: For API + database interaction
- Manual testing: Only for UI/UX
- Coverage target: > 85%
### Code Review Checklist
- [ ] Logic is correct (test passes)
- [ ] Taiwan business rules followed
- [ ] No security holes
- [ ] Performance acceptable
- [ ] Error messages are clear (in Chinese)
- [ ] Documentation updated
為什麼重要:
Claude 知道你的評審標準
自動寫出符合預期的代碼
不用反覆改
一人公司版本的 CLAUDE.md 精簡版
如果你覺得上面太複雜,這是最小版本(30 分鐘可寫完):
# Taiwan Invoice System
## Stack & Language
- TypeScript + React 18 + Node.js
- Database: PostgreSQL
## Code Rules
- File structure: components/ pages/ services/ __tests__/
- Names: Components = PascalCase, functions = camelCase, constants = UPPER_CASE
- MUST: TypeScript strict, unit tests, JSDoc, error handling
- NEVER: console.log, hardcoded config, var, no tests
## Business Rules
- Tax rates: 5% standard, 0% zero-rated, 0% exempt
- Invoice format: GUN, continuous sequence, immutable after submit
- Compliance: Report to MOPS by 15th, keep records 10 years
## When You Ask Me to Build
1. I'll enter Plan Mode
2. Read design doc + this file
3. Propose approach (you approve)
4. Implement with tests
5. You review
## Important Decisions
1. Tax calculation uses Strategy Pattern (easy to add new rates)
2. Invoices immutable after submit (Taiwan law requirement)
---
Done! Keep this updated as rules change.
寫這個花了多少時間? 30-45 分鐘。
省了多少時間? 每週 3-5 小時(因為不用重複解釋)。
真實案例:有沒有 CLAUDE.md 的差別
沒有 CLAUDE.md 的一人公司
Day 1, Prompt:
"Build invoice form with validation.
Use React, TypeScript, follow best practices."
Claude builds... but:
- Uses var instead of const ❌
- Only 60% test coverage ❌
- API call has no error handling ❌
- Component name is lowercase ❌
You: "Oh no, 改了改了改了"
時間消耗:8 小時 (1 小時寫 + 7 小時改)
有 CLAUDE.md 的一人公司
Day 1, CLAUDE.md 寫好,然後 Prompt:
"Build invoice form with validation"
Claude builds:
- Automatically uses let/const ✅
- Automatically writes unit tests ✅
- Automatically adds error handling ✅
- Automatically uses PascalCase ✅
You: "一次到位!"
時間消耗:2.5 小時 (30 分鐘規劃 + 2 小時實施)