docs: Re-write custom agent to show to write a tools agent (#15907)

Shows how to write a tools agent rather than a functions agent.
pull/16417/head
Eugene Yurtsev 8 months ago committed by GitHub
parent 404abf139a
commit e5672bc944
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -19,7 +19,7 @@
"\n",
"This notebook goes through how to create your own custom agent.\n",
"\n",
"In this example, we will use OpenAI Function Calling to create this agent.\n",
"In this example, we will use OpenAI Tool Calling to create this agent.\n",
"**This is generally the most reliable way to create agents.**\n",
"\n",
"We will first create it WITHOUT memory, but we will then show how to add memory in.\n",
@ -61,10 +61,21 @@
},
{
"cell_type": "code",
"execution_count": 5,
"id": "fbe32b5f",
"execution_count": 2,
"id": "490bab35-adbb-4b45-8d0d-232414121e97",
"metadata": {},
"outputs": [],
"outputs": [
{
"data": {
"text/plain": [
"3"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain.agents import tool\n",
"\n",
@ -75,6 +86,16 @@
" return len(word)\n",
"\n",
"\n",
"get_word_length.invoke(\"abc\")"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "c9821fb3-4449-49a0-a708-88a18d39e068",
"metadata": {},
"outputs": [],
"source": [
"tools = [get_word_length]"
]
},
@ -91,7 +112,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 4,
"id": "aa4b50ea",
"metadata": {},
"outputs": [],
@ -116,22 +137,24 @@
"metadata": {},
"source": [
"## Bind tools to LLM\n",
"\n",
"How does the agent know what tools it can use?\n",
"In this case we're relying on OpenAI function calling LLMs, which take functions as a separate argument and have been specifically trained to know when to invoke those functions.\n",
"\n",
"To pass in our tools to the agent, we just need to format them to the [OpenAI function format](https://openai.com/blog/function-calling-and-other-api-updates) and pass them to our model. (By `bind`-ing the functions, we're making sure that they're passed in each time the model is invoked.)"
"In this case we're relying on OpenAI tool calling LLMs, which take tools as a separate argument and have been specifically trained to know when to invoke those tools.\n",
"\n",
"To pass in our tools to the agent, we just need to format them to the [OpenAI tool format](https://platform.openai.com/docs/api-reference/chat/create) and pass them to our model. (By `bind`-ing the functions, we're making sure that they're passed in each time the model is invoked.)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 5,
"id": "e82713b6",
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.tools.convert_to_openai import format_tool_to_openai_function\n",
"from langchain_community.tools.convert_to_openai import format_tool_to_openai_tool\n",
"\n",
"llm_with_tools = llm.bind(functions=[format_tool_to_openai_function(t) for t in tools])"
"llm_with_tools = llm.bind(tools=[format_tool_to_openai_tool(tool) for tool in tools])"
]
},
{
@ -146,30 +169,32 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 6,
"id": "925a8ca4",
"metadata": {},
"outputs": [],
"source": [
"from langchain.agents.format_scratchpad import format_to_openai_function_messages\n",
"from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser\n",
"from langchain.agents.format_scratchpad.openai_tools import (\n",
" format_to_openai_tool_messages,\n",
")\n",
"from langchain.agents.output_parsers.openai_tools import OpenAIToolsAgentOutputParser\n",
"\n",
"agent = (\n",
" {\n",
" \"input\": lambda x: x[\"input\"],\n",
" \"agent_scratchpad\": lambda x: format_to_openai_function_messages(\n",
" \"agent_scratchpad\": lambda x: format_to_openai_tool_messages(\n",
" x[\"intermediate_steps\"]\n",
" ),\n",
" }\n",
" | prompt\n",
" | llm_with_tools\n",
" | OpenAIFunctionsAgentOutputParser()\n",
" | OpenAIToolsAgentOutputParser()\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 7,
"id": "9af9734e",
"metadata": {},
"outputs": [],
@ -181,7 +206,7 @@
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": 8,
"id": "653b1617",
"metadata": {},
"outputs": [
@ -193,10 +218,10 @@
"\n",
"\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
"\u001b[32;1m\u001b[1;3m\n",
"Invoking: `get_word_length` with `{'word': 'educa'}`\n",
"Invoking: `get_word_length` with `{'word': 'eudca'}`\n",
"\n",
"\n",
"\u001b[0m\u001b[36;1m\u001b[1;3m5\u001b[0m\u001b[32;1m\u001b[1;3mThere are 5 letters in the word \"educa\".\u001b[0m\n",
"\u001b[0m\u001b[36;1m\u001b[1;3m5\u001b[0m\u001b[32;1m\u001b[1;3mThere are 5 letters in the word \"eudca\".\u001b[0m\n",
"\n",
"\u001b[1m> Finished chain.\u001b[0m\n"
]
@ -204,17 +229,21 @@
{
"data": {
"text/plain": [
"{'input': 'How many letters in the word educa',\n",
" 'output': 'There are 5 letters in the word \"educa\".'}"
"[{'actions': [OpenAIToolAgentAction(tool='get_word_length', tool_input={'word': 'eudca'}, log=\"\\nInvoking: `get_word_length` with `{'word': 'eudca'}`\\n\\n\\n\", message_log=[AIMessageChunk(content='', additional_kwargs={'tool_calls': [{'index': 0, 'id': 'call_U9SR78eT398r9UbzID2N9LXh', 'function': {'arguments': '{\\n \"word\": \"eudca\"\\n}', 'name': 'get_word_length'}, 'type': 'function'}]})], tool_call_id='call_U9SR78eT398r9UbzID2N9LXh')],\n",
" 'messages': [AIMessageChunk(content='', additional_kwargs={'tool_calls': [{'index': 0, 'id': 'call_U9SR78eT398r9UbzID2N9LXh', 'function': {'arguments': '{\\n \"word\": \"eudca\"\\n}', 'name': 'get_word_length'}, 'type': 'function'}]})]},\n",
" {'steps': [AgentStep(action=OpenAIToolAgentAction(tool='get_word_length', tool_input={'word': 'eudca'}, log=\"\\nInvoking: `get_word_length` with `{'word': 'eudca'}`\\n\\n\\n\", message_log=[AIMessageChunk(content='', additional_kwargs={'tool_calls': [{'index': 0, 'id': 'call_U9SR78eT398r9UbzID2N9LXh', 'function': {'arguments': '{\\n \"word\": \"eudca\"\\n}', 'name': 'get_word_length'}, 'type': 'function'}]})], tool_call_id='call_U9SR78eT398r9UbzID2N9LXh'), observation=5)],\n",
" 'messages': [FunctionMessage(content='5', name='get_word_length')]},\n",
" {'output': 'There are 5 letters in the word \"eudca\".',\n",
" 'messages': [AIMessage(content='There are 5 letters in the word \"eudca\".')]}]"
]
},
"execution_count": 14,
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"agent_executor.invoke({\"input\": \"How many letters in the word educa\"})"
"list(agent_executor.stream({\"input\": \"How many letters in the word eudca\"}))"
]
},
{
@ -227,7 +256,7 @@
},
{
"cell_type": "code",
"execution_count": 15,
"execution_count": 9,
"id": "60f5dc19",
"metadata": {},
"outputs": [
@ -237,7 +266,7 @@
"AIMessage(content='There are 6 letters in the word \"educa\".')"
]
},
"execution_count": 15,
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
@ -270,7 +299,7 @@
},
{
"cell_type": "code",
"execution_count": 16,
"execution_count": 10,
"id": "169006d5",
"metadata": {},
"outputs": [],
@ -301,7 +330,7 @@
},
{
"cell_type": "code",
"execution_count": 17,
"execution_count": 11,
"id": "8c03f36c",
"metadata": {},
"outputs": [],
@ -321,7 +350,7 @@
},
{
"cell_type": "code",
"execution_count": 18,
"execution_count": 12,
"id": "5429d97f",
"metadata": {},
"outputs": [],
@ -329,14 +358,14 @@
"agent = (\n",
" {\n",
" \"input\": lambda x: x[\"input\"],\n",
" \"agent_scratchpad\": lambda x: format_to_openai_function_messages(\n",
" \"agent_scratchpad\": lambda x: format_to_openai_tool_messages(\n",
" x[\"intermediate_steps\"]\n",
" ),\n",
" \"chat_history\": lambda x: x[\"chat_history\"],\n",
" }\n",
" | prompt\n",
" | llm_with_tools\n",
" | OpenAIFunctionsAgentOutputParser()\n",
" | OpenAIToolsAgentOutputParser()\n",
")\n",
"agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)"
]
@ -351,7 +380,7 @@
},
{
"cell_type": "code",
"execution_count": 19,
"execution_count": 13,
"id": "9d9da346",
"metadata": {},
"outputs": [
@ -386,7 +415,7 @@
" 'output': 'No, \"educa\" is not a real word in English.'}"
]
},
"execution_count": 19,
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
@ -402,14 +431,6 @@
")\n",
"agent_executor.invoke({\"input\": \"is that a real word?\", \"chat_history\": chat_history})"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f21bcd99",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
@ -428,7 +449,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.1"
"version": "3.11.4"
},
"vscode": {
"interpreter": {

Loading…
Cancel
Save