mcpField
M
model-compare

model-compare

github.com/moonlight-lupinテスト・品質113126 回インストール1 日前に更新
リポジトリ

model-compare について

model-compare は、複数のモデルを匿名で比較するスキルとスタンドアロンのコマンドラインツールです。プロンプト、コーディング、レビュー、ツール利用、推論レベルの比較に対応します。

主な機能

  1. 01モデル回答の匿名シャッフル
  2. 02シンプル、コーディング、レビュー、ツールの各モード
  3. 03複数プロバイダーへの並列リクエスト
  4. 04推論レベルの A/B 比較
  5. 05トークンとツール呼び出しの効率表示

活用シーン

  1. 01ワークフロー用モデル選定前のタスク比較
  2. 02モデルによるプロンプト解釈のテスト
  3. 03コーディング課題でのモデル評価
  4. 04異なる推論レベルの比較

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/moonlight-lupin/agent-skills --skill model-compare

インストール後、Claude Code で/model-compareを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

requirements-dev.txt
references/
model-behavior.md
provider-tool-support.md
providers.json
scripts/
compare.py
embedding_compare.py
provider_health.py
tests/
__init__.py
test_compare.py
test_embedding_compare.py
test_providers_snapshot.py

詳細

Model Compare — ブラインド方式のサイドバイサイド複数モデルテスト

1 つのプロンプトを複数のモデルに同時に送信し、応答を匿名で提示して、ユーザーが最もよい応答を選んだ後、どの応答がどのモデルによるものかを明らかにします。

PewDiePie の Odysseus プロジェクトにある Compare 機能に着想を得て、Hermes のマルチプロバイダーアーキテクチャ(OpenRouter、NVIDIA、Ollama Cloud、および OpenAI 互換の任意のエンドポイント)向けに調整しています。

使用する場合

  • 「これらのモデルを次の内容で比較して」
  • 「[タスク] にはどのモデルが適していますか?」
  • 「[model1] と [model2] を A/B テストして」
  • 「次のモデルをブラインド比較して」
  • 「異なるモデルがこのプロンプトをどう扱うかテストして」
  • ワークフローに使うモデルを決める前に、モデルを評価したい場合
  • プロンプトエンジニアリング — 異なるモデルが指示をどう解釈するかを確認したい場合

使用しない場合

  • ベンチマーク(MMLU、GSM8K など)→ evaluating-llms-harness スキルを使用してください
  • コスト分析 → プロバイダーの料金ページを確認してください
  • 単一モデルのテスト → モデルを切り替えて直接質問してください
  • 複数ソースの調査統合 → deep-research スキルを使用してください(反復的な調査ループであり、モデル比較ではありません)

アーキテクチャ

4 つの比較モードがあり、すべて scripts/compare.py で実行します。

モードフラグ機能API 機能
simple--mode simple(デフォルト)1 つのプロンプト → 1 つの応答基本的なチャット補完
tools--mode tools実際の web_search/web_extract と、サンドボックス化された run_python/read_file/write_file を使った複数ターンのツール呼び出し。最大 10 ターン(TEST_BANK の max_turns でテストごとに設定可能)。完全なトレースを記録します。リクエスト内の tools 配列、複数ターンのメッセージ
coding--mode codingテストバンクのコーディング用プロンプト(LRU キャッシュ、同時フェッチ、マージソートのデバッグ、リトライデコレーター)基本的なチャット補完
review--mode reviewバグを仕込んだコードレビュー用プロンプト(SQL インジェクション、クリーンコード、競合状態、金額計算での浮動小数点数)基本的なチャット補完
User prompt + model list
  → Step 1: Resolve models to provider endpoints (free providers first)
  → Step 2: Send prompt to all models in parallel
     ├─ simple/coding/review: one-shot chat completion
     └─ tools: multi-turn loop (Think→Search→Extract→Execute→Synthesize→Stop, max 10 turns by default, per-test configurable)
  → Step 3: Quality check responses (handle errors/empty)
  → Step 4: Present anonymously (shuffle + label A/B/C/D)
  → Step 5: Efficiency table (tokens in/out, turns, tool calls — auto for tools mode)
  → Step 6: User votes OR judge model evaluates
  → Step 7: Reveal identities + show mapping
  → Step 8 (optional): Save to JSON file
スクリプト:scripts/compare.py

主なインターフェースとなるスタンドアロンの CLI ツールです(pip 依存関係なし、標準ライブラリと urllib のみ)。ツール呼び出しに対応しているモデルについては、references/provider-tool-support.md を参照してください。16 件の直接比較テスト(GLM 5.2、MiniMax M3、HY3、Laguna)から得られた、モデルの実証的な動作に関する知見については、references/model-behavior.md を参照してください。(tests/ のテストスイートの実行には pytest が必要です。requirements-dev.txt を参照してください。このスキル自体は何もインストールする必要がありません。)

ツールモードの環境依存関係: --mode tools は実際の web_search を実行します。そのため、SearXNG インスタンスを指す SEARXNG_URL を設定するか、ddgs CLI を PATH から利用できるようにする必要があります(こちらがフォールバックです)。どちらも Python のインポート依存関係ではありませんが、ライブ検索にはいずれかが必要です。両方とも利用できない場合、web_search はエラー結果を返します。ほかの 3 つのモード(simple、coding、review)では、どちらも必要ありません。

# Simple 2-model blind comparison
python3 scripts/compare.py --prompt "Explain X" --models "ollama-cloud:glm-5.2" "ollama-cloud:kimi-k2.5"

# Reasoning-effort A/B: SAME model, two effort levels (native syntax)
# Registers a virtual provider per arm; judge can also take an effort suffix.
python3 scripts/compare.py --mode review --test H7 \
  --models "ollama-cloud:@medium:glm-5.3-flash" "ollama-cloud:@high:glm-5.3-flash" \
  --judge "ollama-cloud:@medium:glm-5.3" --reveal

# Tool calling with test bank prompt A + judge + reveal
python3 scripts/compare.py --mode tools --test A --models "ollama-cloud:glm-5.2" "ollama-cloud:kimi-k2.5" --judge "ollama-cloud:glm-5.2" --reveal

# Coding test J with efficiency table
python3 scripts/compare.py --mode coding --test J --models "ollama-cloud:glm-5.2" "ollama-cloud:qwen3-coder:480b" --efficiency

# Code review test O with judge
python3 scripts/compare.py --mode review --test O --models "ollama-cloud:glm-5.2" "ollama-cloud:kimi-k2.5" --judge "ollama-cloud:glm-5.2"

# List available tests
python3 scripts/compare.py --list-tests

# List providers
python3 scripts/compare.py --list-providers

主なフラグ:--prompt、--models、--mode、--test(テストバンク ID)、--judge、--efficiency、--reveal、--output、--timeout、--list-providers、--list-models。

推論 effort の A/B テスト(: @effort サフィックス、2026-08-29 追加)

モデル仕様と --judge では、任意の effort マーカー provider:@effort:model_id を指定できます。例: ollama-cloud:@medium:glm-5.3-flash。一意な(provider、effort)の各ペアは、仮想プロバイダー(ollama-cloud@medium)を登録します。この仮想プロバイダーはベースプロバイダーの設定(同じエンドポイント、同じ環境変数キー、継承した max_tokens)を複製し、ペイロードに reasoning_effort を注入します。これにより、1 回のブラインド実行で同じモデルを 2 つの推論レベルで比較できます。結果の開示時には、各条件が provider@effort と表示されます。2026-08-29 の glm-5.3-flash A/B テスト(Codex による判定、8 件のテスト)で得られた知見:effort と思考トークン数の関係は単調ではありません。high は中央値で約 3 倍高速でしたが、medium が完了した 12 ターンのツールチェーンテストでは収束しませんでした。判定された全体的な品質では medium が優位でした(平均 8.6 対 7.8)。全トレースについては ~/.hermes/data/glm53flash_effort_ab/ab_results.jsonl を参照してください。

--max-turns CLI オーバーライド(2026-07-17 追加): --max-turns N を渡すと、ソースを編集せずに実行時にテストバンクの max_turns フィールドをオーバーライドできます。指定しない場合は、テストバンクのデフォルト値が使用されます。バックグラウンド実行を停止してソースコード内の TEST_BANK["A"]["max_turns"] を修正する方法は脆弱で、並列実行を妨げるため、この機能が追加されました。

利用可能なプロバイダー

3 つのプロバイダーが接続されています(正式な設定は scripts/compare.py の PROVIDERS です)。

プロバイダー環境変数コストモデルファミリーエンドポイント
Ollama CloudOLLAMA_API_KEY無料GLM、Qwen、Kimi、Gemini、Gemmahttps://ollama.com/v1/chat/completions
NVIDIANVIDIA_API_KEY無料Yi、Llama、Nemotron、…https://integrate.api.nvidia.com/v1/chat/completions
OpenRouterOPENROUTER_API_KEY有料(トークンごと)Claude、GPT、Gemini、DeepSeek、Llama、Qwen、Mistralhttps://openrouter.ai/api/v1/chat/completions

モデル一覧を別の場所に置いているのには理由があります。 正確なモデル数と ID は常に変動するため、このドキュメントには意図的に記載していません。最新の一覧を表示するには python3 scripts/compare.py --list-models <provider> を実行してください(該当プロバイダーのキーが必要です)。references/providers.json には、プロバイダーごとの代表的なモデル ID をまとめた、件数を含まない厳選スナップショットがあります。

コストを考慮したプロバイダーのルーティング(必須)

ユーザーがプロバイダーを指定しない場合は、まず無料プロバイダーにルーティングします。

  1. Ollama Cloud — 無料(GLM、Qwen、Kimi、Gemini、Gemma)
  2. NVIDIA — 無料(Yi、Llama、Nemotron)
  3. OpenRouter — 有料(トークンごとの料金)。次の場合にのみ使用します:
    • ユーザーが OpenRouter 専用モデル(例:Claude、GPT-4o)を明示的にリクエストした場合
    • ユーザーが OpenRouter の使用を明示した場合
    • タスクに適したモデルが無料プロバイダーにない場合

OpenRouter を呼び出す前に、必ずユーザーに確認してください。

「この比較では、トークンごとに料金が発生する OpenRouter を使用します。推定コスト:モデルごと、呼び出しごとに約 $0.01~0.05(モデルによって異なります)。続行しますか?」

明示的な確認を得てから続行してください。判断に迷う場合は、無料プロバイダーをデフォルトとして使用してください。

モデルを呼び出すには、プロバイダーの /v1/chat/completions エンドポイントに POST します。

{
  "model": "<model_id>",
  "messages": [{"role": "user", "content": "<prompt>"}],
  "max_tokens": 8192,
  "temperature": 0.7
}

ヘッダー:Authorization: Bearer <API_KEY>

max_tokens は call_model_simple と call_model_with_tools の両方で 8192 に設定されています。以前のデフォルト値 4096 では、コーディングテスト J(LRU キャッシュ)でコード出力が途中で切れていました。モデルが大量のコードを生成し、デコレーター部分を完了する前に 4096 の上限に達したためです。それでもモデルの出力が途中で切れる場合は、ペイロード辞書の値を増やしてください。

ステップ 1 — モデルを決定する

比較するモデルを決定します。ユーザーは次のように指定できます。

  • モデル名を明示:「claude-sonnet-4.6 vs gpt-4o vs gemini-2.5-flash を比較して」
  • プロバイダー + モデル:「OpenRouter の claude-sonnet-4.6 と Ollama の glm-5.2 を比較して」
  • タスクベース:「コーディングに最適なモデルは?」→ 候補を 2~4 個提案します
  • プロバイダー内のすべてのモデル:「OpenRouter のモデルを 3 つテストして」→ 特性の異なるモデルを選びます
モデルの解決

ユーザーが指定したモデル名をprovider:model_id形式にマッピングします。無料プロバイダー(Ollama Cloud、NVIDIA)を優先します。 OpenRouterを使用するのは、無料プロバイダーにないモデル(例:Claude、GPT)の場合、またはユーザーが明示的に希望した場合のみです。

固定のカタログ(古くなるため)ではなく、以下のルールに従います。

  • 無料で、プレフィックスを省略するか、Ollama/NVIDIAのモデルを指定した場合 → 無料プロバイダーで解決します。例:ollama-cloud:glm-5.2、ollama-cloud:qwen3-coder:480b、nvidia:meta/llama-3.3-70b-instruct。
  • プロプライエタリなモデル(Claude、GPT、Gemini-Pro、DeepSeek-R1など) → 取り扱いがあるのはOpenRouterのみです。例:openrouter:anthropic/claude-sonnet-4.6、openrouter:openai/gpt-4o — 有料のため、事前に確認してください(上記のルーティングルールを参照)。
  • 正確なIDがわからない場合 → python3 scripts/compare.py --list-models <provider>を実行して最新の一覧を確認するか、各プロバイダーの代表的なIDを厳選したリストであるreferences/providers.jsonを参照してください。ここでモデルの一覧を手動で管理しないでください。

ユーザーがモデルを指定していない場合:

  1. タスクの種類に適した無料モデルがあるか確認します(例:コーディング → qwen3-coder、glm-5.2、一般用途 → glm-5.2、kimi-k2.5)。
  2. Ollama CloudとNVIDIAから無料モデルを2~4個提案します。
  3. ユーザーがプレミアムモデル(Claude、GPT-4o)を希望する場合、または無料プロバイダーに適切な選択肢がない場合に限り、OpenRouterのモデルを提案します。
  4. 有料モデルを提案する場合は、実行前に費用がかかることを伝えます。

どのプロバイダーがモデルを提供しているか不明な場合は、次のコマンドで確認します。

curl -s https://openrouter.ai/api/v1/models -H "Authorization: Bearer $OPENROUTER_API_KEY" | python3 -c "import sys,json; [print(m['id']) for m in json.load(sys.stdin)['data'] if 'KEYWORD' in m['id'].lower()]"

ルール:

  • 比較するモデルは2~4個にします(これを超えるとチャットで扱いにくくなります)。
  • ユーザーが指定していない場合は、プロバイダーやサイズが異なるモデルを提案します。
  • 実行前に、モデルの一覧を必ずユーザーに確認します。

ステップ2 — すべてのモデルにプロンプトを送信する

すべてのモデルに並列でプロンプトを送信します。スクリプトがconcurrent.futures.ThreadPoolExecutorを使って自動的に処理するため、delegate_taskや手動での並列化は不要です。

シンプル/コーディング/レビューの各モード

モデルごとに1回、チャット補完を実行します。すべての呼び出しはスクリプトが並行して実行します。

ツール呼び出しモード

モデルごとにマルチターンループを実行します(モデル間も並行して処理します)。

Turn 1: Send prompt + tool definitions → Model returns tool_call(s)
Turn 2: Execute real tool → inject result → Model returns tool_call(s) or answer
Turn 3: ... until final answer or max turns (10 by default, configurable per-test via `max_turns` field in TEST_BANK)

実際のツール実行 — スクリプトはweb_searchとweb_extractを実際に実行します。

  • web_search → SearXNG(SEARXNG_URLを使ったセルフホスト構成)、利用できない場合はDDGSにフォールバック
  • web_extract → HTMLをテキストに変換して、HTTPで直接取得(1ページあたり3000文字)

モックツールや偽の結果は使いません。モデルは適切な検索クエリを作成し、正しいURLを選び、実際のコンテンツから情報をまとめる必要があります。検索クエリの質が低いモデルは質の低い結果を受け取り、自力で立て直す必要があります。

OpenAIのtoolsパラメーターで渡すツール定義:

  • web_search(query, limit) — タイトル、URL、スニペットを返します
  • web_extract(urls) — ページの内容をテキストとして返します

ターミナルツールはありません — サンドボックスがないためです。安全上の理由から、比較対象のモデルにはターミナルを公開しません。

ステップ3 — 品質を確認する

各回答について:

  • 空またはエラー:モデルがエラーまたは空の回答を返した場合はその旨を記録し、比較対象から除外します。失敗したモデルをユーザーに伝えます。
  • 途中で切れている:回答がmax_tokensに達した場合は、途中で切れたことを記録します。
  • 拒否:モデルが回答を拒否した場合は、そのまま含めます(拒否も有効な比較データです)。

ステップ4 — 匿名で提示する

回答をシャッフルして、中立的なラベルを割り当てます。どのモデルがどの回答かは明かさないでください。

**シャッフルのルール:**ランダムな順列を使います。常に同じモデルを先頭にしないでください。ユーザーが3つのモデルを比較している場合は、A/B/Cをランダムに割り当てます。

次の形式で提示します。

🧪 Blind Model Comparison
Prompt: "[truncated to 100 chars...]"

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

📦 Model A:
[full response]

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

📦 Model B:
[full response]

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

📦 Model C:
[full response]

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Vote: Reply with the letter of the best response (A, B, or C), or "tie".

書式ルール:

  • 要約ではなく、回答全文を提示します。ユーザーが品質を判断する必要があります。
  • 回答同士がはっきり区別できるようにします。
  • チャットで読みやすいよう、回答ごとに約3000文字で切り詰めます(切り詰めた場合はその旨を記載)。
  • 回答が非常に長い(3000文字を超える)場合は、全文をファイルに保存し、チャットでは切り詰めた回答と注記を提示します。

ステップ 5 — ユーザーの投票

ユーザーが投票するまで待ちます。以下を受け付けます。

  • 文字:「A」、「B」、「C」、「D」
  • 「tie」または「tie between A and B」
  • 「all bad」(有効な投票です。勝者はいません)
  • 具体的なフィードバック:「A のほうがよいが、B のコードのほうがすっきりしている」

ステップ 6 — モデル名の公開

投票後、対応関係を公開します。

🎭 Reveal:

Model A → <actual_model_name> (<provider>)
Model B → <actual_model_name> (<provider>)
Model C → <actual_model_name> (<provider>)

🏆 Your winner: Model <letter> = <actual_model_name>

ステップ 7 — 統合(任意)

ユーザーが最善の回答を希望する場合は、すべての回答を統合します。

"Want me to synthesize the best parts of all responses into one?"

「はい」の場合は、各回答の最も優れた部分を取り入れて、統一された回答を作成します。各部分にどのモデルが貢献したかを記載します。

## Synthesized Answer
[merged response]

## Contributions
- Section X: primarily from <model_name>
- Section Y: primarily from <model_name>

ステップ 8 — 投票履歴(任意)

比較を繰り返す場合は、結果をファイルに記録します。

~/.hermes/data/model_compare_history.jsonl

形式:

{"timestamp": "2026-06-27T12:00:00", "prompt": "...", "models": ["model_a", "model_b"], "winner": "model_a", "is_blind": true, "feedback": "..."}

これにより、時間の経過とともに、タスクの種類ごとにどのモデルが勝つかを把握できます。

テストバンク(24 件のテスト)

事前に用意されたテストプロンプトを実行するには、--test <ID> を使用します。モードはテストのドメインに基づいて自動設定されます。

IDドメインプロンプトの概要ツール?
Atool_calling最新の Python バージョンと主な新機能 2 つ🔧
Btool_callingOdysseus の GitHub リポジトリのスター数を調べる🔧
Ctool_callingホームラボに最適なリバースプロキシを選び、その主な機能を調べる🔧
Etool_callingLRU キャッシュの実装を検索し、より優れたものを書く🔧
H1tool_callingPython 3.14 のフリースレッド化の状況 — 3 つの情報源を探し、信頼できる情報源を特定する🔧
H2tool_callingNode.js の安定版と EOL 日を調べ、公式情報源と照合する🔧
S1tool_callingIPv4 バリデーターを書き、テストケースで実行し、合否を報告する🔧 📦
S2tool_callingCSV をファイルに書き込み、平均値を分析し、スクリプトを実行して結果を報告する🔧 📦
S3tool_callingフィボナッチ数列を生成して JSON として保存し、読み込んで検証する🔧 📦
S4tool_calling連結リストを反転し、テストを実行して出力を検証し、誤りがあればデバッグする🔧 📦
S5tool_callingシーザー暗号の暗号化と復号を行い、実行して往復変換を検証する🔧 📦
JcodingLRU キャッシュを実装する。O(1)、型ヒントと docstring を含める
KcodingURL ごとのタイムアウトを設定し、順序を維持して、URL を並行取得する
Lcodingバグのあるマージソートを修正する(マージ処理に off-by-one エラーがある)
Mcoding3 回、1 秒間隔で再試行するデコレーターを作成し、メタデータを保持する
H3codingTTL と LRU 退避機能を備えたスレッドセーフなキャッシュ
H4coding時計を注入可能なスレッドセーフのトークンバケット方式レートリミッター
Ocode_reviewSQL インジェクションと信頼性の低い rowcount ループ
Pcode_reviewバグのないクリーンなコード — テストの誤検出率を測定する
Qcode_review本番サービスで使用されているスレッドセーフでないキャッシュ
Rcode_review金額に float を使っていることと、送金時の検証が不足していること
H5code_reviewasyncio 接続プール — 処理中接続のリーク、ロック不足、タイムアウトなし
H6code_review認証サービス — MD5、タイミング攻撃への脆弱性、偽造可能なトークン、有効期限の確認なし
H7code_reviewロギングサービス — ループの各反復で fetchone() が 2 回呼び出される

🔧 = web_search/web_extract ツールを使用します。 📦 = サンドボックスツール(run_python/read_file/write_file)を使用します。

各テストには、評価者が使用する評価基準が含まれています。ツール呼び出しテストには、そのテスト固有のターン上限を制御する max_turns フィールド(デフォルトは 10)も含まれています。個別のテストで変更するには、scripts/compare.py の TEST_BANK エントリーを編集します。コードレビューのテストには、客観的な採点のために意図的に仕込まれた問題が含まれています。

ツール呼び出しモード — 仕組み

--mode tools フラグを有効にすると、実際のツール(モックではありません)を使った複数ターンのツール呼び出しが可能になります。

  1. スクリプトで OpenAI の関数ツールとして 5 つのツールを定義します:web_search、web_extract、run_python、read_file、write_file
  2. プロンプトとツール定義を各モデルに並行して送信します
  3. モデルが tool_calls を返すと、スクリプトは実際の呼び出しを実行します:
    • web_search → DDGS にフォールバックする SearXNG(SEARXNG_URL を使ったセルフホスト)
    • web_extract → HTTP で直接取得し、HTML をテキストに変換して、ページごとに 3000 文字で切り捨てます
    • run_python → モデルごとのサンドボックス(一時ディレクトリ、タイムアウト 10 秒、ネットワークなし)で Python コードを実行します
    • read_file → サンドボックスディレクトリからファイルを読み込みます(パスのトラバーサルをブロック)
    • write_file → サンドボックスディレクトリにファイルを書き込みます(パスのトラバーサルをブロック)
  4. 実際の結果を tool ロールのメッセージとして返します
  5. 最終回答に到達するか、最大ターン数に達するまで繰り返します(既定値は 10。TEST_BANK の max_turns でテストごとに設定可能です)
  6. 全ターン、ツール呼び出し、ターンごとのトークン数、収束状況を追跡します

サンドボックスのセキュリティ: 各モデルには独自の一時ディレクトリ(tempfile.mkdtemp)が割り当てられます。パストラバーサル(../)と絶対パスは拒否されます。Python の実行には 10 秒のタイムアウトが設定されています。サンドボックスのサブプロセスからネットワークにはアクセスできません。各モデルの実行後、finally ブロックでサンドボックスをクリーンアップします。

公開されるツール: web_search、web_extract、run_python、read_file、write_file。ツール呼び出しに対応しているモデルについては、references/provider-tool-support.md を参照してください。

ジャッジにはツール呼び出しの全トレースが表示されます — 何を検索したか、何を抽出したか、どのコードを実行して何が出力されたか、ターン数、収束したかどうかが確認できます。これにより、ジャッジは最終回答だけでなく、ツール選択の戦略も評価できます。

効率性の分析

--efficiency フラグ(tools モードでは自動的に有効になります)を指定すると、トークン数の比較表が出力されます:

📊 Efficiency Comparison
                      Turns  Tools   Tok In  Tok Out  Ratio   Time
✅ ollama-cloud:glm-5.2      5      5     7806      777   0.10  15.3s
✅ ollama-cloud:kimi-k2.5    5      4     5434     1051   0.19  14.8s
✅ ollama-cloud:gemma4:31b   2      1      949      248   0.26   6.5s

主な指標:ターン数、ツール呼び出し数、入力トークン数(消費したコンテキスト)、出力トークン数(生成したトークン)、効率比(出力/入力)、所要時間。正確さを伴わない効率性は無駄です — トークン数は少なくても誤った回答をするモデルは効率的なのではなく、単に早く間違えているだけです。

ユースケース

ワークフローに適したモデルの選定

「法律文書の要約に使うモデルが必要です。このプロンプトで claude-sonnet-4.6、gpt-4o、gemini-2.5-flash を比較してください:[法律文書のテキスト]」

コストと品質のトレードオフ

「このコーディング用プロンプトで、glm-5.2(無料)と claude-sonnet-4.6(有料)を比較してください。有料モデルを選ぶ価値はありますか?」

プロンプトの堅牢性テスト

「このプロンプトを 3 つのモデルでテストしてください。書式の指示に従うモデルを確認したいです」

プロバイダーの比較

「同じモデル(llama-4-maverick)を OpenRouter と NVIDIA で比較してください。違いはありますか?」

プロバイダーのヘルス状態の追跡

scripts/provider_health.py モジュールは、プロバイダーのエンドポイントのヘルス状態を追跡し、 デッドホストのクールダウンを実装します。プロバイダーで連続して障害が発生すると、 クールダウン期間中は停止中として扱われ、その後の呼び出しは自動的にスキップされます。

仕組み
  • 2 回連続で失敗 → プロバイダーを停止中として扱います
  • クールダウン:15 秒(Ollama Cloud)、30 秒(NVIDIA)、20 秒(OpenRouter)
  • 成功すると → 失敗カウンターが即座にリセットされます
  • クールダウンの終了後 → プロバイダーに再試行の機会が与えられます
  • 状態は実行間で ~/.hermes/data/provider_health.json に保持されます
CLI
# Check provider health
python3 scripts/provider_health.py --status

# Reset all providers
python3 scripts/provider_health.py --reset all

# Reset a specific provider
python3 scripts/provider_health.py --reset ollama-cloud
compare.py との統合

call_model_simple と call_model_with_tools はどちらも API 呼び出しの前にプロバイダーのヘルス状態を確認します。プロバイダーがクールダウン中の場合、タイムアウトまで待つ代わりに、[Provider X in cooldown (Ns remaining) — skipping] メッセージを表示して呼び出しをスキップします。成功と失敗は自動的に記録されます。

重要な場面
  • 複数のプロバイダーを横断して比較する場合 — 1つのプロバイダーが不安定でも、比較全体が遅れることはありません
  • ツール呼び出しモード(モデルごとに10ターン) — 停止しているプロバイダーは、60秒 × 10ターン = タイムアウトに10分待つ代わりに、数秒でスキップされます
  • 連続して比較する場合 — 前回の実行時にプロバイダーが停止していた場合、次回の実行ではそのプロバイダーをスキップします

ハイブリッドモード — CLI モデルと API モデルの併用

比較スクリプトがサポートするのは、API ベースのプロバイダー(OpenRouter、Ollama Cloud、NVIDIA)のみです。CLI ツール(Codex CLI、Cursor CLI)からしか利用できないモデルも含めたい場合は、次のハイブリッドパターンを使用します。

ハイブリッドモードを使用する場合
  • コスト削減 — OpenRouter のトークンごとの料金を避けるために、ユーザーが「gpt5.6 には codex cli を使って」と指示した場合。Codex(月額20ドル)と Cursor Pro+(月額60ドル)では、トークンごとの追加料金なしでモデルを利用できます。
  • モデルの利用可否 — 一部のモデル(例:cursor-grok-4.5-high)は Cursor CLI からしか利用できず、どの API プロバイダーからも利用できません。
ハイブリッド比較の実行方法
  1. API モデル → 通常どおり scripts/compare.py をバックグラウンドで実行します
  2. CLI モデル → ターミナルからそれぞれ個別に並列実行します:\n - Codex CLI(GPT-5.6): codex exec --skip-git-repo-check -m gpt-5.5 "<prompt>" > /tmp/codex_result.json 2>&1\n - Cursor CLI(Grok 4.5): export PATH="$HOME/.local/bin:$PATH" && export $(grep 'CURSOR_API_KEY=' ~/.hermes/.env | xargs) && agent -p --force --model "cursor-grok-4.5-high" --sandbox disabled "<prompt>" > /tmp/cursor_result.json 2>&1
  3. 結果を統合 — API スクリプトの出力と CLI の出力を集め、すべての回答を匿名で(シャッフルして)提示し、ユーザーに投票してもらってから、回答者を明らかにします。
CLI モデルの詳細
CLIバイナリモデルフラグ認証料金
Codexcodex-m gpt-5.6-solOAuth(hermes auth)月額20ドルに含まれる
Cursoragent--model "cursor-grok-4.5-high".env 内の CURSOR_API_KEY月額60ドルに含まれる

CLI モデルは必ずバックグラウンドで実行してください(background=true + notify_on_complete=true)— 実行に1〜5分かかることがあります。真の並列実行にするには、API スクリプトの起動と同じツールバッチ内で実行してください。

Cursor Grok 4.5 High は最も高負荷な内部ティアです。負荷の軽い タスクには cursor-grok-4.5-medium を使用してください。モデル選択の詳細は cursor-cli スキルを参照してください。

注意点

  • 匿名提示が早すぎる — 匿名の提示にモデル名が漏れないようにしてください。送信前に必ず再確認してください。
  • 常に同じ順序にする — 毎回シャッフルしてください。モデル A が常に最初だと、ユーザーが順序バイアスを持つ可能性があります。
  • 並列で実行しない — すべての API 呼び出しを同じツールブロックで送信してください。逐次呼び出しは時間の無駄です。
  • 失敗を無視する — モデルでエラーが発生した場合は、ユーザーに伝えてください。黙って除外しないでください。
  • 切り詰めすぎる — ユーザーが品質を判断できるだけのテキストが必要です。最低 3000 文字、短い場合は全文を提示してください。
  • 結果の公開を忘れる — 投票の後は必ず公開してください。どのモデルが勝ったかを知ることが目的です。
  • モデル一覧を確認しない — API 呼び出しに費用をかける前に、必ずどのモデルを使うか確認してください。モデルには費用がかかります。
  • 確認なしに有料 API を呼び出す — OpenRouter はトークンごとに課金されます。OpenRouter のモデルを呼び出す前に、必ずユーザーに確認してください。プロバイダーが指定されていない場合は、デフォルトで無料プロバイダー(Ollama Cloud、NVIDIA)を使用してください。ユーザーがプレミアムモデルを明示的に要求した場合、または費用を確認した場合に限り、OpenRouter に切り替えてください。
  • max_tokens を低くしすぎる — 現在のデフォルトは compare.py の 8192 です。以前の 4096 では、テスト J でコードが途中で切り詰められました(LRU キャッシュデコレーターが関数の途中で途切れました)。それでもモデルの出力が切り詰められる場合は、ペイロード辞書の値を増やしてください。
  • Temperature の不一致 — すべてのモデルで同じ temperature(デフォルトは 0.7)を使用してください。temperature が異なると、公平な比較になりません。
  • API キーの漏えい — 出力に API キーを絶対に表示しないでください。curl コマンドでは、必ず環境変数参照を使用してください。
  • レート制限 — OpenRouter と NVIDIA にはレート制限があります。4 つ以上のモデルを比較する場合、必要に応じて呼び出しの間に短い待ち時間を入れてください。OpenRouter の無料枠モデル(:free サフィックス付き)は、わずか 1~2 回の呼び出しで HTTP 429 のレート制限が発生しやすいため、特に注意してください。
  • OpenRouter の無料枠モデル(:free サフィックス付き)と費用確認ゲート — スクリプトは、費用が 0 ドルの :free サフィックス付きモデルも含め、すべての OpenRouter モデルを有料として慎重に扱います。COMPARE_CONFIRM_PAID=1 環境変数を設定すると、費用確認ゲートを回避できます。例:COMPARE_CONFIRM_PAID=1 python3 scripts/compare.py --models "openrouter:tencent/hy3:free" ...。ユーザーはすでに無料枠モデルを選択しているため、追加の費用確認は不要です。
  • NVIDIA NIM のモデル ID には nvidia/ プレフィックスが含まれます — compare.py 経由で NIM を使用するときは、組織プレフィックスを含む完全なモデル ID を渡してください:nvidia:nvidia/nemotron-3.5-lightning-30b-a3b(プロバイダーのコロンの後に完全なモデル ID)。nvidia:nemotron-3.5-lightning-30b-a3b(nvidia/ プレフィックスなし)を渡すと、HTTP 404「page not found」が返されます。NIM では API ペイロードに完全な nvidia/... モデル ID が必要です。
  • Nemotron 3.5 Lightning の無料枠でのツール呼び出し — tools に対応しているのは、OpenRouter の :free サフィックスと NIM の直接利用のみです。OpenRouter の有料枠(:free なしの nvidia/nemotron-3.5-lightning、CoreWeave ホスト)は、tools を指定すると HTTP 404 を返します。nvidia:nvidia/nemotron-3.5-lightning-30b-a3b(NIM、無料、安定)または openrouter:nvidia/nemotron-3.5-lightning:free(無料ですが、502 が発生しやすい)を使用してください。
  • NVIDIA のモデル一覧は古くなっています — /v1/models エンドポイントには多数のモデルが掲載されていますが、その大半は呼び出すと 404/410 を返します。2026 年 6 月時点で動作していたのは meta/llama-3.1-70b-instruct、meta/llama-3.3-70b-instruct、mistralai/mixtral-8x7b-instruct-v0.1 のみです。比較に使う前に、必ず簡単なチャット補完でモデルが動作することを確認してください。現在動作するモデル一覧は references/provider-tool-support.md を参照してください。
  • ツール呼び出しへの対応を決めつける — すべてのモデルが tools API パラメーターに対応しているわけではありません。まず簡単なツール呼び出しリクエストでテストしてください。テキスト内で「search」と言及しても tool_calls を出力しないモデルは、ツール呼び出しに対応していません。テスト済みの一覧は references/provider-tool-support.md を参照してください。
  • すべてのモデルがツール呼び出しに対応しているわけではありません — deepseek-v3.2(Ollama Cloud)はテキスト内で「search」と言及しますが、tool_calls は出力しません。mistralai/mixtral-8x7b-instruct-v0.1(NVIDIA)は、tools パラメーターを指定すると HTTP 400 を返します。--mode tools を実行する前に、モデルごとにツール対応をテストしてください。references/provider-tool-support.md を参照してください。
  • 精度を伴わない効率化は無駄です — 少ないトークンで誤答するモデルは効率的ではありません。効率の統計は、必ず評価者のスコアと照らし合わせてください。gemma4:31b は 949 トークン、2 ターンで回答しましたが、Python 3.13 と誤答しました。kimi-k2.5 は 5434 トークン、5 ターンを要しましたが、信頼できる情報源に基づいて正答しました。
  • ツール呼び出しループが最大ターン数に達することがあります — モデルによっては、情報をまとめずに検索を続けることがあります。デフォルトの上限である 10 ターンは、TEST_BANK の max_turns でテストごとに設定可能で、無限ループを防ぎます。ただし、結果には「収束しなかった」と記録されます。トレースの converged フィールドを確認してください。ターン数を増やすと、まとめるのにより多くのターンが必要なモデルに役立つことがあります。ただし、収束せず同じ URL を繰り返し検索するモデルには注意してください。まとめる能力のないモデルにターン数を増やしても解決しません。
  • --max-turns による CLI 上書き機能はありません(2026-07-17 修正) — 以前のスクリプトでは、TEST_BANK 辞書内のテストごとの max_turns のみがサポートされており、ターン数の上限を変更するにはソースを編集する必要がありました。そのため、ソースを修正するにはバックグラウンド実行を停止する必要がありました。現在は --max-turns N で実行時に上書きできます。フラグが機能しない場合は、compare.py に --max-turns の引数パーサーエントリーがあることを確認してください。
  • ユーザーはコスト削減のために CLI モデルを好みます — ユーザーが「use codex cli for gpt5.6」または「use cursor-grok-4.5-high」と言う場合、OpenRouter のトークンごとの課金を避けたいという意図です。GPT-5.6 は Codex CLI、Grok 4.5 は Cursor CLI 経由で使用し、OpenRouter は使わないでください。上記の Hybrid Mode セクションを参照してください。これは一度限りのリクエストではなく、コストに関する希望です。
  • Codex CLI のモデルバージョン制限 — v0.135 では、codex exec -m gpt-5.6-sol は「requires a newer version of Codex」で失敗します。まず簡単なプロンプトでテストしてください(codex exec --skip-git-repo-check -m <model> "say hello")。新しいモデルに対応していない場合は、gpt-5.5 に切り替えてください。
  • Codex CLI には --skip-git-repo-check が必要です — このフラグがないと、Codex は git リポジトリの外での実行を拒否します。必ずこのフラグを含めてください。
  • Web アクセスには Cursor CLI の --force が必要です — --trust --sandbox disabled だけでは、ヘッドレスモードで Web 検索は有効になりません。Web リクエストは引き続きブロックされます。Web アクセスを有効にするには、--trust も有効にする --force を使用してください。3 回の試行で確認済みです:--trust → ブロック、--trust --sandbox disabled → ブロック、--force → 動作。
  • OpenRouter の地域制限付きモデル — 一部のモデル(例:meta/muse-spark-1.1)は、米国外から呼び出すと HTTP 403「This model is only available in the United States」を返します。米国のプロキシなしでは回避策はありません。米国外から実行する比較では除外してください。
  • SearXNG のデフォルトエンジンでは検索結果が 0 件になることがあります — Google、DuckDuckGo、Brave、Startpage、Mojeek のエンジンは、セルフホストの SearXNG で頻繁に失敗します(レート制限、CAPTCHA)。安定して結果を返すのは Bing と Yandex のみです。スクリプトの execute_web_search は、現在 &engines=bing,yandex,duckduckgo,google を明示的に渡します。すべてのクエリで検索結果が 43 文字の {"results": [], "note": "No results found"} になる場合は、curl -s "http://$SEARXNG_URL/search?q=test&format=json&engines=bing" で SearXNG エンジンの状態を確認し、scripts/compare.py のエンジン一覧を更新してください。
  • DDGS CLI の構文が変更されました — 古い ddgs --json -q ... -m ... 構文は現在動作しません。新しい CLI では ddgs text -q ... -m ... -o <file> を使用します(標準出力ではなくファイルに出力します)。スクリプトの DDGS フォールバックは、新しい構文を使うよう更新されています。フォールバックが失敗する場合は、ddgs text --help で確認してください。
  • SEARXNG_URL がバックグラウンドプロセスにエクスポートされません — 環境変数は、スクリプトの load_env() 関数によって ~/.hermes/.env から読み込まれます。ただし、バックグラウンドプロセス(例:terminal(background=true) 経由)に --mode tools を渡す場合は、コマンド内で export SEARXNG_URL=http://... を明示的に指定してください。load_env() 関数は、os.environ にまだ存在しない変数だけを設定しますが、バックグラウンドシェルの環境は最小限です。
  • compare.py には 2 つ以上のモデルが必要です — モデルを 1 つだけ渡すと、スクリプトは「Error: need at least 2 models to compare」で終了します。レート制限後に 1 つのモデルを再試行する場合は、スクリプトではなく直接 curl API 呼び出しを使用してください。
  • 推論 effort レベルの比較はネイティブで可能です(v1.2.0) — --models と --judge では provider:@effort:model_id 構文を使用してください(上記の「Reasoning-effort A/B」セクションを参照)。旧式のラッパーハーネス方式(/root/.hermes/cache/ab_effort_run.py、ローダースクリプトで仮想プロバイダーを登録)は、テストごとの正解判定を含む複数テストのバッテリーで引き続き使えます。ネイティブ構文は単一実行の比較に対応します。CLI 評価者(例:Codex gpt-5.6-sol)を使う場合は、評価基準と匿名化した回答を一時ファイルに書き込み、codex exec --skip-git-repo-check -m gpt-5.6-sol "Read the file <path> and follow the instructions inside" を実行し、標準出力と標準エラー出力から JSON を解析して、テストごとに Response 1/2 の順序をシャッフルしてください。code_review テストの正解データは、TEST_BANK の evaluation と planted_issues キーから取得します(evaluation_criteria ではありません)。判明している結果(glm-5.3-flash、2026-08-29):effort と推論トークン数の関係は単調ではありません(high がより多く思考するとは限りません)。長いツールチェーンでは high が 12 ターンで収束しなかった一方、medium は収束しました。品質では medium が 4-2-2 で勝利しました(平均 8.6 対 7.8)。high の中央値は約 3 倍高速でした。
  • OpenRouter での Kimi K3 のレート制限 — moonshotai/kimi-k3 は、特に複数テストを並列実行すると、共有 OpenRouter プールで HTTP 429 が発生します。15~30 秒待って再試行するか、OpenRouter に Moonshot API キーを追加して(BYOK)、専用のレート制限を利用してください。
  • Sandbox テスト(S1~S5)には 5 つのツールに対応するモデルが必要です — sandbox テストでは、5 つすべてのツール定義(web_search、web_extract、run_python、read_file、write_file)をモデルに渡します。モデルによっては、5 つのツールを使ったツール呼び出しに対応していない場合や、一度に 1~2 個のツールしか扱えない場合があります。リサーチテスト(A/B/C)は通過するのに sandbox テストで失敗する場合は、ツール定義の数に圧倒されている可能性があります。まず、より簡単な sandbox プロンプトでテストしてください。
  • Sandbox の Python 実行はネットワークから隔離されていません — run_python ツールは subprocess.run([sys.executable, script]) を実行するため、コードが urllib や socket をインポートするとネットワーク呼び出しが可能です。10 秒のタイムアウトで被害を制限できますが、本当の sandbox ではありません。本番環境での強化には、コンテナーまたは seccomp フィルターの使用を検討してください。モデル比較では、このタイムアウトで十分です。
  • Sandbox の一時ファイルはモデルごとにクリーンアップされます — run_tool_loop 関数はモデルごとに一時ディレクトリを作成し、finally ブロックでクリーンアップします。モデルがファイルを書き込み、後のターンで読み戻す場合は、同じ sandbox ディレクトリがターン間で維持されるため、問題ありません。スクリプトが実行途中でクラッシュした場合も、finally ブロックによってクリーンアップされます。
  • Sandbox の出力は 2000 文字に切り詰められます — run_python は標準出力と標準エラー出力をそれぞれ 2000 文字に切り詰めて返します。モデルが大量の出力(例:大きなリストの表示)を生成すると、切り詰められた出力によって混乱することがあります。簡潔な形式で出力するモデルは、sandbox テストでより良い結果を出せます。

関連プロジェクト

Odysseus — PewDiePie のセルフホスト可能な AI ワークスペース — には、概念的に似た目標(匿名での提示、評価、結果の公開)を持つ、モデルを匿名で並べてテストする「Compare」機能が含まれています。このスキルは異なるアプローチを採用しており、UI を使わず、純粋なプロンプトと標準ライブラリのスクリプトで構成され、スタンドアロンのウェブアプリではなく、あらゆるエージェントのツールループ内で実行できるよう設計されています。Odysseus はまた、ファインチューニングされた Qwen 32B モデルが Aider Polyglot ベンチマークで 39%を記録したと報告しており、モデル比較の調整に役立つデータポイントです。

コメント