Skip to content
Published on

100万トークン時代:RAGは不要になるのか?

Authors

疑問の背景

2024〜2025年にかけて、LLMのコンテキストウィンドウは急速に拡大しました。

  • Gemini 1.5 Pro:100万トークン
  • Claude 3.5/3.7:20万トークン
  • GPT-4o:12.8万トークン

この数字を見て、多くの開発者がこう思いました。「100万トークンなら本10冊分を入れられるのに、わざわざベクターDB構築してRAGパイプライン作る必要あるの?全部突っ込めばいいんじゃない?」

合理的な疑問です。RAGは構築が複雑です。チャンキング戦略、埋め込みモデルの選択、ベクターDBの運用、検索品質のチューニング…これらが全て不要になるなら、どれほど楽になるでしょう。

しかし実際にプロダクションシステムを構築した経験のある方なら、「そう単純ではない」とわかるはずです。データとコードをもとに率直に比較してみましょう。


Long Context vs RAG:本当の比較

1. コスト比較 — 数字が全てを語る

# シナリオ:10,000件のドキュメント知識ベース、各500トークン
# 1日1,000クエリ

total_docs_tokens = 10_000 * 500  # 5,000,000トークン

# 方法A:Long Context(全ドキュメントをコンテキストに)
# GPT-4oインプット価格:$2.50 / 1Mトークン
cost_long_context_per_query = total_docs_tokens * (2.50 / 1_000_000)
daily_cost_long_context = cost_long_context_per_query * 1_000
print(f"Long context 1日コスト: ${daily_cost_long_context:.2f}")
# 出力:Long context 1日コスト: $12500.00 (!!)

# 方法B:RAG(関連チャンク上位5件、約1,000トークン)
rag_context_tokens = 1_000
cost_rag_per_query = rag_context_tokens * (2.50 / 1_000_000)
daily_cost_rag = cost_rag_per_query * 1_000
print(f"RAG 1日コスト: ${daily_cost_rag:.2f}")
# 出力:RAG 1日コスト: $2.50

ratio = daily_cost_long_context / daily_cost_rag
print(f"RAGは{ratio:.0f}倍安い")
# 出力:RAGは5000倍安い

1日12,500vs12,500 vs 2.50。月換算で375,000vs375,000 vs 75。スタートアップなら、サービスが成長する前に資金が尽きてしまいます。

これは極端な例ですが、知識ベースが大きくなるほど、クエリが多くなるほど、この差は広がります。

2. 速度比較

プロダクション環境で計測した概算値:

  • 200Kトークンコンテキスト:最初のトークンまで5〜10秒
  • RAG + 2Kコンテキスト:0.3〜0.8秒(検索含む)

ユーザー体験として大きな差です。ストリーミング出力でやや改善できますが、長いコンテキストはTTFT(Time To First Token)も遅い傾向があります。

3. 品質比較 — 「Lost in the Middle」問題

最も重要な比較です。「長いコンテキストを与えるほど精度が上がる」と思われがちですが、研究結果は逆を示しています。

Liu et al. (2023)「Lost in the Middle: How Language Models Use Long Contexts」より:

長いコンテキストにおける位置別の性能:

先頭部分:  ████████████ 85%LLMが注目
中間部分:  ████████     65%  ← 性能低下!(Lost in the Middle)
末尾部分:  ████████████ 87%LLMが注目

RAGは関連情報を常に先頭に配置 → この問題を回避

50万トークンのコンテキスト中間に重要な情報があると、LLMが見落とす可能性が高くなります。RAGは検索されたチャンクをコンテキストの先頭に置くため、この問題を自然に回避できます。


Long ContextがRAGより優れる場面

Long Contextが常に悪いわけではありません。以下のシナリオでは有効です:

1. ドキュメント全体の分析が必要な場合

「この小説全体の主人公の変化を分析して」「この1万行のコードベースをセキュリティ観点でレビューして」のように、本当に全体を理解する必要がある場合はLong Contextが適切です。

2. 複雑なクロスドキュメント推論が必要な場合

2つの契約書の微妙な矛盾を見つけたり、10本のレポートにまたがる因果関係を追跡する場合、チャンク単位の検索では見落としが生じることがあります。

3. クエリが完全に予測不能な場合

何を聞かれるかまったくわからない状況では、全内容を入れるのが安全な選択です。

4. 小規模な知識ベース

50件未満の短いドキュメントなら、全部入れる方がシンプルで効果的な場合があります。


RAGがLong Contextより優れる場面

一方、プロダクションサービスではRAGが優位に立つ場面が多くあります:

1. 大規模な知識ベース

数千〜数百万のドキュメントがある場合、Long Contextは物理的に不可能か、コスト的に現実的ではありません。

2. コスト制約のあるサービス

B2Cアプリ、フリーティア、高頻度の内部ツール — クエリ単価が事業の死活問題になります。

3. 高速レスポンスが必須のサービス

カスタマーサービスボット、リアルタイムヘルプシステム — 10秒の待機時間は許容できません。

4. 頻繁に更新される知識ベース

RAGに新しいドキュメントを追加すれば即座に検索可能。Long Contextはプロンプトを毎回再構成する必要があります。

5. ソース追跡が必要な場合

「この回答の根拠となったドキュメントは何ですか?」という質問に、RAGは検索されたチャンクをそのまま提示できます。


最善の答え:Long Context RAG(両者の組み合わせ)

実践で最も良い結果を出すのは、両者を組み合わせたパターンです:

# Long Context RAGパターン
# ステップ1:RAGで候補チャンクを多めに検索(再現率重視)
# ステップ2:長めのコンテキストに入れてLLMに丁寧に読ませる

def long_context_rag_query(query: str, vectordb, llm):
    # 通常のRAG:上位5チャンク
    # Long Context RAG:上位20チャンク
    retrieved_chunks = vectordb.similarity_search(query, k=20)

    # 約20K〜40Kトークンのコンテキスト
    context = "\n\n---\n\n".join([chunk.page_content for chunk in retrieved_chunks])

    prompt = f"""以下のドキュメントに基づいて質問に答えてください。

ドキュメント:
{context}

質問:{query}

回答:"""

    return llm.invoke(prompt)

このアプローチの利点:

  • 検索段階でのリコール向上(上位20件なら見落としが少ない)
  • 全ドキュメントを詰め込む方法よりはるかに安い
  • 20Kトークン程度なら「Lost in the Middle」問題は深刻ではない

Reranking:品質を高める追加戦略

Rerankerを追加すると、LLM追加コストなしで検索品質を大幅に向上できます:

from sentence_transformers import CrossEncoder

# クロスエンコーダーReranker(Cohere、Jina、BGE-rerankerなど)
reranker = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-6-v2")

def rag_with_reranking(query: str, vectordb, llm, top_k=20, rerank_top=5):
    # 1. 広めに検索(リコール重視)
    candidates = vectordb.similarity_search(query, k=top_k)

    # 2. Rerankerで精密にスコアリング
    pairs = [(query, chunk.page_content) for chunk in candidates]
    scores = reranker.predict(pairs)

    # 3. 上位5件のみ最終コンテキストに使用
    ranked = sorted(zip(scores, candidates), reverse=True)
    top_chunks = [chunk for _, chunk in ranked[:rerank_top]]

    context = "\n\n".join([chunk.page_content for chunk in top_chunks])

    return llm.invoke(f"Context:\n{context}\n\nQuestion: {query}")

クロスエンコーダーは小さく高速なモデルでローカル実行でき、LLMの予算を使わずに精度を大幅に改善します。


今後の展望:コンテキストウィンドウは拡大し続ける

コンテキストウィンドウは拡大し続け、コストは下がり続けるでしょう:

2023GPT-4 → 8Kトークン
2024:Claude 320万、Gemini 1.5100万トークン
2025年以降:さらなる拡大が見込まれる

入力価格の推移:
2023 GPT-4:   $30.00 / 1Mトークン
2024 GPT-4o:   $2.50 / 1Mトークン
2025年以降:さらに低下予定

しかしRAGは消えません。進化します:

  • シングルステージRAGマルチホップRAG(多段階検索)
  • キーワード/セマンティック検索ハイブリッド検索 + Reranking
  • フラット検索階層的/GraphRAG
  • RAGは単なる検索技術からコンテキスト管理の方法論へと発展

将来は「RAG vs Long Context」ではなく「どのRAG戦略が最適か」という問いになるでしょう。


実務意思決定ガイド

知識ベースのサイズは?
├─ 50件未満の短いドキュメント → Long Contextを検討
├─ 数百〜数千件 → Long Context RAG(上位20+ 50Kコンテキスト)
└─ 数万件以上 → Standard RAG + Reranking

クエリの種類は?
├─ 特定事実の検索 → Standard RAG
├─ 複雑なクロスドキュメント推論 → GraphRAGまたはMulti-hop RAG
└─ 全体要約/分析 → Long ContextまたはGlobal GraphRAG

レスポンス速度の要件は?
├─ 1秒未満 → Standard RAG(小さいコンテキスト)
├─ 3秒以内 → Long Context RAG(30K以下)
└─ 柔軟 → Long Contextも選択肢

月次予算は?
├─ $100未満 → Standard RAG一択
├─ $1,000以下 → Long Context RAG可能
└─ 制限なし → 品質優先で選択

まとめ

RAGはなくなりません。 むしろより洗練されていきます。

Long Contextは特定のシナリオ(小規模ドキュメント、全体分析、複雑な推論)では強力なツールです。しかし、プロダクションサービスではコスト・速度・スケーラビリティの観点から、ほとんどの場合RAGが依然として最善の選択です。

実践的なアドバイス:Long Context RAGパターンを出発点にしましょう。 RAGで広くリトリーブし、LLMに十分なコンテキストを与えるこのパターンが、コスト・速度・品質のバランスを最もうまく取れます。

完璧な正解はありません。自分のサービスの特性に合わせて実験し、計測してください。