LangChain × RAGの実装パターン比較 — 2026年版ベストプラクティス
要点
RAGの実装パターンをBasic(LCEL標準型)・Advanced(検索強化型)・Agentic(LangGraph型)の3つに分類し、レイテンシー・精度・コストの定量比較とユースケース別の選定基準を共有。LangChain vs LlamaIndexの選定理由、チャンキング改善でRetrieval Precisionが58%→82%に改善した実例、RAGAS評価パイプラインの実践まで、受託開発の現場知見を凝縮。

RAGの実装パターンには明確な使い分けがあり、選択を間違えると本番で破綻する
これが、私たちが複数の受託プロジェクトでRAGシステムを構築してきた結論だ。
RAGは2024年のブームから2年が経ち、「とりあえず動くPoC」の時代から「運用環境で精度と信頼性を保つ」フェーズに移行している。LangChain自体も大きく変わった。2024年後半にLegacy Chains(RetrievalQA等)が非推奨となり、LCEL(LangChain Expression Language)とcreate_retrieval_chainベースのパイプラインが標準になった。2025年にはLangGraphが安定版となり、エージェント型RAGのパターンが確立された。
本記事では、LangChainの現行アーキテクチャに基づく3つの実装パターンを比較し、ユースケース別の選定基準とハマりどころを共有する。
なぜLangChainか — LlamaIndexを選ばなかった理由
RAGフレームワークの選定で、私たちはLlamaIndexも検証した。LlamaIndexはRAGに特化しており、インデックス構築やクエリエンジンの抽象度が高い。ドキュメントQAに限定するならLlamaIndexの方が立ち上がりは速い。
しかし、私たちの受託案件では「RAG+既存業務ロジック+外部API連携」が複合的に求められる。LangChainはRAG以外のチェーン構築(ツール呼び出し、マルチステップ推論、ワークフロー制御)との統合が容易で、LangGraphとの連続性がある。RAG単機能の最適さより、プロジェクト全体の拡張性を優先した。
3つの実装パターン
パターン1: Basic RAG(LCEL標準型)
最もシンプルな構成。ドキュメントをチャンクに分割し、ベクトル化して格納。クエリに対して類似度検索でチャンクを取得し、LLMに渡す。2026年現在、create_retrieval_chainがLangChain公式の推奨パターンだ。
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_community.vectorstores import TiDBVectorStore
from langchain.chains.retrieval import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.prompts import ChatPromptTemplate
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = TiDBVectorStore(
embedding_function=embeddings,
connection_string=TIDB_CONNECTION,
table_name="documents",
distance_strategy="cosine",
)
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
prompt = ChatPromptTemplate.from_messages([
("system", "以下の文脈に基づいて質問に回答せよ。文脈にない情報は「分かりません」と答えよ。\n\n{context}"),
("human", "{input}"),
])
combine_docs_chain = create_stuff_documents_chain(llm, prompt)
chain = create_retrieval_chain(
vectorstore.as_retriever(search_kwargs={"k": 5}),
combine_docs_chain,
)
response = chain.invoke({"input": "直近のチャーンレートの傾向は?"})適するケース: FAQ対応、社内Wiki検索など質問と回答が1対1で対応する領域。ドキュメント数千件程度。PoC・初期プロトタイプ。
適さないケース: 複数ドキュメントの横断推論、曖昧・複合クエリ、回答精度へのビジネス要求が高い場合。
パターン2: Advanced RAG(検索強化型)
Basic RAGの検索精度を改善するパターン。ハイブリッド検索(ベクトル+BM25キーワード検索)にクロスエンコーダーのリランキングを組み合わせる。
from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever
from langchain_community.cross_encoders import HuggingFaceCrossEncoder
from langchain.retrievers.document_compressors import CrossEncoderReranker
from langchain.retrievers import ContextualCompressionRetriever
bm25_retriever = BM25Retriever.from_documents(documents)
bm25_retriever.k = 10
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 10})
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, vector_retriever],
weights=[0.4, 0.6],
)
model = HuggingFaceCrossEncoder(model_name="cross-encoder/ms-marco-MiniLM-L-6-v2")
reranker = CrossEncoderReranker(model=model, top_n=5)
compression_retriever = ContextualCompressionRetriever(
base_retriever=ensemble_retriever,
base_compressor=reranker,
)
chain = create_retrieval_chain(compression_retriever, combine_docs_chain)適するケース: 稼働環境で検索精度が求められるシステム。専門用語が多くベクトル検索だけでは取りこぼしが発生する領域。ドキュメント数万件規模。
適さないケース: リランキングのレイテンシー(+200-500ms)が許容できないリアルタイム用途。インフラコストを最小限に抑えたい場合。
パターン3: Agentic RAG(LangGraph型)
LLMがクエリの意図を分析し、検索戦略を自律的に決定するパターン。LangGraphのステートマシンとして実装する。LangGraphが2025年に安定版になったことで、このパターンが実用域に入った。
from langgraph.graph import StateGraph, END
from typing import TypedDict
class RAGState(TypedDict):
query: str
search_strategy: str
retrieved_docs: list
answer: str
needs_refinement: bool
def analyze_query(state: RAGState) -> RAGState:
# LLMにクエリ分類を依頼(省略: gpt-4o-miniでquery→strategy分類)
state["search_strategy"] = classify_query(state["query"])
return state
def retrieve(state: RAGState) -> RAGState:
strategy = state["search_strategy"]
if strategy == "multi_query":
docs = multi_query_retrieve(state["query"], vectorstore)
elif strategy == "decompose":
docs = decomposed_retrieve(state["query"], vectorstore)
else:
docs = vectorstore.similarity_search(state["query"], k=5)
state["retrieved_docs"] = docs
return state
def evaluate_and_answer(state: RAGState) -> RAGState:
# 省略: LLMで検索結果の網羅性を判定
state["answer"] = generate_answer(state)
state["needs_refinement"] = check_sufficiency(state)
return state
graph = StateGraph(RAGState)
graph.add_node("analyze", analyze_query)
graph.add_node("retrieve", retrieve)
graph.add_node("answer", evaluate_and_answer)
graph.set_entry_point("analyze")
graph.add_edge("analyze", "retrieve")
graph.add_edge("retrieve", "answer")
graph.add_conditional_edges(
"answer",
lambda s: "retrieve" if s["needs_refinement"] else END,
)
app = graph.compile()適するケース: 複合的な分析質問。複数データソースの横断検索。検索→評価→再検索の反復が必要な調査型タスク。
適さないケース: シンプルなFAQ(オーバーエンジニアリング)。レイテンシー制約が厳しい場合(LLM呼び出しが3-5回に増える)。LLMコストの管理が厳しい場合。
3パターンの定量比較
私たちがドキュメント数千〜数万件規模の案件で計測した実績値に基づく目安:
指標 | Basic RAG | Advanced RAG | Agentic RAG |
|---|---|---|---|
レイテンシー(P95) | 1-2秒 | 2-4秒 | 5-15秒 |
LLM呼び出し回数/クエリ | 1回 | 1回 | 3-5回 |
Retrieval Precision | 60-70% | 80-90% | 85-95% |
月間コスト目安(1,000クエリ/日) | $50-100 | $80-150 | $200-500 |
実装工数 | 1-2日 | 3-5日 | 1-2週間 |
※Retrieval PrecisionはRAGAS準拠の評価指標で計測。コストはGPT-4o-mini + text-embedding-3-small、2026年4月時点の価格ベース。
選定フローチャート
クエリの複雑さに応じて選択する:
- 単純(FAQ、1対1対応) → Basic RAG
- 中程度(専門用語多い、精度要求あり) → Advanced RAG
- 複合的(横断検索、分析型、反復推論) → Agentic RAG
ただし、私たちのプロジェクトでは最初は必ずBasic RAGから始める。理由は3つ。
- ベースラインの確立。 Basic RAGの精度を測定しないと、Advanced/Agenticの改善幅を定量評価できない
- チャンキングとエンベディングの品質が全てに効く。 検索の土台が悪ければ、上のレイヤーで何をやっても改善幅は限定的だ
- コストとレイテンシーの見積もり。 最もシンプルな構成での数値がないと、稼働環境のインフラ設計ができない
ハマりどころ — 私たちの経験から
1. チャンキング戦略の過小評価
私たちの経験上、RAGの精度に最も影響が大きかったのは、LLMの性能でも検索アルゴリズムでもなく、チャンキングの品質だった。
あるプロジェクトで、一律500トークンで分割した結果、表の途中で切れる、手順の3ステップ目が別チャンクに飛ぶ、前提条件と結論が別チャンクになる問題が頻発した。セマンティックチャンキングに切り替え、メタデータ(ドキュメントタイトル、セクション見出し、作成日)をチャンクに埋め込んだところ、Retrieval Precisionが58%から82%に改善した。
2. 評価パイプラインの不在
「RAGを作った、動いた、デモで見せた、良さそうだ」で終わるプロジェクトが多い。しかし稼働環境で最も重要なのは定量的な評価パイプラインだ。
私たちはRAGAS(Retrieval Augmented Generation Assessment)をベースに、以下の3指標で評価している:
- Retrieval Precision: 取得したチャンクのうち、回答に実際に使われた割合
- Faithfulness: 生成された回答が、取得したチャンクの内容に忠実か
- Answer Relevancy: 生成された回答が、元のクエリに対して的確か
これをCI/CDに組み込み、モデル変更やチャンキング変更のたびに自動実行する。評価パイプラインなしにRAGを稼働環境で運用するのは、テストなしにコードをデプロイするのと変わらない。
3. ベクトルDB選定の罠
私たちはTiDB Serverless(MySQL互換 + ベクトル検索)を採用している。選定理由は、既存のRDBワークロードとベクトル検索を同一インフラで扱えること、そしてサーバーレスのスケーリング特性だ。
選ばなかったものと、その理由:
- Pinecone: マネージドで立ち上がりは速いが、データがベクトルDBに閉じる。RDBとのJOINが必要な業務要件では追加のデータ同期が発生する
- pgvector: PostgreSQLエコシステムとの親和性は高いが、大規模ベクトルインデックスでの運用チューニングにコストがかかる。ただし2025年以降の改善(HNSW indexの高速化)で選択肢としての魅力は上がっている
- Chroma: プロトタイプには最適だが、稼働環境のスケーラビリティと永続性に懸念が残る
ベクトルDB単体の性能で選ぶと、「あのデータと結合したいのにできない」問題に直面する。RDBワークロードとの共存を前提に選定すべきだ。
まだ解決できていないこと
チャンクの鮮度管理。 ドキュメントが更新されたとき、対応するチャンクのベクトルを効率的に更新する仕組みは、まだ力技に頼っている。差分更新の自動化は今後の課題だ。
マルチモーダル対応。 表や図を含むドキュメントのRAGは、テキストのみの場合と比べて精度が大きく落ちる。画像をテキストに変換してからチャンク化するアプローチを試しているが、情報の欠落が避けられない。
評価の自動化精度。 RAGAS自体がLLMに依存しているため、評価の精度にもばらつきがある。人手での抜き取り検証を定期的に行っているが、スケールしない。
まとめ
RAGの実装パターンは、ユースケースの複雑さに応じてBasic → Advanced → Agenticと段階的に選択するのが最も合理的だ。最初からAgenticに飛びつくのではなく、Basic RAGでベースラインを確立してから、必要に応じて検索の強化やエージェント化を検討する。
パターン選定よりも重要なのは、チャンキングの設計と評価パイプラインの整備だ。この2つが欠けたRAGは、デモでは動くが運用環境では壊れる。
関連記事
テーマ | 記事 |
|---|---|
Semantic SIの全体像 | |
データの前提のズレとRAG | |
Discovery商品化の思想 |
