diff --git a/docs/core_docs/docs/how_to/custom_tools.ipynb b/docs/core_docs/docs/how_to/custom_tools.ipynb index c29a9c670296..dad45ed65dbd 100644 --- a/docs/core_docs/docs/how_to/custom_tools.ipynb +++ b/docs/core_docs/docs/how_to/custom_tools.ipynb @@ -1,5 +1,19 @@ { "cells": [ + { + "cell_type": "raw", + "id": "04171ad7", + "metadata": { + "vscode": { + "languageId": "raw" + } + }, + "source": [ + "---\n", + "keywords: [custom tool]\n", + "---" + ] + }, { "cell_type": "markdown", "id": "5436020b", @@ -16,12 +30,7 @@ "\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 tools.\n", - "\n", - "In this guide, we will walk through how to do define a tool for two functions:\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", + "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", "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." ] @@ -38,7 +47,13 @@ ":::\n", "\n", "\n", - "The [`tool`](https://api.js.langchain.com/classes/langchain_core_tools.tool.html) function is used to wrap a generic JavaScript/TypeScript function, along with additional arguments that define your tool. 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." + "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." ] }, { @@ -63,9 +78,9 @@ " a: z.number(),\n", " b: z.number(),\n", "});\n", - "const adderTool = tool((input): Promise => {\n", + "const adderTool = tool(async (input): Promise => {\n", " const sum = input.a + input.b;\n", - " return Promise.resolve(`The sum of ${input.a} and ${input.b} is ${sum}`);\n", + " return `The sum of ${input.a} and ${input.b} is ${sum}`;\n", "}, {\n", " name: \"adder\",\n", " description: \"Adds two numbers together\",\n", @@ -82,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://v02.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!" ] }, { @@ -161,13 +176,25 @@ "\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": { "kernelspec": { - "display_name": "TypeScript", + "display_name": "Deno", "language": "typescript", - "name": "tslab" + "name": "deno" }, "language_info": { "codemirror_mode": { diff --git a/docs/core_docs/docs/how_to/migrate_agent.ipynb b/docs/core_docs/docs/how_to/migrate_agent.ipynb index 31b4a39971b3..eacda605931a 100644 --- a/docs/core_docs/docs/how_to/migrate_agent.ipynb +++ b/docs/core_docs/docs/how_to/migrate_agent.ipynb @@ -52,9 +52,9 @@ "use those to create an agent.\n", "\n", ":::note\n", - "The `tool` function available in `@langchain/core` version 0.2.7 and above.\n", + "The `tool` function is available in `@langchain/core` version 0.2.7 and above.\n", "\n", - "[`DynamicStructuredTool`](https://v02.api.js.langchain.com/classes/langchain_core_tools.DynamicStructuredTool.html) should be used in older versions.\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", ":::" ] }, diff --git a/docs/core_docs/docs/how_to/tool_calling.ipynb b/docs/core_docs/docs/how_to/tool_calling.ipynb index 9fc0fe48f635..73c05d7cd136 100644 --- a/docs/core_docs/docs/how_to/tool_calling.ipynb +++ b/docs/core_docs/docs/how_to/tool_calling.ipynb @@ -91,9 +91,9 @@ "Let's create a new tool implementing a Zod schema, then bind it to the model:\n", "\n", ":::note\n", - "The `tool` function available in `@langchain/core` version 0.2.7 and above.\n", + "The `tool` function is available in `@langchain/core` version 0.2.7 and above.\n", "\n", - "[`DynamicStructuredTool`](https://v02.api.js.langchain.com/classes/langchain_core_tools.DynamicStructuredTool.html) should be used in older versions.\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", ":::" ] }, @@ -522,9 +522,9 @@ ], "metadata": { "kernelspec": { - "display_name": "TypeScript", + "display_name": "Deno", "language": "typescript", - "name": "tslab" + "name": "deno" }, "language_info": { "codemirror_mode": { diff --git a/docs/core_docs/docs/how_to/tool_calls_multimodal.ipynb b/docs/core_docs/docs/how_to/tool_calls_multimodal.ipynb index 68d1666bc1d8..a948c68811a1 100644 --- a/docs/core_docs/docs/how_to/tool_calls_multimodal.ipynb +++ b/docs/core_docs/docs/how_to/tool_calls_multimodal.ipynb @@ -25,9 +25,9 @@ "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 available in `@langchain/core` version 0.2.7 and above.\n", + "The `tool` function is available in `@langchain/core` version 0.2.7 and above.\n", "\n", - "[`DynamicStructuredTool`](https://v02.api.js.langchain.com/classes/langchain_core_tools.DynamicStructuredTool.html) should be used in older versions.\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", ":::" ] }, diff --git a/langchain-core/src/tools.ts b/langchain-core/src/tools.ts index 45a08d44ebc3..252571ca084a 100644 --- a/langchain-core/src/tools.ts +++ b/langchain-core/src/tools.ts @@ -34,10 +34,8 @@ export class ToolInputParsingException extends Error { } } -export interface StructuredToolInterface< - // eslint-disable-next-line @typescript-eslint/no-explicit-any - T extends ZodAny = ZodAny -> extends RunnableInterface< +export interface StructuredToolInterface + extends RunnableInterface< (z.output extends string ? string : never) | z.input, string > { @@ -74,7 +72,6 @@ export interface StructuredToolInterface< * Base class for Tools that accept input of any shape defined by a Zod schema. */ export abstract class StructuredTool< - // eslint-disable-next-line @typescript-eslint/no-explicit-any T extends ZodAny = ZodAny > extends BaseLangChain< (z.output extends string ? string : never) | z.input, @@ -241,10 +238,8 @@ export interface DynamicToolInput extends BaseDynamicToolInput { /** * Interface for the input parameters of the DynamicStructuredTool class. */ -export interface DynamicStructuredToolInput< - // eslint-disable-next-line @typescript-eslint/no-explicit-any - T extends ZodAny = ZodAny -> extends BaseDynamicToolInput { +export interface DynamicStructuredToolInput + extends BaseDynamicToolInput { func: ( input: z.infer, runManager?: CallbackManagerForToolRun, @@ -306,7 +301,6 @@ export class DynamicTool extends Tool { * provided function when the tool is called. */ export class DynamicStructuredTool< - // eslint-disable-next-line @typescript-eslint/no-explicit-any T extends ZodAny = ZodAny > extends StructuredTool { static lc_name() {