見出し画像

LangChainドキュメント:複数文書の比較

LangChainのドキュメントが追加されていました。

  • Fanction calling対応Agent(そろそろ短い呼び方を決めたい😅)を使った複数文書の比較をおこなう例題です。

GooglColab環境で動かしてみました。

ライブラリのインストールなど

!pip install langchain
!pip install openai 

!pip install pypdf
!pip install pycryptodome

!pip install faiss-cpu
!pip install tiktoken

# 環境変数の準備
import os
os.environ["OPENAI_API_KEY"] = "YOUR OPENAI_API_KEY"
from pydantic import BaseModel, Field

from langchain.chat_models import ChatOpenAI
from langchain.agents import Tool
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import FAISS
from langchain.document_loaders import PyPDFLoader
from langchain.chains import RetrievalQA

文書の読み込み

  • 文書ごとにベクターDBに格納して、各文書専用のRetrievalQAツールとして定義します。

  • 例題として、東京電力と関西電力の2023年度3月期決算短信を読み込んでみます。

  • 今回は2つですが、文書を増やす場合は単純にツールの定義を増やしていけば良さそうです。

class DocumentInput(BaseModel):
    question: str = Field()


llm = ChatOpenAI(temperature=0, model="gpt-3.5-turbo-0613")

tools = []
files = [
    # 関西電力: https://www.kepco.co.jp/ir/brief/disclosure/pdf/kaiji20230427_1.pdf
    {
        "name": "202303-9503",
        "path": "20230427_9503.pdf",
    },
    # 東京電力: https://www.tepco.co.jp/about/ir/library/results/pdf/2303q4tanshin-j.pdf
    {
        "name": "202303-9501",
        "path": "20230428_9501.pdf"
    }
]

for file in files:
    loader = PyPDFLoader(file["path"])
    pages = loader.load_and_split()
    text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
    docs = text_splitter.split_documents(pages)
    embeddings = OpenAIEmbeddings()
    retriever = FAISS.from_documents(docs, embeddings).as_retriever()

    # Wrap retrievers in a Tool
    tools.append(
        Tool(
            args_schema=DocumentInput,
            name=file["name"],
            description=f"useful when you want to answer questions about {file['name']}",
            func=RetrievalQA.from_chain_type(llm=llm, retriever=retriever)
        )
    )

エージェントの定義

  • 例題ではLLMはgpt-3.5-turbo-0613を使っていましたが、なんとなくgpt-4に変えました。(特に意味はありません)

llm = ChatOpenAI(
    temperature=0,
    model="gpt-4-0613",
)

agent = initialize_agent(
    agent=AgentType.OPENAI_FUNCTIONS,
    tools=tools,
    llm=llm,
    verbose=True,
)

実行サンプル!

  • 親Agent が文書担当LLMに問い合わせて、報告結果を親Agentがいい感じに取りまとめます。

agent({"input": "東電9501と関電9503の2023年3月期の経常利益を比較して"})

> Entering new chain...
Invoking: `202303-9501` with `{'question': '2023年3月期の経常利益は何ですか?'}`

{'query': '2023年3月期の経常利益は何ですか?', 'result': '2023年3月期の経常利益は、285,393百万円の損失です。'}

Invoking: `202303-9503` with `{'question': '2023年3月期の経常利益は何ですか?'}`
{'query': '2023年3月期の経常利益は何ですか?', 'result': '2023年3月期の経常利益は、マイナス6,666百万円です。'}
2023年3月期の経常利益について、東京電力(9501)は285,393百万円の損失を記録しています。一方、関西電力(9503)はマイナス6,666百万円となっています。したがって、両社ともに損失を出していますが、東京電力の損失額が関西電力よりも大きいです。

> Finished chain.
{'input': '東電9501と関電9503の2023年3月期の経常利益を比較して',
'output': '2023年3月期の経常利益について、東京電力(9501)は285,393百万円の損失を記録しています。一方、関西電力(9503)はマイナス6,666百万円となっています。したがって、両社ともに損失を出していますが、東京電力の損失額が関西電力よりも大きいです。'}

このまま、商用サービスとかにも使えるかも。😊

おしまい

この記事が気に入ったらサポートをしてみませんか?