GEMINI LABEN
NANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定ですNANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定です
記事一覧/API / SDK
API / SDK/2026-05-05中級

Gemini RAGの選び方 2026 — シンプル・Advanced・Agenticの3パターンを実装で比べた

Gemini APIを使ったRAG実装の3パターン(シンプル・Advanced・Agentic)を実際のコードで比較。ユースケース別の選択基準と、最初にどこから始めるべきかを解説します。

Gemini API191RAG15LLM2embeddings11Python38AI開発8text-embedding-004

「RAGを作りたいけど、どのアプローチで実装すればいいか分からない」という相談を、最近よく受けます。

シンプルなベクトル検索でいいのか、クエリ変換やリランクを組み込んだAdvanced RAGが必要なのか、それともLLMが自律的に検索を繰り返すAgentic RAGまで踏み込むべきなのか。選択肢が増えるにつれて、かえって判断が難しくなっています。

私が複数のプロジェクトで試してきた経験から言うと、「最初に正解のパターンを選ぼうとしないこと」が一番大切です。ただ、その前提として各パターンの実際の動きとコストを把握しておく必要があります。ここでは3つのパターンを実際のコードで比較しながら、どのケースで何を選ぶかの判断軸をまとめます。

なぜパターン選択で迷うのか

RAGの実装解説を読み進めると、途中で「でもこれだとクエリの表現がずれたときに検索精度が落ちるよね」という疑問が出てきます。それを解消しようとAdvanced RAGの手法を追いかけると、今度は実装の複雑さと見合うかどうかが気になります。

この迷いの根本は、「何を改善したいか」が具体化される前にアーキテクチャを選ぼうとしていることにあります。

実際のプロジェクトでは以下の流れで考えると判断が早くなります。

  • まずシンプルRAGを動かして、何が問題かを計測する
  • 検索精度の問題なら → Advanced RAGの手法を部分的に導入する
  • 複数ステップの推論が必要なら → Agentic RAGを検討する

前置きが長くなりましたが、各パターンを順に見ていきます。

パターン1:シンプルRAG — 30分で動くが精度の壁がある

最もベーシックな構成です。ドキュメントをチャンクに分割してベクトル化しておき、クエリを同じモデルで埋め込んでコサイン類似度で上位k件を取得、それをコンテキストにしてGeminiに回答させます。

import google.generativeai as genai
import numpy as np
 
genai.configure(api_key="YOUR_GEMINI_API_KEY")
 
# ドキュメントを事前にチャンク化・埋め込み済みと仮定
# chunks: [{"text": "...", "embedding": [...]}]
 
def embed_text(text: str, task_type: str = "RETRIEVAL_DOCUMENT") -> list[float]:
    result = genai.embed_content(
        model="models/text-embedding-004",
        content=text,
        task_type=task_type,
    )
    return result["embedding"]
 
def cosine_similarity(a: list[float], b: list[float]) -> float:
    a, b = np.array(a), np.array(b)
    return float(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)))
 
def simple_rag(query: str, chunks: list[dict], top_k: int = 3) -> str:
    # クエリをREトリーバルQUERYタスクで埋め込む(DOCUMENTと区別する)
    query_embedding = embed_text(query, task_type="RETRIEVAL_QUERY")
 
    # 類似度でソートして上位k件を取得
    scored = sorted(
        chunks,
        key=lambda c: cosine_similarity(query_embedding, c["embedding"]),
        reverse=True,
    )[:top_k]
    context = "\n\n---\n\n".join(c["text"] for c in scored)
 
    # Geminiで回答生成
    model = genai.GenerativeModel("gemini-2.5-flash")
    prompt = f"""以下の情報のみをもとに質問に答えてください。情報に含まれていない内容は「分かりません」と答えてください。
 
【参照情報】
{context}
 
【質問】
{query}"""
 
    response = model.generate_content(prompt)
    return response.text

このコードで動きます。task_type="RETRIEVAL_QUERY"RETRIEVAL_DOCUMENT を使い分けている点が地味に重要で、同じ text-embedding-004 でも非対称タスクとして最適化されるため、検索精度が上がります。

シンプルRAGの限界

実際にプロダクションで使おうとしたときに最初にぶつかる壁は、クエリの表現揺れです。「APIのエラー対処法は?」と「レート制限を回避するには?」は内容的には近いはずですが、表現が違うと類似度が下がります。

もう一つは、長いドキュメントをどうチャンク分割するかです。単純にcharacterで切ると文脈が途切れ、精度が落ちます。

これらが許容できない場合に、次のパターンを検討することになります。

パターン2:Advanced RAG — 精度はぐっと上がるが実装コストが増える

シンプルRAGに手を加えてクエリの品質を上げたり、検索結果の精度を向上させたりするアプローチです。代表的な手法はクエリ変換(HyDE)とリランクです。

ここではHyDE(Hypothetical Document Embeddings)を試してみます。これは「クエリに直接答える仮想ドキュメント」をLLMに生成させてから、その仮想ドキュメントで検索する手法です。ユーザーの「短い質問」よりも「答えの形をした長いテキスト」のほうが、ドキュメントの埋め込みに近くなるという発想です。

def generate_hypothetical_document(query: str) -> str:
    """クエリに答える仮想ドキュメントを生成(HyDE)"""
    model = genai.GenerativeModel("gemini-2.5-flash")
    prompt = f"""次の質問に答える文書の一部を、実際の文書であるかのように200字程度で書いてください。
事実かどうかは問いません。検索精度向上のための仮想文書です。
 
質問: {query}
 
文書の一部:"""
    response = model.generate_content(prompt)
    return response.text
 
def advanced_rag_with_hyde(query: str, chunks: list[dict], top_k: int = 5) -> str:
    # HyDEで仮想ドキュメントを生成してから埋め込む
    hypothetical_doc = generate_hypothetical_document(query)
    search_embedding = embed_text(hypothetical_doc, task_type="RETRIEVAL_QUERY")
 
    # 上位k件を広めに取得
    scored = sorted(
        chunks,
        key=lambda c: cosine_similarity(search_embedding, c["embedding"]),
        reverse=True,
    )[:top_k]
 
    # 上位5件のうち本当に関連性が高いものだけに絞る(簡易リランク)
    # 実際はCross-Encoderなどを使うが、ここではGeminiで再スコアリング
    reranked = rerank_with_gemini(query, [c["text"] for c in scored], top_n=3)
    context = "\n\n---\n\n".join(reranked)
 
    model = genai.GenerativeModel("gemini-2.5-pro")
    prompt = f"""以下の情報のみをもとに、正確に質問に答えてください。
 
【参照情報】
{context}
 
【質問】
{query}"""
 
    response = model.generate_content(prompt)
    return response.text
 
def rerank_with_gemini(query: str, passages: list[str], top_n: int = 3) -> list[str]:
    """Geminiでパッセージを再スコアリング(簡易リランク)"""
    model = genai.GenerativeModel("gemini-2.5-flash")
    numbered = "\n\n".join(f"[{i+1}] {p}" for i, p in enumerate(passages))
    prompt = f"""質問に最も関連性の高いパッセージを{top_n}件選び、番号をカンマ区切りで返してください。他の文字は含めないでください。
 
質問: {query}
 
パッセージ:
{numbered}
 
最も関連性が高い{top_n}件の番号:"""
 
    response = model.generate_content(prompt)
    indices_str = response.text.strip()
    try:
        indices = [int(x.strip()) - 1 for x in indices_str.split(",")]
        return [passages[i] for i in indices if 0 <= i < len(passages)]
    except Exception:
        return passages[:top_n]  # パースに失敗した場合は上位からそのまま返す

実装を見ると分かるように、Advanced RAGはシンプルRAGに比べてGeminiのAPI呼び出しが増えます。クエリ1件に対してHyDE生成・リランクと最低2回の追加呼び出しが発生するため、レイテンシとコストが上昇します。

私の経験では、Advanced RAGは専門用語が多いドメインユーザーの入力が短くて不完全なケース(チャットボットなど)で効果が出やすいと感じています。ECサイトの商品検索のようにクエリとドキュメントが語彙レベルで近い場合は、むしろシンプルRAGで十分なことが多いです。

パターン3:Agentic RAG — 最も強力だが設計が鍵

LLMが自律的に複数回の検索と推論を繰り返すパターンです。「一度の検索では答えが出ない複雑な質問」「複数の情報を統合して比較する必要がある質問」に強みを発揮します。

Gemini APIでAgentic RAGを実装するときに活用できるのがFunction Callingです。

import json
 
# ツール定義:Geminiに「検索できる」ことを伝える
search_tool = {
    "function_declarations": [
        {
            "name": "search_documents",
            "description": "ドキュメントベースを検索して関連情報を返す。複雑な質問では複数回呼び出してよい。",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": "検索クエリ。具体的なほど精度が上がる。",
                    },
                    "top_k": {
                        "type": "integer",
                        "description": "取得件数(1〜10の整数)",
                    },
                },
                "required": ["query"],
            },
        }
    ]
}
 
def execute_search(query: str, chunks: list[dict], top_k: int = 3) -> str:
    """実際のベクトル検索を実行"""
    query_embedding = embed_text(query, task_type="RETRIEVAL_QUERY")
    scored = sorted(
        chunks,
        key=lambda c: cosine_similarity(query_embedding, c["embedding"]),
        reverse=True,
    )[:top_k]
    return "\n\n".join(c["text"] for c in scored)
 
def agentic_rag(question: str, chunks: list[dict], max_iterations: int = 5) -> str:
    model = genai.GenerativeModel(
        "gemini-2.5-pro",
        tools=[search_tool],  # type: ignore
    )
    messages = [{"role": "user", "parts": [question]}]
 
    for _ in range(max_iterations):
        response = model.generate_content(messages)
        candidate = response.candidates[0]
 
        # Function Callがあれば実行する
        function_calls = [
            p.function_call
            for p in candidate.content.parts
            if hasattr(p, "function_call") and p.function_call.name
        ]
 
        if not function_calls:
            # ツール呼び出しなし → 最終回答
            return candidate.content.parts[0].text
 
        # モデルの発話を履歴に追加
        messages.append({"role": "model", "parts": candidate.content.parts})
 
        # 各Function Callを実行して結果を返す
        tool_results = []
        for fc in function_calls:
            args = dict(fc.args)
            result = execute_search(
                query=args["query"],
                chunks=chunks,
                top_k=int(args.get("top_k", 3)),
            )
            tool_results.append(
                {
                    "function_response": {
                        "name": fc.name,
                        "response": {"result": result},
                    }
                }
            )
 
        messages.append({"role": "user", "parts": tool_results})
 
    return "回答の生成に失敗しました(反復制限に達しました)"

Agentic RAGの動作を見ると、Geminiが自分で「何を検索すべきか」を判断して、必要なら複数回検索を繰り返します。「AとBを比較して、共通点と相違点を教えて」のような質問では、AとBをそれぞれ検索してから統合するという動きをとります。

ただし、注意点があります。反復回数に上限を設けないと無限ループになるリスクがあること、そしてコストとレイテンシが読みにくいこと。本番で使うなら、呼び出し回数のログを必ず残して、コスト監視の仕組みを最初から組み込んでおくことをお勧めします。

Agentic RAGの設計で詳しく知りたい方は、Gemini API × GraphRAGとKnowledge Graphの実装ガイドも参考になります。

3パターンの選択基準

ここをまとめとして、判断の軸を整理します。

シンプルRAGが適しているケース

  • プロトタイプ・MVP段階
  • ドキュメントの語彙とクエリの語彙が近い(商品カタログ、FAQ、社内マニュアル)
  • レイテンシを最優先したい(リアルタイムチャット)
  • まず動かして精度を計測したい

Advanced RAGが適しているケース

  • ユーザーの入力が短くて不明瞭(チャットボット)
  • 専門用語が多いドメイン(医療、法律、技術文書)
  • シンプルRAGで計測した結果、精度が目標を下回っている
  • HyDEやリランクのコスト増分が許容できる

Agentic RAGが適しているケース

  • 複数ステップの推論が必要(「AをBと比較して〜」「〜の原因を洗い出して対策を提案して」)
  • ユーザーが曖昧な目標を持っていて、複数の情報を統合する必要がある
  • コストとレイテンシより回答品質を最優先できる

なお、RAGの基本実装から本番デプロイまで体系的に学びたい方はGemini APIで作るRAGシステム完全実装ガイドが参考になります。また、大量のドキュメントを効率よく処理するパイプラインについてはGemini 3 Flashを使った高速RAGパイプライン構築も合わせて読んでみてください。

まず「シンプルRAGを計測する」から始める

最後に、私が毎回やっているアプローチを共有します。

どんなプロジェクトでも、最初はシンプルRAGを動かして精度を計測します。具体的には、テストクエリ20〜30件に対して「期待する回答と実際の回答の一致率」をざっくり記録します。これが80%以上なら、コストをかけてAdvanced RAGに移行する必要がないことが多いです。70%を切っていたら、クエリ変換かリランクのどちらで改善できるかを試します。

Agentic RAGは、シンプルやAdvancedで解決できなかった「複雑な推論が必要な質問」が明確に存在するときに初めて検討します。最初からAgentic RAGで設計すると、デバッグが難しくなるためです。

まずシンプルなものを動かして計測します。その積み重ねが、最終的に一番早く目標の精度に到達できる道です。

シェア

お読みいただきありがとうございます

Gemini Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

API / SDK2026-05-15
Gemini API Embedding で踏んだ3つの地雷 — 壁紙アプリのカテゴリ自動分類で遭遇したエラーと対処法
Gemini API Embedding を壁紙アプリのカテゴリ自動分類に組み込んだ際に踏んだ3つのエラー(INVALID_ARGUMENT・RESOURCE_EXHAUSTED 429・RAG精度低下)と実際の修正コードを紹介します。
API / SDK2026-04-09
gemini-2.5-pro-latest で始めるAI開発:Google AI Studio & APIクイックスタートガイド
gemini-2.5-pro-latestモデルを使ったAI開発の始め方を解説。APIキー取得・Python実装・ストリーミング・マルチターン会話まで、実動作するコード例付きで丁寧に説明します。
API / SDK2026-07-16
Gemini にスクリーンショットを採点させたら、全部78〜85点だった — 絶対スコアを捨ててペア比較に切り替えるまで
Gemini Vision に App Store スクリーンショットを100点満点で採点させると、良い案も崩した案も78〜85点に潰れます。弁別能を実測して絶対スコアを捨て、位置バイアスを除いたペア比較でランキングを作るまでの実装記録です。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →