llm-benchmark
Use when the user wants to test, compare, or choose local Ollama models for their machine. Checks Ollama/GPU state, recommends model sizes from available VRAM, preserves existing benchmark records, pulls only approved models, runs repeatable benchmarks, restores stopped services,
Install
npx skills add https://github.com/KerberosClaw/kc_ai_skills/tree/main/llm-benchmark
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install kerberosclaw-kc-ai-skills@llmmart
git clone https://github.com/KerberosClaw/kc_ai_skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole kerberosclaw/kc_ai_skills collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
LLM Benchmark Skill
You are a local LLM benchmarking specialist. 你負責用可重現的命令測 Ollama 模型效能,保護使用者現有服務狀態,並把推薦和限制講清楚。
不適用
- 不評測雲端 API 模型。
- 不用單次主觀聊天感覺取代 benchmark。
- 不在未確認硬體與服務狀態前直接 pull 大模型或重啟服務。
執行以下完整流程:
Step 0:環境檢查
# 確認 Ollama 是否安裝並運行
curl -s http://localhost:11434/api/version 2>/dev/null || echo "NOT_RUNNING"
which ollama 2>/dev/null || echo "NOT_INSTALLED"
- 若 未安裝:執行
curl -fsSL https://ollama.com/install.sh | sh,再啟動服務 - 若 未運行:執行
ollama serve &或systemctl start ollama - 確認成功後繼續
Step 0.5:VRAM 清空(benchmark 前必做)
1. 停止其他吃 GPU / RAM 的本地 LLM 服務(若有且正在運行)
# 檢查是否有 LLM gateway 類容器正在運行(例:OpenClaw、LM 代理服務)
LLM_GATEWAY="your-llm-gateway" # 換成你的服務名,例:openclaw
docker ps --format '{{.Names}}' | grep -i "$LLM_GATEWAY"
- 若有相關容器正在運行 → 停止它:
LLM_STACK_DIR="$HOME/your-llm-stack" # 換成你的 compose 目錄 GATEWAY_SERVICE="gateway" # 換成你的服務名 cd "$LLM_STACK_DIR" && docker compose stop "$GATEWAY_SERVICE" - 若無相關容器,或容器已停止 → 跳過此步驟
記錄該服務是否原本是啟動的,benchmark 完成後需還原狀態。
2. 重啟 Ollama 清除 VRAM(必做)
sudo systemctl restart ollama
sleep 5
3. 確認 VRAM 已釋放
nvidia-smi --query-gpu=memory.used,memory.free --format=csv,noheader,nounits
確認 memory.used 降到 ~1500 MB 以下再繼續。若仍偏高,再等 5 秒重確認。
4. Benchmark 完成後還原服務
若步驟 1 有停止服務,benchmark 全部完成後執行:
cd "$LLM_STACK_DIR" && docker compose start "$GATEWAY_SERVICE"
Step 1:取得 GPU/VRAM 資訊
nvidia-smi --query-gpu=name,memory.total,memory.free --format=csv,noheader,nounits 2>/dev/null \
|| rocm-smi --showmeminfo vram 2>/dev/null \
|| echo "NO_GPU"
依據 可用 VRAM 推薦模型最大參數量(以 Q4 量化為基準):
| 可用 VRAM | 推薦最大 B |
|---|---|
| < 4 GB | 3B |
| 4–6 GB | 7B |
| 6–8 GB | 8B |
| 8–10 GB | 12–14B |
| 10–14 GB | 14B |
| 14–16 GB | 14–20B |
| > 16 GB | 30B+ |
向使用者說明推薦理由,列出推薦模型清單(附 Ollama model tag)。
Step 2:確認要測試的模型
詢問使用者確認測試清單(若使用者已在指令中指定則略過)。
同時列出機器上 現有模型:
curl -s http://localhost:11434/api/tags | python3 -c "
import sys,json
data=json.load(sys.stdin)
for m in data.get('models',[]):
print(m['name'], round(m['size']/1024/1024), 'MB')
"
Step 3:檢查既有 Benchmark 記錄
檢查 ~/benchmark_results.json 是否存在:
python3 -c "
import json, os
path = os.path.expanduser('~/benchmark_results.json')
if not os.path.exists(path):
print('NO_BENCHMARK_FILE')
else:
data = json.load(open(path))
benchmarked = [e['model'] for e in data]
print('BENCHMARKED:', benchmarked)
"
- 若某模型已有 benchmark 記錄 → 直接沿用,不重跑
- 若機器上有模型但無 benchmark 記錄 → 詢問使用者是否要補跑
- 若是新模型(需先 pull)→ 自動 pull 後跑 benchmark
Step 4:Pull 新模型
ollama pull <model_tag>
pull 完成後確認:ollama list | grep <model_name>
Step 5:執行 Benchmark
將 skills/llm-benchmark/scripts/benchmark.py 複製到目標機器並執行:
# 複製到 PC(若透過 SSH)
scp scripts/benchmark.py USER@PC_IP:/tmp/benchmark.py
# 在 PC 上執行(需先 pip install requests)
python3 /tmp/benchmark.py <model1> <model2> ...
benchmark.py 的完整原始碼在
scripts/benchmark.py。
Step 6:生成 Markdown 報告
benchmark 完成後,讀取 ~/benchmark_results.json,生成 ~/model_benchmark.md。
報告結構(參考 ~/model_benchmark.md):
- 執行環境(CPU / GPU / RAM / OS)
- 測試模型列表(參數量、最大 ctx、檔案大小)
- Token/s 速度總覽表格(模型 × context size)
- 若某個 ctx size 的
cpu_offload_detected為 true,在表格該格標示「⚠️ 中止」,並加註說明:此 context size 的 KV cache 超過 GPU VRAM 容量,Ollama 自動將計算 offload 至 CPU,導致 GPU 使用率驟降、CPU 全速運轉,推理速度大幅劣化。測試已提前終止,此 ctx 不列入甜蜜點評估。
- 若某個 ctx size 的
- GPU 資源使用(VRAM、GPU 利用率)
- 回答品質評估(每題正確性分析 + 摘要)
- Context Window 甜蜜點分析(僅含未觸發 cpu_offload 的 ctx)
- 瓶頸分析(Compute Bound vs Memory Bandwidth Bound)
- 排名(邏輯推理 / 程式設計 / Token/s)
- 結論與建議(依使用情境推薦)
Step 7:結論說明
向使用者口頭總結:
- 各模型 token/s 排名
- 回答品質排名(重點標注邏輯題正確性)
- VRAM 使用量
- 最終推薦:哪個模型適合什麼情境
Anti-patterns
- ❌ 沒清 VRAM 就測 — 前一個模型 / gateway 還佔著顯存,量到的 token/s 是髒的;Step 0.5 的重啟釋放是必做
- ❌ 主觀聊感覺當 benchmark — 「這個模型回得比較好」不算數;用可重跑的固定題目 + 數字
- ❌ 重跑已有記錄的模型 —
benchmark_results.json已有的直接沿用,不浪費時間重測 - ❌ 測完不還原服務 — 有停過的 gateway / container,全部測完要 start 回去,不留使用者服務掛掉
- ❌ cpu_offload 的數字混進甜蜜點 — KV cache 溢出 VRAM 被 offload 到 CPU 的 ctx,速度已失真、不列入評估
注意事項
- 全程使用繁體中文
- 每個推理超時設 120 秒,避免卡住
- 若模型 pull 失敗,記錄原因後繼續測其他模型
- 生成報告前先確認
~/benchmark_results.json完整性 - 報告最後更新時間戳記
Files (kc_ai_skills)
-
scripts
-
benchmark.py 4.3 KB
#!/usr/bin/env python3 """LLM Benchmark Runner - Ollama""" import json, time, subprocess, requests, os OLLAMA_URL = "http://localhost:11434" QUESTIONS = { "logic": { "title": "基礎邏輯", "prompt": "請用繁體中文回答:一個房間有3盞燈,對應3個在門外的開關,你無法從門外看到燈的狀態。你可以任意操作開關,但只能進入房間一次。請問如何判斷哪個開關控制哪盞燈?" }, "reasoning": { "title": "多步推理", "prompt": "請用繁體中文回答:有5個嫌疑人,已知:(1)A或B犯案 (2)如果A犯案則C也犯案 (3)如果B犯案則D也犯案 (4)C和D不可能同時犯案 (5)E無罪。請問誰犯案?請列出推理過程。" }, "coding": { "title": "程式設計", "prompt": "請用繁體中文說明,並用 Python 寫一個函數:輸入一個字串,輸出該字串中所有出現次數超過一次的字元及其出現次數,結果按出現次數由多到少排序。" }, "debugging": { "title": "程式除錯", "prompt": "請用繁體中文說明以下 Python 程式碼的 bug 並修正:\n```python\ndef fibonacci(n):\n if n <= 0:\n return []\n elif n == 1:\n return [0]\n fibs = [0, 1]\n for i in range(2, n):\n fibs.append(fibs[i-1] + fibs[i-2])\n return fibs\nprint(fibonacci(5)) # 預期 [0,1,1,2,3]\n```" } } CTX_SIZES = [2048, 4096, 8192, 16384, 32768] def get_gpu_stats(): try: r = subprocess.run( ["nvidia-smi", "--query-gpu=utilization.gpu,memory.used,memory.free,temperature.gpu", "--format=csv,noheader,nounits"], capture_output=True, text=True, timeout=5) parts = r.stdout.strip().split(", ") if len(parts) >= 4: return {"gpu_util": int(parts[0]), "mem_used": int(parts[1]), "mem_free": int(parts[2]), "temp": int(parts[3])} except: pass return {} def run_inference(model, prompt, ctx_size, timeout=180): start = time.time() try: response = requests.post(f"{OLLAMA_URL}/api/generate", json={"model": model, "prompt": prompt, "stream": False, "options": {"num_ctx": ctx_size}}, timeout=timeout) data = response.json() wall = time.time() - start eval_count = data.get("eval_count", 0) eval_duration = data.get("eval_duration", 1) prompt_eval_count = data.get("prompt_eval_count", 0) prompt_eval_duration = data.get("prompt_eval_duration", 1) tok_s = eval_count / (eval_duration / 1e9) if eval_duration > 0 else 0 ttft = prompt_eval_duration / 1e9 if prompt_eval_duration else 0 return { "status": "ok", "response": data.get("response", ""), "tokens_per_sec": round(tok_s, 1), "eval_count": eval_count, "prompt_eval_count": prompt_eval_count, "ttft_s": round(ttft, 2), "wall_time_s": round(wall, 1) } except requests.exceptions.Timeout: return {"status": "timeout", "tokens_per_sec": 0, "eval_count": 0, "wall_time_s": round(time.time() - start, 1)} except Exception as e: return {"status": "error", "response": str(e), "tokens_per_sec": 0} def benchmark_model(model): print(f"\n{'='*60}") print(f" 模型: {model}") print(f"{'='*60}") results = {} for ctx in CTX_SIZES: print(f"\n --- ctx={ctx} ---") gpu_before = get_gpu_stats() questions = {} for qk, qdata in QUESTIONS.items(): print(f" [{qdata['title']}] ...", end="", flush=True) r = run_inference(model, qdata["prompt"], ctx) r["title"] = qdata["title"] questions[qk] = r print(f" {r['tokens_per_sec']} tok/s | {r['eval_count']} tok | TTFT {r.get('ttft_s',0)}s | wall {r['wall_time_s']}s") gpu_after = get_gpu_stats() results[str(ctx)] = {"questions": questions, "gpu_before": gpu_before, "gpu_after": gpu_after} return results if __name__ == "__main__": import sys model = sys.argv[1] if len(sys.argv) > 1 else "qwen3-vl:8b-instruct" data = benchmark_model(model) outpath = os.path.expanduser(f"~/benchmark_{model.replace(':','_').replace('/','_')}.json") with open(outpath, "w") as f: json.dump({"model": model, "ctx_results": data}, f, ensure_ascii=False, indent=2) print(f"\n結果存至 {outpath}")
-
-
SKILL.md 6.8 KB
--- name: llm-benchmark description: "Use when the user wants to test, compare, or choose local Ollama models for their machine. Checks Ollama/GPU state, recommends model sizes from available VRAM, preserves existing benchmark records, pulls only approved models, runs repeatable benchmarks, restores stopped services, and writes a markdown comparison report. NOT for hosted API model evaluation or subjective chat-quality judging without local benchmark commands." version: 1.1.0 status: stable triggers: - "/llm-benchmark" - "測本地模型" - "模型 benchmark" - "比較 ollama 模型" --- # LLM Benchmark Skill You are a local LLM benchmarking specialist. 你負責用可重現的命令測 Ollama 模型效能,保護使用者現有服務狀態,並把推薦和限制講清楚。 ## 不適用 - 不評測雲端 API 模型。 - 不用單次主觀聊天感覺取代 benchmark。 - 不在未確認硬體與服務狀態前直接 pull 大模型或重啟服務。 執行以下完整流程: ## Step 0:環境檢查 ```bash # 確認 Ollama 是否安裝並運行 curl -s http://localhost:11434/api/version 2>/dev/null || echo "NOT_RUNNING" which ollama 2>/dev/null || echo "NOT_INSTALLED" ``` - 若 **未安裝**:執行 `curl -fsSL https://ollama.com/install.sh | sh`,再啟動服務 - 若 **未運行**:執行 `ollama serve &` 或 `systemctl start ollama` - 確認成功後繼續 ## Step 0.5:VRAM 清空(benchmark 前必做) ### 1. 停止其他吃 GPU / RAM 的本地 LLM 服務(若有且正在運行) ```bash # 檢查是否有 LLM gateway 類容器正在運行(例:OpenClaw、LM 代理服務) LLM_GATEWAY="your-llm-gateway" # 換成你的服務名,例:openclaw docker ps --format '{{.Names}}' | grep -i "$LLM_GATEWAY" ``` - 若有相關容器正在運行 → 停止它: ```bash LLM_STACK_DIR="$HOME/your-llm-stack" # 換成你的 compose 目錄 GATEWAY_SERVICE="gateway" # 換成你的服務名 cd "$LLM_STACK_DIR" && docker compose stop "$GATEWAY_SERVICE" ``` - 若無相關容器,或容器已停止 → 跳過此步驟 記錄該服務是否原本是啟動的,**benchmark 完成後需還原狀態**。 ### 2. 重啟 Ollama 清除 VRAM(必做) ```bash sudo systemctl restart ollama sleep 5 ``` ### 3. 確認 VRAM 已釋放 ```bash nvidia-smi --query-gpu=memory.used,memory.free --format=csv,noheader,nounits ``` 確認 `memory.used` 降到 ~1500 MB 以下再繼續。若仍偏高,再等 5 秒重確認。 ### 4. Benchmark 完成後還原服務 若步驟 1 有停止服務,benchmark 全部完成後執行: ```bash cd "$LLM_STACK_DIR" && docker compose start "$GATEWAY_SERVICE" ``` --- ## Step 1:取得 GPU/VRAM 資訊 ```bash nvidia-smi --query-gpu=name,memory.total,memory.free --format=csv,noheader,nounits 2>/dev/null \ || rocm-smi --showmeminfo vram 2>/dev/null \ || echo "NO_GPU" ``` 依據 **可用 VRAM** 推薦模型最大參數量(以 Q4 量化為基準): | 可用 VRAM | 推薦最大 B | |-----------|-----------| | < 4 GB | 3B | | 4–6 GB | 7B | | 6–8 GB | 8B | | 8–10 GB | 12–14B | | 10–14 GB | 14B | | 14–16 GB | 14–20B | | > 16 GB | 30B+ | **向使用者說明推薦理由**,列出推薦模型清單(附 Ollama model tag)。 ## Step 2:確認要測試的模型 詢問使用者確認測試清單(若使用者已在指令中指定則略過)。 同時列出機器上 **現有模型**: ```bash curl -s http://localhost:11434/api/tags | python3 -c " import sys,json data=json.load(sys.stdin) for m in data.get('models',[]): print(m['name'], round(m['size']/1024/1024), 'MB') " ``` ## Step 3:檢查既有 Benchmark 記錄 檢查 `~/benchmark_results.json` 是否存在: ```bash python3 -c " import json, os path = os.path.expanduser('~/benchmark_results.json') if not os.path.exists(path): print('NO_BENCHMARK_FILE') else: data = json.load(open(path)) benchmarked = [e['model'] for e in data] print('BENCHMARKED:', benchmarked) " ``` - 若某模型**已有 benchmark 記錄** → 直接沿用,不重跑 - 若機器上有模型**但無 benchmark 記錄** → 詢問使用者是否要補跑 - 若是**新模型**(需先 pull)→ 自動 pull 後跑 benchmark ## Step 4:Pull 新模型 ```bash ollama pull <model_tag> ``` pull 完成後確認:`ollama list | grep <model_name>` ## Step 5:執行 Benchmark 將 `skills/llm-benchmark/scripts/benchmark.py` 複製到目標機器並執行: ```bash # 複製到 PC(若透過 SSH) scp scripts/benchmark.py USER@PC_IP:/tmp/benchmark.py # 在 PC 上執行(需先 pip install requests) python3 /tmp/benchmark.py <model1> <model2> ... ``` > benchmark.py 的完整原始碼在 `scripts/benchmark.py`。 ## Step 6:生成 Markdown 報告 benchmark 完成後,讀取 `~/benchmark_results.json`,生成 `~/model_benchmark.md`。 報告結構(參考 `~/model_benchmark.md`): 1. **執行環境**(CPU / GPU / RAM / OS) 2. **測試模型列表**(參數量、最大 ctx、檔案大小) 3. **Token/s 速度總覽表格**(模型 × context size) - 若某個 ctx size 的 `cpu_offload_detected` 為 true,在表格該格標示「⚠️ 中止」,並加註說明: > 此 context size 的 KV cache 超過 GPU VRAM 容量,Ollama 自動將計算 offload 至 CPU,導致 GPU 使用率驟降、CPU 全速運轉,推理速度大幅劣化。測試已提前終止,此 ctx 不列入甜蜜點評估。 4. **GPU 資源使用**(VRAM、GPU 利用率) 5. **回答品質評估**(每題正確性分析 + 摘要) 6. **Context Window 甜蜜點分析**(僅含未觸發 cpu_offload 的 ctx) 7. **瓶頸分析**(Compute Bound vs Memory Bandwidth Bound) 8. **排名**(邏輯推理 / 程式設計 / Token/s) 9. **結論與建議**(依使用情境推薦) ## Step 7:結論說明 向使用者口頭總結: - 各模型 token/s 排名 - 回答品質排名(重點標注邏輯題正確性) - VRAM 使用量 - **最終推薦**:哪個模型適合什麼情境 ## Anti-patterns - ❌ **沒清 VRAM 就測** — 前一個模型 / gateway 還佔著顯存,量到的 token/s 是髒的;Step 0.5 的重啟釋放是必做 - ❌ **主觀聊感覺當 benchmark** — 「這個模型回得比較好」不算數;用可重跑的固定題目 + 數字 - ❌ **重跑已有記錄的模型** — `benchmark_results.json` 已有的直接沿用,不浪費時間重測 - ❌ **測完不還原服務** — 有停過的 gateway / container,全部測完要 start 回去,不留使用者服務掛掉 - ❌ **cpu_offload 的數字混進甜蜜點** — KV cache 溢出 VRAM 被 offload 到 CPU 的 ctx,速度已失真、不列入評估 ## 注意事項 - 全程使用**繁體中文** - 每個推理超時設 120 秒,避免卡住 - 若模型 pull 失敗,記錄原因後繼續測其他模型 - 生成報告前先確認 `~/benchmark_results.json` 完整性 - 報告最後更新時間戳記
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.