LLM Council:複数のモデルに審議させる locaux
LLM Councilは、Andrej Karpathyが2025年末に公開した小規模なプロジェクトです。1つのモデルに質問を送る代わりに複数のモデルに質問を送り、各モデルが誰の回答かを知らずに他の回答を順位付けし、「議長」モデルが最終的な要約を作成します。リポジトリはOpenRouter経由のクラウドモデルを対象としていますが、その仕組みは約100行に収まり、Ollamaによって提供されるローカルモデルにも移植できます。このガイドでは3つのステップを説明し、個人用マシンで再現する方法、メモリと時間にかかるコスト、そして評議会が単独の優れたモデルより優れた回答を返すと想定してはいけない理由を詳しく解説します。
#LLM Council:3段階の仕組み
このリポジトリでは、三段階の固定されたフローが説明されています。各段階はツールもメモリも使わない通常のモデル呼び出しです。唯一の工夫は、最初の段階の出力を後の二段階にどのように渡すかにあります。
- 01最初の意見ユーザーの質問は、そのまま各評議会メンバーに個別に送信されます。各メンバーは他のメンバーの回答を見ずに回答します。元のインターフェースでは、これらの回答はモデルごとに一つのタブに表示されます。
- 02校閲と順位付け続いて各メンバーは、他のメンバーの匿名化された回答(「回答A」、「回答B」などのラベル付き)を受け取り、正確さと深さを基準に、最良の回答から最も低い回答まで順位付けします。匿名化は、モデルが既知の競合相手をえこひいきしたり、不利に扱ったりするのを避けるためのものです。
- 03議長による要約議長として指定されたモデルは、質問、すべての回答、すべての順位を受け取り、ユーザーに提示する単一の最終回答を作成します。
この構成では異なるモデルは必要ありませんが、それこそが要点です。学習の多様性に頼ることで、あるモデルの誤りを別のモデルが見つけられるようにします。議長はメンバーの一つでも、別のモデルでも構いません。通常は一覧中で最も能力の高いモデルにします。
#Karpathyのリポジトリに含まれるもの
あなたのマシンで動作するエージェント:エージェント型 Cline、MCP、n8n + Ollama、ローカル自動化。
- 永久に利用できるオンラインスペース
- PDF + ファイル
- 生涯アップデート
github.com/karpathy/llm-councilリポジトリは、一般的なチャットインターフェースに似たローカルWebアプリケーションです。執筆時点のREADMEと設定ファイルによれば、次の要素で構成されています。
- Pythonバックエンド(FastAPI)
- backend/フォルダーには、3つのステップのロジック、OpenRouterのAPI用HTTPクライアント、data/フォルダー内のJSONファイルへの会話保存が含まれています。依存関係はuvで管理されます。
- Reactフロントエンド(Vite)
- frontend/ ディレクトリ:個々の回答、ランキング、要約を表示するインターフェースです。
- 設定ファイル
- backend/config.pyには、評議会のメンバー(COUNCIL_MODELS)と議長(CHAIRMAN_MODEL)がOpenRouterの識別子として、呼び出されるAPIのアドレスとともに記載されています。
- 起動スクリプト
- start.sh はバックエンドとフロントエンドを同時に起動します。.env ファイルには OPENROUTER_API_KEY が必要です。
デフォルトで設定されているモデルは、クローズドなクラウドモデルです(公開版ではGPT、Gemini、Claude、Grokの各ファミリー)。ローカル版にするには、ここを変更します。APIがOpenAIによって普及した「chat completions」形式を扱える限り、残りのコードは誰が回答するかを気にしません。このガイドに従う前にREADMEとconfig.pyを読み直してください。プロジェクトは2026年10月12日以降に変わっている可能性があります。
#ローカル版の前提条件
- Ollamaがインストールされ、動作している状態
- サーバーはデフォルトで http://localhost:11434 をリッスンします。ollama list コマンドでモデルが表示されることを確認してください。
- 異なるファミリーの3〜4モデル
- 同じファミリーに由来するモデルだけで構成された評議会では、多様性の利点が失われます。例えば、Qwen、Llama、Mistral、Gemmaを、近いサイズで組み合わせることを目指してください。
- 適切なメモリ
- Q4_K_Mでは、7Bモデル1つあたり約5 GB、14Bモデル1つあたり9 GBを見込んでください。メンバーはすべてを同時にメモリへ収める必要はありませんが、快適さはメモリ容量に左右されます(コストに関するセクションを参照)。
- Python 3.10以降
- このガイドの最小スクリプトではrequestsパッケージを使います。元のリポジトリでは、さらにuvとNode.jsが必要です。
- Patience
- 一回の審議には、メンバー数の少なくとも二倍に加えて一つ、つまりそれ以上の生成が必要です。これは即時チャット用のツールではありません。
#ステップ1:評議会と議長を選ぶ
メンバーの選択では、多様性とメモリのバランスが重要です。一方、議長には長いコンテキストを正確に読む能力が特に求められます。議長は質問、すべての回答、すべての順位を受け取るため、容易に数千トークンになります。この役割には、処理が遅くても、お使いのマシンがサポートする中で最も高性能なモデルを選んでください。1ターンにつき一度しか呼び出されないためです。
7Bから8Bのサイズなら、12 GBのカード上のメンバーに適しています。一つだけならコンテキスト用の余裕を残してメモリに収まり、Ollamaがそれらを切り替えます。24 GB、または48 GBのユニファイドメモリを搭載したMacなら、メンバーを14Bに上げるか、二つから三つのモデルを同時に読み込めるため、再読み込みをなくせます。
#手順2:複数のモデル向けにOllamaを設定する
ここではOllamaに関する2つの設定が重要です。1つ目はメモリに保持するモデル数で、OLLAMA_MAX_LOADED_MODELS変数で指定します。メモリが許せば、すべてのメンバーをロードしたままにすることで、メンバーを切り替えるたびの再ロードを避けられます。2つ目はコンテキストウィンドウのnum_ctxで、Ollamaではデフォルトが短く設定されています。順位付けのステップと議長による要約では複数の完全な回答を読み込むため、コンテキストが小さすぎるとプロンプトの冒頭がひそかに切り捨てられます。
macOSでは、アプリケーションを再起動する前にlaunchctl setenvを使って同じ変数を設定します。OLLAMA_MAX_LOADED_MODELSの値は、使用可能なメモリと整合させる必要があります。コンテキストを含めると、Q4の8Bモデル2つだけですでに約10 GBを占有します。コンテキスト自体は、リクエストごと(APIのoptions.num_ctxフィールド)または派生したModelfileで設定します。次のセクションでは、これを各呼び出しに渡します。
#ステップ3:Pythonによる最小限の評議会
以下のスクリプトは、インターフェースなしでOllamaのネイティブAPIを使い、評議会の三段階を再現します。ラベルから著者が推測されないよう、順位付けの前に回答の順序を混ぜ、各メンバーに短い順位付けを求めてから、すべてを議長に委ねます。モデル名はお使いのマシンにあるものに合わせてください。
元のリポジトリはさらに踏み込み、各判定役の順位付け行を抽出して回答ごとの平均順位を計算し、タブの横に表示します。各出力の「CLASSEMENT:」行を読み取れば、数行で追加できます。ただし、小規模モデルはこの形式に必ずしも従わないため、この行がない場合のフォールバックを用意してください。
#ステップ4:元のリポジトリをOllamaに適応させる
Webインターフェースが必要なら、最短の方法は、Ollama のOpenAI互換エンドポイントを使用することです。このエンドポイントは http://localhost:11434/v1/chat/completions で提供されています。リポジトリのバックエンドはすでにこの形式でOpenRouterにリクエストを送信しているため、原則として backend/config.py のAPIアドレスとモデル識別子を置き換え、ダミーキー Ollama を設定するだけで済みます。これは認証ヘッダーを無視します。
手作業で対処すべき点が二つ残っています。まずコンテキストです。OpenAI互換のエンドポイントにはnum_ctxフィールドがないため、コンテキストを固定するModelfileでモデルのバリエーションを作るか、オプションを受け付ける/api/chatのネイティブAPIにクライアントを切り替える必要があります。次に、先ほど述べた並列性です。第一段階では呼び出しを同時に開始するため、メンバーをすべてメモリに収められない場合は逐次実行に切り替える価値があります。
複数のコミュニティ製フォークが、Ollama やその他のローカルサーバー向けにこれらの変更を行っています。いずれかを採用する前に、最後のコミット日、元のリポジトリと比べて変更されたファイル数を確認し、モデルを呼び出すコードを読んでください。短いコードであり、違いが現れるのはそこです。このガイドでは特定のフォークを推奨していません。状態の変化が速すぎるためです。
#メモリと時間のコスト
取り組む前に、この計算を確認しておく価値があります。N人のメンバーによる審議では、完全な一回の処理にステップ1でN回、ステップ2でN回、議長用に一回の生成が必要で、合計2N + 1回の呼び出しになります。ステップ2と議長の呼び出しは、プロンプトにすべての回答が含まれるため、最初の呼び出しより処理に時間がかかります。プロンプトの読み取り時間が生成時間に加わるためです。
- 三人のメンバー
- 質問ごとに七回生成します。お使いのマシンで各回答に半分ほどの時間がかかる場合、再読み込みを除いても一巡に三分を超えます。
- 最小メモリ
- 評議会で最大のモデルとそのコンテキストです。Q4の8Bメンバーと16 000トークンのコンテキストなら、読み込むモデルを一つだけにすることを条件に、12 GBのカードに収まります。
- 余裕を持って使えるメモリ容量
- すべてのメンバーを同時に読み込みます。必要なのは、各モデルのサイズの合計に、モデルごとのコンテキストキャッシュを加えた容量です。Q4の8Bモデル三つには、最低でも24 GBのGPUまたは32 GBのユニファイドメモリを搭載したMacが必要です。
- Rechargements
- メンバーを一緒に収められない場合、モデルを切り替えるたびにディスクからの読み込みで数秒かかります。一巡では最大2N回発生します。NVMe SSDならこのコストを許容できますが、遅いディスクでは負担になります。
これらの概算値は、ハードウェア、量子化、回答の長さによって異なります。本記事ではターンの処理時間を測定しておらず、上記の数値は計算上の目安であって結果ではありません。自分のケースを評価するには、各メンバーで単純な生成にかかる時間を計測し、式を適用してください。
#評議会の限界とバイアス
この仕組みが魅力的なのは、ピアレビューに似ているからです。しかし、優れた単独モデルより必ず正確だと考えるべきではありません。リポジトリにはそれを裏付ける測定結果がなく、モデルを評価者として使う際に知られている複数のバイアスも、この仕組みに不利に働きます。
- 不完全な匿名化
- ラベルは名前を隠しますが、文体までは隠しません。モデルは自分独自の書き方、あるいは知っているモデルファミリーの書き方を認識し、それに応じて順位付けする可能性があります。Karpathy自身も、定性的な観察として、モデルはしばしば自分の回答より別のモデルの回答を好んだと記しています。これは観察であり、保証ではありません。
- 位置バイアスと長さバイアス
- 例えば、Zheng et al. (2023)によるMT-Benchの論文など、審判モデルに関する研究では、最初に読んだ回答や長い回答を好む傾向が記録されています。順序を混ぜることで前者のバイアスは弱められますが、後者はうまく補正できません。
- 相関したエラー
- 近いコーパスで学習したモデルは、同じような間違いをすることがよくあります。小規模モデルによる評議会が、誤った回答に全会一致で投票し、議長がそれを採用する可能性もあります。
- 議長だけが残る
- 統合結果は完全に議長モデルに依存します。議長が幻覚を起こせば、評議会は何も変えられません。重要な विषयでは個々の回答を読んでください。これは、元のインターフェースにタブがある理由でもあります。
- 小さなモデル、長い指示
- 順位付け用プロンプトには、三つまたは四つの文章を読み、判断し、根拠を示し、形式を守ることが求められます。7B未満では出力が不規則になり、平均順位の意味が失われます。
#ローカルLLM Councilの実際のユースケース
2N + 1回の生成による追加コストは、質問がまれで重要な場合には正当化できますが、雑談には向きません。ローカルでこのパターンを取り入れた人々からは、三つの状況が浮かび上がります。
- 機密性の高いテキストまたはコードの校閲
- 契約関連の文書、手順、重要な関数では、メンバーがそれぞれ異なる問題を指摘し、議長がそれらを一つのリストにまとめます。ここでは、順位付けよりも指摘の多様性が重要です。
- 根拠のある技術的判断
- 「このデータベースを移行すべきか」、「このエクスポートにはどの形式がよいか」など、回答の食い違い自体が情報になります。議長には、意見の相違を平滑化するのではなく、見える形にするよう求めてください。
- 単一モデルの品質管理
- 評議会を審査員として使い、二つのプロンプト版または同じモデルの二つの量子化を比較するには、別の場所で生成した出力を順位付けさせます。これは手順1を省いた、手順2の直接的な応用です。
これらすべてのケースで、ローカル版の本当の根拠は機密性です。元の版がOpenRouter経由で四つの異なるプロバイダーに送るのに対し、読み込む文書はマシンから外に出ません。待ち時間が数分になることを受け入れられるなら、内部データを扱うチームにとって、このパターンが興味深いものになる理由です。
#トラブルシューティング
- 順位付けで1つの回答が無視される
- コンテキストが短すぎ、プロンプトの冒頭が切り詰められています。num_ctx(またはModelfile)を増やし、Ollamaのログに切り詰めに関する警告がないことを確認してください。
- 手順1の呼び出しが非常に遅い
- メンバーは並列に呼び出されるため、メモリ上で競合します。逐次実行に切り替えるか、VRAMに同時に収まる範囲まで評議会を縮小してください。
- 議長が論点から外れた回答をする
- このモデルのコンテキストは、今回の処理で最も多く使用されています。より大きなモデルを割り当てるか、ランキングを要約してから渡してください。
- 順位付け形式がない
- 小型モデルは「CLASSEMENT :」の行を忘れます。プロンプトの末尾で形式を再度示し、温度を下げるか、根拠を手作業で読むことを受け入れてください。
- メンバーの回答が空、または英語になっている
- モデルが思考フェーズだけを返していないことを確認し、質問内で期待する言語を明示してください。
- 数回の一巡後にメモリが飽和する
- OLLAMA_MAX_LOADED_MODELS がマシンに対して高すぎます。1に戻し、Ollama に切り替えさせてください。
#さらに詳しく
LLM Councilはエージェントのフレームワークではなく、審議のパターンです。ツール、役割、メモリは管理しません。必要が意見の統合を超える場合は、サイト上のこれらのガイドで関連する構成要素を扱っています。
- Ollamaを使ったCrewAI
- 同じ回答を評価するのではなく、モデル同士で役割を分担し、タスクを順番に進める必要がある場合。https://quelllm.fr/guide/crewai-ollama-multi-agents
- ローカルゲートウェイとしてのLiteLLM
- 例えば、二台のマシンに分散した評議会のように、複数のモデルサーバーをOpenAI互換の単一APIの背後に公開するためのものです。https://quelllm.fr/guide/litellm-proxy-gateway-local
- ローカルAIエージェントのアーキテクチャ
- モデルにツールとメモリを与えたいとき、その周囲に組み合わせるコンポーネントです。https://quelllm.fr/guide/agent-ia-local-architecture
- ローカルネットワーク上でOllamaサーバーを共有する
- 評議会のメンバーをより大きなマシンでホストし、お使いの端末から呼び出します。https://quelllm.fr/guide/ollama-serveur-reseau-local-partage
KarpathyのGitHubリポジトリとOllamaのドキュメントに基づき、2026年10月12日に作成したガイドです。この記事では時間も品質も測定していません。メモリの目安はQ4_K_Mでのおおよその値です。定数名、ポート、モデル名は変わるため、コマンドをコピーする前に以下のソースを読み直してください。
- GitHubリポジトリ karpathy/llm-council(README、backend/config.py、start.sh)
- Ollamaのドキュメント(ネイティブAPI /api/chat、OpenAI互換、環境変数)
- Zheng et al., 2023:Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena(審判モデルのバイアス)
ご意見、誤りのご指摘、補足はありますか?ぜひお知らせください。皆さんにとってより良いガイドにするために役立ちます。