🦜🕸️LangGraph¶
⚡ 以图的形式构建语言代理 ⚡
概览¶
LangGraph 是一个用于构建具有 LLM 的多角色应用程序的库,用于创建代理和多代理工作流。查看入门教程这里。
LangGraph 受 Pregel 和 Apache Beam 的启发,其公共接口借鉴了 NetworkX。LangGraph 由 LangChain Inc 创建,该公司也是 LangChain 的创建者,但 LangGraph 可以独立于 LangChain 使用。
为什么使用 LangGraph?¶
LangGraph 助力生产级代理,被 LinkedIn、Uber、Klarna、GitLab 等众多公司信赖。LangGraph 提供了对代理应用程序流程和状态的细粒度控制。它实现了一个中心持久层,支持大多数代理架构中的常见功能:
- 记忆:LangGraph 持久化应用程序状态的任意方面,支持对话记忆和其他更新,这些更新可以在用户交互之间进行;
- 人机交互:由于状态被检查点化,执行可以被中断和恢复,允许在关键阶段通过人工输入进行决策、验证和纠正。
通过标准化这些组件,个人和团队可以专注于代理的行为,而不是其支持基础设施。
通过LangGraph 平台,LangGraph 还提供了用于开发、部署、调试和监控应用程序的工具。
LangGraph 无缝集成到 LangChain 和 LangSmith 中(但并不强制要求)。
要了解更多关于 LangGraph 的信息,请查看我们的第一个 LangChain 学院课程《LangGraph 入门》,免费提供这里。
LangGraph 平台¶
LangGraph 平台 是用于部署 LangGraph 代理的基础设施。它是一个商业解决方案,用于将代理应用程序部署到生产环境中,基于开源的 LangGraph 框架。LangGraph 平台由几个组件组成,这些组件协同工作,支持 LangGraph 应用程序的开发、部署、调试和监控:LangGraph 服务器(APIs)、LangGraph SDK(API 客户端)、LangGraph CLI(构建服务器的命令行工具)和LangGraph Studio(UI/调试器)。
查看部署选项这里(包括免费层)。
以下是一些在复杂部署中常见的问题,LangGraph 平台可以解决这些问题:
- 流式支持:LangGraph 服务器提供多种流式模式,优化以满足各种应用程序需求
- 后台运行:在后台异步运行代理
- 支持长时间运行的代理:可以处理长时间运行进程的基础设施
- 双重文本:处理用户在代理响应之前发送两条消息的情况
- 处理突发性:任务队列,确保在高负载下也能一致地处理请求,而不会丢失请求
安装¶
示例¶
让我们构建一个调用工具的ReAct风格代理,该代理使用搜索工具!
可选地,我们可以设置LangSmith以实现最佳的可观测性。
在LangGraph中创建一个工具调用代理的最简单方法是使用create_react_agent
:
高层次实现
from langgraph.prebuilt import create_react_agent
from langgraph.checkpoint.memory import MemorySaver
from langchain_anthropic import ChatAnthropic
from langchain_core.tools import tool
# 定义代理使用的工具
@tool
def search(query: str):
"""调用以浏览网络。"""
# 这只是一个占位符,但不要告诉LLM...
if "sf" in query.lower() or "san francisco" in query.lower():
return "It's 60 degrees and foggy."
return "It's 90 degrees and sunny."
tools = [search]
model = ChatAnthropic(model="claude-3-5-sonnet-latest", temperature=0)
# 初始化内存以在图运行之间保持状态
checkpointer = MemorySaver()
app = create_react_agent(model, tools, checkpointer=checkpointer)
# 使用代理
final_state = app.invoke(
{"messages": [{"role": "user", "content": "what is the weather in sf"}]},
config={"configurable": {"thread_id": 42}}
)
final_state["messages"][-1].content
"Based on the search results, I can tell you that the current weather in San Francisco is:\n\nTemperature: 60 degrees Fahrenheit\nConditions: Foggy\n\nSan Francisco is known for its microclimates and frequent fog, especially during the summer months. The temperature of 60°F (about 15.5°C) is quite typical for the city, which tends to have mild temperatures year-round. The fog, often referred to as 'Karl the Fog' by locals, is a characteristic feature of San Francisco\'s weather, particularly in the mornings and evenings.\n\nIs there anything else you\'d like to know about the weather in San Francisco or any other location?"
"thread_id"
时,对话上下文将通过保存的状态(即存储的消息列表)保留。
final_state = app.invoke(
{"messages": [{"role": "user", "content": "what about ny"}]},
config={"configurable": {"thread_id": 42}}
)
final_state["messages"][-1].content
"Based on the search results, I can tell you that the current weather in New York City is:\n\nTemperature: 90 degrees Fahrenheit (approximately 32.2 degrees Celsius)\nConditions: Sunny\n\nThis weather is quite different from what we just saw in San Francisco. New York is experiencing much warmer temperatures right now. Here are a few points to note:\n\n1. The temperature of 90°F is quite hot, typical of summer weather in New York City.\n2. The sunny conditions suggest clear skies, which is great for outdoor activities but also means it might feel even hotter due to direct sunlight.\n3. This kind of weather in New York often comes with high humidity, which can make it feel even warmer than the actual temperature suggests.\n\nIt's interesting to see the stark contrast between San Francisco's mild, foggy weather and New York's hot, sunny conditions. This difference illustrates how varied weather can be across different parts of the United States, even on the same day.\n\nIs there anything else you'd like to know about the weather in New York or any other location?"
Tip
LangGraph是一个**低级**框架,允许你实现任何自定义代理架构。点击下面的低级实现以了解如何从头开始实现一个工具调用代理。
低级实现
from typing import Literal
from langchain_anthropic import ChatAnthropic
from langchain_core.tools import tool
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import END, START, StateGraph, MessagesState
from langgraph.prebuilt import ToolNode
# 定义代理使用的工具
@tool
def search(query: str):
"""调用以浏览网络。"""
# 这只是一个占位符,但不要告诉LLM...
if "sf" in query.lower() or "san francisco" in query.lower():
return "It's 60 degrees and foggy."
return "It's 90 degrees and sunny."
tools = [search]
tool_node = ToolNode(tools)
model = ChatAnthropic(model="claude-3-5-sonnet-latest", temperature=0).bind_tools(tools)
# 定义是否继续的函数
def should_continue(state: MessagesState) -> Literal["tools", END]:
messages = state['messages']
last_message = messages[-1]
# 如果LLM进行工具调用,则我们路由到“tools”节点
if last_message.tool_calls:
return "tools"
# 否则,我们停止(回复用户)
return END
# 定义调用模型的函数
def call_model(state: MessagesState):
messages = state['messages']
response = model.invoke(messages)
# 我们返回一个列表,因为这将添加到现有的列表中
return {"messages": [response]}
# 定义一个新的图
workflow = StateGraph(MessagesState)
# 定义我们将循环的两个节点
workflow.add_node("agent", call_model)
workflow.add_node("tools", tool_node)
# 设置入口点为`agent`
# 这意味着这个节点是第一个被调用的节点
workflow.add_edge(START, "agent")
# 现在添加一个条件边
workflow.add_conditional_edges(
# 首先,我们定义起始节点。我们使用`agent`。
# 这意味着这些边是在`agent`节点被调用后所走的边。
"agent",
# 接下来,我们传入一个函数,该函数将确定下一个被调用的节点。
should_continue,
)
# 现在从`tools`到`agent`添加一个正常边。
# 这意味着在`tools`被调用后,`agent`节点将被调用。
workflow.add_edge("tools", 'agent')
# 初始化内存以在图运行之间保持状态
checkpointer = MemorySaver()
# 最后,我们编译它!
# 这将它编译成一个LangChain Runnable,
# 意味着你可以像使用其他任何Runnable一样使用它。
# 注意,我们在编译图时(可选地)传递了内存
app = workflow.compile(checkpointer=checkpointer)
# 使用代理
final_state = app.invoke(
{"messages": [{"role": "user", "content": "what is the weather in sf"}]},
config={"configurable": {"thread_id": 42}}
)
final_state["messages"][-1].content
初始化模型和工具。
-
我们使用
ChatAnthropic
作为我们的LLM。注意:我们需要确保模型知道它有这些工具可以调用。我们可以通过使用.bind_tools()
方法将LangChain工具转换为OpenAI工具调用格式来实现这一点。 - 我们定义要使用的工具——在这种情况下,是一个搜索工具。创建自己的工具非常简单——请参阅此处的文档了解如何操作这里。
初始化带有状态的图。
- 我们通过传递状态模式(在这种情况下为
MessagesState
)来初始化图(StateGraph
)。 MessagesState
是一个预构建的状态模式,它有一个属性——一个包含LangChainMessage
对象的列表,以及将每个节点更新合并到状态中的逻辑。
定义图节点。
我们需要两个主要节点:agent
节点:负责决定是否采取任何行动。- 调用工具的
tools
节点:如果代理决定采取行动,此节点将执行该行动。
定义入口点和图边。
首先,我们需要设置图执行的入口点——agent
节点。
然后我们定义一个正常边和一个条件边。条件边意味着目的地取决于图状态的内容(MessagesState
)。在这种情况下,目的地在代理(LLM)决定之前是未知的。
- 条件边:在代理被调用后,我们应该:
- a. 如果代理指示采取行动,则运行工具,或者
- b. 结束(回复用户)如果代理没有指示运行工具
- 正常边:在工具被调用后,图应该总是返回到代理以决定下一步做什么。
编译图。
-
当我们编译图时,我们将其转换为一个LangChain
Runnable,
这将自动启用调用
.invoke()
、.stream()
和.batch()
与你的输入。 -
我们还可以(可选地)传递检查点对象以在图运行之间保持状态,并启用内存、
人机交互工作流、时间旅行等。在这种情况下,我们使用
MemorySaver
- 一个简单的内存检查点。
执行图。
- LangGraph将输入消息添加到内部状态,然后将状态传递给入口点节点
"agent"
。 "agent"
节点执行,调用聊天模型。- 聊天模型返回一个
AIMessage
。LangGraph将此添加到状态中。 - 图在以下步骤中循环,直到
AIMessage
中没有更多的tool_calls
:- 如果
AIMessage
中有tool_calls
,"tools"
节点执行 "agent"
节点再次执行并返回AIMessage
- 如果
- 执行进展到特殊的
END
值并输出最终状态。结果,我们得到了一个包含所有聊天消息的列表。
文档¶
- 教程: 通过引导示例学习如何使用LangGraph构建应用。
- 操作指南: 在LangGraph中完成特定任务,从流式处理、添加内存和持久性,到常见设计模式(分支、子图等),如果您想复制并运行特定代码片段,这里是您的首选。
- 概念性指南: 对LangGraph背后的关键概念和原则进行深入解释,如节点、边、状态等。
- API参考: 查看重要类和方法,简单示例说明如何使用图和检查点API,高级预构建组件等。
- LangGraph平台: LangGraph平台是一个商业解决方案,基于开源LangGraph框架,用于在生产环境中部署代理应用。
资源¶
- 使用LangGraph构建: 了解行业领导者如何使用LangGraph来构建功能强大且可以投入生产的AI应用程序。
如何贡献¶
有关如何贡献的更多信息,请参见此处。