LangGraph从新手到老师傅 - 3 - StateGraph基础入门

前言

在LangGraph的世界里,StateGraph是构建复杂AI工作流的基础组件。它允许我们以可视化、模块化的方式定义和执行一系列操作,非常适合构建Agent、自动化流程和复杂决策系统。本文将通过示例,深入讲解StateGraph的基础概念、核心组件和使用方法,帮助你快速入门LangGraph的核心功能。

StateGraph基础概念

StateGraph是LangGraph中的一个核心概念,它本质上是一个状态图,由以下三个关键部分组成:

  1. 状态(State):图中流动和共享的数据结构
  2. 节点(Nodes):执行特定操作的函数
  3. 边(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:用于创建状态图
  • STARTEND:图中的特殊节点,表示开始和结束

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的核心,它完成了以下工作:

  1. 创建StateGraph实例,并指定状态类型为BasicState
  2. 使用add_node方法添加三个节点,并为每个节点指定一个唯一名称
  3. 使用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}")

在创建和配置完图后,我们需要:

  1. 使用compile()方法编译图,这一步会验证图的结构并准备执行环境
  2. 使用invoke()方法执行图,并传入初始状态
    • 初始状态包含value: 5result: ""

执行结果会打印在控制台上,显示输入和最终的输出状态。对于这个例子,输入值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提供了一个非常有用的功能,可以将图的结构可视化为图片:

  1. 使用get_graph().draw_mermaid_png()生成图的PNG图像数据
  2. 将图像数据写入文件basic_stategraph.png

生成的图片会直观地展示图中各个节点和它们之间的连接关系,对于理解和调试复杂的图结构非常有帮助。

执行流程分析

让我们详细分析一下整个图的执行流程:

  1. 初始化invoke()方法接收初始状态{"value": 5, "result": ""}
  2. 执行add_one节点 :从START开始,首先执行add_one节点,将value从5更新为6
  3. 执行multiply_by_two节点add_one执行完成后,状态传递给multiply_by_two节点,将value从6更新为12
  4. 执行format_result节点multiply_by_two执行完成后,状态传递给format_result节点,生成结果字符串
  5. 结束format_result执行完成后,到达END节点,执行结束并返回最终状态

整个过程中,状态在各个节点之间流动和更新,每个节点专注于自己的任务,符合模块化和关注点分离的设计原则。

为什么使用StateGraph?

通过这个简单的示例,我们可以看到StateGraph的几个重要优势:

  1. 模块化:将复杂逻辑拆分为独立的节点函数
  2. 可视化:可以直观地看到整个流程的结构
  3. 灵活性:可以轻松地修改、添加或删除节点和边
  4. 可重用性:节点函数可以在不同的图中重用
  5. 可扩展性:可以构建更复杂的图结构,如条件分支、循环等

总结

通过本文的学习,我们了解了LangGraph中StateGraph的基础概念、核心组件和使用方法。StateGraph提供了一种强大而灵活的方式来构建和执行复杂的工作流程,它的模块化设计和可视化特性使得复杂逻辑变得更加清晰和易于维护。

这个简单的示例只是StateGraph功能的冰山一角,在后续的教程中,我们将学习更多高级特性,如条件分支、并行执行、状态持久化等,帮助你构建更加强大和灵活的AI应用。

扩展阅读

相关推荐
洛阳泰山3 小时前
MaxKB4j智能体平台 Docker Compose 快速部署教程
java·人工智能·后端
感哥3 小时前
Django用户认证权限
python·django
思辨共悟3 小时前
python数据分析 与spark、hive数据分析对比
python·数据分析·spark
Christo33 小时前
TFS-2005《A Possibilistic Fuzzy c-Means Clustering Algorithm》
人工智能·算法·机器学习
aiden:)3 小时前
Selenium WebUI 自动化“避坑”指南——从常用 API 到 10 大高频问题
开发语言·前端·javascript·python·selenium
Lenskit3 小时前
使用pyspark对上百亿行的hive表生成稀疏向量
python·spark-ml·spark
掘金一周3 小时前
还在用html2canvas?介绍一个比它快100倍的截图神器!| 掘金一周 9.4
前端·人工智能
AI企微观察3 小时前
用了企业微信 AI 半年,这 5 个功能让我彻底告别重复劳动
人工智能·企业微信
岛屿旅人3 小时前
涉私数据安全与可控匿名化利用机制研究(下)
网络·人工智能·安全·web安全·生成对抗网络