← ブログに戻る

Agentic RAGで11.8点:検索を選ばせる

「エージェントが自律的に判断」と書いてある解説を読んでも、結局コードで何が変わるのかが分からない。私も長いこと分かりませんでした。答えは拍子抜けするほど単純です。どのインデックスを叩くかを、if文で書かず、LLMに選ばせる

それだけです。

先に断っておくと、この11.8はAgentic RAG自体の実測値ではなく、その土台にあたる本の通常RAG実験の数字です。私が書いた本で、Haiku 3+RAGがSonnet 4単体の約2.2倍のスコアを出しています(11.8 vs 5.3)。数字自体はセンセーショナルですが、仕組みはむしろ地味で、地味なぶんちゃんと再現します。

従来RAG vs Agentic RAG:何が違うか

従来のRAGは、質問が来たら必ずベクトル検索を叩きに行きます。

class TraditionalRAG:
    def query(self, question: str):
        query_vector = self.embedder.embed(question)
        docs = self.vector_db.similarity_search(query_vector, k=5)
        return self.llm.generate(question, docs)

固定戦略です。

相手が「昨日のデプロイのログ」を聞いてきても、「Elixirの型システム」を聞いてきても、同じベクトル検索が走る。ドキュメントがベクトル空間で近ければ拾える、遠ければ拾えない。Agentic RAGは、この最初の「どのツールで探すか」からLLMに委ねます。

TOOLS = {
    "semantic": SemanticSearch(),   # 意味の近い文書
    "keyword": KeywordSearch(),     # 完全一致・型名・エラーID
    "graph":   GraphSearch(),       # 依存関係・エンティティ間の道筋
    "log":     TimeSeriesSearch(),  # 時刻範囲でイベントを引く
}

def route(question: str) -> str:
    """LLMに『どのツールを使うべきか』だけ答えさせる"""
    return llm.classify(
        question,
        options=list(TOOLS.keys()),
        rubric="固有名詞・エラーコードならkeyword。時刻範囲ならlog。"
                "関係を辿るならgraph。それ以外はsemantic。"
    )

def agentic_query(question: str):
    tool_name = route(question)
    docs = TOOLS[tool_name].search(question)
    return llm.generate(question, docs)

分岐条件を書き下していないのに、route() は「ImportError X0F32の直近ログ」なら log を選び、「User と Session の関係」なら graph を選びます。LLMが得意な仕事は「短い文字列を見て、有限の選択肢から1つ選ぶ」ですから、これは本来LLMの得意分野です。ルールを書く側が消耗する分岐条件を、LLMに肩代わりさせている。

「Haiku+RAG=11.8 vs Sonnet=5.3」の内訳(本の通常RAG実験)

本の中で走らせた通常RAG実験の一部を、ここで抜き出しておきます。同じベンチマークを4条件で回した結果で、Agentic RAGはこのRAG基盤の上に「どの検索を叩くか」の判断層を足す型です。

条件スコア相対コスト
Sonnet 4(Zero Context)5.312x
Sonnet 4 + Full Context Engineering11.412x
Haiku 3(Zero Context)2.21x
Haiku 3 + RAG11.8~1.5x

Sonnetの単体スコア(5.3)を、Haikuに正しい文脈を渡した状態(11.8)がきれいに超えました。しかもコストはSonnetのおよそ8分の1(RAGの計算コストを50%乗せた見積もり)。上位モデルを買うより、下位モデルに情報を渡すほうが安くて強い、というのが本の主張の中核です。面白いのは、Haikuの「Full CE版(10.1)」よりも「RAGだけ版(11.8)」のほうが高いこと。

足せば足すほど良い、ではない

この問題領域ではRAGが最も効く、というだけの話で、逆に別のタスクではFull CEが勝つ場面もあります。Agentic RAGの本当の価値は「その判断を毎回LLMがやってくれる」点にあります。人間が経験則でチューニングしていた「どの技法をどこで使うか」を、実行時にオフロードできる。

実装3ステップ

自分のプロジェクトに乗せるときの最短経路は、こう組みます。

1. ツールを4つ以下に絞る。SemanticSearch/KeywordSearch/GraphSearch/LogSearchの4種で、実務のクエリの9割は捌けます。5個目を足したくなったら、選択肢が増えるほど誤ルーティングが増えるので、まず既存の4つで足りない事例を10件集めてから決めます。

2. route() のプロンプトに「判断rubric」を書く。LLMに丸投げすると、意味検索とキーワード検索の差を体感で選び分けてくれません。「固有名詞・エラーコード・型名ならkeyword」のように、判断の要件をコードコメントに書かず、rubricに落とす。これがAgentic RAGで最も泥臭い工程で、最も効きます。

3. routingログを残す。どの質問がどのツールに振られたか、結果が良かったか悪かったかを(question, tool, feedback)で保存。ここに数百件溜まると、rubricを更新すべき箇所と、Haikuでは無理でSonnetに上げるべきクラスが見えてきます。3ステップの中で一番地味なのが3番目で、一番後回しにされて、一番後で泣くのも3番目です。

検索精度で見た改善幅

従来RAGの検索精度は70-80%のあたりで頭打ちします(質問とドキュメントのベクトルが離れているケースを拾えない)。Agentic RAGは85-95%まで上がるという報告があります。上がる理由は単純で、ベクトル検索が苦手なクエリ(完全一致・時系列・エンティティ関係)を、LLMが別のツールにルーティングしているからです。ベクトルが全能でないことを認めれば、それを補うツールを別立てで動かすのは自然な発想です。

関連する話として、GraphRAGでLinkedInが問題解決時間の中央値を28.6%短縮した事例は、まさに「グラフ検索を別ツールとして立てた」パターンです。Agentic RAGのroutingがGraph側を選ぶかSemantic側を選ぶかは、質問の型で決まります。同じく、ナレッジグラフ構築の7ステップを先に整えておくと、GraphSearchが答えられる質問の面積が広がって、routingの候補として意味を持つようになります。

まとめ

  • Agentic RAGは「どのツールで検索するか」自体をLLMに選ばせるアーキテクチャ。従来RAGの固定ベクトル検索と根本的に違うのはここ
  • 本の通常RAG実験ではHaiku 3+RAG(11.8)がSonnet 4単体(5.3)の約2.2倍を記録(Agentic RAG自体の実測値ではなく、その土台側の数字)。上位モデルを買うより、下位モデルに正しい文脈を渡すほうが安くて強い
  • 実装は3ステップ: (1)ツールを4個以下に絞る (2)routingプロンプトにrubricを書く (3)routingログを残す
  • 一番地味な3番目を最初にやらないと、後でrubricのチューニング材料が無くて泣く

「エージェントが自律的に判断」と書かれた解説は多いけれど、実装上は「LLMに1回追加のclassifyを走らせる」だけです。

魔法ではありません。

ただ、その1回の分岐で、倍以上の性能差がつくことがある。魔法じゃない代わりに、地味に効きます。

もっと踏み込んだContext Engineeringの型と実験結果は、書籍にまとめました。

コンテキストエンジニアリング入門

LLMを「嘘つき」から「専門家」に変える技術 関連書籍 LLMを「嘘つき」から「専門家」に変える技術 Context Engineering 実践入門 | RAG・MCP・CLAUDE.md・Agentic RAG をベンチマークで体系化 書籍ページを見る →