業務活用事例

RAGシステムの基本設計:Claudeとベクター検索で社内文書を活用する

RAGシステムの基本設計:Claudeとベクター検索で社内文書を活用する

この記事の要点

RAG(Retrieval-Augmented Generation)の仕組みとClaudeを使った実装方法を解説。ベクターDBの選定・チャンキング戦略・検索精度の改善・ハルシネーション防止まで、社内文書Q&Aシステムの設計を実践的に紹介します。

結論

RAG(検索拡張生成)は、Claudeが学習データに含まれない社内情報・最新情報・専門知識を使って回答できるようにする設計パターンです。ユーザーの質問に関連する文書を検索し、その内容をコンテキストとしてClaudeに渡すことで、根拠のある正確な回答が得られます。

社内規程・製品マニュアル・過去の提案書・会議録のような情報を「Claudeに聞けば答えてくれるナレッジベース」に変えられます。


RAGが必要になる場面

Claudeは学習データから知識を持っていますが、2つの限界があります。

  1. 学習データのカットオフ以降の情報は知らない(最新の法改正・今年の社内規程改訂など)
  2. 社内固有の情報は学習されていない(自社の製品仕様・顧客情報・内部手順書など)

RAGはこの限界を補います。Claudeに「社内の規程集」「製品マニュアル」「過去の議事録」を検索する能力を与えることで、これらの質問にも正確に答えられるようになります。

用途具体例
社内規程Q&A「育休取得の手続きを教えて」→ 人事規程を検索して回答
製品サポート「エラーコード503の対処法は?」→ 製品マニュアルを検索
過去事例の活用「同様の案件で過去どんな提案をしたか?」→ 提案書を検索
法令対応「改正個人情報保護法で変わった点は?」→ 最新ガイドラインを検索

RAGシステムの3つのコンポーネント

コンポーネント1: 文書の前処理とベクター化

文書をAIが検索できる形式に変換します。

元の文書 → チャンク分割 → ベクター埋め込み → ベクターDB保存

チャンク分割: 長い文書を適切な大きさに分割します。チャンクが大きすぎると関係のない情報が混入し、小さすぎると文脈が失われます。

チャンクサイズ適した文書
500〜800文字FAQ・規程・手順書
1,000〜2,000文字技術文書・レポート
セクション単位構造化された仕様書

ベクター埋め込み: テキストを数値ベクトルに変換します。意味的に近いテキスト同士が近い位置に配置されます。これによって「経費精算の方法」という質問に「旅費・出張費の申請手順」という文書がヒットするような意味検索が可能になります。

コンポーネント2: 検索エンジン(ベクターDB)

ユーザーの質問に意味的に近い文書チャンクを高速に返します。

主なベクターDB:

ツール特徴向いているシーン
Chroma軽量・Python親和性が高いプロトタイプ・小規模
FAISS高速・Meta開発大規模データのローカル処理
Pineconeマネージドサービス本番環境・スケーラブル
pgvectorPostgreSQL拡張既存DBを活用したい場合

コンポーネント3: 生成(Claude)

検索で見つかった文書をコンテキストとしてClaudeに渡し、回答を生成します。


RAGパイプラインの実装例

import anthropic
from your_vector_db import VectorDB

client = anthropic.Anthropic()
db = VectorDB()

def answer_question(user_question: str) -> str:
    # ステップ1: 関連文書を検索
    relevant_chunks = db.search(
        query=user_question,
        top_k=5,  # 上位5件を取得
        threshold=0.75  # 類似度の閾値
    )
    
    # ステップ2: 検索結果をコンテキストとして整形
    context = "\n\n---\n\n".join([
        f"【出典: {chunk.source}\n{chunk.text}"
        for chunk in relevant_chunks
    ])
    
    # ステップ3: Claudeに質問と文書を渡す
    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1024,
        system="""あなたは社内文書に基づいて質問に答えるアシスタントです。

回答の原則:
- 提供された文書の情報のみを使って回答してください
- 文書に情報がない場合は「この文書からは確認できません」と回答してください
- 回答には必ず出典を示してください""",
        messages=[{
            "role": "user",
            "content": f"""以下の社内文書を参考に質問に答えてください。

【参考文書】
{context}

【質問】
{user_question}"""
        }]
    )
    
    return response.content[0].text

検索精度を上げる3つのテクニック

テクニック1: ハイブリッド検索

ベクター検索(意味的な類似性)とキーワード検索(BM25などの単語一致)を組み合わせます。

ベクター検索は「経費の申請方法」→「旅費の手続き」のような言葉が異なっても意味が近い文書を見つけますが、「第3条第2項」のような固有の語句・コードは弱いです。キーワード検索と組み合わせることで両方の弱点を補えます。

テクニック2: 質問の書き換え

ユーザーの短い質問をそのまま検索クエリにするより、Claudeに「検索に適した形に書き換え」させてから検索します。

# ユーザーの質問を検索クエリに変換
search_query = client.messages.create(
    model="claude-haiku-4-5-20251001",  # 安価なモデルで処理
    messages=[{
        "role": "user",
        "content": f"""次の質問を、文書検索に適したキーワードに書き換えてください。
                      質問: {user_question}
                      キーワードのみを返してください。"""
    }]
).content[0].text

# 書き換えたクエリで検索
results = db.search(query=search_query, top_k=5)

「育休どのくらい取れる?」→「育児休業 取得期間 日数 条件」のように展開することで、より適切な文書がヒットします。

テクニック3: 検索結果の再ランキング

上位N件を取得した後、さらにClaudeに「どれが最も関連性が高いか」を評価させます。ベクター検索で上位に来た文書が必ずしも最適とは限らないためです。


チャンキング戦略の詳細

文書の種類によって最適なチャンク分割の方法が変わります。

構造に沿ったチャンキング

章・節・条項などの構造を尊重した分割です。「第5条(育児休業)」の内容は第5条全体をひとまとまりにします。条の途中で切ると文脈が失われます。

オーバーラップチャンキング

隣接するチャンク間で100〜200文字程度を重複させます。チャンクの境界で文脈が切れる問題を防げます。

チャンク1: A...B[境界100文字]C
チャンク2:         [境界100文字]C...D

親子チャンキング

大きなチャンク(段落・節)と小さなチャンク(文)の両方を保存します。検索は小さいチャンクで行い、ヒットしたチャンクの親(大きいチャンク)をコンテキストとしてClaudeに渡します。詳細すぎず粗すぎない情報量を確保できます。


ハルシネーション防止の設計

RAGを使ってもハルシネーション(根拠のない回答)はゼロにはなりません。抑制するための設計を組み合わせます。

出典を必ず含める

Claudeへの指示:
「回答の各文に、使用した文書の出典(文書名・ページ・条項)を示してください。
出典を確認できない情報は回答に含めないでください。」

「わからない」と言える状態にする

「提供された文書に情報がない場合は、
『この質問については提供された文書から確認できません。
 担当部署(〇〇部)に直接お問い合わせください』
と回答してください。推測や一般的な知識で補完しないでください。」

検索結果の品質をチェックする

検索で見つかった文書の類似度スコアが低い場合(例: 0.6未満)は、「関連する文書が見つかりませんでした」として処理します。低品質な検索結果をそのままClaudeに渡すと、関係のない情報から無理やり回答を作ることがあります。


文書の更新と管理

RAGシステムは文書が最新の状態に保たれていないと、古い情報に基づく回答が出てしまいます。

更新検知の仕組み

def update_document(doc_id: str, new_content: str):
    # 古いチャンクを削除
    db.delete_by_doc_id(doc_id)
    
    # 新しいコンテンツをチャンク化してベクター化
    new_chunks = chunk_document(new_content)
    embeddings = embed_chunks(new_chunks)
    
    # ベクターDBに保存
    db.insert(chunks=new_chunks, embeddings=embeddings, doc_id=doc_id)

メタデータで鮮度を管理する

{
  "content": "育児休業は最長1年取得できます...",
  "source": "人事規程2026年版",
  "updated_at": "2026-04-01",
  "valid_until": "2027-03-31",
  "department": "人事部"
}

検索結果にこのメタデータを含めると、Claudeが「2024年版の規程に基づく情報です(最新版を確認してください)」のように情報の鮮度を示した回答ができます。

マルチエージェント設計と組み合わせて「最初に文書を検索するエージェント」「検索結果を整理するエージェント」「回答を生成するエージェント」に分けることで、より精度が上がります。詳細はマルチエージェント設計の実践パターンを参照してください。


まとめ

RAGシステム設計の実践ポイントをまとめます。

  • RAGは社内文書・最新情報・専門知識への質問に答えるための設計パターン
  • 文書の前処理(チャンキング)→ ベクター検索 → Claudeでの生成の3ステップが基本構造
  • ハイブリッド検索・質問の書き換え・再ランキングで検索精度を上げる
  • 「提供した文書の情報のみ使う」「出典を示す」「わからない場合は認める」の指示でハルシネーションを抑制する
  • 文書の更新・削除の仕組みを最初から設計に含めて情報の鮮度を保つ

RAGを正しく設計することで、社内の散在した情報を「Claudeに聞けば答えてくれるシステム」に変えられます。

よくある質問

RAGとは何ですか?

Retrieval-Augmented Generation の略で、AIが回答を生成する前に関連する文書を検索して取得(Retrieval)し、その情報を使って回答を生成(Generation)する仕組みです。学習データに含まれない社内情報や最新情報を活用できます。

RAGを使うとハルシネーション(幻覚)を防げますか?

完全には防げませんが、大幅に減らせます。「提供した文書の情報のみを使って回答し、情報がない場合は『この文書からは確認できません』と回答してください」という指示と組み合わせることで、根拠のない回答を抑制できます。

どんなベクターDBを使えばよいですか?

小規模(文書数万件以下)はChromaやFAISSのような軽量なものが適しています。大規模(数十万件以上)や本番環境ではPineconeやWeaviateが信頼性が高いです。Supabaseを使っている場合はpgvectorも選択肢です。