見出し画像

LangChainカスタムツールを作ってAI Agentに渡してみた

初めに、

Agentは与えられたツールによって、どのようなタスクでも実行可能になります。つまり、Agent アプリケーションの開発のキーポイントはツールの開発と言えるでしょう。そこで、ツールの開発に挑戦しました。

公式ドキュメントを参考に最もシンプルなカスタムツールを作成しました。これはBaseToolを継承し、ツール名(name)とツールの説明(description)を定義しています。run関数への引数の受け渡しは、descriptionで指定します。

from langchain.tools.base import BaseTool

class HelloTool(BaseTool):
    """Tool that generates a personalized hello message."""

    name = "HelloTool"
    description = (
        "A tool that generates a personalized hello message. "
        "Input should be a name string."
    )

    def _run(self, name: str = None) -> str:
        return f"Hello {name}!"

    async def _arun(self, name: str = None) -> str:
        """Use the HelloTool asynchronously."""
        return self._run(name)

あとは、Toolsにこのツールを加えてAgentに渡すだけです。

tools = [HelloTool()]
mrkl = initialize_agent(tools, llm, agent=AgentType.OPENAI_FUNCTIONS, verbose=True)

実行結果

user : hello to Tom
Agent : Hello Tom!


InsightAgentの作成

ユーザーが特定の有名人やトピックについて深い洞察を得るためのツールです。ユーザーが指定した人物やトピックについて情報を集め、その情報を基にその人物やトピックについての質問に回答します。それはまた、その情報をデータベースに格納し、後で参照するために利用することもできます。

実装は、できるだけ簡単にできる方法で行いましたので、実装方法は適切ではないと思いますが、ご了承ください。。

大まかな処理の流れは以下となります

1. 特定の人物または、トピックについてネットを検索して情報を集める
2. 調べた内容をテキストファイルに出力する
3. テキストファイルからベクトルデータベースを作成
4. ユーザーが与える観点を元にデータベースの情報を使って洞察する

TextFileWriterTool

webページを検索した結果をファイルに出力するためのツールです。

from langchain.tools.base import BaseTool
import os
from pydantic import Field

class TextFileWriterTool(BaseTool):
    """Tool that writes input to a text file."""

    name = "TextFileWriterTool"
    description = (
        "A tool that writes input to a text file. "
        "Input should be a summarized text of no more than 1000 characters."
    )
    
    # Declare file_path as a class field
    file_path: str = Field(default="")

    def __init__(self) -> None:
        super().__init__()  # Call the parent constructor
        self.file_path = os.getenv('MY_FILE_PATH')
        if self.file_path is None:
            raise ValueError("Environment variable 'MY_FILE_PATH' is not set.")
        return

    def _run(self, tool_input: str) -> str:
        """Use the TextFileWriterTool."""
        # Check if input is less than or equal to 1000 characters
        if len(tool_input) > 1000:
            return "Error: Input text is longer than 500 characters."

        # Append the input to the text file
        with open(self.file_path, 'a') as f:
            f.write(tool_input + '\n')

        return "Text successfully appended to the file."

    async def _arun(self, tool_input: str) -> str:
        """Use the TextFileWriterTool asynchronously."""
        return self._run(tool_input)

SimilaritySearchTool

検索結果を元にベクトルデータベースを作成し、検索を行います。

from typing import Type
from pydantic import BaseModel, Field
from langchain.tools import BaseTool
from langchain.document_loaders import TextLoader
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import Chroma

class QueryArgs(BaseModel):
    query: str = Field(..., description="Search query to be executed.")
    # path: str = Field(..., description="Path to the text document.")

class SimilaritySearchTool(BaseTool):
    name = "similarity_search_tool"
    description = "This tool loads a document, splits it into chunks, embeds each chunk and loads it into the vector store, and finally executes a similarity search."
    args_schema: Type[BaseModel] = QueryArgs  # Updated

    def _load_documents(self, path):
        return TextLoader(path).load()

    def _split_documents(self, raw_documents):
        text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
        return text_splitter.split_documents(raw_documents)

    def _create_vectorstore(self, documents):
        return Chroma.from_documents(documents, OpenAIEmbeddings())

    def _run(self, query):
        path = os.getenv('MY_FILE_PATH')
        raw_documents = self._load_documents(path)
        documents = self._split_documents(raw_documents)
        db = self._create_vectorstore(documents)
        return db.similarity_search(query)
        
    async def _arun(self, query):  # Async version of _run
        return self._run(query)

toolsの定義

web検索ツールと上記のツールをtoolsとして定義します。

llm = ChatOpenAI(temperature=0, model="gpt-4-0613")
llm_math_chain = LLMMathChain.from_llm(llm=llm, verbose=True)

tools = [
    Tool(
        name = "Search",
        func=search.run,
        description="useful for when you need to answer questions about current events. You should ask targeted questions"
    ),
    TextFileWriterTool(),
    SimilaritySearchTool()
]

Agentの定義と実行

toolsをAgentに渡します。

from langchain.prompts import MessagesPlaceholder
agent_kwargs = {
    "extra_prompt_messages": [MessagesPlaceholder(variable_name="memory")],
}
memory = ConversationBufferMemory(memory_key="memory", return_messages=True)
mrkl = initialize_agent(tools, llm, agent=AgentType.OPENAI_FUNCTIONS, agent_kwargs=agent_kwargs, memory=memory, verbose=True)
# 会話ループ
user = ""
while user != "exit":
    user = input("入力してください:")
    print(user)
    ai = mrkl.run(input=user)
    print(ai)

実行結果

今回は、Elon Muskについて情報を集め、集めた情報からElon Muskの視点で私の質問に答えてもらいました。

user>
step1 : elon muskについて、バイオグラフィー、パーソナリティ、価値観、ライフスタイルと趣味、最近の話題をそれぞれできるかぎり調べて、webページごとにテキストファイルに記入してください 
step2 :  テキストファイルをベクトルDBに格納して性格と経歴につてい調べてください 
step3 : step2で調べた内容を元にあなたはelon muskになりきって今後の質問に回答してください 
step4 : 実行プランを考えて私にレビューを求めてください


agent> 
以下に実行プランを提案します:

**ステップ1:**
Elon Muskについて以下の5つのカテゴリーで情報を検索します:バイオグラフィー、パーソナリティ、価値観、ライフスタイルと趣味、最近の話題。それぞれの情報をテキストファイルに記入します。

**ステップ2:**
ステップ1で作成したテキストファイルをベクトルDBに格納します。その後、"性格""経歴"についての情報を検索します。

**ステップ3:**
ステップ2で得た情報を元に、Elon Muskの視点で質問に回答します。

**ステップ4:**
以上のプランをレビューしていただき、必要に応じて調整を行います。

このプランでよろしいでしょうか?

user>
はい、


agent>
Invoking: `Search` with `Elon Musk biography`


Elon Reeve Musk is a business magnate and investor. He is the founder, chairman, CEO, and chief technology officer of SpaceX; angel investor, CEO and product architect of Tesla, Inc.; owner and CTO of Twitter; founder of the Boring Company; co-founder of Neuralink and OpenAI; and president of the Musk Foundation.
Invoking: `TextFileWriterTool` with `Elon Reeve Musk is a business magnate and investor. He is the founder, chairman, CEO, and chief technology officer of SpaceX; angel investor, CEO and product architect of Tesla, Inc.; owner and CTO of Twitter; founder of the Boring Company; co-founder of Neuralink and OpenAI; and president of the Musk Foundation.`


Text successfully appended to the file.
Invoking: `Search` with `Elon Musk personality`


16-Personality Types (based on types by Jung, Myers, & Briggs) As an INTJ, Elon tends to be confident, analytical, and ambitious. Elon is likely an independent thinker focused on solving the world's problems.
Invoking: `TextFileWriterTool` with `16-Personality Types (based on types by Jung, Myers, & Briggs) As an INTJ, Elon tends to be confident, analytical, and ambitious. Elon is likely an independent thinker focused on solving the world's problems.`


Text successfully appended to the file.
Invoking: `Search` with `Elon Musk values`


7 Leadership Traits Elon Musk Used To Build Tesla and SpaceX
Invoking: `TextFileWriterTool` with `7 Leadership Traits Elon Musk Used To Build Tesla and SpaceX`


Text successfully appended to the file.
Invoking: `Search` with `Elon Musk lifestyle and hobbies`


Most of his time is spent on design and engineering work. Musk prioritizes meetings and workflow, frequently cuts meetings short, and actively discourages unnecessary meetings. When he's not working, he likes to relax with some whiskey or wine, reading anime, and tweeting. He goes to bed around 1 am.
Invoking: `TextFileWriterTool` with `Most of his time is spent on design and engineering work. Musk prioritizes meetings and workflow, frequently cuts meetings short, and actively discourages unnecessary meetings. When he's not working, he likes to relax with some whiskey or wine, reading anime, and tweeting. He goes to bed around 1 am.`


Text successfully appended to the file.
Invoking: `Search` with `Elon Musk recent news`


News about Elon Musk (SpaceX), including commentary and archival articles published in The New York Times.
Invoking: `TextFileWriterTool` with `News about Elon Musk (SpaceX), including commentary and archival articles published in The New York Times.`


Text successfully appended to the file.
Invoking: `similarity_search_tool` with `{'query': 'Elon Musk personality and career'}`


ステップ1とステップ2の結果を元に、Elon Muskの人物像を以下のようにイメージします:

Elon Reeve Muskはビジネスマグネートであり投資家です。彼はSpaceXの創設者であり、会長、CEO、および最高技術責任者であり、Tesla, Inc.のエンジェル投資家、CEO、製品設計者であり、Twitterの所有者およびCTOであり、Boring Companyの創設者であり、NeuralinkとOpenAIの共同創設者であり、Musk Foundationの会長です。

INTJタイプとして、Elonは自信に満ち、分析的で、野心的です。Elonはおそらく、世界の問題を解決することに集中した独立した思考者です。

彼の大部分の時間は設計とエンジニアリングの仕事に費やされています。Muskは会議とワークフローを優先し、頻繁に会議を短縮し、不必要な会議を積極的に抑制します。彼が働いていないとき、彼はウィスキーやワインを楽しんだり、アニメを読んだり、ツイートしたりするのが好きです。彼は午前1時頃に寝ます。

以上の情報を元に、私はElon Muskになりきって今後の質問に回答します。

user>
科学で未来を変えることに躊躇いはありますか?


agent>
私、Elon Muskとして回答します。

私たちは科学と技術を使って未来を形成することに躊躇はありません。それは私たちが直面している多くの問題、特に気候変動や持続可能なエネルギーの問題を解決するための鍵です。私たちは、科学が提供する解決策を活用しなければならないと信じています。

しかし、それは盲目的に科学を追求することを意味するわけではありません。新しい技術やアイデアを採用する際には、その影響を十分に理解し、可能な限りリスクを最小化する必要があります。それはAIのような強力な技術に特に当てはまります。私たちは、その可能性を最大限に引き出しながら、同時にそのリスクを管理する方法を見つける必要があります。

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