☕
Groq API + LangChainでRAG📌PDFマニュアルを参照して質問に回答する
概要
PDFで作成したマニュアルの情報を参照してLLMが質問に答えられるようにRAGを実装します。
処理の流れ
-
pypdf.PdfReader
でPDF内のテキストを読み込む -
RecursiveCharacterTextSplitter
を用いてテキストを分割 - Faissを用いてVectorDBを作成
- LangChainを用いてRAG chainを作成、実行
構成は下記の図のようになっています。
- VectorDB: Faiss
- LLM: Groq API
今回は動作確認のためにカフェのマニュアル(仮)を作成してみました。
当然このマニュアルの情報はLLMは知らない情報になっています。
コード
PDFからテキストを抽出
read_pdf
from pypdf import PdfReader
def read_text_from_pdf(pdf_path):
reader = PdfReader(pdf_path)
text = ""
for page_num in range(len(reader.pages)):
page = reader.pages[page_num]
text += page.extract_text()
return text
# PDFファイルのパスを指定してテキストを取得
pdf_text = read_text_from_pdf("./rag_example.pdf")
テキストを分割し、Faiss DBを作成
prepare_retriever
from langchain_community.vectorstores import FAISS
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
# チャンク間でoverlappingさせながらテキストを分割
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=200,
chunk_overlap=50,
)
# テキストを分割
splited_text = text_splitter.split_text(pdf_text)
embeddings = HuggingFaceEmbeddings(
model_name="oshizo/sbert-jsnli-luke-japanese-base-lite"
)
# テキストを埋め込みベクトルに変換
index = FAISS.from_texts(splited_text, embedding=embeddings)
# FaissのRetrieverを取得
retriever = index.as_retriever(search_kwargs={"k": 4})
RAG chainを実行
main
import os
from langchain_core.prompts import ChatPromptTemplate
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_groq import ChatGroq
# Get Groq API key
groq_api_key = os.environ["GROQ_API_KEY"]
groq_chat = ChatGroq(groq_api_key=groq_api_key, model_name="llama3-70b-8192")
system_prompt = (
"あなたは便利なアシスタントです。"
"マニュアルの内容から回答してください。"
"\n\n"
"{context}"
)
user_input = input("質問を入力してください: ")
prompt = ChatPromptTemplate.from_messages(
[
("system", system_prompt),
("human", "{input}"),
]
)
# ドキュメントのリストを渡せるchainを作成
question_answer_chain = create_stuff_documents_chain(groq_chat, prompt)
# RetrieverとQAチェーンを組み合わせてRAGチェーンを作成
rag_chain = create_retrieval_chain(retriever, question_answer_chain)
response = rag_chain.invoke({"input": user_input})
print("User: ", user_input)
print("Assistant:", response["answer"])
『この店で開催されるイベントは?』と聞いてみました。想定していた正解は6.1と6.3に記載のあるバリスタショーとワークショップでしたが、正しく回答できています。
User: この店で開催されるイベントは?
Assistant: この店で開催されるイベントは、以下の2つです。
1. バリスタショー:毎週土曜日の午後 2時から、バリスタによるラテアートのデモンストレーションを開催。
2. ワークショップ:月に一度、コーヒーの淹れ方講座を開催。予約制。
ちなみに、RAGで参照されたドキュメント情報はresponseに含まれているので下記のように確認することができます。
response["context"][0].page_content
RAG chainを実行(LCELで実装するパターン)
main
import os
from langchain_core.prompts import ChatPromptTemplate
from langchain_groq import ChatGroq
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
# Get Groq API key
groq_api_key = os.environ["GROQ_API_KEY"]
groq_chat = ChatGroq(groq_api_key=groq_api_key, model_name="llama3-70b-8192")
system_prompt = (
"あなたは便利なアシスタントです。"
"マニュアルの内容から回答してください。"
"\n\n"
"{context}"
)
user_input = input("質問を入力してください: ")
prompt = ChatPromptTemplate.from_messages(
[
("system", system_prompt),
("human", "{input}"),
]
)
rag_chain = (
# contextにはRetriever、inputにはユーザーの質問を渡す
{"context": retriever, "input": RunnablePassthrough()}
| prompt
| groq_chat
| StrOutputParser()
)
response = rag_chain.invoke(user_input)
print("User: ", user_input)
print("Assistant:", response)
User: この店は何時に開店しますか?
Assistant: この店は、平日は8:00 AM、土曜日は9:00 AM、日曜日は10:00 AMに開店します。
参考
参考にさせていただきました。ありがとうございます。
Discussion