工具 (Tools)
工具扩展了智能体的能力,使其能够与外部系统交互、检索信息或执行操作。每个工具都是一个带有名称、描述和参数模式的函数。
创建工具
使用 tool() 函数定义工具。模式描述了工具期望的输入参数:
import { tool } from "langchain";
import * as z from "zod";
const getWeather = tool(
(input) => `${input.city}的天气是晴天!`,
{
name: "get_weather",
description: "获取指定城市的天气",
schema: z.object({
city: z.string().describe("要查询天气的城市"),
}),
}
);
访问运行时
工具可以访问运行时功能,例如上下文、存储和流写入器。这些功能通过传递给工具的第二个参数(配置对象)来访问。
上下文
上下文允许工具访问调用时提供的配置数据。这对于需要会话特定信息的工具非常有用。
import { tool, ToolRuntime } from "langchain";
import * as z from "zod";
type AgentContext = { user_id: string };
const getUserLocation = tool(
(_, config: ToolRuntime<unknown, AgentContext>) => {
const { user_id } = config.context;
// 根据用户 ID 返回位置
return user_id === "1" ? "北京" : "上海";
},
{
name: "get_user_location",
description: "获取用户的位置",
}
);
存储 (Store)
使用存储在对话之间访问持久化数据。通过 config.store 访问存储,允许你保存和检索用户特定或应用特定的数据。
import * as z from "zod";
import { createAgent, tool } from "langchain";
import { InMemoryStore } from "@langchain/langgraph";
import { ChatOpenAI } from "@langchain/openai";
const store = new InMemoryStore();
// 访问存储
const getUserInfo = tool(
async ({ user_id }) => {
const value = await store.get(["users"], user_id);
console.log("get_user_info", user_id, value);
return value;
},
{
name: "get_user_info",
description: "查询用户信息",
schema: z.object({
user_id: z.string(),
}),
}
);
// 更新存储
const saveUserInfo = tool(
async ({ user_id, name, age, email }) => {
console.log("save_user_info", user_id, name, age, email);
await store.put(["users"], user_id, { name, age, email });
return "用户信息保存成功";
},
{
name: "save_user_info",
description: "保存用户信息",
schema: z.object({
user_id: z.string(),
name: z.string(),
age: z.number(),
email: z.string(),
}),
}
);
const agent = createAgent({
model: new ChatOpenAI({ model: "gpt-4o" }),
tools: [getUserInfo, saveUserInfo],
store,
});
// 第一个会话:保存用户信息
await agent.invoke({
messages: [
{
role: "user",
content: "保存以下用户:userid: abc123, name: 张三, age: 25, email: zhangsan@example.com",
},
],
});
// 第二个会话:获取用户信息
const result = await agent.invoke({
messages: [
{ role: "user", content: "获取 ID 为 'abc123' 的用户信息" },
],
});
console.log(result);
// 用户 ID 为 "abc123" 的信息:
// - 姓名:张三
// - 年龄:25
// - 邮箱:zhangsan@example.com
流写入器 (Stream Writer)
使用 config.writer 在工具执行时流式传输自定义更新。这对于向用户提供工具正在执行的实时反馈非常有用。
import * as z from "zod";
import { tool, ToolRuntime } from "langchain";
const getWeather = tool(
({ city }, config: ToolRuntime) => {
const writer = config.writer;
// 在工具执行时流式传输自定义更新
if (writer) {
writer(`正在查询城市数据:${city}`);
writer(`已获取城市数据:${city}`);
}
return `${city}总是阳光明媚!`;
},
{
name: "get_weather",
description: "获取指定城市的天气",
schema: z.object({
city: z.string(),
}),
}
);
工具类型
基础工具
最简单的工具形式,接收输入并返回输出:
const add = tool(
({ a, b }) => a + b,
{
name: "add",
description: "两数相加",
schema: z.object({
a: z.number().describe("第一个数字"),
b: z.number().describe("第二个数字"),
}),
}
);
异步工具
工具可以是异步的,适用于调用外部 API 或执行 I/O 操作:
const fetchData = tool(
async ({ url }) => {
const response = await fetch(url);
return await response.json();
},
{
name: "fetch_data",
description: "从 URL 获取数据",
schema: z.object({
url: z.string().url().describe("要获取数据的 URL"),
}),
}
);
无模式工具
对于不需要任何输入的工具,可以省略模式:
const getCurrentTime = tool(
() => new Date().toISOString(),
{
name: "get_current_time",
description: "获取当前时间",
}
);
最佳实践
- 描述清晰 - 提供清晰、具体的工具描述,帮助智能体理解何时使用该工具
- 参数文档化 - 使用
.describe()为每个参数添加说明 - 错误处理 - 在工具中实现适当的错误处理
- 返回有意义的结果 - 返回对智能体有用的结构化数据
- 保持简单 - 每个工具应该只做一件事,保持功能单一