Slide 1

Slide 1 text

LangChain Agentの仕組み 2024/05/25 那珂将人

Slide 2

Slide 2 text

内容 1. 「Agentをよく使うが実際にどうなっているのかよくわからない」を全体の流れをわかる ようになる 2. AgentのTypeが多いので一つを例にでも理解を深めておくと今後役立つ 3. 今後AgentなどLangChainの中身を見るきっかけになる (今回はLangChain 0.1までのAgentsに関してです。 LangChain 0.2では、AgentsもLangGraphに移行するよ うに奨励されています。Ref: How to migrate from legacy LangChain agents to LangGraph)

Slide 3

Slide 3 text

Agentとは The core idea of agents is to use a language model to choose a sequence of actions to take. 言語モデルを使って一連の実行アクションを選択する Agent Tool Google検索 Tool Graph可視化 日本の人口の 推移をグラフ にして

Slide 4

Slide 4 text

Concepts 1. Schema: AgentAction, AgentFinish, Intermediate Steps a. Agentから返されるのは次の AgentのアクションかAgentのアクションの終了サインか b. 中間Stepsの結果はIntermediate stepsに格納 2. Agent: Agent inputs & Agent outputs a. AgentのInputに合わせてAgentを実行してOutputを取得 3. AgentExecutor: Agentを実際に呼び出し、Actionを実行し、Outputをベースに次の Actionを実行していく 4. Tools: Agentが実行できる選択肢 a. 例. TavilySearchResults https://tavily.com/ (月1000コールまで無料)、自分で書いた関数を Toolとし て使うこともできる

Slide 5

Slide 5 text

全体像 1. AgentExecutor 2. Agent

Slide 6

Slide 6 text

Example 1. tool: a. TavilySearchResults: https://docs.tavily.com/docs/welcome (search engine for AI agents) b. multiply: custom tool 2. prompt: hub 3. llm: ChatOpenAI 4. agent: create_react_agent 5. agent_executor

Slide 7

Slide 7 text

Step1: Toolの準備 1. TavilySearchResults a. API keyが必要 b. 1000 requests per monthまで無料 2. multiply a. 2 つの数字の掛け算をする関数 + @tool

Slide 8

Slide 8 text

Step2: Chat model & Prompt 1. ChatOpenAI を設定 2. Promptを準備 a. https://smith.langchain.com/hub/hwchase17/openai-functions-agent b. langchain hubで公開されているpromptを仕様できる

Slide 9

Slide 9 text

Step3: Agentを設定 1. create_tool_calling_agentにllm, tools, promptを入れる 2. agent.invokeすると、ToolAgentActionが返される create_tool_calling_agentは後ほど

Slide 10

Slide 10 text

Step3: Agentをinvoke例: “hi” 1. input: hi 2. output: AgentFinish(return_values{‘output’: ‘Hello! How can I assist you today?’})

Slide 11

Slide 11 text

Step3: Agentをinvoke例: “What’s the weather in SF?” 1. input: What’s the weather in SF? 2. output: ToolAgentAction(tool=’tavily_search_results_json’, tool_input={‘query’: ‘current weather in San Francisco’}})

Slide 12

Slide 12 text

Step3: Agentをinvoke例: “What’s 3 times 2?” 1. input: What’s 3 times 2? 2. output: ToolAgentAction(tool=’multiply’, tool_input={‘a’: 3, ‘b’: 2}})

Slide 13

Slide 13 text

Step4: AgentExecutor 1. AgentExecutorにagent, toolsを渡して初期化

Slide 14

Slide 14 text

Step4: AgentExecutor 実行してみる 1. What’s the weather in SF? 2. What’s 2 times 3?

Slide 15

Slide 15 text

Step4: AgentExecutor 「what’s 2 times 3の答えとSFのセ氏での気温とどちらの数字が大きいですか」

Slide 16

Slide 16 text

Agentの中身

Slide 17

Slide 17 text

Agent: 作成create_tool_calling_agent 全体の流れ 1. バリデーション 2. llm.bind_tools(tools) 3. agentの作成

Slide 18

Slide 18 text

Agentのステップ Agentは4つのステップからなっている

Slide 19

Slide 19 text

Agent.steps[0] format_to_tool_messages: AgentActionとツールのアウトプットからFunctionMessageへ変 換する 1. Input: intermediate_steps: Sequence[Tuple[AgentAction, str]] 2. Output: List[BaseMessage] AgentActionを実行し、ToolのOutputを取得してから、それらを中間ステップ (intermediate_steps)にBaseMessageのリストとしてためていくためのステップ

Slide 20

Slide 20 text

Agent: agent.steps[1].prompt 一つ目のステップで生成した、過去のAgentActionとToolのOutputの歴史が入ったもの も含めて、次のllm呼び出しで使うpromptを決める 1. input_variables: a. agent_scratchpad: 1つ目のstepで生成されたagentとToolのOutputの歴史 b. input: もともとの質問 2. input_types 3. messages: a. SystemMessagePromptTemplate: “You are a helpful assistant” b. MessagesPlaceholder: chat_history c. HumanMessagePromptTemplate: input d. MessagesPlaceholder: agent_scratchpad

Slide 21

Slide 21 text

Agent: agent.steps[2] 1. 次のActionをllmに聞く a. tool_calls に name: tavily_search_results_jsonと引数argsが返される 2. 返ってくるのはAIMessage

Slide 22

Slide 22 text

Agent: agent.steps[2]: llm.bind_tools 1. llm.bind_tools -> Runnableを返す 2. llmを呼ぶときにtoolを一緒に渡して、ツールと Argsを取得できる 3. 例.

Slide 23

Slide 23 text

llm.bind_tools 1. llm.bind_tools(tools, tool_choice, **kwargs) a. Runnableを返す 2. toolを追加 3. BaseChatOpenAI.bind_tools(tools, tool_choice) a. 4. BaseChatModel.bind(**kwargs) a. Useful when a runnable in a chain requires an argument that is not in the output of the previous runnable or included in the user input. b. kwargsにはtool 5. Runnable.bind() -> Runnable 6.

Slide 24

Slide 24 text

agent.steps[3]: Output Parser 1. ToolsAgentOutputParser() 前のStepで返されたAIMessageをToolAgentAction/AgentFinishに変換 ※Toolはまだ実行されてない

Slide 25

Slide 25 text

ここまでのまとめ 1. AgentのStepは4つ a. steps[0]: AgentActionとToolの結果からMessageに変換してagent_scratchpadへ格納 b. steps[1]: prompt (input, agent_scratchpad)をinput variablesにもつ c. steps[2]: RunnableBinding llmにtoolsをbindしたもので、inputからどのツールを使えばよいかを llm に聞くステップ d. steps[3]: Output parser 上のステップでllmから返ってきた結果を ToolAgentAction/AgentFinishに変 換する 2. 注意 a. 実際のToolの実行はしない b. Agentで定義されているのは、次の Actionを決定すること

Slide 26

Slide 26 text

全体像 1. AgentExecutor 2. Agent

Slide 27

Slide 27 text

AgentExecutor

Slide 28

Slide 28 text

AgentExecutor: AgentとToolを使って最後の答えを出す AgentExecutorの仕事は、 1. Agentを呼び出して、次のアクションを聞く 2. ツールを使う場合は、実際のツールの呼び出しをする 3. その結果を含めて、Agentを呼び出して次のアクションを聞く 4. … 5. Agentに終了と言われたら、最後の答えを返す

Slide 29

Slide 29 text

AgentExecutorの作成 AgentExecutorをagent, toolsで初期化

Slide 30

Slide 30 text

AgeneExecutorはChainの子クラス

Slide 31

Slide 31 text

Chainのinvokeが呼ばれ、その中のself._callが呼ばれる ChainのInvoke _callは子クラスで実装される

Slide 32

Slide 32 text

AgentExecutorに戻って _call 1. whileループ: continueの条件を満 たす限り 2. self._take_next_step: agentを呼び Next Actionを取得し、 AgentActionがあればtoolを呼び実 行した結果を返す 3. next_step_outputに値よって終了 か、intermediate_stepsに追加 4. (_get_tool_return: agentからの結 果を直接返すかどうか) 5. _return(): 最終的な結果を返す

Slide 33

Slide 33 text

まとめ 1. Agent a. 質問の内容と今までの Agentの実行履歴から、次の Actionを返す b. Input: 最初のユーザからの質問、 intermediate_steps c. Output: 次のAction (AgentFinish or AgentAction) 2. AgentExecutor a. AgentがFinishを返すか、実行最大数 or最大時間に 到達するまで、Agentを繰り返し呼ぶ b. Agentに選ばれたツールを実行し、その結果を intermediate_stepsを更新しながらAgentを呼び続ける