LangGraph.js - 快速入门¶
介绍¶
在本快速入门指南中,您将使用一个简单的推理 + 行动代理(通常称为 ReAct 代理)开始运行,该代理可以使用 Tavily 搜索 API 搜索网络。代码是完全可配置的。您可以
- 交换组件
- 自定义执行流程
- 使用自定义代码或工具进行扩展
- 更改正在使用的大型语言模型 (LLM) 和提供商
先决条件¶
要继续学习,您需要具备以下条件
- NodeJS 版本 18 或更高版本
- 一个 Tavily 帐户和 API 密钥
- 一个 OpenAI 开发者平台 帐户和 API 密钥
首先创建一个用于项目的文件夹。打开您的终端并运行以下代码
mkdir langgraph-agent
cd langgraph-agent
您还需要安装一些依赖项来创建一个代理
- @langchain/langgraph 包含用于组装代理的构建块
- @langchain/openai 使您的代理能够使用 OpenAI 的 LLM
- @langchain/community 包含 Tavily 集成,为您的代理提供搜索功能
您可以通过在终端中运行以下 npm 命令来安装这些依赖项
npm install @langchain/core @langchain/langgraph @langchain/openai @langchain/community
LangSmith¶
或者,设置 LangSmith 以获得一流的可观察性。设置很简单 - 将以下变量添加到您的环境中,并将 LANGCHAIN_API_KEY
值更新为您的 API 密钥。
// Optional, add tracing in LangSmith
// process.env.LANGCHAIN_API_KEY = "ls__...";
// process.env.LANGCHAIN_CALLBACKS_BACKGROUND = "true";
// process.env.LANGCHAIN_TRACING_V2 = "true";
// process.env.LANGCHAIN_PROJECT = "Quickstart: LangGraphJS";
使用 LangGraph 创建您的第一个代理¶
创建一个名为 agent.ts
(推理 + 行动代理的简称)的文件,并将以下 TypeScript 代码添加到其中。
确保将文件顶部的环境变量更新为包含您的 API 密钥。如果您没有这样做,OpenAI 和 Tavily API 调用将产生错误,您的代理将无法正常工作。
添加完 API 密钥后,保存文件并使用以下命令运行代码
npx tsx agent.ts
// agent.ts
// IMPORTANT - Add your API keys here. Be careful not to publish them.
process.env.OPENAI_API_KEY = "sk-...";
process.env.TAVILY_API_KEY = "tvly-...";
import { TavilySearchResults } from "@langchain/community/tools/tavily_search";
import { ChatOpenAI } from "@langchain/openai";
import { MemorySaver } from "@langchain/langgraph";
import { HumanMessage } from "@langchain/core/messages";
import { createReactAgent } from "@langchain/langgraph/prebuilt";
// Define the tools for the agent to use
const agentTools = [new TavilySearchResults({ maxResults: 3 })];
const agentModel = new ChatOpenAI({ temperature: 0 });
// Initialize memory to persist state between graph runs
const agentCheckpointer = new MemorySaver();
const agent = createReactAgent({
llm: agentModel,
tools: agentTools,
checkpointSaver: agentCheckpointer,
});
// Now it's time to use!
const agentFinalState = await agent.invoke(
{ messages: [new HumanMessage("what is the current weather in sf")] },
{ configurable: { thread_id: "42" } },
);
console.log(
agentFinalState.messages[agentFinalState.messages.length - 1].content,
);
const agentNextState = await agent.invoke(
{ messages: [new HumanMessage("what about ny")] },
{ configurable: { thread_id: "42" } },
);
console.log(
agentNextState.messages[agentNextState.messages.length - 1].content,
);
The current weather in San Francisco is as follows: - Temperature: 82.0°F (27.8°C) - Condition: Sunny - Wind: 11.9 mph from the NW - Humidity: 41% - Pressure: 29.98 in - Visibility: 9.0 miles - UV Index: 6.0 For more details, you can visit [Weather in San Francisco](https://www.weatherapi.com/). The current weather in New York is as follows: - Temperature: 84.0°F (28.9°C) - Condition: Sunny - Wind: 2.2 mph from SSE - Humidity: 57% - Pressure: 29.89 in - Precipitation: 0.01 in - Visibility: 9.0 miles - UV Index: 6.0 For more details, you can visit [Weather in New York](https://www.weatherapi.com/).
它是如何工作的?¶
createReactAgent 构造函数允许您在一行代码中创建一个简单的使用工具的 LangGraph 代理。以下是图的直观表示
// Note: tslab only works inside a jupyter notebook. Don't worry about running this code yourself!
import * as tslab from "tslab";
const graph = agent.getGraph();
const image = await graph.drawMermaidPng();
const arrayBuffer = await image.arrayBuffer();
await tslab.display.png(new Uint8Array(arrayBuffer));
自定义代理行为¶
createReactAgent 非常适合简单的代理,但有时您需要更强大的功能。
当您需要对代理的行为进行细粒度控制时,LangGraph 真的大放异彩。以下代码创建了一个与上面示例具有相同行为的代理,但您可以清楚地看到执行逻辑以及如何对其进行自定义。
将 agent.ts
文件中的代码更新为与以下示例匹配。再次确保更新文件顶部的环境变量。
更新完环境变量并保存文件后,您可以使用与之前相同的命令运行它
npx tsx agent.ts
// agent.ts
// IMPORTANT - Add your API keys here. Be careful not to publish them.
process.env.OPENAI_API_KEY = "sk-...";
process.env.TAVILY_API_KEY = "tvly-...";
import { TavilySearchResults } from "@langchain/community/tools/tavily_search";
import { ChatOpenAI } from "@langchain/openai";
import { HumanMessage } from "@langchain/core/messages";
import { ToolNode } from "@langchain/langgraph/prebuilt";
import { StateGraph, MessagesAnnotation } from "@langchain/langgraph";
// Define the tools for the agent to use
const tools = [new TavilySearchResults({ maxResults: 3 })];
const toolNode = new ToolNode(tools);
// Create a model and give it access to the tools
const model = new ChatOpenAI({
model: "gpt-4o-mini",
temperature: 0,
}).bindTools(tools);
// Define the function that determines whether to continue or not
function shouldContinue({ messages }: typeof MessagesAnnotation.State) {
const lastMessage = messages[messages.length - 1];
// If the LLM makes a tool call, then we route to the "tools" node
if (lastMessage.additional_kwargs.tool_calls) {
return "tools";
}
// Otherwise, we stop (reply to the user) using the special "__end__" node
return "__end__";
}
// Define the function that calls the model
async function callModel(state: typeof MessagesAnnotation.State) {
const response = await model.invoke(state.messages);
// We return a list, because this will get added to the existing list
return { messages: [response] };
}
// Define a new graph
const workflow = new StateGraph(MessagesAnnotation)
.addNode("agent", callModel)
.addEdge("__start__", "agent") // __start__ is a special name for the entrypoint
.addNode("tools", toolNode)
.addEdge("tools", "agent")
.addConditionalEdges("agent", shouldContinue);
// Finally, we compile it into a LangChain Runnable.
const app = workflow.compile();
// Use the agent
const finalState = await app.invoke({
messages: [new HumanMessage("what is the weather in sf")],
});
console.log(finalState.messages[finalState.messages.length - 1].content);
const nextState = await app.invoke({
// Including the messages from the previous run gives the LLM context.
// This way it knows we're asking about the weather in NY
messages: [...finalState.messages, new HumanMessage("what about ny")],
});
console.log(nextState.messages[nextState.messages.length - 1].content);
在这个版本的 ReAct 代理中,有一些新内容。
一个 ToolNode
使 LLM 能够使用工具。在这个例子中,我们创建了一个 shouldContinue
函数并将其传递给 addConditionalEdge
,以便我们的 ReAct 代理可以调用工具或响应请求。
注释 是 LangGraph 中表示图形状态的方式。我们使用 MessagesAnnotation
,这是一个实现通用模式的助手:将消息历史记录保存在数组中。