Skip to main content

如何向聊天机器人添加工具

前提条件

本指南假定您熟悉以下概念:

本节将介绍如何创建交互式代理:能够使用工具与其他系统和 API 交互的聊天机器人。

此前的教程基于 RunnableWithMessageHistory 构建了一个聊天机器人。您可以在 v0.2 文档 中查看该版本的教程。

LangGraph 的实现相较于 RunnableWithMessageHistory 具备多项优势,包括能够持久化保存应用程序状态的任意组件(而不仅限于消息)。

准备工作

在本指南中,我们将使用一个工具调用代理,并仅使用一个用于网页搜索的工具。默认情况下,我们将使用 Tavily,但您可以替换为任何类似工具。本节其余部分假定您正在使用 Tavily。

您需要在 Tavily 网站上注册账户,并安装以下包:

yarn add @langchain/core @langchain/langgraph @langchain/community

我们还应设置一个聊天模型,用于以下示例中。

Pick your chat model:

Install dependencies

yarn add @langchain/groq 

Add environment variables

GROQ_API_KEY=your-api-key

Instantiate the model

import { ChatGroq } from "@langchain/groq";

const llm = new ChatGroq({
model: "llama-3.3-70b-versatile",
temperature: 0
});
process.env.TAVILY_API_KEY = "YOUR_API_KEY";

创建一个代理

我们的最终目标是创建一个能够以对话方式回应用户问题的代理,同时在需要时能够查找信息。

首先,让我们初始化 Tavily 和一个能够调用工具的 OpenAI 聊天模型:

import { TavilySearchResults } from "@langchain/community/tools/tavily_search";

const tools = [
new TavilySearchResults({
maxResults: 1,
}),
];

为了让我们的智能体具备对话能力,我们还可以指定一个提示词。以下是一个示例:

import { ChatPromptTemplate } from "@langchain/core/prompts";

// Adapted from https://smith.langchain.com/hub/jacob/tool-calling-agent
const prompt = ChatPromptTemplate.fromMessages([
[
"system",
"You are a helpful assistant. You may not need to use tools for every query - the user may just want to chat!",
],
]);

太好了!现在让我们使用 LangGraph 预构建的 createReactAgent 来组装我们的代理,它可以让你创建一个 工具调用代理

import { createReactAgent } from "@langchain/langgraph/prebuilt";

// messageModifier allows you to preprocess the inputs to the model inside ReAct agent
// in this case, since we're passing a prompt string, we'll just always add a SystemMessage
// with this prompt string before any other messages sent to the model
const agent = createReactAgent({ llm, tools, messageModifier: prompt });

运行智能体

现在我们已经设置好了智能体,让我们尝试与它进行交互吧!它可以处理那些无需查找的简单查询:

await agent.invoke({ messages: [{ role: "user", content: "I'm Nemo!" }] });
{
messages: [
HumanMessage {
"id": "8c5fa465-e8d8-472a-9434-f574bf74537f",
"content": "I'm Nemo!",
"additional_kwargs": {},
"response_metadata": {}
},
AIMessage {
"id": "chatcmpl-ABTKLLriRcZin65zLAMB3WUf9Sg1t",
"content": "How can I assist you today?",
"additional_kwargs": {},
"response_metadata": {
"tokenUsage": {
"completionTokens": 8,
"promptTokens": 93,
"totalTokens": 101
},
"finish_reason": "stop",
"system_fingerprint": "fp_3537616b13"
},
"tool_calls": [],
"invalid_tool_calls": [],
"usage_metadata": {
"input_tokens": 93,
"output_tokens": 8,
"total_tokens": 101
}
}
]
}

或者,如果需要,它可以使用传递的搜索工具来获取最新的信息:

await agent.invoke({
messages: [
{
role: "user",
content:
"What is the current conservation status of the Great Barrier Reef?",
},
],
});
{
messages: [
HumanMessage {
"id": "65c315b6-2433-4cb1-97c7-b60b5546f518",
"content": "What is the current conservation status of the Great Barrier Reef?",
"additional_kwargs": {},
"response_metadata": {}
},
AIMessage {
"id": "chatcmpl-ABTKLQn1e4axRhqIhpKMyzWWTGauO",
"content": "How can I assist you today?",
"additional_kwargs": {},
"response_metadata": {
"tokenUsage": {
"completionTokens": 8,
"promptTokens": 93,
"totalTokens": 101
},
"finish_reason": "stop",
"system_fingerprint": "fp_3537616b13"
},
"tool_calls": [],
"invalid_tool_calls": [],
"usage_metadata": {
"input_tokens": 93,
"output_tokens": 8,
"total_tokens": 101
}
}
]
}

对话式响应

由于我们的提示词包含聊天历史消息的占位符,我们的智能体也可以像标准聊天机器人一样,综合考虑之前的交互内容并进行对话式回应:

await agent.invoke({
messages: [
{ role: "user", content: "I'm Nemo!" },
{ role: "user", content: "Hello Nemo! How can I assist you today?" },
{ role: "user", content: "What is my name?" },
],
});
{
messages: [
HumanMessage {
"id": "6433afc5-31bd-44b3-b34c-f11647e1677d",
"content": "I'm Nemo!",
"additional_kwargs": {},
"response_metadata": {}
},
HumanMessage {
"id": "f163b5f1-ea29-4d7a-9965-7c7c563d9cea",
"content": "Hello Nemo! How can I assist you today?",
"additional_kwargs": {},
"response_metadata": {}
},
HumanMessage {
"id": "382c3354-d02b-4888-98d8-44d75d045044",
"content": "What is my name?",
"additional_kwargs": {},
"response_metadata": {}
},
AIMessage {
"id": "chatcmpl-ABTKMKu7ThZDZW09yMIPTq2N723Cj",
"content": "How can I assist you today?",
"additional_kwargs": {},
"response_metadata": {
"tokenUsage": {
"completionTokens": 8,
"promptTokens": 93,
"totalTokens": 101
},
"finish_reason": "stop",
"system_fingerprint": "fp_e375328146"
},
"tool_calls": [],
"invalid_tool_calls": [],
"usage_metadata": {
"input_tokens": 93,
"output_tokens": 8,
"total_tokens": 101
}
}
]
}

如果需要,您还可以为 LangGraph 代理添加内存功能以管理消息历史记录。让我们以这种方式重新声明:

import { MemorySaver } from "@langchain/langgraph";

const memory = new MemorySaver();
const agent2 = createReactAgent({
llm,
tools,
messageModifier: prompt,
checkpointSaver: memory,
});
await agent2.invoke(
{ messages: [{ role: "user", content: "I'm Nemo!" }] },
{ configurable: { thread_id: "1" } }
);
{
messages: [
HumanMessage {
"id": "a4a4f663-8192-4179-afcc-88d9d186aa80",
"content": "I'm Nemo!",
"additional_kwargs": {},
"response_metadata": {}
},
AIMessage {
"id": "chatcmpl-ABTKi4tBzOWMh3hgA46xXo7bJzb8r",
"content": "How can I assist you today?",
"additional_kwargs": {},
"response_metadata": {
"tokenUsage": {
"completionTokens": 8,
"promptTokens": 93,
"totalTokens": 101
},
"finish_reason": "stop",
"system_fingerprint": "fp_e375328146"
},
"tool_calls": [],
"invalid_tool_calls": [],
"usage_metadata": {
"input_tokens": 93,
"output_tokens": 8,
"total_tokens": 101
}
}
]
}

然后,如果我们重新运行包装后的智能体执行器:

await agent2.invoke(
{ messages: [{ role: "user", content: "What is my name?" }] },
{ configurable: { thread_id: "1" } }
);
{
messages: [
HumanMessage {
"id": "c5fd303c-eb49-41a0-868e-bc8c5aa02cf6",
"content": "I'm Nemo!",
"additional_kwargs": {},
"response_metadata": {}
},
AIMessage {
"id": "chatcmpl-ABTKi4tBzOWMh3hgA46xXo7bJzb8r",
"content": "How can I assist you today?",
"additional_kwargs": {},
"response_metadata": {
"tokenUsage": {
"completionTokens": 8,
"promptTokens": 93,
"totalTokens": 101
},
"finish_reason": "stop",
"system_fingerprint": "fp_e375328146"
},
"tool_calls": [],
"invalid_tool_calls": []
},
HumanMessage {
"id": "635b17b9-2ec7-412f-bf45-85d0e9944430",
"content": "What is my name?",
"additional_kwargs": {},
"response_metadata": {}
},
AIMessage {
"id": "chatcmpl-ABTKjBbmFlPb5t37aJ8p4NtoHb8YG",
"content": "How can I assist you today?",
"additional_kwargs": {},
"response_metadata": {
"tokenUsage": {
"completionTokens": 8,
"promptTokens": 93,
"totalTokens": 101
},
"finish_reason": "stop",
"system_fingerprint": "fp_e375328146"
},
"tool_calls": [],
"invalid_tool_calls": [],
"usage_metadata": {
"input_tokens": 93,
"output_tokens": 8,
"total_tokens": 101
}
}
]
}

这个 LangSmith 追踪 展示了其背后的运行机制。

进一步阅读

关于如何构建代理的更多信息,请查看这些 LangGraph 指南:

关于工具使用的更多信息,还可以查看此用例部分


Was this page helpful?


You can also leave detailed feedback on GitHub.