はじめに
LangChainの会話履歴を保存するMemory機能の1つであるConversationSummaryMemoryを検証してみました。LangChainのConversationSummaryMemoryの挙動を確認したい方におすすめです。
開発環境
- Windows 11
- Python 3.11.5
- dotenv
- LangChain
- Azure OpenAI Embeddings
- CharacterTextSplitter
- FAISS
- PyPDFLoader
実装
事前準備
今回は以下の記事で事前にベクトルストアを作成し、そこから回答を生成する方式をとります。
https://qiita.com/tatsuki-tsuchiyama/items/a48d1cc4afce588e1797
私はランニングを行っていることもあり、以下のランニング時計の取扱説明書のPDFをベクトル化しました。
https://download.garmin.com/jp/download/manuals/Forerunner255_OM_JA.pdf
必要なパッケージのインストール
以下のコマンドで必要なパッケージをインストールします。
1 2 3 4 5 6 7 |
pip install langchain pip install openai pip install python-dotenv pip install faiss-cpu pip install PyPDF2 pip install tiktoken |
環境変数の設定と依存関係の読み込み
.envファイルを作成し、Azure Open AIの環境変数の設定をします。
ご自身の環境に合わせて設定してください。
1 2 3 4 5 6 7 8 9 |
# APIキー OPENAI_API_KEY = "XXXXX" # エンドポイント AZURE_OPENAI_ENDPOINT = "XXXXX" # 使用するOpenAI APIのバージョン OPENAI_API_VERSION = "XXXXX" |
必要なライブラリをインポートします。
1 2 3 4 5 6 7 8 9 10 11 |
<span class="c1"># 環境変数を.envファイルから読み込む </span><span class="kn">from</span> <span class="n">dotenv</span> <span class="kn">import</span> <span class="n">load_dotenv</span> <span class="nf">load_dotenv</span><span class="p">()</span> <span class="kn">from</span> <span class="n">langchain.chat_models</span> <span class="kn">import</span> <span class="n">AzureChatOpenAI</span> <span class="kn">from</span> <span class="n">langchain.embeddings</span> <span class="kn">import</span> <span class="n">AzureOpenAIEmbeddings</span> <span class="kn">from</span> <span class="n">langchain.vectorstores</span> <span class="kn">import</span> <span class="n">FAISS</span> <span class="kn">from</span> <span class="n">langchain.chains</span> <span class="kn">import</span> <span class="n">ConversationalRetrievalChain</span> <span class="kn">from</span> <span class="n">langchain.memory</span> <span class="kn">import</span> <span class="n">ConversationSummaryMemory</span> |
使用するモデルの準備
Azure Chat OpenAIとAzure OpenAI Embeddingsを定義します。
1 2 3 4 5 6 7 8 9 10 |
<span class="n">llm</span> <span class="o">=</span> <span class="nc">AzureChatOpenAI</span><span class="p">(</span> <span class="n">temperature</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">azure_deployment</span><span class="o">=</span><span class="sh">"</span><span class="s">gpt-35-turbo-16k</span><span class="sh">"</span><span class="p">,</span> <span class="p">)</span> <span class="n">embeddings</span> <span class="o">=</span> <span class="nc">AzureOpenAIEmbeddings</span><span class="p">(</span> <span class="n">azure_deployment</span><span class="o">=</span><span class="sh">"</span><span class="s">text-embedding-ada-002</span><span class="sh">"</span><span class="p">,</span> <span class="n">chunk_size</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="p">)</span> |
FAISSベクトルストアの読み込み
ローカルに保存しているベクトルストアの読み込みを行い、as_retriever()メソッドで検索機能を作成します。
1 2 3 |
<span class="n">vectorstore</span> <span class="o">=</span> <span class="n">FAISS</span><span class="p">.</span><span class="nf">load_local</span><span class="p">(</span><span class="sh">"</span><span class="s">./vectorstore</span><span class="sh">"</span><span class="p">,</span> <span class="n">embeddings</span><span class="p">)</span> <span class="n">retriever</span> <span class="o">=</span> <span class="n">vectorstore</span><span class="p">.</span><span class="nf">as_retriever</span><span class="p">()</span> |
ConversationSummaryMemoryの定義
以下のようにConversationSummaryMemoryを定義します。要約にllmを使います。会話履歴と出力のキーを指定しています。
ConversationBufferMemoryは会話履歴を要約して保持します。
1 2 3 4 5 6 7 |
<span class="n">memory</span> <span class="o">=</span> <span class="nc">ConversationSummaryMemory</span><span class="p">(</span> <span class="n">llm</span><span class="o">=</span><span class="n">llm</span><span class="p">,</span> <span class="n">memory_key</span><span class="o">=</span><span class="sh">"</span><span class="s">chat_history</span><span class="sh">"</span><span class="p">,</span> <span class="n">return_messages</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">output_key</span><span class="o">=</span><span class="sh">"</span><span class="s">answer</span><span class="sh">"</span><span class="p">,</span> <span class="p">)</span> |
chainを作成し、実行
最後にchainを作成し、実行します。質問は3問準備しており、2問目は1問目を詳しく説明する質問、3問目はそれまでの会話をもとに回答できるかを検証する質問に設定しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<span class="n">chain</span> <span class="o">=</span> <span class="n">ConversationalRetrievalChain</span><span class="p">.</span><span class="nf">from_llm</span><span class="p">(</span> <span class="n">llm</span><span class="o">=</span><span class="n">llm</span><span class="p">,</span> <span class="n">retriever</span><span class="o">=</span><span class="n">retriever</span><span class="p">,</span> <span class="n">memory</span><span class="o">=</span><span class="n">memory</span> <span class="p">)</span> <span class="n">results</span> <span class="o">=</span> <span class="nf">chain</span><span class="p">({</span><span class="sh">"</span><span class="s">question</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">心拍変動は計測可能ですか?</span><span class="sh">"</span><span class="p">})</span> <span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">あなた:</span><span class="sh">"</span><span class="p">,</span> <span class="n">results</span><span class="p">[</span><span class="sh">"</span><span class="s">question</span><span class="sh">"</span><span class="p">])</span> <span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">ボット:</span><span class="sh">"</span><span class="p">,</span> <span class="n">results</span><span class="p">[</span><span class="sh">"</span><span class="s">answer</span><span class="sh">"</span><span class="p">])</span> <span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">会話履歴:</span><span class="sh">"</span><span class="p">,</span> <span class="n">results</span><span class="p">[</span><span class="sh">"</span><span class="s">chat_history</span><span class="sh">"</span><span class="p">])</span> <span class="n">results</span> <span class="o">=</span> <span class="nf">chain</span><span class="p">({</span><span class="sh">"</span><span class="s">question</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">もっと詳しく説明してください。</span><span class="sh">"</span><span class="p">})</span> <span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">あなた:</span><span class="sh">"</span><span class="p">,</span> <span class="n">results</span><span class="p">[</span><span class="sh">"</span><span class="s">question</span><span class="sh">"</span><span class="p">])</span> <span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">ボット:</span><span class="sh">"</span><span class="p">,</span> <span class="n">results</span><span class="p">[</span><span class="sh">"</span><span class="s">answer</span><span class="sh">"</span><span class="p">])</span> <span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">会話履歴:</span><span class="sh">"</span><span class="p">,</span> <span class="n">results</span><span class="p">[</span><span class="sh">"</span><span class="s">chat_history</span><span class="sh">"</span><span class="p">])</span> <span class="n">results</span> <span class="o">=</span> <span class="nf">chain</span><span class="p">({</span><span class="sh">"</span><span class="s">question</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">血中酸素濃度は?</span><span class="sh">"</span><span class="p">})</span> <span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">あなた:</span><span class="sh">"</span><span class="p">,</span> <span class="n">results</span><span class="p">[</span><span class="sh">"</span><span class="s">question</span><span class="sh">"</span><span class="p">])</span> <span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">ボット:</span><span class="sh">"</span><span class="p">,</span> <span class="n">results</span><span class="p">[</span><span class="sh">"</span><span class="s">answer</span><span class="sh">"</span><span class="p">])</span> <span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">会話履歴:</span><span class="sh">"</span><span class="p">,</span> <span class="n">results</span><span class="p">[</span><span class="sh">"</span><span class="s">chat_history</span><span class="sh">"</span><span class="p">])</span> |
これまでのPythonコードを上から順に記述し終わったら、Pythonファイルを実行します。
実行結果は以下のようになりました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<span class="go">あなた: 心拍変動は計測可能ですか? ボット: 申し訳ありませんが、提供された情報には心拍変動を計測する機能についての記述はありません。 会話履歴: [SystemMessage(content='')] あなた: もっと詳しく説明してください。 ボット: デバイス情報を確認するためには、以下の手順を実行します。 1. デバイスのUPキーを長押しします。 2. [システム]メニューに移動し、[デバイス情報]を選択します。 デバイス情報では、デバイスのユニットID、ソフトウェアバージョン、規制情報、ライセンス契約などの情報が表示されます。 また、電子ラベルの規制および準拠情報を確認するためにも、同じ手順を実行します。 デバイスを充電するためには、以下の手順を実行します。 1. チャージングケーブルのマークの付いた方の端子を、デバイスの裏面にある充電端子に接続します。 2. チャージングケーブルのもう一方の端子を、充電可能なUSBポートに差し込みます。 デバイスを装着する際には、注意が必要です。長期間装着すると、敏感肌やアレルギーを持つ方に炎症やかぶれが生じることがあります。炎症やかぶれが生じた場合は、デバイスを取り外すようにしてください。 以上がデバイス情報の確認方法、充電方法、および装着方法の詳細です。 会話履歴: [SystemMessage(content='The human asks if heart rate variability is measurable. The AI apologizes and states that there is no description of a feature to measure heart rate variability in the provided information.')] あなた: 血中酸素濃度は? ボット: はい、Garminデバイスは血中酸素濃度を測定する機能があります。血中酸素トラッキング機能を使用することで、血液中の 酸素のレベルを測定することができます。 会話履歴: [SystemMessage(content='The human asks if heart rate variability is measurable. The AI apologizes and states that there is no description of a feature to measure heart rate variability in the provided information. The human asks for a more detailed explanation. The AI provides step-by-step instructions on how to check device information, charge the device, and wear the device. It also warns about potential skin inflammation or allergies that may occur with prolonged wearing of the device.')] </span> |
会話履歴が英語で要約されていることが分かります。日本語ではないので、使用する際は注意が必要です。
おわりに
LangChainの会話履歴を保存するmemory機能の一つであるConversationSummaryMemoryを検証してみました。文書検索に会話履歴を導入する際の選択肢の1つになります。ぜひ、試してみてください。
最後までお読みいただき、ありがとうございました!