前言
在LangGraph的世界里,StateGraph是构建复杂AI工作流的基础组件。它允许我们以可视化、模块化的方式定义和执行一系列操作,非常适合构建Agent、自动化流程和复杂决策系统。本文将通过示例,深入讲解StateGraph的基础概念、核心组件和使用方法,帮助你快速入门LangGraph的核心功能。
StateGraph基础概念
StateGraph是LangGraph中的一个核心概念,它本质上是一个状态图,由以下三个关键部分组成:
- 状态(State):图中流动和共享的数据结构
- 节点(Nodes):执行特定操作的函数
- 边(Edges):定义节点之间的连接和执行顺序
简单来说,StateGraph允许我们将复杂的业务逻辑拆分为独立的节点函数,然后通过边来定义它们之间的执行流程,数据则通过状态在整个流程中传递和共享。
示例代码
python
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
from langchain_core.runnables.graph_mermaid import MermaidDrawMethod
print("======= 示例1: 基本的StateGraph创建和使用 =======")
# 定义状态类型
class BasicState(TypedDict):
value: int
result: str
# 定义节点函数
def add_one(state: BasicState) -> dict:
"""将value加1的节点"""
new_value = state["value"] + 1
return {"value": new_value}
def multiply_by_two(state: BasicState) -> dict:
"""将value乘以2的节点"""
new_value = state["value"] * 2
return {"value": new_value}
def format_result(state: BasicState) -> dict:
"""格式化结果的节点"""
result = f"最终结果: {state['value']}"
return {"result": result}
# 创建StateGraph
basic_graph = StateGraph(BasicState)
# 添加节点
basic_graph.add_node("add_one", add_one)
basic_graph.add_node("multiply_by_two", multiply_by_two)
basic_graph.add_node("format_result", format_result)
# 添加边
basic_graph.add_edge(START, "add_one")
basic_graph.add_edge("add_one", "multiply_by_two")
basic_graph.add_edge("multiply_by_two", "format_result")
basic_graph.add_edge("format_result", END)
# 编译图
compiled_basic_graph = basic_graph.compile()
# 执行图
result = compiled_basic_graph.invoke({"value": 5, "result": ""})
print(f"输入: {{'value': 5, 'result': ''}}")
print(f"输出: {result}")
# 输出图
data = compiled_basic_graph.get_graph().draw_mermaid_png()
with open("basic_stategraph.png", "wb") as f:
f.write(data)
# 示例说明:
# 1. 这个示例展示了如何创建一个简单的顺序执行的StateGraph
# 2. 定义了三个节点函数,依次对输入值进行加1、乘2和格式化结果操作
# 3. 使用add_edge方法定义了节点之间的连接顺序
# 4. 编译图后,可以通过invoke方法执行并传入初始状态

示例解析
1. 导入必要的库
python
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
这部分导入了我们需要的核心组件:
TypedDict
:用于定义状态的数据结构StateGraph
:用于创建状态图START
和END
:图中的特殊节点,表示开始和结束
2. 定义状态类型
python
# 定义状态类型
class BasicState(TypedDict):
value: int
result: str
这里使用TypedDict
定义了一个名为BasicState
的状态类型,它包含两个字段:
value
:整数类型,用于存储计算过程中的数值result
:字符串类型,用于存储最终的格式化结果
状态类型的定义非常重要,它决定了整个图中可以共享和传递哪些数据。在实际应用中,你可以根据业务需求定义更复杂的状态结构。
3. 定义节点函数
python
# 定义节点函数
def add_one(state: BasicState) -> dict:
"""将value加1的节点"""
new_value = state["value"] + 1
return {"value": new_value}
def multiply_by_two(state: BasicState) -> dict:
"""将value乘以2的节点"""
new_value = state["value"] * 2
return {"value": new_value}
def format_result(state: BasicState) -> dict:
"""格式化结果的节点"""
result = f"最终结果: {state['value']}"
return {"result": result}
在这个示例中,我们定义了三个节点函数:
add_one
:接收当前状态,将value
字段加1,并返回更新后的value
multiply_by_two
:接收当前状态,将value
字段乘以2,并返回更新后的value
format_result
:接收当前状态,将value
字段格式化为字符串,并返回结果
节点函数的特点是:
- 接收一个状态参数
- 返回一个字典,表示要更新的状态字段
- 函数专注于完成单一的任务(单一职责原则)
4. 创建和配置StateGraph
python
# 创建StateGraph
basic_graph = StateGraph(BasicState)
# 添加节点
basic_graph.add_node("add_one", add_one)
basic_graph.add_node("multiply_by_two", multiply_by_two)
basic_graph.add_node("format_result", format_result)
# 添加边
basic_graph.add_edge(START, "add_one")
basic_graph.add_edge("add_one", "multiply_by_two")
basic_graph.add_edge("multiply_by_two", "format_result")
basic_graph.add_edge("format_result", END)
这部分代码是整个StateGraph的核心,它完成了以下工作:
- 创建StateGraph实例,并指定状态类型为
BasicState
- 使用
add_node
方法添加三个节点,并为每个节点指定一个唯一名称 - 使用
add_edge
方法定义节点之间的连接关系- 从
START
开始,连接到add_one
节点 - 从
add_one
连接到multiply_by_two
- 从
multiply_by_two
连接到format_result
- 最后从
format_result
连接到END
- 从
这样就形成了一个简单的线性执行流程:START -> add_one -> multiply_by_two -> format_result -> END
5. 编译和执行图
python
# 编译图
compiled_basic_graph = basic_graph.compile()
# 执行图
result = compiled_basic_graph.invoke({"value": 5, "result": ""})
print(f"输入: {{'value': 5, 'result': ''}}")
print(f"输出: {result}")
在创建和配置完图后,我们需要:
- 使用
compile()
方法编译图,这一步会验证图的结构并准备执行环境 - 使用
invoke()
方法执行图,并传入初始状态- 初始状态包含
value: 5
和result: ""
- 初始状态包含
执行结果会打印在控制台上,显示输入和最终的输出状态。对于这个例子,输入值5会先加1变成6,然后乘以2变成12,最后格式化为"最终结果: 12"。
6. 图的可视化
python
# 输出图
data = compiled_basic_graph.get_graph().draw_mermaid_png()
with open("basic_stategraph.png", "wb") as f:
f.write(data)
LangGraph提供了一个非常有用的功能,可以将图的结构可视化为图片:
- 使用
get_graph().draw_mermaid_png()
生成图的PNG图像数据 - 将图像数据写入文件
basic_stategraph.png
生成的图片会直观地展示图中各个节点和它们之间的连接关系,对于理解和调试复杂的图结构非常有帮助。
执行流程分析
让我们详细分析一下整个图的执行流程:
- 初始化 :
invoke()
方法接收初始状态{"value": 5, "result": ""}
- 执行
add_one
节点 :从START
开始,首先执行add_one
节点,将value
从5更新为6 - 执行
multiply_by_two
节点 :add_one
执行完成后,状态传递给multiply_by_two
节点,将value
从6更新为12 - 执行
format_result
节点 :multiply_by_two
执行完成后,状态传递给format_result
节点,生成结果字符串 - 结束 :
format_result
执行完成后,到达END
节点,执行结束并返回最终状态
整个过程中,状态在各个节点之间流动和更新,每个节点专注于自己的任务,符合模块化和关注点分离的设计原则。
为什么使用StateGraph?
通过这个简单的示例,我们可以看到StateGraph的几个重要优势:
- 模块化:将复杂逻辑拆分为独立的节点函数
- 可视化:可以直观地看到整个流程的结构
- 灵活性:可以轻松地修改、添加或删除节点和边
- 可重用性:节点函数可以在不同的图中重用
- 可扩展性:可以构建更复杂的图结构,如条件分支、循环等
总结
通过本文的学习,我们了解了LangGraph中StateGraph的基础概念、核心组件和使用方法。StateGraph提供了一种强大而灵活的方式来构建和执行复杂的工作流程,它的模块化设计和可视化特性使得复杂逻辑变得更加清晰和易于维护。
这个简单的示例只是StateGraph功能的冰山一角,在后续的教程中,我们将学习更多高级特性,如条件分支、并行执行、状态持久化等,帮助你构建更加强大和灵活的AI应用。