こんにちは、JS2IIUです。
ChatGPTに代表される生成AIの活用は急速に広がっています。チャット形式でも十分に威力を発揮してくれますが、一般的な内容の回答にとどまってしまいます。社内文書などの特定のドキュメントをベースに応答を生成するシステムを構成するのがRAGです。具体的な構成方法をみていきたいと思います。今回もよろしくお願いします。
1. RAG(Retrieval-Augmented Generation)とは
RAG(Retrieval-Augmented Generation)は、大規模言語モデル(LLM)に外部データソースを統合する技術です。通常のLLMは事前学習された知識に基づいて回答を生成しますが、RAGを使用すると以下のメリットがあります:
- 最新情報の利用:LLMが学習していない最新データを回答に活用できる。
- 専門知識の統合:ドメイン固有の文書を利用することで、より正確で詳細な回答を提供。
- 回答精度の向上:関連情報を検索し、よりコンテキストに即した回答を生成。
RAGの仕組み
- データ取得(Retrieval):外部データソースから関連情報を検索。
- 生成(Generation):取得した情報を元にLLMが回答を生成。
このプロジェクトでは、PDF文書を対象にRAGを構成し、チャット形式で情報を検索・回答するシステムを構築します。
2. LangChainを使ったRAGの構成方法
LangChainは、RAGシステムを簡単に構築できるPythonライブラリです。以下の主要コンポーネントを使用します:
- Document Loader:PDFなどの文書を読み込む。
- Text Splitter:長文を小さなチャンクに分割。
- Embeddings:テキストをベクトル表現に変換。
- Vector Store:ベクトル化したデータを保存し検索を効率化。
- LLM:OpenAI APIを使った大規模言語モデル。
RAG構築の流れ
- PDF文書を読み込む。
- テキストをチャンクに分割し、埋め込みを作成。
- FAISSを使って埋め込みをベクトルストアに保存。
- OpenAIモデルと連携し、ユーザーの質問に応答。
3. サンプルプログラム
import streamlit as st
import os
from langchain.document_loaders import PyPDFLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
from langchain.chat_models import ChatOpenAI
from langchain.chains import RetrievalQA
def process_pdf(uploaded_file, api_key):
with open("temp.pdf", "wb") as f:
f.write(uploaded_file.getbuffer())
loader = PyPDFLoader("temp.pdf")
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=100)
docs = text_splitter.split_documents(documents)
embeddings = OpenAIEmbeddings(openai_api_key=api_key)
vectorstore = FAISS.from_documents(docs, embeddings)
return vectorstore
def initialize_chatbot(api_key):
st.session_state.llm = ChatOpenAI(model_name="gpt-4", openai_api_key=api_key)
st.session_state.vectorstore = None
st.session_state.qa_chain = None
def main():
st.set_page_config(page_title="PDF対応 RAGチャット", layout="wide")
st.title("\ud83d\udcc4 PDF対応 RAGチャット")
openai_api_key = os.getenv("OPENAI_API_KEY")
if not openai_api_key:
st.error("OpenAI APIキーが環境変数に設定されていません。")
return
if "llm" not in st.session_state:
initialize_chatbot(openai_api_key)
uploaded_file = st.file_uploader("PDFファイルをアップロード", type="pdf")
if uploaded_file is not None:
with st.spinner("PDFを処理しています..."):
st.session_state.vectorstore = process_pdf(uploaded_file, openai_api_key)
st.session_state.qa_chain = RetrievalQA.from_chain_type(
llm=st.session_state.llm,
retriever=st.session_state.vectorstore.as_retriever()
)
st.success("PDFの処理が完了しました。チャットを開始できます!")
if st.session_state.qa_chain:
user_query = st.text_input("\ud83d\udcac 質問を入力してください")
if user_query:
with st.spinner("考えています..."):
response = st.session_state.qa_chain.run(user_query)
st.text_area("\ud83e\udd16 回答", value=response, height=200)
if __name__ == "__main__":
main()4. サンプルプログラムの詳細解説
1. 環境構築
必要なパッケージをインストールします。
pip install streamlit langchain openai faiss-cpu環境変数にOpenAI APIキーを設定します。
export OPENAI_API_KEY="your-api-key"2. コードの概要
process_pdf関数:PDFを読み込み、テキストを分割してベクトルストアを作成。initialize_chatbot関数:OpenAIモデルを初期化。main関数:Streamlitのインターフェースを構築。
3. コード詳細説明
このPythonコードは、StreamlitとLangChainを使用して、アップロードされたPDFファイルに基づいて質問応答を行うRAG(Retrieval Augmented Generation)チャットボットを構築するものです。以下に、コードのステップバイステップ解説を示します。
1. 必要なライブラリのインポート
import streamlit as st
import os
from langchain.document_loaders import PyPDFLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
from langchain.chat_models import ChatOpenAI
from langchain.chains import RetrievalQAstreamlit: WebアプリケーションのUI構築に使用os: 環境変数の取得に使用langchain.document_loaders: PDFファイルの読み込みに使用langchain.text_splitter: テキストをチャンクに分割するために使用langchain.embeddings: テキストのベクトル化に使用langchain.vectorstores: ベクトルデータベースの構築に使用langchain.chat_models: OpenAIのチャットモデルを使用langchain.chains: 質問応答チェーンの構築に使用
2. PDF処理関数 process_pdf
def process_pdf(uploaded_file, api_key):
with open("temp.pdf", "wb") as f:
f.write(uploaded_file.getbuffer())
loader = PyPDFLoader("temp.pdf")
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=100)
docs = text_splitter.split_documents(documents)
embeddings = OpenAIEmbeddings(openai_api_key=api_key)
vectorstore = FAISS.from_documents(docs, embeddings)
return vectorstore- アップロードされたPDFファイルを一時ファイルとして保存
PyPDFLoaderでPDFファイルを読み込み、テキストを抽出CharacterTextSplitterでテキストを固定長のチャンクに分割OpenAIEmbeddingsでテキストをベクトル化FAISSでベクトルデータベースを構築し、返す
ちなみに、今回のサンプルで読み込ませたPDFファイルには以下の内容が書かれています。
私の昨日の夕食はカレーライスでした。チキンカレー、とても辛く旨みのあるカレーでした。
今朝はエッグベネディクトを近所のレストランで。天気のいい朝でした。
3. チャットボット初期化関数 initialize_chatbot
def initialize_chatbot(api_key):
st.session_state.llm = ChatOpenAI(model_name="gpt-4", openai_api_key=api_key)
st.session_state.vectorstore = None
st.session_state.qa_chain = None- セッションステートにOpenAIのチャットモデル、ベクトルデータベース、質問応答チェーンを初期化
4. メイン関数 main
def main():
st.set_page_config(page_title="PDF対応 RAGチャット", layout="wide")
st.title(" PDF対応 RAGチャット")
openai_api_key = os.getenv("OPENAI_API_KEY")
if not openai_api_key:
st.error("OpenAI APIキーが環境変数に設定されていません。")
return
if "llm" not in st.session_state:
initialize_chatbot(openai_api_key)
uploaded_file = st.file_uploader("PDFファイルをアップロード", type="pdf")
if uploaded_file is not None:
with st.spinner("PDFを処理しています..."):
st.session_state.vectorstore = process_pdf(uploaded_file, openai_api_key)
st.session_state.qa_chain = RetrievalQA.from_chain_type(
llm=st.session_state.llm,
retriever=st.session_state.vectorstore.as_retriever()
)
st.success("PDFの処理が完了しました。チャットを開始できます!")
if st.session_state.qa_chain:
user_query = st.text_input(" 質問を入力してください")
if user_query:
with st.spinner("考えています..."):
response = st.session_state.qa_chain.run(user_query)
st.text_area(" 回答", value=response, height=200)
if __name__ == "__main__":
main()- Streamlitアプリの設定とタイトル表示
- 環境変数からOpenAI APIキーを取得し、存在しない場合はエラーを表示
- セッションステートにチャットボットが初期化されていない場合は初期化
- PDFファイルのアップロードウィジェットを表示
- PDFファイルがアップロードされた場合、
process_pdfで処理し、質問応答チェーンを構築 - 質問入力ウィジェットを表示し、質問が入力されたら回答を生成して表示
5. 実行
if __name__ == "__main__":でmain関数を実行し、Streamlitアプリを起動します。
コードのポイント
- RAG(Retrieval Augmented Generation): アップロードされたPDFから関連する情報を検索し、その情報に基づいて回答を生成します。
- セッションステート: Streamlitアプリの状態を保持し、ページ遷移後もデータを維持します。
- 環境変数: OpenAI APIキーを環境変数から取得することで、コード内に直接APIキーを記述せずに済みます。
このコードを実行するには、以下の準備が必要です。
- 必要なライブラリのインストール:
pip install streamlit langchain pypdf faiss-cpu openai - OpenAI APIキーの取得: OpenAIのウェブサイトでAPIキーを取得し、環境変数
OPENAI_API_KEYに設定 - コードの実行:
streamlit run your_script_name.py
4. まとめと参考リンク
まとめ
このプログラムでは、StreamlitとLangChainを使い、PDF文書に基づくRAGチャットを構築しました。
- RAGの概念とその利点
- LangChainを用いた実装方法
- サンプルコードの詳細な解説
参考リンク
最後に、書籍のPRです。
最新のOpenAIのチャットAPIの使い方もしっかりと解説されている良書です。2024年11月初版発行、「LangChainとLangGraphによるRAG・AIエージェント[実践]入門」西見、吉田、大嶋著。
最後まで読んでいただきありがとうございます。


コメント