工具¶
工具是一种封装函数及其输入 schema 的方式,可以将其传递给支持工具调用的聊天模型。这允许模型请求使用特定的输入执行此函数。
您可以定义自己的工具,或使用 LangChain 提供的预构建集成。
定义工具¶
您可以使用 tool
函数创建工具
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";
import { tool } from "@langchain/core/tools";
import { z } from "zod";
const multiply = tool(
async (input: { a: number; b: number }) => {
return input.a * input.b;
},
{
name: "multiply",
schema: z.object({
a: z.number().describe("First operand"),
b: z.number().describe("Second operand"),
}),
description: "Multiply two numbers.",
}
);
const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agent = createReactAgent({
llm,
tools: [multiply],
});
有关其他自定义,请参阅自定义工具指南。
向模型隐藏参数¶
某些工具需要仅在运行时使用的参数(例如,用户 ID 或会话上下文),这些参数不应由模型控制。
您可以将这些参数放在代理的 state
或 config
中,并在工具内部访问此信息
import { z } from "zod";
import { tool } from "@langchain/core/tools";
import {
getCurrentTaskInput,
LangGraphRunnableConfig,
} from "@langchain/langgraph";
import { MessagesAnnotation } from "@langchain/langgraph";
const myTool = tool(
async (input: {
// This will be populated by an LLM
toolArg: string,
},
// access static data that is passed at agent invocation
config: LangGraphRunnableConfig
) => {
// Fetch the current agent state
const state = getCurrentTaskInput() as typeof MessagesAnnotation.State;
doSomethingWithState(state.messages);
doSomethingWithConfig(config);
// ...
},
{
name: "myTool",
schema: z.object({
myToolArg: z.number().describe("Tool arg"),
}),
description: "My tool.",
}
);
禁用并行工具调用¶
某些模型提供商支持并行执行多个工具,但允许用户禁用此功能。
对于支持的提供商,您可以通过 model.bindTools()
方法将 parallel_tool_calls
设置为 false
来禁用并行工具调用
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { ChatOpenAI } from "@langchain/openai";
import { tool } from "@langchain/core/tools";
import { z } from "zod";
const add = tool(
async (input: { a: number; b: number }) => {
return input.a + input.b;
},
{
name: "add",
schema: z.object({
a: z.number().describe("First operand"),
b: z.number().describe("Second operand"),
}),
description: "Add two numbers.",
}
);
const multiply = tool(
async (input: { a: number; b: number }) => {
return input.a * input.b;
},
{
name: "multiply",
schema: z.object({
a: z.number().describe("First operand"),
b: z.number().describe("Second operand"),
}),
description: "Multiply two numbers.",
}
);
const llm = new ChatOpenAI({ model: "gpt-4.1" });
const tools = [add, multiply];
const agent = createReactAgent({
// disable parallel tool calls
llm: llm.bindTools(tools, { parallel_tool_calls: false }),
tools,
});
const response = await agent.invoke(
{ messages: [ { role: "user", content: "what's 3 + 5 and 4 * 7?" } ] }
);
直接返回工具结果¶
使用 returnDirect: true
可以立即返回工具结果并停止代理循环
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";
import { tool } from "@langchain/core/tools";
import { z } from "zod";
const add = tool(
async (input: { a: number; b: number }) => {
return input.a + input.b;
},
{
name: "add",
schema: z.object({
a: z.number().describe("First operand"),
b: z.number().describe("Second operand"),
}),
description: "Add two numbers.",
returnDirect: true
}
);
const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agent = createReactAgent({
llm,
tools: [add],
});
const response = await agent.invoke(
{ messages: [ { role: "user", content: "what's 3 + 5?" } ] }
);
强制使用工具¶
要强制代理使用特定工具,您可以在 model.bindTools()
中设置 tool_choice
选项
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";
import { tool } from "@langchain/core/tools";
import { z } from "zod";
const greet = tool(
async (input: { userName: string }) => {
return `Hello ${input.userName}!`;
},
{
name: "greet",
schema: z.object({
userName: z.string().describe("Name of the user to greet"),
}),
description: "Greet user.",
returnDirect: true
}
);
const llm = new ChatAnthropic({ model: "claude-3-7-sonnet-latest" });
const tools = [greet];
const agent = createReactAgent({
llm: llm.bindTools(tools, { tool_choice: { type: "tool", name: "greet" } }),
tools,
});
const response = await agent.invoke({
messages: "Hi, I am Bob"
});
避免无限循环
在没有停止条件的情况下强制使用工具可能会产生无限循环。请使用以下任一安全措施
- 使用
returnDirect: True
标记工具,以便在执行后结束循环。 - 设置
recursionLimit
以限制执行步数。
处理工具错误¶
默认情况下,代理会捕获工具调用期间引发的所有异常,并将这些异常作为工具消息传递给 LLM。要控制错误的处理方式,您可以使用预构建的 ToolNode
(即在 createReactAgent
内部执行工具的节点)的 handleToolErrors
参数
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";
import { tool } from "@langchain/core/tools";
import { z } from "zod";
const multiply = tool(
async (input: { a: number; b: number }) => {
if (input.a === 42) {
throw new Error("The ultimate error");
}
return input.a * input.b;
},
{
name: "multiply",
schema: z.object({
a: z.number().describe("First operand"),
b: z.number().describe("Second operand"),
}),
description: "Multiply two numbers.",
}
);
// Run with error handling (default)
const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agent = createReactAgent({
llm,
tools: [multiply],
});
const response = await agent.invoke(
{ messages: [ { role: "user", content: "what's 42 x 7?" } ] }
);
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";
import { tool } from "@langchain/core/tools";
import { z } from "zod";
import { ToolNode } from "@langchain/langgraph/prebuilt";
const multiply = tool(
async (input: { a: number; b: number }) => {
if (input.a === 42) {
throw new Error("The ultimate error");
}
return input.a * input.b;
},
{
name: "multiply",
schema: z.object({
a: z.number().describe("First operand"),
b: z.number().describe("Second operand"),
}),
description: "Multiply two numbers.",
}
);
const toolNode = new ToolNode({
tools: [multiply],
handleToolErrors: false, // (1)!
});
const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agentNoErrorHandling = createReactAgent({
llm,
tools: toolNode,
});
const response = await agentNoErrorHandling.invoke(
{ messages: [ { role: "user", content: "what's 42 x 7?" } ] }
);
- 这将禁用错误处理(默认已启用)。
预构建工具¶
LangChain 支持广泛的预构建工具集成,用于与 API、数据库、文件系统、Web 数据等进行交互。这些工具扩展了代理的功能,并支持快速开发。
您可以在LangChain 集成目录中浏览所有可用集成的完整列表。
一些常用的工具类别包括
- 搜索:Exa、SerpAPI、Tavily
- 代码解释器:Python REPL
- 数据库:SQL、MongoDB、Redis
- Web 数据:Web 抓取和浏览
- API:Discord、Gmail 及其他
可以使用上面示例中所示的相同 tools
参数配置这些集成并将其添加到您的代理中。