mirror of
https://github.com/hwchase17/langchain.git
synced 2025-09-29 23:38:51 +00:00
484 lines
14 KiB
Plaintext
484 lines
14 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "raw",
|
||
"id": "500e8846-91c2-4716-9bd6-b9672c6daf78",
|
||
"metadata": {},
|
||
"source": [
|
||
"---\n",
|
||
"sidebar_position: 0\n",
|
||
"---"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "14b94240",
|
||
"metadata": {},
|
||
"source": [
|
||
"# How to use tools in a chain\n",
|
||
"\n",
|
||
"In this guide, we will go over the basic ways to create Chains and Agents that call Tools. Tools can be just about anything — APIs, functions, databases, etc. Tools allow us to extend the capabilities of a model beyond just outputting text/messages. The key to using models with tools is correctly prompting a model and parsing its response so that it chooses the right tools and provides the right inputs for them."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "e6b79a42-0349-42c6-9ce8-72220e838e8d",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Setup\n",
|
||
"\n",
|
||
"We'll need to install the following packages for this guide:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "f2274266-755a-4e90-b257-5180fb089af2",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"%pip install --upgrade --quiet langchain"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "36a9c6fc-8264-462f-b8d7-9c7bbec22ef9",
|
||
"metadata": {},
|
||
"source": [
|
||
"If you'd like to trace your runs in [LangSmith](https://docs.smith.langchain.com/) uncomment and set the following environment variables:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "57a81b7a-4fd9-4f28-bc32-7b98b522e1b0",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import getpass\n",
|
||
"import os\n",
|
||
"\n",
|
||
"# os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\n",
|
||
"# os.environ[\"LANGCHAIN_API_KEY\"] = getpass.getpass()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "68946881",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Create a tool\n",
|
||
"\n",
|
||
"First, we need to create a tool to call. For this example, we will create a custom tool from a function. For more information on creating custom tools, please see [this guide](/docs/how_to/custom_tools)."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 6,
|
||
"id": "90187d07",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"from langchain_core.tools import tool\n",
|
||
"\n",
|
||
"\n",
|
||
"@tool\n",
|
||
"def multiply(first_int: int, second_int: int) -> int:\n",
|
||
" \"\"\"Multiply two integers together.\"\"\"\n",
|
||
" return first_int * second_int"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 2,
|
||
"id": "d7009e1a",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"multiply\n",
|
||
"multiply(first_int: int, second_int: int) -> int - Multiply two integers together.\n",
|
||
"{'first_int': {'title': 'First Int', 'type': 'integer'}, 'second_int': {'title': 'Second Int', 'type': 'integer'}}\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"print(multiply.name)\n",
|
||
"print(multiply.description)\n",
|
||
"print(multiply.args)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 3,
|
||
"id": "be77e780",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"20"
|
||
]
|
||
},
|
||
"execution_count": 3,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"multiply.invoke({\"first_int\": 4, \"second_int\": 5})"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "19ba4d63",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Chains\n",
|
||
"\n",
|
||
"If we know that we only need to use a tool a fixed number of times, we can create a chain for doing so. Let's create a simple chain that just multiplies user-specified numbers.\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"### Tool/function calling\n",
|
||
"One of the most reliable ways to use tools with LLMs is with tool calling APIs (also sometimes called function calling). This only works with models that explicitly support tool calling. You can see which models support tool calling [here](/docs/integrations/chat/), and learn more about how to use tool calling in [this guide](/docs/how_to/function_calling).\n",
|
||
"\n",
|
||
"First we'll define our model and tools. We'll start with just a single tool, `multiply`.\n",
|
||
"\n",
|
||
"```{=mdx}\n",
|
||
"import ChatModelTabs from \"@theme/ChatModelTabs\";\n",
|
||
"\n",
|
||
"<ChatModelTabs customVarName=\"llm\"/>\n",
|
||
"```"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 7,
|
||
"id": "9bce8935-1465-45ac-8a93-314222c753c4",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# | echo: false\n",
|
||
"# | output: false\n",
|
||
"\n",
|
||
"from langchain_openai.chat_models import ChatOpenAI\n",
|
||
"\n",
|
||
"llm = ChatOpenAI(model=\"gpt-4o-mini\", temperature=0)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "c22e6f0f-c5ad-4c0f-9514-e626704ea51c",
|
||
"metadata": {},
|
||
"source": [
|
||
"We'll use `bind_tools` to pass the definition of our tool in as part of each call to the model, so that the model can invoke the tool when appropriate:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 8,
|
||
"id": "3bfe2cdc-7d72-457c-a9a1-5fa1e0bcde55",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"llm_with_tools = llm.bind_tools([multiply])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "07fc830e-a6d2-4fac-904b-b94072e64018",
|
||
"metadata": {},
|
||
"source": [
|
||
"When the model invokes the tool, this will show up in the `AIMessage.tool_calls` attribute of the output:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 9,
|
||
"id": "68f30343-14ef-48f1-badd-b6a03977316d",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"[{'name': 'multiply',\n",
|
||
" 'args': {'first_int': 5, 'second_int': 42},\n",
|
||
" 'id': 'call_cCP9oA3tRz7HDrjFn1FdmDaG'}]"
|
||
]
|
||
},
|
||
"execution_count": 9,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"msg = llm_with_tools.invoke(\"whats 5 times forty two\")\n",
|
||
"msg.tool_calls"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "330015a3-a5a7-433a-826a-6277766f6c27",
|
||
"metadata": {},
|
||
"source": [
|
||
"Check out the [LangSmith trace here](https://smith.langchain.com/public/81ff0cbd-e05b-4720-bf61-2c9807edb708/r)."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "8ba1764d-0272-4f98-adcf-b48cb2c0a315",
|
||
"metadata": {},
|
||
"source": [
|
||
"### Invoking the tool\n",
|
||
"\n",
|
||
"Great! We're able to generate tool invocations. But what if we want to actually call the tool? To do so we'll need to pass the generated tool args to our tool. As a simple example we'll just extract the arguments of the first tool_call:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 12,
|
||
"id": "4f5325ca-e5dc-4d1a-ba36-b085a029c90a",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"92"
|
||
]
|
||
},
|
||
"execution_count": 12,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"from operator import itemgetter\n",
|
||
"\n",
|
||
"chain = llm_with_tools | (lambda x: x.tool_calls[0][\"args\"]) | multiply\n",
|
||
"chain.invoke(\"What's four times 23\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "79a9eb63-383d-4dd4-a162-08b4a52ef4d9",
|
||
"metadata": {},
|
||
"source": [
|
||
"Check out the [LangSmith trace here](https://smith.langchain.com/public/16bbabb9-fc9b-41e5-a33d-487c42df4f85/r)."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "0521d3d5",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Agents\n",
|
||
"\n",
|
||
"Chains are great when we know the specific sequence of tool usage needed for any user input. But for certain use cases, how many times we use tools depends on the input. In these cases, we want to let the model itself decide how many times to use tools and in what order. [Agents](/docs/tutorials/agents) let us do just this.\n",
|
||
"\n",
|
||
"LangChain comes with a number of built-in agents that are optimized for different use cases. Read about all the [agent types here](/docs/concepts#agents).\n",
|
||
"\n",
|
||
"We'll use the [tool calling agent](https://python.langchain.com/v0.2/api_reference/langchain/agents/langchain.agents.tool_calling_agent.base.create_tool_calling_agent.html), which is generally the most reliable kind and the recommended one for most use cases.\n",
|
||
"\n",
|
||
""
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 13,
|
||
"id": "21723cf4-9421-4a8d-92a6-eeeb8f4367f1",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"from langchain import hub\n",
|
||
"from langchain.agents import AgentExecutor, create_tool_calling_agent"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 14,
|
||
"id": "6be83879-9da3-4dd9-b147-a79f76affd7a",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"================================\u001b[1m System Message \u001b[0m================================\n",
|
||
"\n",
|
||
"You are a helpful assistant\n",
|
||
"\n",
|
||
"=============================\u001b[1m Messages Placeholder \u001b[0m=============================\n",
|
||
"\n",
|
||
"\u001b[33;1m\u001b[1;3m{chat_history}\u001b[0m\n",
|
||
"\n",
|
||
"================================\u001b[1m Human Message \u001b[0m=================================\n",
|
||
"\n",
|
||
"\u001b[33;1m\u001b[1;3m{input}\u001b[0m\n",
|
||
"\n",
|
||
"=============================\u001b[1m Messages Placeholder \u001b[0m=============================\n",
|
||
"\n",
|
||
"\u001b[33;1m\u001b[1;3m{agent_scratchpad}\u001b[0m\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"# Get the prompt to use - can be replaced with any prompt that includes variables \"agent_scratchpad\" and \"input\"!\n",
|
||
"prompt = hub.pull(\"hwchase17/openai-tools-agent\")\n",
|
||
"prompt.pretty_print()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "616f9714-5b18-4eed-b88a-d38e4cb1de99",
|
||
"metadata": {},
|
||
"source": [
|
||
"Agents are also great because they make it easy to use multiple tools."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 15,
|
||
"id": "95c86d32-ee45-4c87-a28c-14eff19b49e9",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"@tool\n",
|
||
"def add(first_int: int, second_int: int) -> int:\n",
|
||
" \"Add two integers.\"\n",
|
||
" return first_int + second_int\n",
|
||
"\n",
|
||
"\n",
|
||
"@tool\n",
|
||
"def exponentiate(base: int, exponent: int) -> int:\n",
|
||
" \"Exponentiate the base to the exponent power.\"\n",
|
||
" return base**exponent\n",
|
||
"\n",
|
||
"\n",
|
||
"tools = [multiply, add, exponentiate]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 16,
|
||
"id": "17b09ac6-c9b7-4340-a8a0-3d3061f7888c",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Construct the tool calling agent\n",
|
||
"agent = create_tool_calling_agent(llm, tools, prompt)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 17,
|
||
"id": "675091d2-cac9-45c4-a5d7-b760ee6c1986",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Create an agent executor by passing in the agent and tools\n",
|
||
"agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "a6099ab6-2fa6-452d-b73c-7fb65daab451",
|
||
"metadata": {},
|
||
"source": [
|
||
"With an agent, we can ask questions that require arbitrarily-many uses of our tools:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 18,
|
||
"id": "f7dbb240-809e-4e41-8f63-1a4636e8e26d",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"\n",
|
||
"\n",
|
||
"\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
|
||
"\u001b[32;1m\u001b[1;3m\n",
|
||
"Invoking: `exponentiate` with `{'base': 3, 'exponent': 5}`\n",
|
||
"\n",
|
||
"\n",
|
||
"\u001b[0m\u001b[38;5;200m\u001b[1;3m243\u001b[0m\u001b[32;1m\u001b[1;3m\n",
|
||
"Invoking: `add` with `{'first_int': 12, 'second_int': 3}`\n",
|
||
"\n",
|
||
"\n",
|
||
"\u001b[0m\u001b[33;1m\u001b[1;3m15\u001b[0m\u001b[32;1m\u001b[1;3m\n",
|
||
"Invoking: `multiply` with `{'first_int': 243, 'second_int': 15}`\n",
|
||
"\n",
|
||
"\n",
|
||
"\u001b[0m\u001b[36;1m\u001b[1;3m3645\u001b[0m\u001b[32;1m\u001b[1;3m\n",
|
||
"Invoking: `exponentiate` with `{'base': 405, 'exponent': 2}`\n",
|
||
"\n",
|
||
"\n",
|
||
"\u001b[0m\u001b[38;5;200m\u001b[1;3m13286025\u001b[0m\u001b[32;1m\u001b[1;3mThe result of taking 3 to the fifth power is 243. \n",
|
||
"\n",
|
||
"The sum of twelve and three is 15. \n",
|
||
"\n",
|
||
"Multiplying 243 by 15 gives 3645. \n",
|
||
"\n",
|
||
"Finally, squaring 3645 gives 13286025.\u001b[0m\n",
|
||
"\n",
|
||
"\u001b[1m> Finished chain.\u001b[0m\n"
|
||
]
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"{'input': 'Take 3 to the fifth power and multiply that by the sum of twelve and three, then square the whole result',\n",
|
||
" 'output': 'The result of taking 3 to the fifth power is 243. \\n\\nThe sum of twelve and three is 15. \\n\\nMultiplying 243 by 15 gives 3645. \\n\\nFinally, squaring 3645 gives 13286025.'}"
|
||
]
|
||
},
|
||
"execution_count": 18,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"agent_executor.invoke(\n",
|
||
" {\n",
|
||
" \"input\": \"Take 3 to the fifth power and multiply that by the sum of twelve and three, then square the whole result\"\n",
|
||
" }\n",
|
||
")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "8fdb0ed9-1763-4778-a7d6-026578cd9585",
|
||
"metadata": {},
|
||
"source": [
|
||
"Check out the [LangSmith trace here](https://smith.langchain.com/public/eeeb27a4-a2f8-4f06-a3af-9c983f76146c/r)."
|
||
]
|
||
}
|
||
],
|
||
"metadata": {
|
||
"kernelspec": {
|
||
"display_name": "Python 3 (ipykernel)",
|
||
"language": "python",
|
||
"name": "python3"
|
||
},
|
||
"language_info": {
|
||
"codemirror_mode": {
|
||
"name": "ipython",
|
||
"version": 3
|
||
},
|
||
"file_extension": ".py",
|
||
"mimetype": "text/x-python",
|
||
"name": "python",
|
||
"nbconvert_exporter": "python",
|
||
"pygments_lexer": "ipython3",
|
||
"version": "3.11.4"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 5
|
||
}
|