前言
本系列前五篇文章:
- 深入浅出LangGraph AI Agent智能体开发教程(一)---全面认识LangGraph
- 深入浅出LangGraph AI Agent智能体开发教程(二)---LangGraph预构建图API快速创建Agent
- 深入浅出LangGraph AI Agent智能体开发教程(三)---LangGraph工具调用实战
- 深入浅出LangGraph AI Agent智能体开发教程(四)---LangGraph全生态开发工具使用与智能体部署
- 深入浅出LangGraph AI Agent智能体开发教程(五)---LangGraph 数据分析助手智能体项目实战
通过以上文章的分享我们学习了LangGraph高级预构建图API create_react_agent
的使用技巧,掌握了LangGraph Agent开发全生态核心工具的开发方法。从本期分享开始我们就深入到LangGraph底层API进行学习。
本系列分享是笔者结合自己学习工作中使用LangChain&LangGraph经验倾心编写的,力求帮助大家体系化快速掌握LangChain&LangGraph AI Agent智能体开发的技能!笔者的LangChain系列教程暂时更完,后面也会实时补充工作实践中的额外知识点,建议大家在学习LangGraph分享前先学习LangChain的基本使用技巧。大家感兴趣可以关注笔者掘金账号和系列专栏。更可关注笔者同名微信公众号: 大模型真好玩 , 每期分享涉及的代码均可在公众号私信: LangChain智能体开发获得。
一、为什么要学习LangGraph底层API?
在整个系列分享的一开始我们绘制过如下的LangGraph核心设计的层级结构图。
第一层 是预构建图的API,也就是预定义的图结构图模板,比如我们一直使用的create_react_agent
表示使用一行命令创建基于预构建ReACT图的智能体,通过它我们可以方便的接入外部工具函数或者MCP服务。其它的图结构模板API与create_react_agent
类似所以我们没有去深入讲解。
第二层是一些AgentNode API,有时我们并不会简单的使用ReACT等图模板,往往还需要添加一些组件。AgentNode API就是方便我们快速封装节点并引入图结构的API,例如一些规定模型如何调度,工具如何封装的节点API。
第三层是最底层的API,借助底层API,开发者可以更加灵活的完成各类智能体的开发,将任意的函数,大模型都编排成节点和边封装到图结构中。在很多场景下,比如人在环中(必须有人类参与协助的Agent结构,例如一些模型输出结果后要经过人类审核才能生成最终答案)或者搭建多智能体协作系统时,必须使用更加底层的图结构API才能完成,因此这也使得掌握底层API是目前大模型开发人员进阶的必备技巧。

这里也要说明底层API学习起来还是有些难度(可以想象一个图既有节点又有边,还是一个有向有环图,内部还有条件判别、循环等结构,肯定不是一行create_react_agent
命令能完成的)
二、LangGraph图结构对象创建方法与核心语法
2.1 LangGraph图结构概念说明
在介绍API之前,我们先梳理一下LangGraph 底层 API的基本语法与设计理念,LangGraph的宗旨是创建一个图结构,该图结构包含大模型、外部工具等,通过点线间的连接构成灵活的处理链路。基于该宗旨,LangGraph定义了一套由点、边、状态组成的有向有环的结构图语法。
节点(Nodes)
任何可执行的功能包括大语言模型API,工具,甚至Agent都可以作为LangGraph图的点。
边(Edges)
边通常负责传递数据,也有一些边负责进行逻辑控制,例如if-else的判断和选择,从而让整个图状结构更加丰富。
State(状态)
LangGraph通过组合点和边去创建复杂的循环工作流程,节点产生的消息通过边传递给别的节点从而形成通路。为了维持节点和边之间的消息传递,LangGraph势必要对所有的消息进行统一管理,这就引出了概念"State(状态)"。在LangGraph构建的流程中,每次执行都会启动一个状态,图中的节点在处理时会传递和修改该状态。这个状态不仅仅是一组静态数据,而是由每个节点的输出动态更新,然后影响循环内的后续操作,确保图通路顺畅。

2.2 手动创建图流程
具备理论基础后接下来我们通过代码实战来理解LangGraph的设计原理。为了方便大家理解,我们先在不接入大模型的情况下构建一个加减法图工作流。
- LangGraph图结构构建的第一步是创建
State
, 构建state的方法非常简单,我们可以将图的状态设计为一个字典,用于在不同节点间共享和修改数据,然后使用StateGraph
类进行图的实例化。代码如下, 需要注意的是builder
也是后面要用到的图构建器(Graph Builder)对象,用于逐步添加节点、边、控制流逻辑,最终编译成可执行的图。
python
from langgraph.graph import StateGraph
# 创建一个字典类型的State
builder = StateGraph(dict)
- 接下来使用代码定义图结构的两个节点,对LangGraph来说,图结构节点的类型包括很多种,可以是大语言模型,工具函数等等,简而言之可以顺序式处理数据的节点都可以作为图节点。我们这里自定义两个简单函数:一个是加法函数接收当前State并将其中的x值加1,另一个是减法函数接收当前State并将其中的x值减2,代码如下:
python
def addition(state):
print(f'加法节点收到的初始值:{state}')
return {"x": state["x"] + 1}
def subtraction(state):
print(f'减法节点收到的初始值:{state}')
return {"x": state["x"] - 2}
- 接下来进行图结构的设计,添加名为
addition
和subtraction
的节点,并关联到两个函数上。 对于LangGraph来说有两个名为START
和END
的特殊节点,这两个节点没有明确功能,只是起到标识开始和结束的作用。
python
from langgraph.graph import START, END
# 向图中添加两个节点
builder.add_node("addition", addition)
builder.add_node("subtraction", subtraction)
# 构建节点之间的边
builder.add_edge(START, "addition")
builder.add_edge("addition", "substraction")
builder.add_edge("subtraction", END)
上述的代码语义非常明确,我们可以构建出如下图:

我们也可以通过builder.nodes
和builder.edges
查看图的节点和边的相关情况:

- 执行图的编译,需要通过调用
compile()
方法将编排后的builder
编译成一个可执行的图,添加如下代码:
python
graph = builder.compile()
编译后的图也支持可视化效果展示,笔者喜欢ascii
风格的展示效果。我们首先在anaconda
虚拟环境langgraphenv
中执行pip install grandalf
安装依赖环境,然后在代码中添加 graph.get_graph().print_ascii()
打印字符风格的图,效果如下:


2.3 LangGraph图对象运行
当我们通过builder.compile()
方法编译图后,编译后的graph
对象提供了invoke
方法,该方法用于启动图的执行。在图执行前我们需要通过invoke
方法传递一个初始状态,这个状态作为图执行的起始输入:
python
initial_state={"x": 10}
result = graph.invoke(initial_state)
print('最后的结果:', result)

可以看到最后的输出和我们的预期相符合,x初始值为10, 首先经过加法节点变为11后传递给减法节点,减法节点减去2后变为9输出为最终结果。
三、借助Pydantic构建稳定的State
以上的写法虽然灵活但有一个致命缺陷,我们的State状态缺乏预定义的模式,节点可以在没有严格类型约束的情况下自由地读取和写入状态,这样的灵活性虽然有利于动态数据处理,但这也要求开发者在整个图的执行过程中保持对键和值的一致性管理(例如我们在加减法函数中返回的都是只包含键值对x的字典对象)。因为在任何节点中尝试访问State中不存在的键,会直接中断整个图的运行状态。
3.1 Pydantic基本使用方法
通过集成pydantic中的BaseModel
抽象类来定义状态State, 定义后的状态可以对键值对属性进行自动校验,我们编写如下代码,对x和y键定义不同的类型,错误的类型会报错。
python
from pydantic import BaseModel
class MyState(BaseModel):
x: int
y: str = "default" # 设置默认值
# 自动校验
state = MyState(x=1)
print(state.x) # 输出 1
print(state.y) # 输出 default
# 错误类型会报错
state = MyState(x="abc")

3.2 Pydantic应用于StateGraph
下面我们使用Pydantic
对第2节的代码进行修改,采用如下方法编写的代码可以对状态键内容和属性进行约束,代码健壮性更强。
python
from pydantic import BaseModel
from langgraph.graph import StateGraph, START, END
# 1. 定义结构化状态模型
class CalcState(BaseModel):
x: int
# 2. 定义节点函数,接收并返回 CalcState
def addition(state: CalcState) -> CalcState:
print(f"[addition] 初始状态: {state}")
return CalcState(x=state.x + 1)
def subtraction(state: CalcState) -> CalcState:
print(f"[subtraction] 接收到状态: {state}")
return CalcState(x=state.x - 2)
# 3. 构建图
builder = StateGraph(CalcState)
builder.add_node("addition", addition)
builder.add_node("subtraction", subtraction)
builder.add_edge(START, "addition")
builder.add_edge("addition", "subtraction")
builder.add_edge("subtraction", END)
graph = builder.compile()
# 4. 执行图:传入结构化状态对象
initial_state = CalcState(x=10)
final_state = graph.invoke(initial_state)
# 5. 打印最终结果
print("\n[最终结果] ->", final_state)

四、总结
本期内容分享了LangGraph底层自定义图API点、边、状态State的设计理念,并通过简单的加减法串联结构图演示了LangGraph底层API的使用方法,同时介绍了如何使用Pydantic约束State使代码更健壮的基本方法。当然我们使用LangGraph构建的图不可能仅仅是串行关系这么简单,下期分享我们将介绍如何使用底层API构建条件判断图和循环结构图,大家敬请期待~
本系列分享预计会有20节左右的规模,保证大家看完一定能够掌握LangChain&LangGraph的开发能力,大家感兴趣可关注笔者掘金账号和专栏,更可关注笔者的同名微信公众号:大模型真好玩 , 本系列分享的全部代码均可在微信公众号私信笔者: LangChain智能体开发 免费获得。