[go: nahoru, domu]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core[minor]docs[minor]: new tool wrapper #5782

Merged
merged 20 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 89 additions & 10 deletions docs/core_docs/docs/how_to/custom_tools.ipynb
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
{
"cells": [
{
"cell_type": "raw",
"id": "04171ad7",
"metadata": {
"vscode": {
"languageId": "raw"
}
},
"source": [
"---\n",
"keywords: [custom tool, custom tools]\n",
"---"
]
},
{
"cell_type": "markdown",
"id": "5436020b",
Expand All @@ -16,14 +30,64 @@
"\n",
":::\n",
"\n",
"When constructing your own agent, you will need to provide it with a list of Tools that it can use. While LangChain includes some prebuilt tools, it can often be more useful to use tools that use custom logic. This guide will walk you through how to use these `Dynamic` tools.\n",
"When constructing your own agent, you will need to provide it with a list of Tools that it can use. While LangChain includes some prebuilt tools, it can often be more useful to use tools that use custom logic. This guide will walk you through some ways you can create custom tools.\n",
"\n",
"In this guide, we will walk through how to do define a tool for two functions:\n",
"The biggest difference here is that the first function requires an object with multiple input fields, while the second one only accepts an object with a single field. Some older agents only work with functions that require single inputs, so it's important to understand the distinction."
]
},
{
"cell_type": "markdown",
"id": "f6ec6ee8",
"metadata": {},
"source": [
"## `tool` function\n",
"\n",
"1. A multiplier function that will multiply two numbers by each other\n",
"2. A made up search function that always returns the string \"LangChain\"\n",
":::note\n",
"Only available in `@langchain/core` version 0.2.7 and above.\n",
":::\n",
"\n",
"The biggest difference here is that the first function requires an object with multiple input fields, while the second one only accepts an object with a single field. Some older agents only work with functions that require single inputs, so it's important to understand the distinction."
"\n",
"The [`tool`](https://api.js.langchain.com/classes/langchain_core_tools.tool.html) wrapper function is a convenience method for turning a JavaScript function into a tool. It requires the function itself along with some additional arguments that define your tool. The most important are:\n",
"\n",
"- The tool's `name`, which the LLM will use as context as well as to reference the tool\n",
"- An optional, but recommended `description`, which the LLM will use as context to know when to use the tool\n",
"- A `schema`, which defines the shape of the tool's input\n",
"\n",
"The `tool` function will return an instance of the [`StructuredTool`](https://api.js.langchain.com/classes/langchain_core_tools.StructuredTool.html) class, so it is compatible with all the existing tool calling infrastructure in the LangChain library."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "ecc1ce9d",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The sum of 1 and 2 is 3\n"
]
}
],
"source": [
"import { z } from \"zod\";\n",
"import { tool } from \"@langchain/core/tools\";\n",
"\n",
"const adderSchema = z.object({\n",
" a: z.number(),\n",
" b: z.number(),\n",
"});\n",
"const adderTool = tool(async (input): Promise<string> => {\n",
" const sum = input.a + input.b;\n",
" return `The sum of ${input.a} and ${input.b} is ${sum}`;\n",
"}, {\n",
" name: \"adder\",\n",
" description: \"Adds two numbers together\",\n",
" schema: adderSchema,\n",
"});\n",
"\n",
"await adderTool.invoke({ a: 1, b: 2 });"
]
},
{
Expand All @@ -33,7 +97,7 @@
"source": [
"## `DynamicStructuredTool`\n",
"\n",
"Newer and more advanced agents can handle more flexible tools that take multiple inputs. You can use the [`DynamicStructuredTool`](https://v02.api.js.langchain.com/classes/langchain_core_tools.DynamicStructuredTool.html) class to declare them. Here's an example - note that tools must always return strings!"
"You can also use the [`DynamicStructuredTool`](https://api.js.langchain.com/classes/langchain_core_tools.DynamicStructuredTool.html) class to declare tools. Here's an example - note that tools must always return strings!"
]
},
{
Expand Down Expand Up @@ -112,6 +176,18 @@
"\n",
"await searchTool.invoke(\"foo\");"
]
},
{
"cell_type": "markdown",
"id": "8eceaf09",
"metadata": {},
"source": [
"## Next steps\n",
"\n",
"You've now seen a few ways to create custom tools in LangChain.\n",
"\n",
"Next, you might be interested in learning [how to use a chat model to call tools](/docs/how_to/tool_calling/)."
]
}
],
"metadata": {
Expand All @@ -121,12 +197,15 @@
"name": "deno"
},
"language_info": {
"codemirror_mode": {
"mode": "typescript",
"name": "javascript",
"typescript": true
},
"file_extension": ".ts",
"mimetype": "text/x.typescript",
"mimetype": "text/typescript",
"name": "typescript",
"nb_converter": "script",
"pygments_lexer": "typescript",
"version": "5.3.3"
"version": "3.7.2"
},
"vscode": {
"interpreter": {
Expand Down
24 changes: 14 additions & 10 deletions docs/core_docs/docs/how_to/migrate_agent.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,13 @@
"\n",
"For basic creation and usage of a tool-calling ReAct-style agent, the\n",
"functionality is the same. First, let's define a model and tool(s), then we'll\n",
"use those to create an agent.\n"
"use those to create an agent.\n",
"\n",
":::note\n",
"The `tool` function is available in `@langchain/core` version 0.2.7 and above.\n",
"\n",
"If you are on an older version of core, you should use instantiate and use [`DynamicStructuredTool`](https://api.js.langchain.com/classes/langchain_core_tools.DynamicStructuredTool.html) instead.\n",
":::"
]
},
{
Expand All @@ -61,7 +67,7 @@
},
"outputs": [],
"source": [
"import { DynamicStructuredTool } from \"@langchain/core/tools\";\n",
"import { tool } from \"@langchain/core/tools\";\n",
"import { z } from \"zod\";\n",
"import { ChatAnthropic } from \"@langchain/anthropic\";\n",
"\n",
Expand All @@ -70,15 +76,14 @@
" temperature: 0,\n",
"});\n",
"\n",
"const magicTool = new DynamicStructuredTool({\n",
"const magicTool = tool(async ({ input }: { input: number }) => {\n",
" return `${input + 2}`;\n",
"}, {\n",
" name: \"magic_function\",\n",
" description: \"Applies a magic function to an input.\",\n",
" schema: z.object({\n",
" input: z.number(),\n",
" }),\n",
" func: async ({ input }: { input: number }) => {\n",
" return `${input + 2}`;\n",
" },\n",
"});\n",
"\n",
"const tools = [magicTool];\n",
Expand Down Expand Up @@ -1532,15 +1537,14 @@
}
],
"source": [
"const badMagicTool = new DynamicStructuredTool({\n",
"const badMagicTool = tool(async ({ input }) => {\n",
" return \"Sorry, there was an error. Please try again.\";\n",
"}, {\n",
" name: \"magic_function\",\n",
" description: \"Applies a magic function to an input.\",\n",
" schema: z.object({\n",
" input: z.string(),\n",
" }),\n",
" func: async ({ input }) => {\n",
" return \"Sorry, there was an error. Please try again.\";\n",
" },\n",
"});\n",
"\n",
"const badTools = [badMagicTool];\n",
Expand Down
80 changes: 36 additions & 44 deletions docs/core_docs/docs/how_to/tool_calling.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,23 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"A number of models implement helper methods that will take care of formatting and binding different function-like objects to the model.\n",
"Let's take a look at how we might take the following Zod function schema and get different models to invoke it:"
"We can use the `.bindTools()` method to handle the conversion from LangChain tool to our model provider's specific format and bind it to the model (i.e., passing it in each time the model is invoked). A number of models implement helper methods that will take care of formatting and binding different function-like objects to the model.\n",
"Let's create a new tool implementing a Zod schema, then bind it to the model:\n",
"\n",
":::note\n",
"The `tool` function is available in `@langchain/core` version 0.2.7 and above.\n",
"\n",
"If you are on an older version of core, you should use instantiate and use [`DynamicStructuredTool`](https://api.js.langchain.com/classes/langchain_core_tools.DynamicStructuredTool.html) instead.\n",
":::"
]
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import { tool } from \"@langchain/core/tools\";\n",
"import { z } from \"zod\";\n",
"\n",
"/**\n",
Expand All @@ -109,43 +116,25 @@
" .describe(\"The type of operation to execute.\"),\n",
" number1: z.number().describe(\"The first number to operate on.\"),\n",
" number2: z.number().describe(\"The second number to operate on.\"),\n",
"});"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can use the `.bindTools()` method to handle the conversion from LangChain tool to our model provider's specific format and bind it to the model (i.e., passing it in each time the model is invoked). Let's create a `DynamicStructuredTool` implementing a tool based on the above schema, then bind it to the model:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import { ChatOpenAI } from \"@langchain/openai\";\n",
"import { DynamicStructuredTool } from \"@langchain/core/tools\";\n",
"});\n",
"\n",
"const calculatorTool = new DynamicStructuredTool({\n",
"const calculatorTool = tool(async ({ operation, number1, number2 }) => {\n",
" // Functions must return strings\n",
" if (operation === \"add\") {\n",
" return `${number1 + number2}`;\n",
" } else if (operation === \"subtract\") {\n",
" return `${number1 - number2}`;\n",
" } else if (operation === \"multiply\") {\n",
" return `${number1 * number2}`;\n",
" } else if (operation === \"divide\") {\n",
" return `${number1 / number2}`;\n",
" } else {\n",
" throw new Error(\"Invalid operation.\");\n",
" }\n",
"}, {\n",
" name: \"calculator\",\n",
" description: \"Can perform mathematical operations.\",\n",
" schema: calculatorSchema,\n",
" func: async ({ operation, number1, number2 }) => {\n",
" // Functions must return strings\n",
" if (operation === \"add\") {\n",
" return `${number1 + number2}`;\n",
" } else if (operation === \"subtract\") {\n",
" return `${number1 - number2}`;\n",
" } else if (operation === \"multiply\") {\n",
" return `${number1 * number2}`;\n",
" } else if (operation === \"divide\") {\n",
" return `${number1 / number2}`;\n",
" } else {\n",
" throw new Error(\"Invalid operation.\");\n",
" }\n",
" }\n",
"});\n",
"\n",
"const llmWithTools = llm.bindTools([calculatorTool]);"
Expand All @@ -169,9 +158,9 @@
"text": [
"[\n",
" {\n",
" name: \"calculator\",\n",
" args: { operation: \"multiply\", number1: 3, number2: 12 },\n",
" id: \"call_Ri9s27J17B224FEHrFGkLdxH\"\n",
" name: 'calculator',\n",
" args: { operation: 'multiply', number1: 3, number2: 12 },\n",
" id: 'call_5KWEQgV40XVoY1rqDhwyDmli'\n",
" }\n",
"]\n"
]
Expand All @@ -189,7 +178,7 @@
"source": [
"```{=mdx}\n",
":::tip\n",
"See a LangSmith trace for the above [here](https://smith.langchain.com/public/14e4b50c-c6cf-4c53-b3ef-da550edb6d66/r).\n",
"See a LangSmith trace for the above [here](https://smith.langchain.com/public/b2222205-7da9-4a5a-8efe-6bc62347705d/r).\n",
":::\n",
"```\n",
"\n",
Expand Down Expand Up @@ -538,12 +527,15 @@
"name": "deno"
},
"language_info": {
"codemirror_mode": {
"mode": "typescript",
"name": "javascript",
"typescript": true
},
"file_extension": ".ts",
"mimetype": "text/x.typescript",
"mimetype": "text/typescript",
"name": "typescript",
"nb_converter": "script",
"pygments_lexer": "typescript",
"version": "5.3.3"
"version": "3.7.2"
}
},
"nbformat": 4,
Expand Down
19 changes: 12 additions & 7 deletions docs/core_docs/docs/how_to/tool_calls_multimodal.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@
"\n",
"To call tools using such models, simply bind tools to them in the [usual way](/docs/how_to/tool_calling), and invoke the model using content blocks of the desired type (e.g., containing image data).\n",
"\n",
"Below, we demonstrate examples using [OpenAI](/docs/integrations/platforms/openai) and [Anthropic](/docs/integrations/platforms/anthropic). We will use the same image and tool in all cases. Let's first select an image, and build a placeholder tool that expects as input the string \"sunny\", \"cloudy\", or \"rainy\". We will ask the models to describe the weather in the image."
"Below, we demonstrate examples using [OpenAI](/docs/integrations/platforms/openai) and [Anthropic](/docs/integrations/platforms/anthropic). We will use the same image and tool in all cases. Let's first select an image, and build a placeholder tool that expects as input the string \"sunny\", \"cloudy\", or \"rainy\". We will ask the models to describe the weather in the image.\n",
"\n",
":::note\n",
"The `tool` function is available in `@langchain/core` version 0.2.7 and above.\n",
"\n",
"If you are on an older version of core, you should use instantiate and use [`DynamicStructuredTool`](https://api.js.langchain.com/classes/langchain_core_tools.DynamicStructuredTool.html) instead.\n",
":::"
]
},
{
Expand All @@ -32,21 +38,20 @@
"metadata": {},
"outputs": [],
"source": [
"import { DynamicStructuredTool } from \"@langchain/core/tools\";\n",
"import { tool } from \"@langchain/core/tools\";\n",
"import { z } from \"zod\";\n",
"\n",
"const imageUrl = \"https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg\";\n",
"\n",
"const weatherTool = new DynamicStructuredTool({\n",
"const weatherTool = tool(async ({ weather }) => {\n",
" console.log(weather);\n",
" return weather;\n",
"}, {\n",
" name: \"multiply\",\n",
" description: \"Describe the weather\",\n",
" schema: z.object({\n",
" weather: z.enum([\"sunny\", \"cloudy\", \"rainy\"])\n",
" }),\n",
" func: async ({ weather }) => {\n",
" console.log(weather);\n",
" return weather;\n",
" },\n",
"});"
]
},
Expand Down
Loading
Loading