【2026年版】LangChainで作るRAG実装30分入門

3つのインターロックする歯車が連動し中央で光るデータの流路を駆動している構図

【2026年版】LangChainで作るRAG実装30分入門

社内ドキュメントや FAQ を AI に答えさせたいけれど、ファインチューニングはコストも手間も大きく、何から始めれば良いか迷いがちです。本記事では、Python と LangChain を使った RAG(Retrieval-Augmented Generation)の最小実装を、コピペで動くサンプルコードとともに30分で組み立てます。RAG の仕組みから、本番運用に向けた拡張ポイント、RAG とファインチューニングの使い分けまでを一気に把握できる構成です。読み終わるころには、自分のドキュメントに対して質問応答するナレッジボットの最初のプロトタイプが手元で動いている状態を目指します。

目次

RAGとは何か:30秒で押さえる仕組みとデータフロー

蜂の巣状の格子状ベクトルストアにデータの流れが入り検索後に外側へ戻っていく構図
RAGのインデックス側とクエリ側のデータフロー

RAG(Retrieval-Augmented Generation)は、外部の知識ベースから関連情報を検索し、それを LLM へのプロンプトに埋め込んで回答を生成する手法です。Lewis らによる2020年の原論文で「パラメトリック記憶(モデル重み)と非パラメトリック記憶(外部知識)を組み合わせる」枠組みとして提案され、現在のプロダクション RAG はこの基本構造を実装パターン化したものです。

データフローは「ドキュメント読み込み → チャンク分割 → 埋め込み生成 → ベクトルDB保存」のインデックス側と、「質問の埋め込み → 類似チャンク検索 → LLM 生成」のクエリ側の2段階で構成されます。RAG の利点は、モデルを再学習せずにドキュメントを差し替えるだけで知識を更新できる点と、回答の根拠となる原文を引用できる点です。

LangChain は、この一連の流れを Document Loader / Text Splitter / Embedding / Vector Store / Retriever / LLM / Chain として組み合わせるオーケストレーションフレームワークです。詳細はLangChain 公式の RAG ガイドに最新の API 仕様がまとまっています。

30分で動かす最小RAG実装(Python + LangChain + Chroma)

ここからは実装に入ります。ローカルでまず動かすことを優先し、ベクトルDB は組み込みで動く Chroma、埋め込みは OpenAI の text-embedding-3-small、生成は Anthropic Claude を使う構成にします。生成 LLM は OpenAI の gpt-4o でも置き換え可能で、その場合のコード差分は最後に示します。

環境構築(pip install)

Python 3.10 以上が動く環境で、以下を実行します。仮想環境を作っておくと後片付けが楽です。


python -m venv .venv
source .venv/bin/activate   # Windows は .venv\Scripts\activate
pip install langchain langchain-openai langchain-anthropic langchain-chroma langchain-community chromadb pypdf

API キーは環境変数で渡します。.env に書く運用が一般的です。


export OPENAI_API_KEY="sk-..."         # 埋め込み用
export ANTHROPIC_API_KEY="sk-ant-..."  # 生成用

load → split のサンプルコード

まずドキュメントを読み込み、チャンクに分割します。load 段ではローダーが PDF / Markdown / テキスト等を統一フォーマットの Document オブジェクトに揃え、split 段では LLM のコンテキスト窓に収まるサイズに切り分けます。


# rag_build.py
from pathlib import Path
from langchain_community.document_loaders import PyPDFLoader, TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter

# 1) load: docs/ 配下の PDF/TXT をまとめて読み込む
docs = []
for path in Path("docs").iterdir():
    if path.suffix.lower() == ".pdf":
        docs.extend(PyPDFLoader(str(path)).load())
    elif path.suffix.lower() in {".txt", ".md"}:
        docs.extend(TextLoader(str(path), encoding="utf-8").load())

# 2) split: 600 文字 / 80 文字オーバーラップでチャンク化
splitter = RecursiveCharacterTextSplitter(
    chunk_size=600,
    chunk_overlap=80,
    separators=["\n\n", "\n", "。", " ", ""],
)
chunks = splitter.split_documents(docs)
print(f"chunks: {len(chunks)}")

separators に日本語の句点「。」を含めると、英語前提のデフォルト挙動より段落境界が綺麗に切れます。チャンクサイズは経験的に 400〜800 文字が小〜中規模ドキュメントの目安です。

embed → store のサンプルコード

次に、各チャンクを埋め込みベクトルに変換し、Chroma に保存します。Chroma は pip install chromadb だけで動くため、最初の検証段階ではこれで十分です。


from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma

# 3) embed: text-embedding-3-small は 1,536 次元・$0.02/1M tokens
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")

# 4) store: persist_directory を指定するとローカルディスクに永続化される
vectorstore = Chroma.from_documents(
    documents=chunks,
    embedding=embeddings,
    persist_directory="./chroma_db",
    collection_name="knowledge_base",
)
print("インデックス構築完了")

埋め込みモデルの選択肢と料金はOpenAI の Embeddings 公式記事に整理されています。-small は2026年5月時点で $0.02/1M tokens と低コストで、多くの本番ユースケースで十分な品質です。

retrieve → generate(Claude を使う場合)

最後にクエリ側の処理です。質問を埋め込みに変換し、Chroma から類似チャンクを取り出し、Claude にコンテキストとして渡して回答を生成します。


from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain_anthropic import ChatAnthropic
from langchain.chains 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 = Chroma(
    persist_directory="./chroma_db",
    embedding_function=embeddings,
    collection_name="knowledge_base",
)
retriever = vectorstore.as_retriever(search_kwargs={"k": 4})

# Claude を生成 LLM として使う
llm = ChatAnthropic(model="claude-sonnet-4-6", temperature=0)

prompt = ChatPromptTemplate.from_messages([
    ("system", "あなたは社内ドキュメントに精通したアシスタントです。"
               "以下のコンテキストの範囲で日本語で答え、推測した部分は明示してください。\n\n"
               "コンテキスト:\n{context}"),
    ("user", "{input}"),
])

document_chain = create_stuff_documents_chain(llm, prompt)
rag_chain = create_retrieval_chain(retriever, document_chain)

result = rag_chain.invoke({"input": "返金ポリシーの上限金額は?"})
print(result["answer"])
for src in result["context"]:
    print("-", src.metadata.get("source"), src.page_content[:60])

search_kwargs={"k": 4} で上位4チャンクを取得しています。多すぎるとプロンプトが膨張し、少なすぎると答えに必要な根拠が落ちる、というトレードオフがあるため、後述の評価で適切な k を測ります。

OpenAI の GPT-4o を生成側で使いたい場合は、ChatAnthropicChatOpenAI(model="gpt-4o", temperature=0) に置き換えるだけで動きます。詳細はAnthropic Claude API ドキュメントを参照してください。

RAG vs ファインチューニング:選び方の判断軸

形の異なる2つのジグソーパズルピースが向かい合って噛み合おうとしている対比的な構図
RAGとファインチューニングを2ピースで対比

RAG が向くケースとファインチューニングが向くケースは、目的によって明確に分かれます。判断軸を1枚に整理します。

判断軸 RAG が向く ファインチューニングが向く
知識の更新頻度 週次以上で更新される 半年に1回以下で安定
ドキュメント量 数百〜数十万チャンク 教師データを十分用意できる
回答に出典が必要か 必要(コンプライアンス文脈) 不要(文体・タスク特化)
初期コスト 数千〜数万円 数万〜数十万円
ランニングコスト 検索+生成のトークン課金 推論のみ(独自モデル運用)
強み 鮮度・根拠の引用 文体・タスク特化の挙動

両者は排他ではなく、文体は軽量ファインチューニング、知識検索は RAG という組み合わせも有効です。ファインチューニングの選択肢はLLMファインチューニング完全ガイドに QLoRA / PEFT を含めて整理しています。

本番運用に向けた4つの拡張ポイント

中央のハブから4方向へ伸びる光の経路の先に小さな幾何学的拠点がある放射状の構図
4つの拡張ポイントを中央ハブから放射状に表現

最小実装が動いたら、本番に向けて次の4軸を順番に詰めます。順序は「評価 → チャンク戦略 → 埋め込みモデル → ベクトルDB」が現実的です。

チャンク分割戦略(固定 / 意味境界 / 階層)

RecursiveCharacterTextSplitter の固定長分割は出発点として優秀ですが、本番では意味境界(段落・節・H2)で切る方が retrieval 精度が上がります。LangChain の MarkdownHeaderTextSplitter は H1/H2/H3 をメタデータに保持したまま分割でき、Markdown 化された社内ドキュメントと相性が良い選択肢です。

階層分割(親チャンクと子チャンクの2層を持つ手法)は、検索時は短い子チャンクで精度を取り、生成時は長い親チャンクをコンテキストに渡す、というハイブリッドな運用ができます。中規模以上のナレッジベースで効果が出やすい設計です。

埋め込みモデル選択(text-embedding-3-small / large)

OpenAI の埋め込みモデルは、2026年5月時点で text-embedding-3-small が 1,536 次元・$0.02/1M tokens、text-embedding-3-large が 3,072 次元・$0.13/1M tokens という構成です。MTEB ベンチマークでは -large が約2ポイント上ですが、本番の多くは -small で十分です。

両者は Matryoshka 表現に対応し、256/512/1024 次元への切り詰めが可能で、ベクトルDB のストレージとレイテンシを下げる手段になります。日本語ドキュメントで精度が振るわない場合は、-large または日本語特化のオープン埋め込みモデル(intfloat/multilingual-e5 等)への切り替えを検討します。

ベクトルDB選択(Chroma / Pinecone)

ベクトルDB はワークロード規模で選び方が変わります。Chromaは Apache 2.0 ライセンスのオープンソースで、ローカル/インメモリ/Docker で動かせるため、10M ベクトル未満のローカル RAG や検証段階で最適です。1.0 GA では Raft によるHA、S3 互換のティアードストレージ、ハイブリッド検索が追加されました。

Pineconeはフルマネージド型で、数十億ベクトル規模でも高パーセンタイルレイテンシが概ね50ms以下に収まるという公開資料の言及があります。一方、Pinecone 2.0(2026年Q1)で Serverless 読み取り単価が $0.04→$0.12 / 1M read units に改定されており、大規模化前のコスト試算が以前より重要になりました。

数十万ベクトル規模で運用するなら、Chroma の Docker 運用または pgvector(PostgreSQL 拡張)も有力候補です。判断は「現在のベクトル数」「同時クエリ数」「マネージドが必要か」の3軸で行うと整理しやすくなります。

評価指標(Hit Rate / Faithfulness)

RAG の評価は「検索」と「生成」を分けて測ります。検索側は Hit Rate(正解チャンクが上位 k に入る確率)や MRR / nDCG、生成側は Faithfulness(回答が引用元と一致しているか)と Answer Relevancy(質問に直接答えているか)が代表指標です。

ragas や LangSmith のような評価フレームワークを使うと、これらを Python から自動測定できます。本番運用では、回帰テストとして「golden質問セット」に対するスコアを CI に組み込み、プロンプト変更やモデル切り替えのたびに自動評価する運用が現実的です。

よくあるエラーと対処

実装中につまずきやすいパターンを4つだけ先回りで共有します。

  • OpenAIError: insufficient_quota:OpenAI 課金設定が未完。Embeddings は API キーがあっても課金登録がないと弾かれます。
  • Chroma の IndexError / 0件返却:persist_directory が空、もしくは別プロセスで from_documents してすぐ retrieve するときに永続化が間に合っていない場合があります。一度プロセスを分けてください。
  • 日本語回答が英語になる:prompt の system 側に明示的に「日本語で」と書いていないか、temperature が高すぎるケース。0〜0.2 を推奨。
  • 回答が完全に外れる:多くはチャンクが大きすぎて埋め込みが平均化されているのが原因。chunk_size を 400〜600 に下げると劇的に改善することがあります。

ノーコードで RAG 的な体験から始めたい場合は、Claude Projects のレビュー記事に、Anthropic のマネージドナレッジ機能の使い勝手をまとめています。外部ツールとの連携を別アプローチで実装したい場合は、Claude MCP サーバー作成ガイドも合わせて参照すると俯瞰しやすくなります。

まとめ:最小実装→評価→拡張の順で本番に近づける

RAG は「動かす」だけなら本記事のコードで30分以内に到達できます。重要なのは、その後に「評価」を入れてから拡張に進むことです。チャンク戦略・埋め込みモデル・ベクトルDB の3つは、評価指標を持たないままチューニングするとどこを変えても主観的になりがちです。最小実装をベースに golden 質問セットを10〜20問用意し、Hit Rate と Faithfulness を計測する仕組みを並走させると、改善ループが短くなります。

FAQ

Q1: RAG とファインチューニングはどちらを先に試すべきですか?

ほとんどのケースで RAG が先です。RAG は教師データが不要で、知識の差し替えがファイル更新だけで済むため、初期コストとリスクが小さくなります。文体やタスク特化の挙動が必要になった段階で、軽量なファインチューニングを RAG と組み合わせるのが現実的な順序です。

Q2: ベクトルDB は Chroma と Pinecone のどちらを選べば良いですか?

検証段階や 10M ベクトル未満のローカル運用なら Chroma、本番で大規模・マネージドが必要なら Pinecone が基本線です。中規模では pgvector(PostgreSQL 拡張)も選択肢に入ります。Pinecone 2.0 の料金改定で、以前ほど「とりあえず Pinecone」が安全な選択ではなくなった点には注意が必要です。

Q3: 日本語ドキュメントで精度が出ません。何から見直せば良いですか?

最初に見るのはチャンク分割です。separators に「。」「、」を入れ、chunk_size を 400〜600 に下げると改善することが多くあります。次に埋め込みモデルを text-embedding-3-large または多言語特化モデルに切り替え、最後にプロンプトを「日本語で・コンテキスト範囲内で」と明示的に縛ります。

Q4: 商用利用で気をつけるべきライセンスは?

LangChain と Chroma は OSS(MIT / Apache 2.0)で商用利用可です。一方、ドキュメント側の著作権・社内情報の取り扱い・外部API送信時のデータ保護方針(OpenAI / Anthropic それぞれの企業向けプラン)を確認してください。社外データを送る場合は、暗号化と監査ログの要件を IT 部門と擦り合わせるのが安全です。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次