deaw.ai

誰もが自分のドキュメントから質問に答えられるチャットボットを求めています——会社のハンドブック、契約書、研究論文などです。この背後にある手法はRAG (Retrieval-Augmented Generation)と呼ばれます。

私は生業として本番向けのRAGおよびLLMシステムを構築しており、すべてのプロジェクトで同じ基盤を再構築し続けていました。そこでそれを整理して、小さなオープンソーススターターにまとめました。この記事では、RAGの実際の仕組み、重要な設計判断、そしてAPIキーなしで完全に無料で実行する方法を説明します。

最後に、クローンして数分で実行できる完全なオープンソースリポジトリへのリンクがあります。

なぜRAGなのか?

GPTやClaudeのようなLLMは、訓練された内容しか知りません。ノートパソコンにあるドキュメントについて尋ねると、推測するか——幻覚を引き起こします。

RAGはシンプルなアイデアでこれを修正します:まず関連情報を取得し、次にLLMにそれだけを使って答えさせる。 その結果、実際のドキュメントに基づいた回答が得られ、特定のページまで遡れる引用が提供されます。

2つの経路によるパイプライン

経路1 — インデックス作成(ドキュメントが到着したとき):

  1. PDFからテキストを抽出
  2. 重複するチャンクに分割
  3. 各チャンクを意味を捉えたベクトル(埋め込み)に変換
  4. それらのベクトルをベクトルデータベースに保存

経路2 — クエリ(ユーザーが質問したとき):

  1. 同じモデルで質問を埋め込み
  2. ベクトルデータベースで最も類似したチャンクを検索
  3. それらのチャンクと質問をLLMに送信
  4. LLMはそのコンテキストを使って回答し、ソースページを返します

スタックの選択

いくつか構築した経験から、簡単に始められ、本番環境でも耐えうるスタックは以下の通りです:

  • FastAPI — 書きやすく、クリーンな非同期API
  • ChromaDB — 軽量なベクトルデータベースで、埋め込み型で別サーバーの管理が不要
  • SentenceTransformers — 無料の埋め込み、多言語モデルも利用可能
  • 任意のLLM — OpenAI、Claude、Gemini、またはローカルのOllama

見落とされがちな詳細:APIキーなしでパイプライン全体をテストできます。マッチしたチャンクを返す検索のみのモードか、何も外部に出さない完全ローカルのOllamaを使用します。

検索ステップの核心

クエリ側の概要は次のようになります——質問を埋め込み、検索し、チャンクをLLMに渡す:

def answer_question(question: str, top_k: int = 3):
    # 1. Embed the question with the same model used at indexing time
    query_embedding = embed(question)

    # 2. Retrieve the most similar chunks from the vector store
    chunks = vector_store.search(query_embedding, top_k=top_k)

    # 3. Build a prompt grounded in those chunks, then ask the LLM
    context = "\n\n".join(c["text"] for c in chunks)
    answer = llm.generate(question=question, context=context)

    return answer, chunks  # chunks double as citations

Enter fullscreen mode Exit fullscreen mode

重要な制約:質問とドキュメントに同じ埋め込みモデルを使用すること。 異なるモデルからのベクトルは比較できず、これは驚くほどよくあるバグです。

品質を左右する詳細

経験から、RAGシステムがうまく回答できるかどうかは、人々が過小評価しがちないくつかの点にかかっています:

  • チャンクサイズ。 大きすぎると無関係なコンテンツが混ざり、小さすぎると各チャンクが文脈を失います。チャンク間のオーバーラップは、思考の途中で文が切れるのを防ぎます。
  • スキャンされたPDF。 ファイルが画像の場合、通常のテキスト抽出は何も返しません。OCRフォールバックが必要で、そうでないとそれらのページは空としてインデックスされます。
  • リランキング。 純粋なベクトル検索は高速ですが粗いです。質問と各チャンクを一緒に読むクロスエンコーダーリランカーを追加すると、実際にモデルに渡すチャンクの品質が大幅に向上します。

試してみる(無料、オープンソース)

これらすべてをMITライセンスのスターターテンプレートにまとめました。クローンして1つのDockerコマンドを実行すれば、ソース引用付きの動作するドキュメントQ&Aチャットボットが手に入ります。多言語対応で、APIキーなしで無料で実行できます。

👉 GitHub: https://github.com/panutpl/rag-chatbot-template-starter

git clone https://github.com/panutpl/rag-chatbot-template-starter
cd rag-chatbot-template-starter
cp .env.example .env
docker compose up --build

Enter fullscreen mode Exit fullscreen mode

次にhttp://localhost:8000/docsを開き、PDFをアップロードして質問を始めます。


RAGを構築している方、またはこれから始める方は、フィードバックを歓迎します——特にチャンク化と検索戦略について、私自身もまだ調整中です。うまく機能している点についてコメントをお願いします。