はじめに
LangChainの会話履歴を保存するmemory機能の1つであるConversationBufferWindowMemoryを検証してみました。LangChainのConversationBufferWindowMemoryの挙動を確認したい方におすすめです。
開発環境
- Windows 11
- Python 3.11.5
- dotenv
- LangChain
- Azure OpenAI Embeddings
- CharacterTextSplitter
- FAISS
- PyPDFLoader
実装
事前準備
今回は以下の記事で事前にベクトルストアを作成し、そこから回答を生成する方式をとります。
私はランニングを行っていることもあり、以下のランニング時計の取扱説明書のPDFをベクトル化しました。
必要なパッケージのインストール
以下のコマンドで必要なパッケージをインストールします。
pip install langchain
pip install openai
pip install python-dotenv
pip install faiss-cpu
pip install PyPDF2
pip install tiktoken
環境変数の設定と依存関係の読み込み
.envファイルを作成し、Azure Open AIの環境変数の設定をします。
ご自身の環境に合わせて設定してください。
# APIキー
OPENAI_API_KEY = "XXXXX"
# エンドポイント
AZURE_OPENAI_ENDPOINT = "XXXXX"
# 使用するOpenAI APIのバージョン
OPENAI_API_VERSION = "XXXXX"
必要なライブラリをインポートします。
# 環境変数を.envファイルから読み込む
from dotenv import load_dotenv
load_dotenv()
from langchain.chat_models import AzureChatOpenAI
from langchain.embeddings import AzureOpenAIEmbeddings
from langchain.vectorstores import FAISS
from langchain.chains import ConversationalRetrievalChain
from langchain.memory import ConversationBufferMemory
使用するモデルの準備
Azure Chat OpenAIとAzure OpenAI Embeddingsを定義します。
llm = AzureChatOpenAI(
temperature=0,
azure_deployment="gpt-35-turbo-16k",
)
embeddings = AzureOpenAIEmbeddings(
azure_deployment="text-embedding-ada-002",
chunk_size=1,
)
FAISSベクトルストアの読み込み
ローカルに保存しているベクトルストアの読み込みを行い、as_retriever()メソッドで検索機能を作成します。
vectorstore = FAISS.load_local("./vectorstore", embeddings)
retriever = vectorstore.as_retriever()
ConversationBufferWindowMemoryの定義
以下のようにConversationBufferWindowMemoryを定義します。会話履歴と出力のキーを指定しています。
ConversationBufferMemoryはkで指定している個数だけ前の会話履歴を保持します。
memory = ConversationBufferWindowMemory(
k=1,
memory_key="chat_history",
output_key="answer",
return_messages=True,
)
chainを作成し、実行
最後にchainを作成し、実行します。質問は3問準備しています。
chain = ConversationalRetrievalChain.from_llm(
llm=llm, retriever=retriever, memory=memory
)
results = chain({"question": "心拍変動は計測可能ですか?"})
print("あなた:", results["question"])
print("ボット:", results["answer"])
print("会話履歴:", results["chat_history"])
results = chain({"question": "もっと詳しく説明してください。"})
print("あなた:", results["question"])
print("ボット:", results["answer"])
print("会話履歴:", results["chat_history"])
results = chain({"question": "血中酸素濃度は?"})
print("あなた:", results["question"])
print("ボット:", results["answer"])
print("会話履歴:", results["chat_history"])
これまでのPythonコードを上から順に記述し終わったら、Pythonファイルを実行します。
実行結果は以下のようになりました。
kで指定した個数分(この場合は1つ)前の会話履歴が保存されていることが確認できます。
k=2にすると、以下のように2つ前の会話まで保持されます。
この個数は使うシチュエーションに応じて調整してください。ただし、多く設定すると入力トークン数が増えるため、注意が必要です。
おわりに
LangChainの会話履歴を保存するmemory機能の1つであるConversationBufferWindowMemoryを検証してみました。文書検索に会話履歴を導入する際の選択肢の1つになります。ぜひ、試してみてください。
最後までお読みいただき、ありがとうございました! 記事に関する質問等ございましたら、コメントもしくは以下のDMにてよろしくお願いします。
参考文献