Claude Skill

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,

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download kerberosclaw-kc_ai_skills-llm-benchmark-ad005ac.zip · 6 KB
Part of kerberosclaw/kc_ai_skills — 25 skills

Install

skills CLI npx skills add https://github.com/KerberosClaw/kc_ai_skills/tree/main/llm-benchmark
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install kerberosclaw-kc-ai-skills@llmmart
Git 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):

  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 完整性
  • 報告最後更新時間戳記
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.

No comments yet.

Reviews (0)

No reviews yet.

Related