LangGraph 状态快照与回滚|Agent 故障自愈、流程回溯
每执行完一个图节点LangGraph 自动保存一份当前完整状态就是快照。每条快照包含全量状态、父快照 ID、时间戳、自定义业务元数据。Checkpointer存储器快照存放载体分三类MemorySaver内存存储本地测试临时使用进程关闭数据丢失RedisSaverRedis 持久化中小型线上项目首选PostgresSaver数据库持久化大规模企业业务thread_id 会话隔离每一条独立对话 / 任务分配唯一thread_id不同线程快照完全隔离互不干扰。回滚机制指定checkpoint_id即可加载历史快照不删除原有链路生成新分支完全可逆最小可运行图 自动生成快照使用内置MemorySaver内存存储无需中间件适合本地测试。from langgraph.graph import StateGraph, START, END, MessagesState from langgraph.checkpoint.memory import MemorySaver from langchain_core.messages import HumanMessage, AIMessage # 1. 定义基础图 builder StateGraph(MessagesState) # 简单节点回复用户消息 def chat_node(state: MessagesState): last_msg state[messages][-1].content return {messages: [AIMessage(contentf收到你的消息{last_msg})]} builder.add_node(chat, chat_node) builder.add_edge(START, chat) builder.add_edge(chat, END) # 2. 挂载检查点存储器核心开启快照 checkpointer MemorySaver() graph builder.compile(checkpointercheckpointer) # 3. 会话唯一标识thread_id thread_config {configurable: {thread_id: test-thread-001}} # 4. 多轮执行自动生成多条快照 graph.invoke({messages: [HumanMessage(第一步初始化对话)]}, thread_config) graph.invoke({messages: [HumanMessage(第二步发送第二个请求)]}, thread_config) graph.invoke({messages: [HumanMessage(第三步发送第三个请求)]}, thread_config) # 5. 查询全部历史快照 history list(graph.get_state_history(thread_config)) print(f总快照数量{len(history)}) # 倒序输出[0]最新[-1]最早 for idx, snap in enumerate(history): msg_cnt len(snap.values[messages]) print(f[{idx}] 快照ID{snap.id[:16]}... | 消息数{msg_cnt} | 父快照ID{snap.parent_id[:16] if snap.parent_id else 无})输出执行后会输出 4 条快照初始空状态 三轮执行后列表按时间倒序排列最新快照在最前面。基础回滚跳转到历史快照继续执行回滚核心在 config 中传入checkpoint_id指定目标快照执行会生成新分支原有历史保留。# 承接上面代码继续执行 history list(graph.get_state_history(thread_config)) # 选取倒数第二个快照第二轮执行后的状态 target_snap history[-2] rollback_config { configurable: { thread_id: test-thread-001, checkpoint_id: target_snap.id } } # 加载回滚后的状态 rollback_state graph.get_state(rollback_config) print(f\n回滚完成当前消息数{len(rollback_state.values[messages])}) # 从历史快照继续运行生成新分支快照 new_result graph.invoke( {messages: [HumanMessage(从历史快照重新执行)]}, rollback_config ) print(回滚后新执行结果, new_result[messages][-1].content) # 再次查看历史会多出一条新快照分支 new_history list(graph.get_state_history(thread_config)) print(f回滚后快照总数{len(new_history)})进阶 Redis 持久化快照内存存储进程销毁即丢失生产环境使用RedisSaver持久化快照多服务共享历史。Redis 初始化与持久化图from langgraph.checkpoint.redis import RedisSaver from langgraph.graph import StateGraph, START, END, MessagesState from langchain_core.messages import HumanMessage, AIMessage # 1. 初始化Redis检查点 redis_checkpointer RedisSaver() redis_checkpointer.setup(redis://localhost:6379/0) # 2. 构建相同对话图 builder StateGraph(MessagesState) def chat_node(state: MessagesState): last_msg state[messages][-1].content return {messages: [AIMessage(contentfRedis持久化响应{last_msg})]} builder.add_node(chat, chat_node) builder.add_edge(START, chat) builder.add_edge(chat, END) graph builder.compile(checkpointerredis_checkpointer) # 会话配置 thread_cfg {configurable: {thread_id: redis-thread-001}} # 多轮执行持久化快照 graph.invoke({messages: [HumanMessage(Redis测试1)]}, thread_cfg) graph.invoke({messages: [HumanMessage(Redis测试2)]}, thread_cfg) # 查询Redis存储的历史快照 history list(graph.get_state_history(thread_cfg)) print(Redis持久化快照列表) for snap in history: print(f快照ID{snap.id[:16]} | 消息数{len(snap.values[messages])})给快照添加自定义元数据业务标记通过update_state给快照附加标签、用户 ID、步骤标识方便筛选历史快照# 承接上面Redis代码 meta_cfg {configurable: {thread_id: redis-thread-001}} # 更新状态并写入自定义元数据 graph.update_state( meta_cfg, {}, metadata{ label: 业务流程-步骤2完成, step_name: chat_finish, user_id: 10086 } ) # 获取最新快照查看元数据 latest_snap graph.get_state(meta_cfg) print(快照自定义元数据, latest_snap.metadata)高阶实战场景异常自动回滚重试故障自愈from typing_extensions import TypedDict from langgraph.graph import StateGraph, START, END from langgraph.checkpoint.memory import MemorySaver from langchain_core.messages import HumanMessage, AIMessage # 自定义状态继承消息状态增加错误计数、成功快照ID class ResilientState(TypedDict): messages: list error_count: int last_success_checkpoint: str # 模拟会随机报错的危险工具 import random def risky_tool(): if random.random() 0.6: raise Exception(工具调用超时/LLM格式异常) return 工具执行成功获取数据完成 def safe_exec_node(state: ResilientState): thread_id retry-thread-001 cfg {configurable: {thread_id: thread_id}} try: res risky_tool() # 执行成功记录当前快照ID current_snap graph.get_state(cfg) return { messages: state[messages] [AIMessage(res)], error_count: 0, last_success_checkpoint: current_snap.id } except Exception as e: err_cnt state.get(error_count, 0) 1 if err_cnt 3: # 重试耗尽终止流程 return { messages: state[messages] [AIMessage(f重试3次全部失败{str(e)})], error_count: err_cnt } # 回滚到上一个成功快照 history list(graph.get_state_history(cfg)) parent_id history[1].parent_id # 取上一级父快照 rollback_cfg {configurable: {thread_id: thread_id, checkpoint_id: parent_id}} graph.get_state(rollback_cfg) return { messages: state[messages] [AIMessage(f执行失败第{err_cnt}次重试)], error_count: err_cnt } # 构建容错图 builder StateGraph(ResilientState) builder.add_node(safe_exec, safe_exec_node) builder.add_edge(START, safe_exec) builder.add_edge(safe_exec, END) checkpointer MemorySaver() graph builder.compile(checkpointercheckpointer) # 启动流程 run_cfg {configurable: {thread_id: retry-thread-001}} result graph.invoke({messages: [HumanMessage(执行危险工具)], error_count: 0}, run_cfg) print(最终流程输出, result[messages][-1].content)多分支策略对比from langgraph.graph import StateGraph, START, END, MessagesState from langgraph.checkpoint.memory import MemorySaver from langchain_core.messages import HumanMessage, AIMessage # 基础对话图 builder StateGraph(MessagesState) def strategy_a(state): return {messages: [AIMessage(策略A精简快速方案得分80)]} def strategy_b(state): return {messages: [AIMessage(策略B精细完整方案得分95)]} builder.add_node(A, strategy_a) builder.add_node(B, strategy_b) builder.add_edge(START, A) builder.add_edge(A, END) builder.add_edge(START, B) checkpointer MemorySaver() graph builder.compile(checkpointercheckpointer) thread_id branch-compare-001 base_cfg {configurable: {thread_id: thread_id}} # 1. 执行到分支基准点 graph.invoke({messages: [HumanMessage(业务需求基准)]}, base_cfg) base_snap graph.get_state(base_cfg).id # 2. 分支A不回滚直接执行 res_a graph.invoke({messages: []}, base_cfg) score_a 80 # 3. 回滚到基准快照执行分支B rollback_cfg {configurable: {thread_id: thread_id, checkpoint_id: base_snap}} res_b graph.invoke({messages: []}, rollback_cfg) score_b 95 # 对比择优 if score_a score_b: print(最优策略A, res_a[messages][-1].content) else: print(最优策略B, res_b[messages][-1].content)Postgres 限制最大快照数量from langgraph.checkpoint.postgres import PostgresSaver from sqlalchemy import create_engine engine create_engine(postgresql://user:pwd127.0.0.1:5432/agent_db) # 仅保留每个thread最近20条快照自动清理更早历史 pg_checkpointer PostgresSaver(engine, max_history20) pg_checkpointer.setup()定时清理过期快照import asyncio from datetime import datetime, timedelta async def clean_expired_checkpoints(checkpointer): 删除7天前所有快照保留最近50条 expire_time datetime.now() - timedelta(days7) # 遍历全部thread批量删除过期快照 all_threads checkpointer.list_threads() for tid in all_threads: history list(checkpointer.list_checkpoints(tid)) # 过滤过期快照并删除 pass完整可运行整合代码 运行前置本地启动 Redis 运行功能LangGraph Redis快照 历史查询 回滚重试 元数据标记 依赖langgraph1.2.7、langgraph-checkpoint-redis、redis-py from langgraph.graph import StateGraph, START, END, MessagesState from langgraph.checkpoint.redis import RedisSaver from langchain_core.messages import HumanMessage, AIMessage # 1. 初始化Redis存储 # 连接本地Redis无密码默认端口6379 redis_saver RedisSaver() redis_saver.setup(redis://localhost:6379/0) # 2. 构建基础对话图 graph_builder StateGraph(MessagesState) def chat_handler(state: MessagesState) - dict: user_input state[messages][-1].content resp AIMessage(f已处理{user_input}) return {messages: [resp]} graph_builder.add_node(chat, chat_handler) graph_builder.add_edge(START, chat) graph_builder.add_edge(chat, END) # 绑定Redis检查点 agent_graph graph_builder.compile(checkpointerredis_saver) # 3. 会话配置 THREAD_ID full-demo-thread-001 base_config {configurable: {thread_id: THREAD_ID}} # 4. 多轮执行生成快照 print( 执行多轮对话自动生成快照 ) agent_graph.invoke({messages: [HumanMessage(第一轮创建任务)]}, base_config) agent_graph.invoke({messages: [HumanMessage(第二轮补充参数)]}, base_config) agent_graph.invoke({messages: [HumanMessage(第三轮提交执行)]}, base_config) # 给最新快照添加业务元数据 agent_graph.update_state( base_config, {}, metadata{step: task_submit, user_id: 999, tag: 任务提交完成} ) # 5. 查询全部历史快照 history_snapshots list(agent_graph.get_state_history(base_config)) print(f\n 共生成 {len(history_snapshots)} 条快照 ) for idx, snap in enumerate(history_snapshots): msg_count len(snap.values[messages]) meta snap.metadata print(f[{idx}] ID:{snap.id[:20]} 消息数:{msg_count} 元数据:{meta}) # 6. 回滚到第二轮快照倒数第二个 target_snap history_snapshots[-2] rollback_config { configurable: { thread_id: THREAD_ID, checkpoint_id: target_snap.id } } rollback_state agent_graph.get_state(rollback_config) print(f\n 回滚完成 ) print(f目标快照ID{target_snap.id[:20]}) print(f回滚后消息条数{len(rollback_state.values[messages])}) # 7. 从回滚快照重新执行生成新分支 new_run_result agent_graph.invoke( {messages: [HumanMessage(回滚后重新提交任务修正参数)]}, rollback_config ) print(f\n 回滚后新执行输出 ) print(new_run_result[messages][-1].content) # 再次查看快照验证新增分支 new_history list(agent_graph.get_state_history(base_config)) print(f\n回滚后快照总数更新为{len(new_history)})学AI大模型的正确顺序千万不要搞错了2026年AI风口已来各行各业的AI渗透肉眼可见超多公司要么转型做AI相关产品要么高薪挖AI技术人才机遇直接摆在眼前有往AI方向发展或者本身有后端编程基础的朋友直接冲AI大模型应用开发转岗超合适就算暂时不打算转岗了解大模型、RAG、Prompt、Agent这些热门概念能上手做简单项目也绝对是求职加分王给大家整理了超全最新的AI大模型应用开发学习清单和资料手把手帮你快速入门学习路线:✅大模型基础认知—大模型核心原理、发展历程、主流模型GPT、文心一言等特点解析✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑✅开发基础能力—Python进阶、API接口调用、大模型开发框架LangChain等实操✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经以上6大模块看似清晰好上手实则每个部分都有扎实的核心内容需要吃透我把大模型的学习全流程已经整理好了抓住AI时代风口轻松解锁职业新可能希望大家都能把握机遇实现薪资/职业跃迁这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

相关新闻

HDMI视频寄存器配置实战:从同步时序到色彩空间转换详解

HDMI视频寄存器配置实战:从同步时序到色彩空间转换详解

1. 项目概述与核心价值在嵌入式视频系统开发,尤其是涉及HDMI、DisplayPort这类高速数字接口的领域,工程师们常常会遇到一个看似简单实则棘手的问题:如何让一块屏幕准确地、稳定地显示出我们想要的图像?这背后远不止是发送像素数据…

2026/9/23 13:41:04 阅读更多 →
TMS320C28x FPU64软件流水线优化:从延迟槽到指令级并行实战

TMS320C28x FPU64软件流水线优化:从延迟槽到指令级并行实战

1. 项目概述与核心价值在嵌入式数字信号处理器(DSP)的开发中,尤其是面向电机控制、数字电源、新能源逆变器等对实时性要求极高的领域,每一纳秒的指令执行时间都至关重要。TMS320C28x系列DSP,凭借其强大的定点运算能力和…

2026/9/23 21:44:49 阅读更多 →
深入解析PCIe SERDES寄存器配置与内存映射实战

深入解析PCIe SERDES寄存器配置与内存映射实战

1. 项目概述与核心价值在嵌入式系统和硬件驱动开发领域,尤其是涉及高速数据传输的场景,理解并掌握底层硬件的配置是通往高阶的必经之路。今天,我想和大家深入聊聊一个看似枯燥但至关重要的主题:PCIe模块的内存映射与SERDES寄存器配…

2026/9/23 15:52:17 阅读更多 →

最新新闻

JavaWeb购物车系统实现:基于Session存储的完整工程示例

JavaWeb购物车系统实现:基于Session存储的完整工程示例

简介:这是一份面向Java Web初学者的简易购物车系统案例,完整演示了基于Servlet与Tomcat的商品选购流程;案例来自课程设计或实验场景,需求中要求设计商品展示页面,点击“添加到购物车”超链接后进入Servlet记录选购信息…

2026/9/24 0:02:36 阅读更多 →
图联邦学习毕设实战:GCN拆解、结构感知聚合与灾难性遗忘防护

图联邦学习毕设实战:GCN拆解、结构感知聚合与灾难性遗忘防护

简介:本资源是一套面向本科毕业设计与人工智能课程实践的图联邦学习系统实现方案,聚焦社交网络、知识图谱与推荐系统等典型图数据场景,为算法工程师与高校研究者提供可复现的联邦化GNN开发范例。压缩包共149个文件,含32个核心Pyth…

2026/9/24 0:02:35 阅读更多 →
Flutter数值映射库num_remap在鸿蒙开发中的应用与优化

Flutter数值映射库num_remap在鸿蒙开发中的应用与优化

1. Flutter 三方库 num_remap 鸿蒙适配实战指南在 OpenHarmony 生态中开发动态交互应用时,数值范围映射是个高频需求场景。无论是处理传感器数据、手势操作还是动画效果,都需要将原始数据转换为适合 UI 展示的数值范围。传统的手写映射代码不仅冗长难维护…

2026/9/24 0:01:25 阅读更多 →
Lss-bev IndexPut插件:前端高效索引操作实践

Lss-bev IndexPut插件:前端高效索引操作实践

1. 项目背景与核心价值Lss-bev系列插件作为现代前端工程化体系中的重要组成部分,其IndexPut模块的部署实践直接影响着数据索引操作的性能表现。在实际项目中,我们经常遇到需要高效处理大规模索引更新的场景,而传统方案往往面临以下痛点&#…

2026/9/24 0:01:25 阅读更多 →
JSP+JDBC+MySQL+Servlet图书管理系统实战:从源码部署到性能优化

JSP+JDBC+MySQL+Servlet图书管理系统实战:从源码部署到性能优化

简介:面向Java Web初学者,这份图书管理项目源码以图书信息增删改查为主线,完整整合了JSP、JDBC、MySQL与Servlet技术栈,演示了从页面展示、请求处理到数据库读写的基本路径,适合用来理解MVC分层与原生Web开发流程。压缩…

2026/9/24 0:01:25 阅读更多 →
Lombok与JDK版本冲突引发NoSuchFieldError:根因排查与修复指南

Lombok与JDK版本冲突引发NoSuchFieldError:根因排查与修复指南

如果你在某个平平无奇的下午执行mvn clean package,看到编译进度条卡在注解处理阶段,随之蹦出这么一行:java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCImport does not have member field ...基本可以确认一件事&…

2026/9/24 0:01:25 阅读更多 →

日新闻

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:19 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/24 0:00:19 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/23 4:55:02 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/23 4:49:06 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/23 9:53:41 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/23 9:53:40 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/23 9:53:40 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/23 9:53:40 阅读更多 →