LangGraph.js - 快速入门¶
简介¶
在本快速入门指南中,您将使用一个简单的推理+行动智能体(通常称为 ReAct 智能体)快速启动并运行,该智能体可以使用 Tavily 搜索 API 搜索网页。代码是完全可配置的。您可以:
- 更换组件
- 自定义执行流程
- 使用自定义代码或工具进行扩展
- 更改正在使用的大型语言模型 (LLM) 和提供商
先决条件¶
要继续操作,您需要具备以下条件:
- NodeJS 18 或更高版本
- 一个 Tavily 账户和 API 密钥
- 一个 OpenAI 开发者平台账户和 API 密钥
首先为项目创建一个新文件夹。打开您的终端并运行以下代码:
您还需要安装一些依赖项来创建一个智能体:
- langchain/langgraph 包含用于组装智能体的构建块
- langchain/openai 使您的智能体能够使用 OpenAI 的 LLM
- langchain/community 包含 Tavily 集成,为您的智能体提供搜索功能
您可以通过在终端中运行以下 npm 命令来安装这些依赖项:
LangSmith¶
(可选)设置 LangSmith 以获得一流的可观察性。设置很简单——将以下变量添加到您的环境中,并使用您的 API 密钥更新 LANGCHAIN_API_KEY
的值。
// 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
(Reason + Act Agent 的缩写)的文件,并将下面的 TypeScript 代码添加到其中。
确保您更新文件顶部的环境变量,使其包含您的 API 密钥。如果您不这样做,OpenAI 和 Tavily API 调用将产生错误,您的智能体将无法正常工作。
添加 API 密钥后,保存文件并使用以下命令运行代码:
// 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));
另外,您可以使用以下方法将图保存为本地 PNG 文件:
import { writeFileSync } from "node:fs";
const graphStateImage = await drawableGraphGraphState.drawMermaidPng();
const graphStateArrayBuffer = await graphStateImage.arrayBuffer();
const filePath = "./graphState.png";
writeFileSync(filePath, new Uint8Array(graphStateArrayBuffer));
自定义智能体行为¶
createReactAgent 对于简单的智能体来说非常棒,但有时您需要更强大的功能。
当您需要对智能体行为进行细粒度控制时,LangGraph 真正大放异彩。以下代码创建了一个与上述示例行为相同的智能体,但您可以清楚地看到执行逻辑以及如何自定义它。
更新您 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, AIMessage } 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] as AIMessage;
// If the LLM makes a tool call, then we route to the "tools" node
if (lastMessage.tool_calls?.length) {
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
,这是一个实现了常见模式的辅助函数:将消息历史记录保存在一个数组中。
下一步¶
使用 LangGraph 创建您的第一个 AI 智能体,干得好!如果您准备构建更多功能,请查看我们的其他教程,了解如何实现其他端到端智能体工作流程,例如:
- 检索增强生成 (RAG)
- 多智能体协作
- 反思,即智能体评估其工作
如果您想改进您的智能体,我们有操作指南可以帮助您,包括:
- 工具调用,使智能体能够与 API 交互
- 为您的智能体提供持久内存,以继续对话和调试意外行为
- 对于您希望人工验证的操作,可以将人工纳入循环
- 流式传输智能体输出,使您的应用程序感觉更灵敏
- 一行代码更改 AI 模型