AIエージェント開発

RAGとは?ChromaDB×Pythonで精度改善する実装ガイド

RAGとは?ChromaDB×Pythonで精度改善する実装ガイド

この記事の結論

RAG(Retrieval-Augmented Generation)をPythonで実装する方法を解説。ChromaDB、ベクトルDB選定、チャンク分割、リランキングまで。社内データでAIの回答精度を劇的に改善する実装ガイド。

結論

結論: RAG(検索拡張生成)は、LLMの幻覚(ハルシネーション)を抑制し、自社データに基づく正確な回答を実現する技術。2026年はハイブリッド検索とGraphRAGの組み合わせが主流になりつつある。

この記事の要点:

  • 要点1: RAGは「検索(Retrieval)→ 拡張(Augmented)→ 生成(Generation)」の3ステップで、LLMに社内データを参照させる仕組み
  • 要点2: PoCにはChromaDB(無料・ローカル完結)、本番にはPineconeやpgvectorが定番
  • 要点3: 2026年のベストプラクティスは「ハイブリッド検索 + リランキング + ファインチューニング」の併用

対象読者: 社内データを活用したAIチャットボットを構築したいエンジニア
読了後にできること: PythonでRAGパイプラインを構築し、自社ドキュメントに基づくQ&Aシステムを実装できる

はじめに

ChatGPTに社内の就業規則について質問したら、もっともらしいウソを返された——そんな経験はありませんか?

LLM(大規模言語モデル)は汎用的な知識を持っていますが、自社固有の情報は知りません。しかも「知らない」と言わずに、それっぽい回答を生成してしまう(ハルシネーション)。この問題を解決するのがRAG(Retrieval-Augmented Generation:検索拡張生成)です。

RAGを使えば、LLMが回答を生成する前に関連する社内ドキュメントを検索し、その内容に基づいて回答します。2026年現在、エンタープライズAIシステムの53%がRAGパイプラインを採用しており、「AIを実業務で使う」ための必須技術となっています。

まず試したい「5分即効」セットアップ3選

即効1: ChromaDBで最小構成のRAG

# 動作環境: Python 3.10+
# pip install chromadb openai

import chromadb
from openai import OpenAI

# 1. ベクトルDBにドキュメントを格納
chroma = chromadb.Client()
collection = chroma.create_collection("company_docs")

# 社内ドキュメントを登録(実際はPDF/Notion/Confluenceから取得)
documents = [
    "有給休暇は入社6ヶ月後に10日付与されます。勤続年数に応じて最大20日まで増加します。",
    "リモートワークは週3日まで可能です。事前に上長の承認が必要です。申請はSlackの#remote-workチャンネルで。",
    "経費精算の上限は月5万円です。5万円を超える場合は事前に経理部の承認が必要です。",
    "育児休業は子が1歳になるまで取得可能。保育所に入れない場合は最長2歳まで延長できます。",
]

collection.add(
    documents=documents,
    ids=[f"doc_{i}" for i in range(len(documents))]
)

# 2. 質問に対して関連ドキュメントを検索
query = "リモートワークのルールを教えてください"
results = collection.query(query_texts=[query], n_results=2)

# 3. 検索結果をコンテキストとしてLLMに渡す
context = "n".join(results["documents"][0])
client = OpenAI()

response = client.chat.completions.create(
    model="gpt-4.1-nano",  # 低コスト
    messages=[
        {"role": "system", "content": f"以下の社内ドキュメントに基づいて回答してください。ドキュメントに情報がない場合は「確認が必要です」と回答してください。nn{context}"},
        {"role": "user", "content": query}
    ]
)

print(response.choices[0].message.content)

ポイント: ChromaDBはpip install chromadbだけで使えるベクトルDB。OpenAI Embeddingsを内部で自動呼び出しするため、明示的なエンベディング生成コードが不要です。

即効2: PDF文書をRAGに取り込む

# pip install chromadb openai pymupdf langchain-text-splitters

import fitz  # PyMuPDF
from langchain_text_splitters import RecursiveCharacterTextSplitter

# PDFからテキスト抽出
def extract_pdf(path):
    doc = fitz.open(path)
    return "n".join(page.get_text() for page in doc)

text = extract_pdf("company_rules.pdf")

# チャンク分割(日本語に適した設定)
splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,        # 日本語は1文字≒1トークンなので500文字
    chunk_overlap=50,      # 前後50文字を重複させて文脈を保持
    separators=["nn", "n", "。", "、", " "]
)
chunks = splitter.split_text(text)

# ChromaDBに格納
collection.add(
    documents=chunks,
    ids=[f"chunk_{i}" for i in range(len(chunks))]
)
print(f"{len(chunks)}チャンクを登録完了")

ポイント: チャンクサイズは日本語の場合300-500文字が最適。大きすぎると検索精度が下がり、小さすぎると文脈が失われます。chunk_overlapで段落境界のコンテキスト切れを防ぎます。

即効3: Claudeで高品質な回答を生成

# pip install anthropic

import anthropic

client = anthropic.Anthropic()  # ANTHROPIC_API_KEY環境変数を設定

# 検索結果をXMLタグで構造化して渡す(Claude推奨パターン)
context_docs = results["documents"][0]
context_xml = "n".join(
    f"<document index="{i+1}">n{doc}n</document>"
    for i, doc in enumerate(context_docs)
)

response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    system=f"""以下の社内ドキュメントに基づいて、正確に回答してください。
ドキュメントに記載がない情報は「社内規定で確認が必要です」と回答してください。
回答にはどのドキュメントを参照したかを明記してください。

<documents>
{context_xml}
</documents>""",
    messages=[{"role": "user", "content": query}]
)

print(response.content[0].text)

ポイント: ClaudeはXMLタグで構造化された入力を正確に処理します。<document index="1">のように番号付きで渡すと、「ドキュメント2より」のように出典を明示した回答が得られます。

RAGアーキテクチャの全体像

【RAGパイプライン】

[ドキュメント] → [チャンク分割] → [エンベディング] → [ベクトルDB]
                                                          ↓
[ユーザー質問] → [エンベディング] → [類似検索] → [リランキング]
                                                          ↓
                                              [プロンプト構築]
                                                          ↓
                                                  [LLM生成]
                                                          ↓
                                                    [回答]
ステップ 処理内容 2026年のベストプラクティス
チャンク分割 文書を検索単位に分割 セマンティック分割(意味の切れ目で分割)
エンベディング テキストをベクトルに変換 OpenAI text-embedding-3-large / Cohere embed-v4
ベクトルDB ベクトルを格納・検索 PoC: ChromaDB、本番: Pinecone / pgvector
検索 類似ドキュメントを取得 ハイブリッド検索(ベクトル + キーワード)
リランキング 検索結果を再順位付け Cohere Rerank / Cross-Encoder
生成 コンテキスト付きで回答 出典明示 + ハルシネーション検出

ベクトルDB選定ガイド

DB 特徴 コスト 推奨シーン
ChromaDB ローカル完結、pip install可 無料(OSS) PoC・個人開発
Pinecone マネージド、スケーラブル $0〜(Free Tier) 本番SaaS
pgvector PostgreSQL拡張、SQLで操作 無料(OSS) 既存PostgreSQL環境
Qdrant Rust製高速、フィルタリング強い 無料(OSS) 大規模・高速要件
Weaviate GraphQL API、マルチモーダル 無料(OSS) 画像+テキスト混在

2026年の選定基準: 「PoCならChroma、SQLが使いたいならpgvector、マネージドが良いならPinecone」が鉄則。既存のPostgreSQLがある企業はpgvectorが最もROIが高いです。

【要注意】よくある失敗パターンと回避策

失敗1: チャンクサイズが不適切

❌ 1000文字以上の大きなチャンクで検索精度が低下。関係ない情報が混入
✅ 日本語は300-500文字。セマンティック分割(段落・見出し単位)を併用

失敗2: 「RAGの精度が悪い」のに生成側を調整する

❌ プロンプトを何度変えても回答が改善しない
✅ RAGの精度問題の80%は検索側の問題。まずリランキングを導入し、検索結果の上位3件が本当に関連しているか確認

失敗3: エンベディングモデルの選定ミス

❌ 英語向けモデルで日本語ドキュメントをエンベディングし、検索精度が壊滅
✅ 日本語対応モデルを選択: OpenAI text-embedding-3-large(多言語対応)、Cohere embed-v4(多言語特化)

失敗4: ドキュメントの更新を忘れる

❌ 就業規則が改訂されたのに古い情報が返される
✅ ドキュメント更新のWebhookをトリガーに、ベクトルDBを自動再インデックス(n8nと連携すると効果的)

参考・出典


あわせて読みたい:


著者: 佐藤傑(さとう・すぐる)
株式会社Uravation代表取締役。X(@SuguruKun_ai)フォロワー約10万人。
100社以上の企業向けAI研修・導入支援。著書『AIエージェント仕事術』(SBクリエイティブ)。
SoftBank IT連載7回執筆(NewsPicks最大1,125ピックス)。

ご質問・ご相談は お問い合わせフォーム からお気軽にどうぞ。

あわせて読みたい

AIエージェントの導入・活用についてのご相談は、Uravationのサービス一覧をご覧ください。

あわせて読みたい

Need help moving from reading to rollout?

この記事を読んで導入イメージが固まってきた方へ

Uravationでは、AIエージェントの要件整理、PoC設計、社内導入、研修まで一気通貫で支援しています。

この記事をシェア

X Facebook LINE

※ 本記事の情報は2026年3月時点のものです。サービスの料金・仕様は変更される可能性があります。最新情報は各サービスの公式サイトをご確認ください。

関連記事