RAGパイプライン構築の実装手順:LangChainとベクトルDBで作る質問応答システム
RAGパイプラインで何ができるか
質問応答システムを自分たちのデータで作ることができます。例えば、会社の提案書や過去の案件資料から自動で情報を引き出して、生成AIに答えさせるような使い方です。
RAGは「データ取得と質問回答を組み合わせた仕組み」という意味です。ユーザーが質問すると、関連する資料を自動で探して、その内容をふまえた回答が返ってきます。社内マニュアルを読み込ませたり、顧客の問い合わせに自動で対応したり、膨大なドキュメントから必要な情報だけを抽出したりするときに活躍します。
従来は「生成AIに質問を投げて、学習データから回答を生成する」という流れでしたが、RAGを使うと「質問に関連する資料を先に見つけて、その資料の内容を参考に回答を作る」という流れになります。最新データへの対応や、企業秘密の保持、回答の正確さが大きく改善されます。
準備するもの
実装に必要なのは、Pythonの開発環境(バージョン3.8以上)と、下記のライブラリです:
- LangChain:質問応答の流れを組み立てるためのツール
- ベクトルDB(FAISS、Pinecone、Chromaなど):資料を数値に変換して保存・検索するデータベース
- OpenAI APIキーまたはそれに相当するAPI:テキストを数値に変換したり(埋め込み)、質問に答えたりするAI機能
- テキスト処理用ライブラリ:PDFやテキストファイルから情報を読み込む
実装の段階に応じて、Pythonのパッケージマネージャー(pip)でインストールを進めます。
手順
1. LangChainの基本構造を理解する(所要時間:15分)
RAGパイプラインは大きく3つの工程に分かれます。
第一段階:資料の準備 会社の資料やWebサイトなど、回答の根拠にしたいデータを集めます。テキストファイル、PDF、データベースなど、形式は自由です。
第二段階:埋め込み処理(ベクトル化) 資料の内容を「ベクトル」という数値のセットに変換して、ベクトルDBに保存します。この処理によって、後で「この質問に似た資料は何か」という検索が高速で実行できるようになります。
第三段階:質問応答 ユーザーが質問をすると、その質問もベクトル化されて、保存されている資料と比較されます。最も関連性の高い資料を見つけ出し、その内容を生成AIに与えて、質問に対する答えを作成します。
LangChainはこの3段階全体を管理するためのフレームワークです。
2. ライブラリをインストールする(所要時間:10分)
ターミナルやコマンドプロンプトを開いて、下記を実行します:
pip install langchain langchain-openai faiss-cpu openai
Nodeでの実装も可能です。JavaScriptでRAGパイプラインを動かすことができ、その場合はOpenAIの埋め込み機能とFAISSをNode環境で使用できます。
3. テキストデータを読み込む(所要時間:20分)
Pythonのコードで、使う資料を読み込みます。例えば、テキストファイルの場合:
with open('company_manual.txt', 'r', encoding='utf-8') as f:
documents = f.read()
複数のファイルがあれば、ループで処理します。PDFを使う場合は、別のライブラリ(例:PyPDFLoader)で読み込むことになります。
4. テキストを小分けにする(所要時間:15分)
長いテキストをそのまま使うと、検索が効率的になりません。適切なサイズに分割します。LangChainの「テキストスプリッター」を使う方法が一般的です:
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200
)
docs = splitter.split_text(documents)
chunk_size は1回の分割で何文字にするか、chunk_overlap は分割したテキスト同士がどのくらい重複するかを指定します。重複があると、境界線の情報が失われにくくなります。
5. ベクトルDBを初期化する(所要時間:20分)
読み込んだテキストを数値に変換して、保存します。FAISSの場合:
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import FAISS
embeddings = OpenAIEmbeddings(api_key='your-api-key')
vectorstore = FAISS.from_texts(docs, embeddings)
ここで初めてOpenAI APIが呼ばれます。テキストが数値(ベクトル)に変換されて、FAISS内に保存されます。
6. 質問応答チェーンを構築する(所要時間:25分)
LangChainの古いバージョンでは「RetrievalQA」という機能を使っていたのですが、新しいバージョンではこの機能の位置が変わっています。最新の書き方は、OpenAIのモデルと検索機能を直接つなぐ方法です:
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model='gpt-3.5-turbo', api_key='your-api-key')
retriever = vectorstore.as_retriever()
qa_chain = RetrievalQA.from_chain_type(llm=llm, retriever=retriever)
LangChainの更新でRetrievalQAの位置が変わった場合は、別のインポート方法やクラス構造を確認する必要があります。StackOverflowなどのQ&Aサイトで最新の正しいインポート方法が議論されていることが多いので、エラーメッセージをもとに調べることをお勧めします。
7. 質問を投げて回答を得る(所要時間:10分)
準備ができたら、実際に質問してみます:
query = '会社の新入社員向けトレーニング期間は何日ですか?'
result = qa_chain.run(query)
print(result)
つまずきやすいところ
APIキーの設定ミス
OpenAI APIキーが正しくセットされていないと、埋め込み処理も質問応答も動きません。キーは環境変数として設定するか、コード内で明示的に指定します。本番環境ではキーをソースコードに直接書かないよう注意してください。
インポートエラー
LangChainは頻繁に更新されており、ライブラリの構造が変わることがあります。「ImportError: cannot import name ‘RetrievalQA’」というエラーが出た場合は、LangChainのバージョンを確認し、公式ドキュメントまたはStackOverflowで最新のインポート方法を調べてください。
メモリ機能がない
基本的なRetrievalQAには、会話の履歴を覚える機能がありません。ユーザーが前の質問に基づいて「それについてもっと詳しく教えて」と聞いても、新しい質問として扱われてしまいます。この問題は「ConversationalRetrievalChain」で解決でき、メモリオプションを追加することで過去の会話を参考にできるようになります。
チャット履歴の不具合
会話形式のRAGシステムを作る場合、チャット履歴の管理がうまくいかないことがあります。回答が不正確になったり、文脈がぐちゃぐちゃになったりするのは、多くの場合メモリの設定か、プロンプト(生成AIへの指示文)の書き方の問題です。
評価の難しさ
RAGパイプラインが「ちゃんと動いているか」を測るのは思った以上に難しいです。回答の正確さ、資料の検索精度、ユーザー満足度など、複数の指標を組み合わせて判断する必要があります。グラフデータベース(Graph RAG)を使ったり、複数の指標を組み合わせたりする方法が業界で検討されています。
慣れてきたら試したいこと
メモリ機能を追加する
基本的なRAGでは毎回独立した質問として処理されますが、会話形式にするにはメモリを追加します。ConversationalRetrievalChainを使って、過去の質問と回答を保持させることで、より自然な対話ができるようになります。
カスタムプロンプトを用意することで、生成AIにどんな役割を果たすか明確に指示することもできます。例えば「あなたは会社のサポート担当者です。ユーザーの質問には資料を参考に、丁寧に答えてください」というような指示を追加します。
複数の情報源を統合する
最初は1つのテキストファイルやデータベースだけかもしれませんが、複数のシステムや資料から同時に情報を引き出すようにカスタマイズできます。
回答の評価を自動化する
生成される回答の質を自動で測定する仕組みを入れることで、パイプラインの改善箇所を見つけやすくなります。複数の評価方法を並行して走らせるアプローチもあります。
別の言語での実装
Pythonでの実装が一般的ですが、NodeJSでRAGパイプラインを完全に動かすことも可能です。JavaScriptを得意とする環境では、Node版の実装を検討する価値があります。
参考ソース
- What Is RAG (Retrieval-Augmented Generation)? A Plain-English Guide
- ImportError: cannot import name 'RetrievalQA' from 'langchain.chains' in Python project
- How can I efficiently run a RAG pipeline fully in Node.js using OpenAI embeddings and FAISS without relying on Python?
- Best Approach to Evaluate a Graph RAG Pipeline Using Metrics?
- RAG model chat history does not work properly
- How do i add memory to RetrievalQA.from_chain_type? or, how do I add a custom prompt to ConversationalRetrievalChain?