Skip to content

第18章 设计模式与架构决策

18.1 引言

经过前面十七章的深入剖析,我们已经从源码层面理解了 LangGraph 的每一个核心组件——StateGraph 的编译流程、Channel 的类型体系、Pregel 的超步调度、Checkpoint 的持久化、Send 的动态并行、Runtime 的依赖注入、Store 的长期记忆、以及预构建的 Agent 组件。

本章将从更高的视角审视这些设计选择。我们不再逐行分析源码,而是提炼出 LangGraph 中可迁移的设计模式——那些超越 LLM 应用框架本身、在更广泛的软件工程领域中具有通用价值的架构思想。同时,我们也将诚实地评估每个关键决策的权衡,帮助读者在设计自己的系统时做出更明智的选择。

本章要点

  1. Pregel 计算模型的选择——为什么图 + 消息传递胜过其他范式
  2. Channel 版本追踪——通过版本号实现精确的变更检测
  3. Checkpoint 时间旅行——快照 + 写入日志的混合策略
  4. 中断/恢复模式——从 GraphInterrupt 异常到确定性重放
  5. 构建你自己的工作流引擎——从 LangGraph 中提炼的设计原则

18.2 Pregel 计算模型的选择

18.2.1 为什么选择 Pregel?

LangGraph 选择 Google Pregel 作为计算模型的灵感来源,这是一个深思熟虑的决策。让我们对比几种候选模型:

Pregel 模型的核心优势:

  1. 超步边界提供确定性:每个超步内,所有节点基于相同的状态快照执行,输出在超步结束时统一应用。这消除了竞态条件,使得图的执行在相同输入下是确定性的。

  2. Channel 解耦:生产者写入 Channel,消费者在下一个超步读取。这种间接通信让节点不需要知道谁在监听,也不需要等待消费者就绪。

  3. 快照友好:超步边界是天然的 Checkpoint 点——所有 Channel 值稳定,没有"进行中"的状态。

  4. 简单的编程模型:开发者只需要定义"给定当前状态,节点输出什么",不需要管理并发、同步或消息队列。

18.2.2 超步 vs 事件驱动

超步模型的关键约束是写入延迟一步可见——NodeA 在超步 N 写入的值,NodeB 要在超步 N+1 才能读取。这看似是限制,实际上是优势:它避免了在同一步中"读到尚未稳定的中间值"的问题。

18.2.3 从 Pregel 到 LangGraph 的适配

原始 Pregel 设计用于大规模图计算(如 PageRank),LangGraph 做了几个关键适配:

  1. Channel 替代顶点消息:原始 Pregel 每个顶点接收邻居消息,LangGraph 使用 Channel 提供更丰富的聚合语义(LastValue、BinaryOperatorAggregate、Topic)
  2. 有限步数:LangGraph 通过 recursion_limit 保证终止,而非依赖算法收敛
  3. 可中断:原始 Pregel 设计为批处理,LangGraph 支持人机交互的中断/恢复
  4. 异构节点:原始 Pregel 所有顶点运行相同程序,LangGraph 每个节点可以是不同的函数

18.3 Channel 版本追踪

18.3.1 版本号机制

LangGraph 使用单调递增的版本号追踪每个 Channel 的更新历史。这是整个调度系统的基石——版本号决定了哪些节点在下一个超步中需要被触发。

python
# Checkpoint 中的版本追踪结构
checkpoint = {
    "channel_versions": {
        "messages": 5,       # messages Channel 最后更新于版本 5
        "status": 3,         # status Channel 最后更新于版本 3
        "__start__": 1,      # 入口 Channel 版本 1
    },
    "versions_seen": {
        "agent": {           # agent 节点上次看到的版本
            "messages": 4,   # agent 看到 messages 时是版本 4
            "status": 3,     # agent 看到 status 时是版本 3
        },
        "tools": {
            "messages": 5,   # tools 看到 messages 时是版本 5
        },
    }
}

基于 VitePress 构建