RAGとは?【2026年版】仕組み・60行の最小サンプル・検索精度を上げる方法をやさしく解説

エンジニア

確認日:2026年9月24日。各社の公式ドキュメントと原論文で確認し、サンプルコードの検索部分は筆者の Mac(Python 3.12)で実行しました。この記事は2025年1月に公開した「RAG完全実装ガイド」を、今の状況に合わせて全面的に書き直したものです。

はじめに:AI に「社内の資料」を見ながら答えさせたい

ChatGPT や Claude に社内のルールを聞いても、正しく答えられません。AI は学習したときのデータしか知らず、あなたの会社の資料は読んだことがないからです。

そこで使われるのが RAG(ラグ、Retrieval-Augmented Generation:検索拡張生成)です。質問に関係する資料を先に探して、その資料を AI に渡してから答えてもらう仕組みです。

この記事では、次のことを順番に説明します。

  1. RAG とは何か、なぜ必要か
  2. AI が長い文章を読めるようになった今でも RAG が必要な理由
  3. 仕組みと、約60行で動く最小のサンプル
  4. 検索の精度を上げる方法
  5. 自分で作らずに使えるサービス
  6. 評価の方法とセキュリティの注意点

RAG とは:「持ち込み可の試験」のようなもの

RAG は、AI にとっての持ち込み可の試験にたとえられます。何も持たずに答える(ふつうのチャット)のではなく、手元の資料から関係するページを探して、それを見ながら答えます。

  1. 検索する:質問に関係しそうな資料の一部を探す
  2. 渡す:見つかった資料と質問を、まとめて AI に渡す
  3. 答える:AI が資料の内容をもとに回答する

RAG でできるようになること

困りごとRAG を使うと
AI が社内の情報を知らない社内の資料をもとに答えられる
AI の知識が古い最新の資料を渡せば、最新の内容で答えられる
もっともらしい嘘(ハルシネーション)が心配根拠にした資料を一緒に示せるので、確認しやすい
AI に覚えさせ直すのは大変資料を差し替えるだけで内容を更新できる

RAG という名前は、2020年に Meta(当時の Facebook)の研究者らが発表した論文(Lewis ほか, 2020)に由来します。

長い文章を読める AI の時代に、RAG はまだ必要?

2026年9月時点で、Claude Opus 5.5 や Sonnet 5 は一度に100万トークン(日本語で数十万字程度)を読めます。GPT や Gemini の上位モデルも同じくらいです。それなら、資料を全部そのまま渡せばいいのでは、と思うかもしれません。

実際、Anthropic は2024年9月の記事「Contextual Retrieval」で、資料が20万トークン(約500ページ)に収まるなら、RAG を作らずに全部をプロンプトに入れる方法を勧めています。同じ資料を何度も使うなら、プロンプトキャッシュ(送った文章を一時保存して割り引く仕組み)で費用も抑えられます。

一方で、次のような場合は今でも RAG が向いています。

  • 資料が多すぎて、一度に読める量に収まらない
  • 資料が頻繁に増えたり変わったりする
  • 人によって見てよい資料が違う(権限の管理が必要)
  • 質問のたびに大量の文章を送ると、費用や待ち時間が大きくなる

資料が少なければまず全部渡してみる、多ければ RAG、と考えるのが今の現実的な使い分けです。AI に渡す情報量の考え方は コーディングエージェントのコンテキスト管理入門 でも解説しています。

RAG の仕組み

RAG は「前もって準備しておく作業」と「質問が来たときの作業」の2つに分かれます。

前もって準備しておく作業

  1. 分割(チャンク化):資料を数百〜千文字くらいのかたまり(チャンク)に分ける
  2. ベクトル化(埋め込み):各チャンクを、意味を表す数値の並び(ベクトル)に変換する。意味が近い文章ほど、近い数値になる
  3. 保存:ベクトルを検索できる場所(ベクトルデータベース)に保存する

質問が来たときの作業

  1. 質問も同じ方法でベクトルに変換する
  2. 質問と意味が近いチャンクを数件探す
  3. 見つかったチャンクと質問を AI に渡して、答えてもらう

ポイントは、キーワードが一致しなくても意味が近ければ見つけられることです。たとえば「家で働けるのは週何日?」という質問で、「リモートワーク」と書かれた資料を探し出せます。

約60行で動く、いちばん小さな RAG

実際に動くサンプルを見てみましょう。社内ルールの文書4件から関係するものを探し、Claude に出典付きで答えてもらいます。ベクトル化には、無料で使える多言語対応の公開モデル multilingual-e5-small を使います。

準備

python3 -m venv .venv
source .venv/bin/activate
pip install anthropic sentence-transformers
export ANTHROPIC_API_KEY="取得したAPIキー"

Python 3.10 以上が必要です。API キーは Claude Console で作成できます。

コード(rag_min.py)

"""いちばん小さな RAG:社内ルールを検索して、出典付きで Claude に答えてもらう。"""
import anthropic
from sentence_transformers import SentenceTransformer

# 1. 検索対象の文書(実際はファイルやデータベースから読み込む)
DOCS = [
    {"title": "経費精算ルール", "text": "経費の精算は、支払った月の翌月10日までに経費システムから申請します。領収書の写真の添付が必要です。"},
    {"title": "リモートワーク規程", "text": "リモートワークは週3日まで認められます。前日の18時までにチャットで上長に連絡してください。"},
    {"title": "PC貸与ルール", "text": "貸与PCの修理や交換は情報システム部に依頼します。私物のUSBメモリは接続禁止です。"},
    {"title": "有給休暇", "text": "有給休暇は取得日の3営業日前までに勤怠システムで申請します。半日単位でも取得できます。"},
]

# 2. 文書を「意味を表す数値の並び(ベクトル)」に変換しておく
model = SentenceTransformer("intfloat/multilingual-e5-small")
doc_vecs = model.encode(["passage: " + d["text"] for d in DOCS], normalize_embeddings=True)


def search(question: str, k: int = 2) -> list[dict]:
    """質問と意味が近い文書を上位 k 件返す"""
    q_vec = model.encode(["query: " + question], normalize_embeddings=True)[0]
    scores = doc_vecs @ q_vec  # 正規化済みなので内積 = コサイン類似度
    top = scores.argsort()[::-1][:k]
    return [DOCS[i] | {"score": float(scores[i])} for i in top]


def answer(question: str) -> str:
    """検索した文書だけを根拠に、Claude に出典付きで答えてもらう"""
    hits = search(question)
    documents = [
        {
            "type": "document",
            "source": {"type": "text", "media_type": "text/plain", "data": h["text"]},
            "title": h["title"],
            "citations": {"enabled": True},  # どの文書のどこを根拠にしたかを返してもらう
        }
        for h in hits
    ]
    client = anthropic.Anthropic()  # 環境変数 ANTHROPIC_API_KEY を使う
    response = client.beta.messages.create(
        model="claude-opus-5",
        max_tokens=2000,
        # 安全判定で断られたときに、自動で別モデルに切り替えてもらう設定
        betas=["server-side-fallback-2026-07-01"],
        fallbacks="default",
        system="社内ルールの質問に答えるアシスタントです。渡された文書に書かれていないことは「文書には記載がありません」と答えてください。",
        messages=[{"role": "user", "content": [*documents, {"type": "text", "text": question}]}],
    )
    if response.stop_reason == "refusal":
        return "回答できませんでした。"
    parts = []
    for block in response.content:
        if block.type == "text":
            parts.append(block.text)
            for c in block.citations or []:
                parts.append(f"  (出典: {c.document_title})")
    return "\n".join(parts)


if __name__ == "__main__":
    print(answer("経費の申請期限はいつですか?"))

search() が「検索する」、answer() が「渡す・答える」の部分です。文書を document という形式で渡し、citations(引用)をオンにすると、Claude が回答のどの部分をどの文書から引いたかを返してくれます。

検索部分を動かした結果

筆者の Mac で、search() だけを実行した結果です(数字は意味の近さで、1に近いほど近い)。

質問1位2位
経費の申請期限はいつですか?経費精算ルール(0.882)有給休暇(0.821)
家で働けるのは週に何日まで?リモートワーク規程(0.830)有給休暇(0.825)
USBメモリを使ってもいい?PC貸与ルール(0.849)リモートワーク規程(0.804)

3問とも正しい文書が1位になりました。ただ、2問目は2位との差がわずかです。文書が増えると、このような「僅差の取り違え」が起こりやすくなります。次の章の工夫は、この精度を上げるためのものです。

筆者の環境には API キーを設定していないため、answer() で実際に Claude を呼び出すところまでは試していません。送信する内容が正しい形式になっていることは、SDK(anthropic 1.8.0)で確認しました。

検索の精度を上げる方法

方法内容
ハイブリッド検索意味の近さ(ベクトル検索)と、キーワードの一致(BM25 などの全文検索)を組み合わせる。製品名や型番のような「正確な言葉」に強くなる
リランキング最初に多めに候補を集め、専用のモデルで並べ直してから上位を使う
チャンクに文脈を付ける各チャンクの先頭に「この部分は何の資料のどの話か」という短い説明を付けてからベクトル化する
分割の調整チャンクの大きさや、隣のチャンクとの重なりを調整する。OpenAI の File Search の標準は最大800トークン・重なり400トークン
質問の言い換え質問を検索しやすい形に書き換えたり、複数の小さな質問に分けたりする
AI に検索させる(エージェント型 RAG)AI 自身が「何を、何回検索するか」を決め、足りなければ検索し直す

Anthropic の Contextual Retrieval の検証では、チャンクに文脈を付けるだけで検索の失敗率が35%減り、キーワード検索との併用で49%減、さらにリランキングを加えると67%減ったと報告されています(出典)。

最近は、事前にすべてを検索しておくのではなく、AI エージェントが必要なときに道具として検索する形も増えています。社内のサービスや資料を AI の道具としてつなぐ仕組みは MCP 実践ガイド で紹介しています。

自分で作らずに使えるサービス

RAG は、分割・ベクトル化・保存・検索をすべて任せられるサービスも増えています。まずはこうしたサービスで試し、足りなければ自分で作る、という順番がおすすめです。

サービス特徴
OpenAI File Searchファイルを置くだけで、意味検索とキーワード検索を組み合わせて引用付きで答える
Gemini API File Search保存や分割を含めてすべておまかせ。課金は取り込み時のベクトル化のみ
Claude(API)ベクトルの保存場所はないが、自分の検索結果を出典付きで答えさせる機能(Search results・Citations)がある
Claude の Projects資料が多くなると自動で RAG に切り替わり、より多くの資料を扱える(有料プラン)
Amazon Bedrock Knowledge BasesSharePoint などとの接続、文書ごとの権限、リランキングに対応
Azure AI Searchハイブリッド検索や、AI が質問を分けて検索する機能(agentic retrieval)に対応

自分で組み立てる場合は、LangChain や LlamaIndex といった部品集(フレームワーク)がよく使われます。

ベクトル化のモデルを選ぶ

モデル特徴
OpenAI text-embedding-3-small安くて手軽(100万トークンあたり0.02ドル)
Voyage(voyage-4 など)Anthropic のドキュメントで例として案内されている
Cohere embed-v4.0多言語・画像・PDF に対応
Gemini embedding画像も扱える gemini-embedding-2 がある
BAAI/bge-m3・multilingual-e5無料の公開モデル。日本語にも対応し、手元で動かせる

一度ベクトル化した後にモデルを変えると、すべての資料をベクトル化し直す必要があります。最初に候補をいくつか試してから決めましょう。

うまく動いているかを測る

RAG は「検索がうまくいったか」と「回答が資料に沿っているか」を分けて確かめるのが基本です。評価用の道具としては RAGAS がよく使われ、次のような指標があります。

指標確かめること
Faithfulness(忠実さ)回答が、渡した資料の内容に沿っているか
Response Relevancy(回答の関連性)回答が質問に合っているか
Context Precision(検索の正確さ)検索した資料に、関係ないものが混ざっていないか
Context Recall(検索の網羅性)答えに必要な資料を取りこぼしていないか

RAGAS を実際に動かしながら学べるアプリの作り方は RAGAS × FastAPI × Next.js × Docker で学ぶ Web アプリ開発入門 で紹介しています。

セキュリティの注意点

AI アプリの代表的なリスクをまとめた OWASP Top 10 for LLM Applications(2025年版) では、RAG に関係する次のリスクが挙げられています。

  • 資料に仕込まれた指示(間接プロンプトインジェクション):検索した資料の中に「これまでの指示を無視して…」のような文章が紛れ込んでいると、AI がそれに従ってしまうおそれがある。RAG を使っても完全には防げないとされています
  • 権限の漏れ:本来見られない人の質問に、閲覧権限のない資料が検索されて答えに使われてしまう(LLM08:2025)

対策としては、検索のときに質問した人の権限で絞り込む、AI に渡す資料と指示をはっきり分ける、メール送信など影響の大きい操作の前には人が確認する、といった方法があります。

まとめ

  • RAG は、質問に関係する資料を探して AI に渡し、それをもとに答えてもらう仕組みです。
  • AI が100万トークンを読める今は、資料が少なければ全部渡す方法も有力です。資料が多い・頻繁に変わる・権限が必要なら RAG が向いています。
  • 精度を上げるには、ハイブリッド検索・リランキング・チャンクへの文脈付けが効果的です。
  • まずは OpenAI や Gemini の File Search など、おまかせのサービスで試すのが近道です。
  • 評価は「検索」と「回答」を分けて行い、権限と間接プロンプトインジェクションに注意しましょう。

参考リンク

PR

生成AIを体系的に学びたい方へ

「DMM 生成AI CAMP 学び放題」は、ChatGPTなどの生成AIを学べる月額制のオンライン学習サービスです。仕事への活用に向けて継続的に学びたい方は、公式サイトでコース内容や入会条件をご確認ください。

DMM 生成AI CAMP 学び放題

リンク先は公式サイトです。

エンジニア
Takuyaをフォローする