🤖

【LangChain】ChatGPTのAPIを利用して、医薬品の添付文書から適切に回答するチャットボットの作り方を解説

2023/08/21に公開

langchainでチャットボットと書類の内容について会話しよう

ページ数の多い書類を読むのは大変ですよね。
そこで、今回はPDFファイルの内容について会話できるチャットボットを作ってみましょう。

実装

必要なライブラリのインストール

pip install chromadb
pip install langchain
pip install openai
pip install pypdf

実装コード

from langchain.document_loaders import PyPDFLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.chat_models import ChatOpenAI
from langchain.chains import ConversationalRetrievalChain

import os

# apiキーをセットする
os.environ['OPENAI_API_KEY']='OPENAI APIキー'

# PDFを読み込む
loader = PyPDFLoader("PDFファイルのパス")
pages = loader.load_and_split()
text_splitter = CharacterTextSplitter(
    chunk_size=1000, 
    separator='', 
    chunk_overlap=50
)
docs = text_splitter.split_documents(pages)

# ベクトルストアを作成する
vector_stores = Chroma.from_documents(docs, OpenAIEmbeddings())

# チャットボットを作成する
qa = ConversationalRetrievalChain.from_llm(
    ChatOpenAI(model_name="gpt-3.5-turbo",temperature=0), # ボットの文章を生成するためのllm
    vector_stores.as_retriever(),
    return_source_documents=True # sourceを返すか
)

# ボットとの対話(10回質問するとシステムが終了する)
chat_history = []
for _ in range(10):
    query = input("ボットへの質問:")
    result = qa({'question': query, "chat_history": chat_history})
    print('chat bot:',result['answer'])
    chat_history.append((query, result['answer']))

解説1. PDFの読み込み

from langchain.document_loaders import PyPDFLoader
from langchain.text_splitter import CharacterTextSplitter

loader = PyPDFLoader("PDFファイルのパス")
pages = loader.load_and_split()
text_splitter = CharacterTextSplitter(
    chunk_size=1000, 
    separator='', 
    chunk_overlap=50
)
docs = text_splitter.split_documents(pages)

PDFの読み込みには、langchainのPyPDFLoaderと、load_and_split()を使用します。

PyPDFLoaderは、langchainで提供されているDocumentLoaderの一つで、構造化されたPDFの文章を正しい順番で読み込むことができます。

langachainで提供されているDocumentLoaderは、CSV、JSON、HTMLなどのファイル形式に対応しているLoaderが提供されているので、必要に応じて変更してください。

https://python.langchain.com/docs/modules/data_connection/document_loaders/

PDFの読み込みは、load_and_split()で行われ、ページごとに分割された文章が以下のようなDocumentsオブジェクトのリストとして返されます。

    [
        Document(page_content='1ページ目の文章', metadata={'source': 'PDFファイルのパス', 'page': 0}),
        Document(page_content='2ページ目の文章', metadata={'source': 'PDFファイルのパス', 'page': 1}),
        ...
    ]

chatGPTなどのLLMモデルには、一度に入力できる文字数に制限があるため、CharacterTextSplitterを使用して、文章を分割します。

chunk_sizeは、一度に入力する文字数の目安を指定できます。chunk_overlapは、分割した文章の重複する文字数を指定できます。separatorで指定した文字列で文章を分割することができます。

今回は、chunk_sizeを1000、chunk_overlapを50、separatorを空文字列に指定しています。separatorに空文字を指定することで、chunk_sizeで指定した文字数で文章を分割することができます。

    [
        Document(page_content='1ページ目の文章の1000文字目まで', metadata={'source': 'PDFファイルのパス', 'page': 0}),
        Document(page_content='1ページ目の文章の950文字目から1950文字目まで', metadata={'source': 'PDFファイルのパス', 'page': 0}),
        ...
    ]

解説2. Vector storeの作成

from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Chroma

vector_stores = Chroma.from_documents(docs, OpenAIEmbeddings())

ベクトルストアは、文章をベクトル化して、ベクトルの類似度を計算することができる機能です。
文章をベクトル化する際には、LLMモデルを使用して、文章をベクトル化します。
今回は、OpenAIのAPIを使用して、文章をベクトル化するため、OpenAIEmbeddingsを使用しています。

query = "ボットへの質問"
response = vector_stores.similarity_search(query)
print(response)

作成したvecrorer_storesにsimilarity_search()を使用して、queyを投げると、類似度の高い文章をDocumentsオブジェクトのリストとして返してくれます。

3. チャットボットの作成

# チャットボットを作成する
qa = ConversationalRetrievalChain.from_llm(
    ChatOpenAI(model_name="gpt-3.5-turbo",temperature=0), # ボットの文章を生成するためのllm
    vector_stores.as_retriever(),
    return_source_documents=True # sourceを返すか
)

query = input("ボットへの質問:")
chat_history = []
result = qa({'question': query, "chat_history": chat_history})
print('chat bot:',result['answer'])
chat_history.append((query, result['answer']))

チャットボットは、ConversationalRetrievalChainを使用して作成します。
ConversationalRetrievalChainは、質問に対して、過去の会話とVector storeを使用して、回答を生成することができる機能です。

from_llm()を使用して、LLMモデルを指定と、Vector storeの指定を行います。

実行する際には、{'question': query, "chat_history": chat_history}のように、質問と過去の会話を指定する必要があります。

1回目の質問では、過去の会話がないため、過去の会話は空のリストを指定します。

2回目以降の質問では、過去の会話を[('質問内容', '回答内容')]のようにリストに格納していき、これを引数に渡します。

実行

今回は、医療医薬品の添付文書のpdfファイルを読み込ませてみました。

「ボットへの質問」がユーザーの入力で、「chat bot」がボットの回答です。

資料の内容について会話することができていることがわかります。

ボットへの質問:何についての資料ですか?
chat bot: この文書は、特定の抗凝固薬に関する情報を提供しています。具体的には、製造販売元や文献の引用先、特定の背景を持つ患者に関する注意事項などが含まれています。
ボットへの質問:内容を要約してください
chat bot: この文書は、小児の抗凝固薬療法に精通した医師の指導のもとで治療を行うことが重要であることを述べています。また、文献請求先や問い合わせ先、製造販売業者の情報も提供されています。さらに、リバーロキサバン錠(Xarelto)の処方箋医薬品としての情報や副作用についても記載されています。
ボットへの質問:情報を教えてください
chat bot: 申し訳ありませんが、提供された文書からは具体的な情報がわかりません。どのような情報をお探しですか?
ボットへの質問:リバーロキサバン錠
chat bot: リバーロキサバン錠は、D6選択的直接作用型第Ⅹa因子阻害剤として使用される医薬品です。主成分はリバーロキサバンで、血液凝固を抑制する作用があります。主な効能は、非弁膜症性心房細動患者における虚血性脳卒中及び全身性塞栓症の発症抑制です。

リバーロキサバン錠は、15mgの錠剤として販売されており、処方箋医薬品として使用されます。投与量は1日1回で、腎機能の程度に応じて投与量が調整されます。

薬物相互作用については、他の薬剤との併用による相互作用試験が行われており、リトナビル、ケトコナゾール・フルコナゾール、クラリスロマイシン・エリスロマイシン、リファンピシン、エノキサパリンとの併用により、リバーロキサバンの薬物動態や抗凝固作用に影響があることが報告 されています。

腎障害患者や肝障害患者におけるリバーロキサバンの使用についても、薬物動態や薬力学的効果に差があることが報告されています。

なお、リバーロキサバン錠の成人における承認用法・用量は、非弁膜症性心房細動患者においては15mgを1日1回投与することが推奨されています。

以上が、リバーロキサバン錠に関する情報です。
ボットへの質問:

おわりに

いかがでしたか?

今回は、PDFファイルの内容について会話できるチャットボットを作成してみました。

皆さんも、ぜひ、読むのが面倒な資料を読み込ませて、チャットボットに質問してみてください!

株式会社piponでは定期的に技術勉強会を開催しています。
ChatGPT・AI・データサイエンスについてご興味がある方は是非、ご参加ください。
https://chatgptllm.connpass.com/
株式会社piponではChatGPT・AI・データサイエンスについて業界ごとの事例を紹介しています。ご興味ある方はこちらのオウンドメディアをご覧ください。
https://bigdata-tools.com/

株式会社piponのテックブログ

Discussion