LangGraph 的出现
在 LangChain 框架中,智能体(Agent)从数据结构的角度来看等同于一个有向无环图。这意味着传统的 Chain 在推理过程中无法被循环调用。尽管 AgentExecutor(代理执行器)支持循环机制,但它缺乏精确的控制能力,时常导致失控并陷入死循环。
使用代理执行器实现循环调用大语言模型(LLM)的能力,其调用过程主要有两步:
- 通过大模型来决定采取什么行动、使用什么工具,或对用户输出响应。
- 执行步骤 1 中的行动,并将结果继续交给大模型进行决策。
AgentExecutor 存在的问题是决策过程隐藏在背后,过于黑盒,缺乏更精细的控制能力,这在构建复杂的 Agent 时受到限制:
- 难以控制工具的使用顺序。
- 在执行过程中添加人机交互较为困难。
- 灵活更换 Prompt 或背后的 LLM 不够便捷。
在 LangChain 中,简单的链不具备循环能力,而 AgentExecutor 调用 Agent 又过于黑盒,因此需要一个具备更精细控制能力的框架来支持复杂场景的 LLM 应用。LangGraph 的出现标志着 LangChain 进入多智能体框架领域。LangGraph 基于图论运作,提供了一种状态机技术,可驱动循环代理调用,实现有向有环图。因此,LangGraph 有三个关键元素:
StateGraph:状态图
这是 LangChain 的一个类,表示图的数据结构并反映其状态。节点会更新图的状态。
Node:节点
图中关键元素之一。每个 LangGraph 节点都有一个名称值,可以是 LangChain 表达式中的函数或者可运行项(Runnable)。每个节点接收一个字典类型的数据,返回具有相同结构的更新状态。有一个名为 END 的特殊节点,用于识别状态机的结束状态。
Edge:边缘
边维系节点之间的关系,分为三种类型:开始边(没有上游节点)、普通边和条件边。
- 普通边:定义上游节点应始终调用的下游节点。
- 条件边:通过函数(路由器)来确定下游节点。条件边需要三个元素:
- 上游节点:边的起点,表示转换的起点。
- 路由函数:此函数根据返回值有条件地确定应进行转换的下游节点。
- 状态映射:根据路由函数的返回值,指定下游节点。它将路由函数可能的返回值与相应的下游节点相关联。
构建 LangGraph 实例
LangGraph 的状态
类似于状态机(State Machine),由一组状态(State)和状态之间的转换(Transition)组成,用于表示系统在不同状态之间的转换和响应事件的行为。
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph import StateGraph
from langgraph.graph.message import add_messages
class State(TypedDict):
# Messages have the type "list". The `add_messages` function
# in the annotation defines how this state key should be updated
messages: Annotated[, add_messages]
graph_builder = StateGraph(State)


