尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

LangGraph 基础入门3(小白必看)

LangGraph 基础入门3(小白必看) LangGraph 持久化与记忆管理检查点、可恢复执行、Time Travel 与长期记忆前面学习 LangGraph 时我们主要关注了两个问题图怎么搭 节点怎么流转但是到了真实项目里只会搭图还不够。因为 Agent 或工作流经常会遇到这些问题运行到一半失败了能不能从失败位置继续 用户多轮对话能不能记住上下文 我想查看图每一步的状态能不能看到 我想回到某个历史节点重新执行能不能做到 程序重启后之前的状态还在不在这些问题对应的就是 LangGraph 里的持久化机制、检查点、可恢复执行和记忆管理。这篇文章按由浅到深整理检查点是什么、如何启用、如何查看历史状态、如何恢复执行、Time Travel、短期记忆、长期记忆、运行时上下文以及 PostgreSQL 在持久化中的作用。一、什么是可恢复执行可恢复执行可以简单理解成图运行过程中每执行到关键步骤就保存一次状态。 如果后面失败了可以从之前保存的状态继续执行。这就像打游戏时的存档。没有存档时失败就要从头开始。有了存档后可以从最近一次存档继续。在 LangGraph 里这个“存档”就叫Checkpoint检查点二、LangGraph 的持久化机制是什么LangGraph 的持久化机制就是把图运行过程中的状态保存下来。保存的内容通常包括当前状态值下一步要执行哪些节点当前检查点 ID父检查点信息当前任务信息中断信息这些信息合起来就可以描述图在某一刻的完整运行状态。核心组件主要有两个组件作用Checkpointer负责保存和读取检查点thread_id区分不同会话或不同运行线程可以这样理解Checkpointer 存档器 thread_id 存档属于哪个会话 checkpoint_id 某一次具体存档的编号三、启用检查点InMemorySaver最简单的检查点存储器是fromlanggraph.checkpoint.memoryimportInMemorySaver示例checkpointerInMemorySaver()config{configurable:{thread_id:123}}graphbuilder.compile(checkpointercheckpointer)resgraph.invoke({topic:猫咪},configconfig)这里有三个关键点。1. InMemorySavercheckpointerInMemorySaver()表示检查点保存在内存中。优点是简单适合学习和测试。缺点是程序一关数据就没了。所以它不适合生产环境长期保存。2. thread_idconfig{configurable:{thread_id:123}}thread_id用来标识一次会话。如果是聊天机器人可以把一个用户的一次对话看成一个thread_id。比如用户 A 的会话thread_id user_a_session_001 用户 B 的会话thread_id user_b_session_001这样不同用户、不同会话的检查点就不会混在一起。3. compile(checkpointer…)graphbuilder.compile(checkpointercheckpointer)编译图时传入checkpointer表示这张图启用检查点功能。如果没有传检查点存储器后面就不能正常查看历史状态也无法恢复执行。四、一个并行图的检查点示例假设图结构是START ↓ node_poem 和 node_joke 并行执行 ↓ node_output 汇总结果 ↓ END输入graph.invoke({topic:猫咪},configconfig)运行过程中大概会产生这些检查点Step -1 - Step 0 - Step 1 - Step 2真实执行顺序是从小到大Step -1 - Step 0 - Step 1 - Step 2但查看历史记录时get_state_history()默认是倒序返回Step 2 - Step 1 - Step 0 - Step -1也就是最新检查点 - 最旧检查点五、StateSnapshot 是什么查看历史检查点时history_checkpointslist(graph.get_state_history(configconfig))返回的是一组StateSnapshot对象。StateSnapshot可以理解成某一个检查点时刻的状态快照。常见字段有字段含义values当前检查点的状态值next如果从该检查点继续执行下一步要运行的节点config当前检查点配置包含thread_id、checkpoint_ns、checkpoint_idparent_config父检查点配置也就是上一个检查点tasks当前检查点关联的任务信息interrupts中断信息常用于 human-in-the-loop六、检查点里的 values 和 next看检查点时最重要的是两个字段valuesnextvaluesvalues表示当前状态。比如values{topic:猫咪,poem:...,joke:...}说明图已经生成了诗和笑话。nextnext表示从当前检查点继续执行时下一步要执行哪些节点。比如next(node_output,)表示下一步执行node_output。如果next()说明图已经执行结束。七、检查点顺序为什么是 Step 2 - Step 1 - Step 0 - Step -1因为get_state_history()默认按倒序返回。真实运行顺序是Step -1 - Step 0 - Step 1 - Step 2历史查询顺序是Step 2 - Step 1 - Step 0 - Step -1原因很简单查询历史时通常最关心最新状态所以 LangGraph 会把最新检查点放在最前面。可以记成一句话图执行从旧到新 查历史从新到旧八、Step -1、Step 0、Step 1、Step 2 分别代表什么以这个并行图为例START - node_poem START - node_joke node_poem - node_output node_joke - node_output node_output - ENDStep -1输入检查点还没有真正进入图计算。通常可以看到values{}next(__start__,)意思是下一步准备进入图的内部起点。Step 0输入写入状态输入已经进入状态values{topic:猫咪}下一步next(node_poem,node_joke)说明要并行执行node_poem和node_joke。Step 1并行节点执行完成node_poem和node_joke已经执行完。状态大概是values{topic:猫咪,poem:...,joke:...}下一步next(node_output,)Step 2最终输出完成node_output已经执行完。状态大概是values{topic:猫咪,poem:...,joke:...,final_output:...}下一步next()说明图结束。九、查看最新检查点如果只想看最新状态可以用snapshotgraph.get_state(configconfig)它返回当前thread_id最新的StateSnapshot。常用查看方式print(snapshot.values)print(snapshot.next)print(snapshot.config)如果next ()说明这个线程已经运行结束。十、根据 checkpoint_id 查看指定检查点每个检查点都有自己的checkpoint_id。一般结构在snapshot.config[configurable][checkpoint_id]如果想回到某个具体检查点可以把对应的checkpoint_id放进 config 里。大概形式是target_config{configurable:{thread_id:123,checkpoint_id:某个检查点ID}}snapshotgraph.get_state(configtarget_config)这样就能查看指定检查点的状态。十一、持久化数据库PostgresSaverInMemorySaver只适合临时测试。如果希望程序重启后检查点还在就需要用持久化存储比如 PostgreSQL。常见用法是fromlanggraph.checkpoint.postgresimportPostgresSaver大致流程1. 启动 PostgreSQL 2. 准备数据库连接地址 3. 创建 PostgresSaver 4. 执行 setup 初始化表 5. compile 时传入 checkpointer示意代码DB_URIpostgresql://用户名:密码localhost:5432/数据库名withPostgresSaver.from_conn_string(DB_URI)ascheckpointer:checkpointer.setup()graphbuilder.compile(checkpointercheckpointer)PostgreSQL 的作用就是把检查点真正保存到数据库里。这样就算 Python 程序退出后面仍然可以根据thread_id找回历史状态。十二、失败后恢复运行有了检查点后如果图运行到一半失败就可以从最近一次检查点恢复。比如Step 0 已保存 Step 1 执行某个节点时报错下次可以从 Step 0 或某个指定检查点继续。这对于长任务很有用比如多步骤文档处理多轮 Agent 工具调用数据分析流水线人工审核流程长时间运行的工作流否则失败一次就从头跑成本太高。十三、Time Travel回放和分叉LangGraph 的 Time Travel 可以理解成回到历史检查点重新看或重新跑。它有两个重要概念Replay回放 Fork分叉Replay回放Replay 是从某个历史检查点重新执行。如果之前某些节点已经成功执行并且检查点里记录了结果LangGraph 可以避免重复执行已经完成的部分。这适合调试我想看看从某一步开始后面到底怎么跑。Fork分叉Fork 是从某个历史检查点创建一条新的执行路线。比如原路线是A - B - C你回到 B然后换一种输入或状态继续A - B - D这就像从历史存档开了一条新支线。适合对比不同策略调试不同分支人工修改状态后继续执行Agent 推理路径实验十四、短期记忆短期记忆通常指当前会话内的记忆。在 LangGraph 里短期记忆常常通过检查点实现。比如聊天机器人中同一个 thread_id 下保存多轮 messages 下一轮调用时继续带上历史消息这就是短期记忆。特点和当前会话绑定适合多轮对话上下文通常依赖thread_id可以用检查点保存十五、长期记忆长期记忆不是只记住当前会话而是跨会话保存用户偏好、事实、资料等。比如用户喜欢 Python 用户偏好中文回答 用户常用 DeepSeek 用户正在学习 LangGraph这些信息不应该只存在一次对话里而应该保存到长期存储中。长期记忆通常需要独立存储器比如数据库。在 LangGraph 项目中可以把长期记忆理解为跨 thread_id 的持久数据。短期记忆和长期记忆区别类型作用生命周期短期记忆保存当前会话上下文通常绑定一个thread_id长期记忆保存跨会话信息用户长期有效十六、访问长期记忆的常见流程一个常见设计是用户输入 ↓ 检查当前状态里有没有用户偏好 ↓ 如果没有从长期记忆数据库查询 ↓ 把查到的偏好写入状态 ↓ 模型节点基于偏好回答伪流程defrouter(state):ifpreferencenotinstate:returnload_memory_nodereturnllm_node意思是如果状态里没有记忆先去加载长期记忆。 如果已经有了就直接进入模型节点。十七、运行时上下文 Runtime Context除了StateLangGraph 还支持运行时上下文。状态State是图运行中会被节点读写、合并、保存的业务状态。运行时上下文context更像是本次调用附带的环境信息。比如当前用户 ID用户等级请求来源当前语言是否 VIP当前租户 ID定义上下文类型fromtypingimportTypedDictclassContext(TypedDict):user_id:stris_vip:bool创建图时声明builderStateGraph(state_schemaOverAllState,context_schemaContext)节点里可以通过运行时对象访问defnode_a(state,runtime):user_idruntime.context[user_id]调用时传入graph.invoke(input_data,context{user_id:u_001,is_vip:True})可以这样区分State图内部业务状态会被节点更新 Context本次调用的环境信息一般不作为状态更新十八、节点完整形态LangGraph 的节点本质上就是函数。最简单形态defnode_a(state):return{}带配置fromlangchain_core.runnablesimportRunnableConfigdefnode_a(state,config:RunnableConfig):thread_idconfig[configurable][thread_id]return{}带运行时上下文defnode_a(state,runtime):user_idruntime.context[user_id]return{}节点的核心职责始终是读取状态或上下文 执行业务逻辑 返回状态更新十九、PostgreSQL 为什么重要PostgreSQL 常用于保存 LangGraph 的检查点和长期记忆。原因很直接内存存储不能跨进程真实项目需要程序重启后还能恢复多用户会话需要统一存储长期记忆需要持久化数据库如果只是学习InMemorySaver()就够了。如果是项目PostgreSQL / Redis / 其他持久化后端会更合适。二十、学习时最容易混的点1. thread_id 不是 checkpoint_idthread_id是会话 ID。checkpoint_id是某一个具体检查点的 ID。一个thread_id下面可以有多个checkpoint_id。2. get_state_history 是倒序执行顺序Step -1 - Step 0 - Step 1 - Step 2查询历史Step 2 - Step 1 - Step 0 - Step -13. InMemorySaver 不等于长期保存InMemorySaver是内存版。程序退出后检查点就没了。如果想真正持久化需要数据库。4. 短期记忆和长期记忆不是一回事短期记忆通常是一个会话里的上下文。长期记忆是跨会话保存的用户信息或知识。5. State 和 Context 不一样State会参与图状态更新和检查点保存。Context更像本次调用时附带的环境参数。总结LangGraph 的持久化和记忆管理本质上是在解决一个问题图运行到某一步时它当时的状态能不能被保存、查看、恢复和复用核心知识可以这样记Checkpointer负责保存检查点 thread_id区分会话 checkpoint_id定位具体检查点 StateSnapshot某一步的状态快照 values当前状态 next下一步节点 get_state_history查看历史检查点默认从新到旧 get_state查看最新或指定检查点 Replay回放历史执行 Fork从历史检查点分叉新路线 短期记忆当前会话上下文 长期记忆跨会话持久信息 Runtime Context本次调用的环境信息学完这一部分后LangGraph 就不只是能跑一个流程而是开始具备真实 Agent 工程里的核心能力多轮记忆、状态恢复、失败续跑、历史回放和长期记忆管理。
返回列表