十、LangGraph能力详解(2)LangGraph入门教程,构建AI工作流

目录

[1. 编码前的版本说明](#1. 编码前的版本说明)

[2. 【案例一】智能快递配送系统](#2. 【案例一】智能快递配送系统)

[2.1 Graph API 编码思路](#2.1 Graph API 编码思路)

[2.2 代码实现](#2.2 代码实现)

[2.2.1 步骤1:定义 State,设置快递的"包裹信息"](#2.2.1 步骤1:定义 State,设置快递的"包裹信息")

[2.2.1.1 【知识点】State 更新机制:Reducers](#2.2.1.1 【知识点】State 更新机制:Reducers)

[2.2.2 步骤2:定义 StateGraph 图,成立快递公司](#2.2.2 步骤2:定义 StateGraph 图,成立快递公司)

[2.2.3 步骤3:定义 Nodes,创建配送站点](#2.2.3 步骤3:定义 Nodes,创建配送站点)

[2.2.4 步骤4:添加 Nodes,建设配送站点](#2.2.4 步骤4:添加 Nodes,建设配送站点)

[2.2.5 步骤5:添加 Edges,规划运输路线](#2.2.5 步骤5:添加 Edges,规划运输路线)

代码(总):


1. 编码前的版本说明

LangGraph 放弃了对 Python 3.9 的支持,所有 LangChain 包现在都需要 Python 3.10 或更高版本。. 使用 python --version 查看 Python 版本。如低于3.9,需要重装。

2. 【案例一】智能快递配送系统

2.1 Graph API 编码思路

构建 Graph 图,首先需要【定义状态】,然后【定义并添加节点和边】,最后【编译】它。编译提供 了对图形结构的一些基本检查(没有孤立节点等)

LangGraph 所谓的"编译" 与 传统意义上的语言编译完全不同,LangGraph 编译本质是在运行时动 态构建和验证一个复杂的图,而非翻译代码

C++的编译是"完整编译"或"静态编译"的典范。 它追求在程序运行之前,就将所有代码"解 决"完毕,生成一个独立、高效、可直接被操作系统调用的"成品"。它比 Java 的编译更彻底(直接 到机器码,而非中间码),也更底层(紧密绑定操作系统和CPU架构)。 "编译"对比表格:

特性 LangGraph 的编译 Java 的编译 C++ 的编译
本质 配置组装与验证 语言翻译与转换(到中间码/字节码) 语言翻译与转换(到本地机器码)
发生阶段 应用程序运行时(初始化阶段) 应用程序开发时(构建阶段) 应用程序开发时(构建阶段)
主要目的 1. 构建可执行的工作流对象 2. 进行结构验证 1. 将高级语言转为低级语言(字节码) 2. 进行语法和深度语义检查 1. 将高级语言转为特定平台的本地机器码 2. 进行彻底的语法、语义检查与优化 3. 链接所有模块,生成完整的可执行文件

2.2 代码实现

先明确流程,敲定好状态,节点,边

2.2.1 步骤1:定义 State,设置快递的"包裹信息"

定义图时要做的第一件事是定义图的 状态 。**状态 将是图中所有 节点 和 边 的输入,**可以是 TypedDict 或 Pydantic 模型( Pydantic 的性能不如 TypedDict )。如下所示:

python 复制代码
import operator
from typing import TypedDict, Annotated

from langgraph.constants import END
from langgraph.constants import START
from langgraph.graph import StateGraph
#1、状态定义(贯穿整个图)
class PackageState(TypedDict):
    #input:str
    #output:str

    #包裹状态:
    #包裹id
    package_id:str
    #包裹始发站
    origin:str
    #包裹终点站
    destination:str
    #next

    #配送状态:
    #状态("待揽收","已揽收","运输中","派送中","已签收")
    status:str
    #流转历史 list
    #知识点:
    #history:list[str]   #覆盖耿欣
    history:Annotated[list[str],operator.add]   #最追加更新
    #总历程
    total_distance:Annotated[int,operator.add]

    #配送详情:
    #("普通","加急")
    priority:str

2.2.1.1 【知识点】State 更新机制:Reducers

状态 支持更新的关键是 Reducers。在示例中,我们使用 Annotated 类型为 history 和 total_distance 指定了一个 reducer 函数 ( operator.add )。这定义了如何更新包裹信 息,特别是当多个站点都要记录信息时。当状态更新时,新的值会追加到现有值中,而不是替换。如 下所示:

python 复制代码
 #配送状态:
    #状态("待揽收","已揽收","运输中","派送中","已签收")
    status:str
    #流转历史 list
    #知识点:
    #history:list[str]   #覆盖耿欣
    history:Annotated[list[str],operator.add]   #最追加更新
    #总历程
    total_distance:Annotated[int,operator.add]

2.2.2 步骤2:定义 StateGraph 图,成立快递公司

StateGraph 是一个有状态图计算框架,它基于有向图(Directed Graph) 模型构建,专门设计用于处 理多步骤、有状态的工作流程。 **StateGraph 用来将复杂的工作流程可视化、模块化,让开发者能够像设计快递配送网络一样设计软件 系统。**通过这种思维方式,即使是复杂的多步骤 AI 应用也变得清晰可控。 我们需要使用 langgraph.graph.state.StateGraph 来定义。 StateGraph 仅是一个构建 器类,可以使用 State 来构建。如下所示:

python 复制代码
#2、定义图(依赖状态)
delivery = StateGraph(PackageState)

注意,这里仅是构建出 StateGraph ,还无法直接用于执行。

2.2.3 步骤3:定义 Nodes,创建配送站点

接着我们可以定义各个配送站点(节点)。在 LangGraph 中, 节点 就是一个 Python 函数(同步或 异步)。注意

• 节点 接收 状态 作为参数。

• 节点 不需要返回整个 状态 模式,只需一个更新。 如下所示:

python 复制代码
#3、节点定义(函数)
#输入:状态
#输出:状态的更新
#节点之间使用state进行通信
# def test(state:PackageState):
#     return {
#         "history":["揽收站"],
#         "total_distance":500
#     }

#揽收站节点
def receive_package(state:PackageState):
    """揽收站"""
    # 进行状态扭转
    # 状态值获取
    print("---执行到揽收站节点")
    origin=state["origin"]
    return {
        "status":"已揽收",
        "history":[f"在{origin}揽收"]
    }

#分拣中心节点:根据目的地进行分拣
def sort_package(state:PackageState):
    """分拣中心"""
    print("---执行到分拣中心节点")
    destination=state["destination"]

    if"北京" in destination:
        next="北京分拣中心"
    elif"上海" in destination:
        next="上海分拣中心"
    else:
        next="其他分拣中心"
    return {
        "status": "已分拣",
        "history": [f"将分拣至{next}"]
    }

#派送站节点
def final_delivery(state:PackageState):
    """派送站"""
    print("---执行到派送站节点")
    return {
        "status":"已签收",
        "history":[f"已送达{state['destination']}"]
    }
#标准配送节点
def standard_delivery(state:PackageState):
    """标准配送"""
    print("---执行到标准配送节点")

    return{
        "status": "运输中",
        "history": ["标准陆运"],
        "total_distance": 500
    }

#加急配送节点
def express_delivery(state:PackageState):
    """加急配送"""
    print("---执行到加急配送节点")

    return {
        "status": "加急运输",
        "history": ["空运加急"],
        "total_distance": 800
    }

2.2.4 步骤4:添加 Nodes,建设配送站点

接下来,我们需要将各节点,组织进图中,即添加节点到 StateGraph 中。可以使用 add_node() 将新节点添加到 StateGraph 。 add_node() 方法常用参数说明:

参数名 类型 描述
node 字符串 或 StateNode 对象 作用 :指定节点要运行的函数或可执行对象。 使用方式 : - 如果传入字符串,该字符串将作为节点名称,此时会使用 action 参数作为实际的执行函数。 - 如果传入 StateNode 对象,则直接使用该对象定义节点。
action StateNode 对象 或 None(默认值) 作用 :定义与节点关联的动作(执行逻辑)。 使用方式 : - 当 node 参数是字符串时,action 会作为该节点的实际执行函数。 - 当 node 参数已经是 StateNode 对象时,action 通常为 None。

示例:

python 复制代码
#4、添加节点
delivery.add_node("揽收站",receive_package)
delivery.add_node("分拣中心",sort_package)
delivery.add_node("派送站",final_delivery)
delivery.add_node("标准配送",standard_delivery)
delivery.add_node("加急配送",express_delivery)

2.2.5 步骤5:添加 Edges,规划运输路线

各节点(站点)准备好后,则需要为快递运输规划路线。如:

实际上,这就是为 图 定义 边 。边有几种关键类型:

• 普通边/固定边(Normal Edges):直接从一个节点转到下一个节点。

• 条件边(Conditional Edges):调用函数来确定下一步要转到哪个节点。 例如,设置最简单运输路线:快递由揽收站接收,下一站固定为分拣中心,最后到派送中进行派送。 这就是固定边,如下图所示:

再例如,我们可以根据以下条件,判断快递如何运输:

• 包裹是加急件 → 走空运线路

• 包裹不是加急件 → 走标准线路 这就是条件边,如下图所示:

要说明的是,在 LangGraph 中:

• START 节点:是一个特殊节点,表示将用户输入发送到图形的节点。引用此节点的主要目的是确 定应该首先调用哪些节点。

• END 节点:是一个表示终端节点的特殊节点。当想要指示哪些边在完成后没有后续动作时,将引 用此节点。

• 条件入口点(Conditional Entry Point):调用一个函数来确定在用户输入到达时首先调用哪个节 点。

1)使用 add_edge() 向图中添加从开始节点(或起始节点列表)到结束节点的固定边。 add_edge() 方法常用参数说明:

2)使用 add_conditional_edges() 向图中添加 从起始节点到任意数量的目标节点 的条件边。 add_conditional_edges() 方法常用参数说明:

开始实现代码:

这里的路由方法有两种写法哈:

cpp 复制代码
#5、添加边
delivery.add_edge(START,"揽收站")  #固定边
delivery.add_edge("揽收站","分拣中心")

#路由方法
# def select_delivery(state:PackageState):
#     priority=state["priority"]
#     if priority=="加急":
#         return "加急配送"  #返回的是字符串,不是节点
#     else:
#         return "标准配送"  #返回的是字符串,不是节点
#
# #添加条边(需要我们先写一个方法,来对后续节点进行映射)
# delivery.add_conditional_edges(
#     "分拣中心", #条件的起始节点
#     select_delivery, #path:确定下一个节点可调节对象
#     ["加急配送","标准配送"] #path_map:节点名称(这里的这种写法要求路由字符串要与节点名称一致)
# )
def select_delivery(state:PackageState):
    priority=state["priority"]
    if priority=="加急":
        return "备注加急"  #返回的是字符串,不是节点
    else:                 #这里的两个字符串可以随便给,此时需要在后面的添加边里面给出一个map映射,映射后续的节点名称
        return "无备注"  #返回的是字符串,不是节点

#添加条边(需要我们先写一个方法,来对后续节点进行映射)
delivery.add_conditional_edges(
    "分拣中心", #条件的起始节点
    select_delivery, #path:确定下一个节点可调节对象
    {
        "备注加急":"加急配送",
        "无备注":"标准配送"
    } #path_map:节点名称(对后续节点的映射)
)
delivery.add_edge("加急配送","派送站")
delivery.add_edge("标准配送","派送站")
delivery.add_edge("派送站",END)

2.2.6 步骤6:StateGraph 图编译,从公司创建到运行

在步骤2中,我们仅是构建出 StateGraph ,还无法直接用于执行。LangGraph 要求:必须先编译 图,然后才能使用它。编译提供了对图结构的一些基本检查,这会验证:

• 从 START 到所有节点的可达性

• 从所有节点到 END 的可达性

• 没有孤立节点或死循环

使用compile() 方法即可编译图。 该方法将StateGraph 编译为 CompiledStateGraph 对 象 。**编译后的图实现了 Runnable 接口,可以异步调用、流式传输、批处理和运行。**代码如下:

python 复制代码
#6、编译图(这一步是系统来编译检查,光是人工检查还不够)
delivery_system = delivery.compile()

#7、执行图(输入初始状态,输出最终状态)
test_packages = [
    {
    "package_id": "P001",
    "origin": "北京",
    "destination": "上海",
    "priority": "普通",
    "history": [],
    "total_distance": 0
    },
    {
    "package_id": "P002",
    "origin": "广州",
    "destination": "乌鲁木齐",
    "priority": "加急",
    "history": [],
    "total_distance": 0
    }
]
for package in test_packages:
    print(f"\n配送包裹: {package['package_id']}")
    #执行图,发一次快递
    result = delivery_system.invoke(package)
    print("最终状态:", result["status"])
    print("配送历史:", result["history"])
    print("总里程:", result["total_distance"])

运行:

到此,我们已经构建出了一个图式的智能快递配送系统,来理解 LangGraph 图的基本能力与用法!

回顾一下:

  1. State = 包裹信息卡(记录所有状态)

  2. Nodes = 配送站点(执行具体操作)

  3. Edges = 运输路线(控制流转顺序)

  4. Reducers = 信息更新规则(如何记录变更)

  5. 编译 = 从路线图到运营系统的转换

代码(总):

python 复制代码
import operator
from typing import TypedDict, Annotated

from langgraph.constants import END
from langgraph.constants import START
from langgraph.graph import StateGraph
#1、状态定义(贯穿整个图)
class PackageState(TypedDict):
    #input:str
    #output:str

    #包裹状态:
    #包裹id
    package_id:str
    #包裹始发站
    origin:str
    #包裹终点站
    destination:str
    #next

    #配送状态:
    #状态("待揽收","已揽收","运输中","派送中","已签收")
    status:str
    #流转历史 list
    #知识点:
    #history:list[str]   #覆盖耿欣
    history:Annotated[list[str],operator.add]   #最追加更新
    #总历程
    total_distance:Annotated[int,operator.add]

    #配送详情:
    #("普通","加急")
    priority:str

#2、定义图(依赖状态)
delivery = StateGraph(PackageState)


#3、节点定义(函数)
#输入:状态
#输出:状态的更新
#节点之间使用state进行通信
# def test(state:PackageState):
#     return {
#         "history":["揽收站"],
#         "total_distance":500
#     }

#揽收站节点
def receive_package(state:PackageState):
    """揽收站"""
    # 进行状态扭转
    # 状态值获取
    print("---执行到揽收站节点")
    origin=state["origin"]
    return {
        "status":"已揽收",
        "history":[f"在{origin}揽收"]
    }

#分拣中心节点:根据目的地进行分拣
def sort_package(state:PackageState):
    """分拣中心"""
    print("---执行到分拣中心节点")
    destination=state["destination"]

    if"北京" in destination:
        next="北京分拣中心"
    elif"上海" in destination:
        next="上海分拣中心"
    else:
        next="其他分拣中心"
    return {
        "status": "已分拣",
        "history": [f"将分拣至{next}"]
    }

#派送站节点
def final_delivery(state:PackageState):
    """派送站"""
    print("---执行到派送站节点")
    return {
        "status":"已签收",
        "history":[f"已送达{state['destination']}"]
    }
#标准配送节点
def standard_delivery(state:PackageState):
    """标准配送"""
    print("---执行到标准配送节点")

    return{
        "status": "运输中",
        "history": ["标准陆运"],
        "total_distance": 500
    }

#加急配送节点
def express_delivery(state:PackageState):
    """加急配送"""
    print("---执行到加急配送节点")

    return {
        "status": "加急运输",
        "history": ["空运加急"],
        "total_distance": 800
    }


#4、添加节点
delivery.add_node("揽收站",receive_package)
delivery.add_node("分拣中心",sort_package)
delivery.add_node("派送站",final_delivery)
delivery.add_node("标准配送",standard_delivery)
delivery.add_node("加急配送",express_delivery)


#5、添加边
delivery.add_edge(START,"揽收站")  #固定边
delivery.add_edge("揽收站","分拣中心")

#路由方法
# def select_delivery(state:PackageState):
#     priority=state["priority"]
#     if priority=="加急":
#         return "加急配送"  #返回的是字符串,不是节点
#     else:
#         return "标准配送"  #返回的是字符串,不是节点
#
# #添加条边(需要我们先写一个方法,来对后续节点进行映射)
# delivery.add_conditional_edges(
#     "分拣中心", #条件的起始节点
#     select_delivery, #path:确定下一个节点可调节对象
#     ["加急配送","标准配送"] #path_map:节点名称(这里的这种写法要求路由字符串要与节点名称一致)
# )
def select_delivery(state:PackageState):
    priority=state["priority"]
    if priority=="加急":
        return "备注加急"  #返回的是字符串,不是节点
    else:                 #这里的两个字符串可以随便给,此时需要在后面的添加边里面给出一个map映射,映射后续的节点名称
        return "无备注"  #返回的是字符串,不是节点

#添加边(需要我们先写一个方法,来对后续节点进行映射)
delivery.add_conditional_edges(
    "分拣中心", #条件的起始节点
    select_delivery, #path:确定下一个节点可调节对象
    {
        "备注加急":"加急配送",
        "无备注":"标准配送"
    } #path_map:节点名称(对后续节点的映射)
)
delivery.add_edge("加急配送","派送站")
delivery.add_edge("标准配送","派送站")
delivery.add_edge("派送站",END)

#6、编译图(这一步是系统来编译检查,光是人工检查还不够)
delivery_system = delivery.compile()

#7、执行图(输入初始状态,输出最终状态)
test_packages = [
    {
    "package_id": "P001",
    "origin": "北京",
    "destination": "上海",
    "priority": "普通",
    "history": [],
    "total_distance": 0
    },
    {
    "package_id": "P002",
    "origin": "广州",
    "destination": "乌鲁木齐",
    "priority": "加急",
    "history": [],
    "total_distance": 0
    }
]
for package in test_packages:
    print(f"\n配送包裹: {package['package_id']}")
    #执行图,发一次快递
    result = delivery_system.invoke(package)
    print("最终状态:", result["status"])
    print("配送历史:", result["history"])
    print("总里程:", result["total_distance"])
相关推荐
xiami_world3 小时前
Multi-Agent架构选型实战:5个主流平台工具深度横评
人工智能·ui·ai·agi·用户界面
码农阿强3 小时前
PixVerse 全系列视频生成模型技术架构详解 + Python 基于 StartAPI.top 接口实战调用
python·ai·架构·音视频·ai编程
marsh02064 小时前
59 openclaw与边缘计算:低延迟分布式计算方案
人工智能·ai·边缘计算·技术美术
格桑阿sir4 小时前
16-大模型智能体开发工程师:全面学习Agent Skill系统
ai·工具·原理·技能·智能体·skill·skillhub
Dragon Wu4 小时前
AI视频创作笔记(二)分镜、运镜、角度
ai
多年小白5 小时前
AI 日报 - 2026年6月3日
科技·ai
深蓝电商API5 小时前
用LangChain + Playwright打造智能网页数据助手
爬虫·langchain
nebula-AI5 小时前
Understand Anything 简要使用文档
人工智能·ai·github·项目管理·知识图谱·dashboard