经过这些年的蓬勃发展,市面上已经涌现出了太多AI Agent的开发平台、框架和工具,但是毫无疑问,其中集大成者首推LangChain。利用LangChain开发的Agent可以看成是一个具有状态的、由Node和Edge组成的有环图 。Agent的内部循环被 "展开" 并映射到了LangGraph的StateGraph体现的拓扑结构中,后者经过编译的结果实际上是一个Pregel对象,这是一个由Node和Channel构成的Actor模型。新版本的LangGraph采用全新的设计重写了Pregel,目前社区基本上没有系统介绍Pregel的资料,我希望这个系列的文章能够弥补这一空白。
01. 以Actor模型的角度来看Pregel
本文系统阐述了Agent、StateGraph和Pregel三者的关系。StateGraph作为构建Agent的概念视图,通过Node和Edge组成有环图;而Pregel作为执行视图,采用Actor模型实现高效运行。文章详细解析了Pregel的底层机制,包括基于Pub/Sub的驱动执行、Node构建、多Channel读写等核心概念,并通过一个笑话生成Agent的完整示例,展示了从StateGraph编译到Pregel执行的全过程。阅读原文
02. Channel------驱动Node执行的原力
Pregel基于Node和Channel构建分布式计算框架,其中Channel不仅是状态存储中心,更是驱动Node执行的原力 。系统提供了多种Channel类型(如LastValue、BinaryOperatorAggregate等)以适应不同场景需求。Pregel采用BSP计算模型实现高效并发,通过Superstep(超步)机制将计算过程分解为有序的并行-同步循环:在并行阶段多个Node并发执行,在同步阶段统一更新Channel状态并确定下一超步任务。这种设计既保证了数据一致性,又避免了锁竞争。系统还实现了状态持久化机制,通过Checkpoint保存执行快照,支持故障恢复和时间旅行 功能。不同Channel类型在数据读写行为和可用性控制上各有特点,开发者可根据具体场景选择合适的Channel实现。阅读原文
03. __pregel_tasks通道------成就"PUSH任务"的功臣
Pregel框架内部维护一个名为__pregel_tasks的系统Channel,用于管理任务执行。该Channel采用Push模式,通过Send对象指定待执行节点和参数,具有阅后即焚特性。文章通过代码示例验证了该Channel的存在和保护机制:
- 该Channel是专用
Topic类型; - 禁止用户声明同名Channel;
- 常规写入方式会被拦截。最后提出唯一可行的写入方案是通过
ChannelWriteTupleEntry封装写入意图,绕过引擎保护机制。
这为理解Pregel的任务调度机制提供了重要视角。阅读原文
04. ManagedValue------一种特殊的只读虚拟通道
Pregel框架通过Channel和ManagedValue两种机制维护和传递状态。Channel用于业务状态传递,而ManagedValue作为虚拟Channel,负责传递运行时状态,不参与持久化。PregelScratchpad对象为每个任务提供执行上下文,包含步数、中断计数器和子图调用计数器等关键信息,支持中断恢复和子图调用场景。中断恢复采用从头执行 方式,要求Node设计遵循幂等性原则。子图调用通过Checkpoint命名空间机制实现状态匹配,命名空间由执行路径和调用顺序共同决定,确保状态恢复的准确性。阅读原文
05. PregelNode------无状态的功能节点
PregelNode是LangGraph中的核心组件,其核心是一个Runnable可执行对象。它通过channels和triggers字段定义输入源,支持字符串或列表形式,影响参数传递方式。输出通过writers字段的ChannelWrite对象实现,可写入单通道或多通道,支持值映射和空值过滤。PregelNode的设计使其能灵活处理数据流,支持复杂计算图的构建。阅读原文
06. PregelProtocol------定义了"LangChain执行体"最小功能集
PregelProtocol协议将LangGraph升级为可插拔的图计算框架,其核心功能包括:
- 配置绑定:通过
RunnableConfig控制执行行为(如迭代限制、并发),并传递运行时组件(如Runtime、PregelScratchpad)。with_config方法支持动态绑定配置。 - 可视化呈现:提供
Graph类支持图的构建与可视化,支持ASCII、Mermaid图表及PNG渲染(依赖Graphviz)。通过get_graph方法获取图结构,参数xray决定是否展开嵌套子图。
该协议定义了图的最小功能集,包括执行配置与可视化能力,使LangGraph更灵活直观。阅读原文
07. 静态上下文在Pregel中的应用
Pregel模型中的静态上下文是一个类型安全的依赖注入容器,用于处理图计算中只读且固定的外部环境信息(如用户身份、数据库连接等)。它通过强类型Schema定义和单次运行锁定机制,确保运行时一致性,同时避免持久化存储。静态上下文通过Runtime类传递,开发者在Pregel构造函数中声明context_schema类型,在调用时注入具体实例。这种设计既保持了Pregel内核的简洁性,又解决了复杂对象注入与状态一致性要求的矛盾,特别适合大型Agent系统的模块化开发和测试。阅读原文
08. 基于Checkpoint的持久化
Pregel的Checkpoint持久化机制通过状态快照和操作日志实现高可用性和长期记忆。核心机制包括:
- 采用增量持久化策略,仅存储更新的Channel状态,通过版本控制管理变更
CheckpointMetadata记录执行谱系,包含来源类型(source)、步骤号(step)和父级关系(parents)- 版本系统采用
序列号.随机数的复合格式,确保并发安全和时间旅行能力 Checkpoint结构包含版本兼容标识、时间戳、更新通道列表和版本信息versions_seen字段维护节点执行时的输入状态,保证因果一致性和幂等性
该机制支持执行中断恢复、状态回溯和并行处理,为复杂图计算提供可靠的状态管理基础。阅读原文
09. 持久状态的提取
本文介绍了BaseCheckpointSaver的持久化机制,重点分析了Checkpoint和Pending Write的结合使用。通过CheckpointTuple结构体封装检查点状态、待处理写入和配置信息,实现了中断恢复功能。文章详细讲解了get_tuple/aget_tuple方法的读取逻辑,以及alist方法的历史记录查询功能。最后通过一个包含三个节点的Pregel示例,演示了如何利用InMemorySaver检查点机制处理正常执行和中断场景,验证了该持久化方案的有效性。关键点包括检查点状态管理、中断恢复机制以及历史记录查询的实现原理。阅读原文
10. 三种持久化模式的差异
本文探讨了Pregel系统中三种Checkpoint持久化模式的特点及应用场景。通过实例演示了sync、async和exit三种模式在Superstep执行与持久化时机上的差异:
sync模式确保Checkpoint完全持久化后才执行下一步,安全性最高但延迟较大;async模式实现计算与持久化的并行,平衡性能与安全性;exit模式仅在最终结果时才持久化,性能最优但风险最高。
实验通过ExtendedInMemorySaver类模拟持久化过程,展示了不同模式下节点执行与持久化的时序关系,验证了sync模式会等待持久化完成才继续执行,而async和exit模式则允许重叠操作。研究还发现Pending Write的持久化始终采用异步方式,不受主持久化模式影响。这些发现为分布式图计算系统的容错机制设计提供了重要参考。阅读原文
11. Pregel的迭代控制机制
本文分析了Pregel执行框架的两种调用流程:常规调用和恢复调用。常规调用从输入开始,通过PregelLoop对象进行迭代,每个Superstep生成任务、执行、持久化状态,最终输出结果。恢复调用则从指定检查点恢复执行,利用历史状态重建执行环境,可选择性提供恢复值。两种方式都通过PregelScratchpad管理执行状态,并确保数据一致性,主要区别在于初始状态来源和执行起点。阅读原文
12. 回到过去,开启平行世界[上篇]
Pregel提供了update_state和bulk_update_state方法用于增量修改状态,通过创建子Checkpoint实现非破坏性更新。状态更新需指定Node名称,依赖Node的writers列表完成写入操作。示例展示了单一Node更新的过程,当多个Node可能触发更新时需明确指定as_node参数。状态更新实际通过ChannelWrite对象实现,其writes字段包含Channel写入意图。更新操作基于最新Checkpoint版本,若存在歧义则需手动指定更新来源Node。阅读原文
13. 回到过去,开启平行世界[下篇]
本文介绍了如何通过update_state方法在历史节点开启新分支修改状态。以转账流程为例,演示了三种场景:
- 在计算金额节点修改金额并重新执行后续流程;
- 通过设置as_node="input"修改原始输入数据;
- 使用as_node="copy"单纯fork分支而不修改状态。
每种方法都通过具体代码示例展示了实现方式,并输出了状态历史以验证分支创建效果。这些技术为流程控制和状态管理提供了灵活的操作方式。阅读原文
14. 通过一个实例理解LangChain的所有的流模式
本文介绍了Pregel框架中stream/astream方法的使用,重点分析了流模式(StreamMode)的工作原理。文章首先指出传统的请求/回复模式存在客户端等待问题,而流模式能实现实时交互。随后详细解读了7种流模式的功能差异:values输出通道值、updates跟踪节点更新、checkpoints记录检查点、tasks监控任务状态、debug组合任务和检查点信息、messages获取模型输出、以及custom自定义输出。通过示例代码展示了如何配置多节点工作流,并演示了不同流模式下的输出结果特点,包括节点调用顺序、超级步骤(Superstep)状态变化等关键信息。最后总结了各流模式输出数量的计算逻辑,为开发者提供了实用的调试参考。阅读原文
15. 支持自然语言查询的长期存储
Pregel的Checkpointer采用基于Checkpoint的短期存储机制,而长期存储则通过BaseStore抽象实现,支持层次化命名空间、向量检索和生命周期管理(TTL)。BaseStore的核心功能包括:
- 数据存储:支持键值对存储,可指定命名空间和TTL过期时间,通过
put/aput方法实现,可选择是否建立向量索引以支持语义搜索。 - 数据检索:通过
get/aget获取数据,search/asearch支持自然语言查询和分页,返回结果包含相似度得分。 - 生命周期管理:支持配置
refresh_on_read(读取刷新TTL)、default_ttl(默认过期时间)和定期清理机制。 - 批处理与删除:核心操作通过
batch/abatch优化分布式性能,并提供delete和命名空间查询功能。
该设计适用于复杂流程的长期数据管理,平衡存储效率与查询灵活性。阅读原文
16. Agent状态是如何被写入通道的?
Pregel执行流程中的通道写入机制通过ChannelWriteEntry、ChannelWriteTupleEntry和Send三种对象表示写入意图,由ChannelWrite统一提交。这些对象在Superstep同步阶段批量更新通道,确保执行有序性。ChannelWrite作为RunnableCallable,处理透传值转换并验证写入合法性,最终将写入意图转换为通道名和值的二元组序列提交给引擎。阅读原文
17. Agent状态是如何从通道读取的?
本文探讨了Agent节点如何通过ChannelRead读取通道状态,补充了前文关于状态写入的内容。重点介绍了ChannelRead的静态方法do_read的使用方式和参数配置,包括select、fresh和mapper参数的功能。通过代码示例展示了如何创建单节点Pregel对象并读取不同通道组合的状态。文章还分析了do_read方法的底层实现,揭示了其通过RunnableConfig获取读取函数的机制,并介绍了local_read函数作为实际读取操作的核心实现。这些机制共同构成了LangGraph中Agent状态读取的完整流程。阅读原文