🦜

Langchain Custom ToolにGPTに作らせたくない引数を渡す

2024/01/18に公開
1

やりたいこと

タイトルの通り。
カスタムツールで任意の関数を実行させたいが、すべての変数をGPTに作らせたいわけではない場合が出てきたので備忘録として書き留める。
もっとスマートなやり方があるかもしれないが、ひとまず実現できる方法をメモ📝

結論

BaseToolでツールを定義し、インスタンス変数にGPTに作成させたくない変数を入れる。

https://python.langchain.com/docs/modules/agents/tools/custom_tools

実装

from langchain.pydantic_v1 import BaseModel, Field
from langchain.tools import BaseTool
from typing import Optional, Type
from langchain.callbacks.manager import (
    AsyncCallbackManagerForToolRun,
    CallbackManagerForToolRun,
)
from langchain.agents import AgentExecutor, create_openai_functions_agent
from langchain_openai import ChatOpenAI
from langchain import hub

# 入力するべき変数の説明を加える。GPTはこれを元に変数を作成する。
class CustomFunctionInput(BaseModel):
    number: int = Field(description="should be the number of something enough satisfying user's needs.")

# GPTが用いるツールの定義。
class CustomFunction(BaseTool):
    name = 'custom_function'
    description = 'useful when the user wants sweets'
    args_schema: Type[BaseModel] = CustomFunctionInput
    variable1: int = 1 # これはGPTに作らせたくない変数

    def _run(self, number: int, run_manager: Optional[CallbackManagerForToolRun] = None) -> str :
        return f'{number * self.variable1} chocolates'
    
    def _arun(self, number: int, run_manager: Optional[AsyncCallbackManagerForToolRun] = None) -> str :
        raise NotImplementedError("custom_function does not support async")

customfunc = CustomFunction()
llm = ChatOpenAI(temperature=0)
prompt = hub.pull("hwchase17/openai-functions-agent")

agent = create_openai_functions_agent(llm, [customfunc], prompt)

agent_executor = AgentExecutor(
    agent=agent, tools=[customfunc], verbose=True, return_intermediate_steps=True
)

上記のようにツールとそれを実行するagentを作成した上で、変数を挿入したい部分で以下のようにインスタンス変数を書き換える。

for agent_tool in agent_executor.tools:
    if isinstance(agent_tool, CustomFunction):
        agent_tool.variable1 = 2  #ここで変数を挿入

実行イメージ

質問文

user_message = 'please give me 4 sweets.'
message = agent_executor.invoke({"input": user_message})

toolのインスタンス変数変更前

> Entering new AgentExecutor chain...

Invoking: `custom_function` with `{'number': 4}`


4 chocolatesHere are 4 chocolates for you. Enjoy!

> Finished chain.

toolのインスタンス変数変更後

> Entering new AgentExecutor chain...

Invoking: `custom_function` with `{'number': 4}`


8 chocolatesHere are 8 chocolates for you. Enjoy!

> Finished chain.

Discussion

kou88kou88

わーやりたかったことです
書いてくださりありがとうございます