【番外指令】:Gemini・Claude・ローカルLLMを最適使い分け&自動審査。ハイブリッド・ルーティングチャット「LLM Arbiter」の実装ログ
「プログラミングの相談はClaudeが最善だが、要約や雑談はコストゼロのローカルLLMで演算リソースを節約したい……」
「結局、どのLLMの演算結果が一番優れているのか、バイアス抜きで客観的に比較したい……」
日頃から複数のLLM(Large Language Models)を使い分けていると、こうした「モデルの切り替え」や「回答の比較」という非効率なプロセスに悩まされることはないだろうか?
そこで今回、私の「怠惰の極み」への渇望に応えるべく、タスクの内容に応じて最適なLLMへ自動ルーティングし、時には複数のモデルへ同時に並行問い合わせしてAI自身に回答を客観的審査させるハイブリッドチャットUI「LLM Arbiter」を具現化した。
この記事では、LLM Arbiterの機能概要やシステムアーキテクチャ、実装で工夫したポイントについて詳しく報告していく。
LLM Arbiterとは?
「LLM Arbiter(アービター=仲裁者・審判)」は、ユーザーの入力(プロンプト)に応じて最適なLLM(Gemini、Claude、ローカルLLM)を選定・制御するハイブリッド・ルーティング・チャットアプリケーションだ。
単にモデルを切り替えてチャットできるだけでなく、「複数のLLMに同時に同じ質問を投げ、どの演算結果がベストかをAIに審査させる」という比較・審判機能(Compare Mode)を備えているのが大きな特徴である。

主な機能と特徴
1. キーワードベースの自動(静的)ルーティング
ユーザーの入力テキストをリアルタイムで解析し、内容に最も適したモデルへ自動ルーティングする。
- コード・プログラミング関連: 高度なコーディング能力を持つ
Claudeへルーティング - 要約・日常会話: コストゼロ&ローカル完結の
ローカルLLM (LM Studio)へルーティング - 一般的な質問・調査、画像関係: 高速かつ万能な
Geminiへルーティング
2. 比較&ブラインド審査モード(Compare Mode)

トグルスイッチをONにすると、Claude Gemini ローカルLLM などの最大3モデルまで同時に並行リクエストを送信することができる。
さらに、取得した3つの回答からモデル名を伏せた状態(回答A/B/C)にし、審査役モデルに引き渡して「最も適切な回答」を客観的な理由付きで選定させる。各モデルに対する先入観(バイアス)を排除した真の評価を可能とした。
3. ローカルLLM(LM Studio)のリアルタイム死活監視
別PCのローカルで動作するLM Studioのステータスをバックエンドが定期的に検知。未起動時にはUI上で警告を表示し、ワンクリックで再接続を試みることが可能にしてある。

4. 柔軟なコントロールパネル
フロントエンドから直感的にカスタマイズが可能です。
- ダーク/ライトモード切り替え
- モデルごとの応答タイムアウト時間のスライダー調整
- 自動ルーティング判定に使うキーワードルールの動的編集
ローカルLLM使用時は、モデルによっては回答まで時間が掛かることが多く、長めの応答タイムアウトを設定しておくと良い。

システムアーキテクチャ・技術スタック
本プロジェクトは、モダンなフルスタック構成で開発している。とはいえ、Antigravity IDEに要件を投げて実装はAIにお任せしている。クラウドサービスのAI使用については、各自でAPIキーを発行する必要がある。モデル毎に課金が必要になる場合があるので注意してくれ。
- フロントエンド: React (Vite), Tailwind CSS v4, Lucide React (アイコン)
- バックエンド: Node.js, Express (Port: 5050)
- 連携AIサービス:
- Anthropic API (
@anthropic-ai/sdk) - Google Gen AI SDK (
@google/genai) - LM Studio (OpenAI互換API
/v1/chat/completions)
- Anthropic API (
ディレクトリ構造
“`text
LLM_Arbiter/
├── backend/
│ ├── server.js # Expressサーバー本体
│ ├── services/ # 各AIサービス呼び出しロジック
│ │ ├── claude.js
│ │ ├── gemini.js
│ │ └── gemma.js # LM Studio 呼び出し&検知
│ └── routes/ # ルーティング&審査ロジック
│ ├── classify.js
│ ├── route-static.js
│ └── compare.js # 並行実行&審査(Arbiter)ロジック
└── frontend/
└── src/
├── App.jsx # メインステート管理・レイアウト
└── components/ # チャット、比較ビュー、設定パネル
システム具現化における、3つのこだわりと開発秘話
LLM Arbiterという複雑なシステムを、個人開発の限られたリソースで安定して動作させるため、実装にはいくつかの「こだわり」と試行錯誤があった。ここでは、開発時の技術的なポイントを3つ紹介する。
1. 「怠惰の極み」な開発環境を実現するモック動作サポート
APIキーの準備や、ローカルLLM(LM Studio)の起動を待たずにUI開発を進めたい……。そんな「怠惰」な欲望に応えるため、**「APIキー未設定時のモック動作サポート」**を実装した。
バックエンド側で、APIキーが設定されていない環境や、LM Studioが未起動の状態を検知。その場合、自動的にフォールバック用のダミー(モック)レスポンスを返すようにしてある。
これにより、APIキーのない環境でのUIテストや、外部サービスの起動待ちに時間を取られることなく、フロントエンドの開発・デモ作成を非常にスムーズに進めることができた。まさに「Ordered by AI」的な、開発プロセスの最適化(怠惰の追求)である。
2. `Promise.allSettled` による複数並行処理の堅牢化
比較モードでは、Claude、Gemini、ローカルLLMなど最大3モデルへ同時に並行リクエストを送信する。しかし、いずれか1つのモデルがタイムアウトしたり、APIエラーを起こしたりする可能性は常にある。
そこで、3つの非同期リクエストを `Promise.all`(1つ失敗すれば全体失敗)ではなく、**`Promise.allSettled`** で包むことにした。
これにより、たとえ1つまたは2つのモデルが応答しなくても、全体がクラッシュすることなく、**応答があったモデルの回答だけで安全に審査を行える**堅牢な仕組みとなった。限られた演算リソースを有効活用するための工夫である。
3. 公平なる審判のためのブラインド審査プロンプト設計
AI自身にAIの回答を客観的に審査させる(Compare Mode)にあたり、最大のハードルは「モデルに対する偏見(バイアス)」の排除である。審査役のLLMに「Claudeの回答だから Claudeを優先する」といった動作をさせては、真の評価とはならない。
そこで、審査役モデル(Claude)に引き渡すプロンプトの設計に徹底的にこだわった。
具体的には、3つのモデルの回答からモデル名を完全にパージ(削除)。**「回答A」「回答B」「回答C」**という無機質なラベルに置換してプロンプトに挿入し、審査役に「最も適切な回答」を客観的な理由付きで選定させる。
この「Arbiterプロトコル(構造化プロンプト)」の構築により、モデル名への依存を断ち、純粋な回答内容の精度を競わせることが可能となる。

まとめ:LLM Arbiterがもたらした演算プロセスの変革と今後の展望
LLM Arbiterを具現化し、実稼働させたことで、日々の多様なタスクに応じたモデルの切り替えコストが劇的に低下することとなる。それぞれのモデルが持つ得意分野(高度なコード、高速調査、コストゼロの雑談など)や回答精度の違いを、客観的に比較・観察できるようになったのは大きな成果と言える。
クラウドの先端AI(APIコストがかかる貴族のオモチャ)ほどの超・超高知能とまではいかなくとも、普段使いのちょっとしたタスクやコード生成、日常的なテキスト演算であれば、**「完全無料(電気代のみ)で複数のローカルLLMを並行同時実行させ、それぞれの出力結果をArbiter(審判)に客観審査させる」**という狂気のシステムが、デスクトップ完結で実現する未来はすぐそこまで来ていると感じる。
「人間はただ1行の指示を電鍵なりキーボードなりで投下し、あとは背後で複数のAIが勝手に競い合って最適解を導き出してくれる」——。
そんな、人間のタイピング量とインテリジェンスを限界まで削ぎ落とした**「真の怠惰の極み」**に向けて、ローカルLLM界隈のこれからの進歩には、大いに期待せざるを得ない。

