365bet官网是多少

Agent 为什么需要 Checkpoint?

发布时间 2026-08-02 11:45:03 作者 admin 阅读 1067

文章目录

前言:为什么我会学这个问题

一、问题背景

二、核心概念

[Checkpoint 是什么?](#Checkpoint 是什么?)

[LangGraph Checkpoint 机制](#LangGraph Checkpoint 机制)

[Checkpoint 的存储方式](#Checkpoint 的存储方式)

[三、错误理解 / 常见误区](#三、错误理解 / 常见误区)

四、正确实现思路

[步骤1:设计可恢复的 State](#步骤1:设计可恢复的 State)

[步骤2:每个 Node 检查进度再执行](#步骤2:每个 Node 检查进度再执行)

[步骤3:配置 Checkpoint 并执行](#步骤3:配置 Checkpoint 并执行)

五、代码示例

[六、运行结果 / 流程图](#六、运行结果 / 流程图)

七、项目中怎么用

[八、总结 + 下篇预告](#八、总结 + 下篇预告)

前言:为什么我会学这个问题

上篇我们讲了 LangGraph 里 State、Node、Edge 怎么配合完成多步骤任务。主包在学习Langgraph的时候准备构建一个客服Agent,跑完一个客服流程需要 5-6 步,但如果执行到一半服务器崩了呢?或者用户突然关闭页面?所有 State 都没了,流程只能从头再来。

这就很蛋疼了------用户问了个复杂问题,Agent 查了半天文档,刚要返回结果时网络断了。用户重新打开页面,发现一切要从头开始,肯定骂街。

Checkpoint 就是来解决这个问题的。它是 Agent 执行过程的"存档点"。

前文关联:本文接续《LangGraph 中 State、Node、Edge 是怎么协作的?》,在前文理解 State 流转的基础上,探讨如何让 State 持久化、不怕中断。

一、问题背景

假设一个复杂的数据分析 Agent,执行流程是这样的:

跑了 4 步,刚到"生成图表"这一步,突然:

服务器重启了

用户关掉了浏览器

网络断了

进程被 OOM Kill 了

没有 Checkpoint = 从头来过。用户得重新等 4 步重新跑一遍,浪费时间和资源。

二、核心概念

Checkpoint 是什么?

Checkpoint = State 的快照。在某个 Node 执行完成后,把当前的 State 完整保存下来。

就像游戏存档:打到 BOSS 血剩一半,保存一下。哪天游戏崩了,从存档点恢复,不用从头打。

python

复制代码

# 伪代码:Checkpoint 本质就是保存 State

checkpoint = {

"step": 4,

"state": {

"user_question": "分析Q2销售额",

"retrieved_data": {...},

"analysis_result": {...},

"chart_data": {...}, # 已生成,还没用来生成报告

"response": ""

},

"node_history": ["understand", "query", "analyze", "generate_chart"]

}

LangGraph Checkpoint 机制

LangGraph 的 Checkpoint 在每个 Node 执行完成后自动保存。恢复时从最近的 Checkpoint 开始,不用重新跑。

python

复制代码

from langgraph.checkpoint import MemorySaver

from langgraph.graph import StateGraph

# 创建带 Checkpoint 的 Graph

checkpointer = MemorySaver()

graph = StateGraph(DataAnalysisState)

# ... 添加 Node 和 Edge ...

app = graph.compile(checkpointer=checkpointer)

# 正常执行(每个 Node 完成后自动保存 Checkpoint)

config = {"configurable": {"thread_id": "user-123-session-1"}}

result = app.invoke(initial_state, config)

# 中断后恢复(从最近 Checkpoint 继续)

restored_result = app.invoke(None, config) # 传 None 表示从存档点恢复

Checkpoint 的存储方式

存储方式

适用场景

特点

MemorySaver

开发测试

内存存储,重启丢失

SqliteSaver

单机部署

SQLite 文件持久化

PostgresSaver

生产环境

PostgreSQL,支持多实例

生产环境推荐 PostgresSaver,多个 Agent 实例可以共享同一个 Checkpoint 存储。

三、错误理解 / 常见误区

误区1:Checkpoint 会拖慢执行速度

错。Checkpoint 保存是异步的,不阻塞 Node 执行。而且只有 State 变化时才保存,不是每次都全量写入。

误区2:有了 Checkpoint 就不用担心数据丢失

不完全对。Checkpoint 保存的是 Node 执行完成后的 State,如果 Node 执行到一半崩溃,那一步的修改会丢失。所以要保证 Node 的原子性------每个 Node 要么完全成功,要么完全失败,不要有中间状态。

误区3:Checkpoint 可以无限恢复

不对。Checkpoint 存储会消耗资源,生产环境通常只保留最近 N 个版本。或者设置过期时间,比如只保留 24 小时内的 Checkpoint。

误区4:所有 State 都需要 Checkpoint

错。只保存关键数据就行,比如中间结果、用户输入、配置参数。不需要保存的是:临时变量、缓存数据、日志等。

四、正确实现思路

步骤1:设计可恢复的 State

State 要设计成可以"从哪里继续"的样子:

python

复制代码

class DataAnalysisState(TypedDict):

# 用户原始问题(不变)

user_question: str

# 流程进度(关键!用于判断从哪继续)

current_step: str # understand / query / analyze / chart / report

completed_steps: list[str]

# 各步骤的结果(保存中间产物)

understanding: str

query_result: str

analysis_result: str

chart_data: dict

response: str

步骤2:每个 Node 检查进度再执行

python

复制代码

def analyze_data(state: DataAnalysisState) -> DataAnalysisState:

# 如果已经分析过了,直接返回(防止重跑)

if "analyze" in state["completed_steps"]:

print(" [analyze] 已完成,跳过")

return state

# 正常执行分析逻辑

print(" [analyze] 执行数据分析...")

result = do_analysis(state["query_result"])

return {

"analysis_result": result,

"current_step": "analyze",

"completed_steps": state["completed_steps"] + ["analyze"]

}

步骤3:配置 Checkpoint 并执行

python

复制代码

from langgraph.checkpoint import PostgresSaver

import psycopg2

# 生产环境:PostgreSQL 存储

conn = psycopg2.connect(os.getenv("DATABASE_URL"))

checkpointer = PostgresSaver(conn)

# 开发环境:内存存储

# checkpointer = MemorySaver()

app = graph.compile(checkpointer=checkpointer)

# 第一次执行

config = {"configurable": {"thread_id": "user-123"}}

result = app.invoke(initial_state, config)

# 模拟中断后恢复

# (同一个 thread_id 会自动找到最近的 Checkpoint)

result = app.invoke(None, config) # None 表示从存档点继续

五、代码示例

python

复制代码

"""

LangGraph Checkpoint 完整示例

演示:执行中断 → 自动从 Checkpoint 恢复

"""

from typing import TypedDict, Literal

from langgraph.graph import StateGraph

from langgraph.checkpoint import MemorySaver

class ShoppingAgentState(TypedDict):

"""购物 Agent 状态"""

user_request: str

current_step: Literal["understand", "search", "compare", "recommend", "done"]

completed_steps: list[str]

products: list[str]

recommendation: str

def understand(state: ShoppingAgentState) -> ShoppingAgentState:

"""理解用户需求"""

print(f" [understand] 理解需求: {state['user_request']}")

return {

"current_step": "understand",

"completed_steps": ["understand"]

}

def search(state: ShoppingAgentState) -> ShoppingAgentState:

"""搜索商品"""

if "search" in state["completed_steps"]:

print(" [search] 已完成,跳过")

return state

print(" [search] 搜索商品中...")

return {

"products": ["商品A", "商品B", "商品C"],

"current_step": "search",

"completed_steps": state["completed_steps"] + ["search"]

}

def compare(state: ShoppingAgentState) -> ShoppingAgentState:

"""对比商品"""

if "compare" in state["completed_steps"]:

print(" [compare] 已完成,跳过")

return state

print(" [compare] 对比商品...")

return {

"current_step": "compare",

"completed_steps": state["completed_steps"] + ["compare"]

}

def recommend(state: ShoppingAgentState) -> ShoppingAgentState:

"""推荐商品"""

if "recommend" in state["completed_steps"]:

print(" [recommend] 已完成,跳过")

return state

best = state["products"][0] if state["products"] else "无"

print(f" [recommend] 推荐: {best}")

return {

"recommendation": f"强烈推荐 {best}!",

"current_step": "recommend",

"completed_steps": state["completed_steps"] + ["recommend"]

}

# 构建图

graph = StateGraph(ShoppingAgentState)

graph.add_node("understand", understand)

graph.add_node("search", search)

graph.add_node("compare", compare)

graph.add node("recommend", recommend) # 注意:不是 recommend()

graph.set_entry_point("understand")

graph.add_edge("understand", "search")

graph.add_edge("search", "compare")

graph.add_edge("compare", "recommend")

graph.set_finish_point("recommend")

# 模拟中断:在 compare 步骤手动抛出异常

class InterruptException(Exception):

pass

def compare_with_interrupt(state: ShoppingAgentState) -> ShoppingAgentState:

if "compare" in state["completed_steps"]:

print(" [compare] 已完成,跳过")

return state

print(" [compare] 对比商品... (模拟中断点)")

# 模拟执行到一半崩了

if len(state["completed_steps"]) < 3: # 只有前3步完成时抛出

raise InterruptException("模拟中断:服务器崩了")

return {

"current_step": "compare",

"completed_steps": state["completed_steps"] + ["compare"]

}

# 用带中断的版本替换

graph.add_node("compare", compare_with_interrupt)

# 编译(启用 Checkpoint)

checkpointer = MemorySaver()

app = graph.compile(checkpointer=checkpointer)

# ========== 第一次执行:跑到 compare 时中断 ==========

print("=" * 50)

print("第一次执行:模拟中断")

print("=" * 50)

config = {"configurable": {"thread_id": "user-456"}}

initial_state: ShoppingAgentState = {

"user_request": "想买一个打游戏快的笔记本电脑",

"current_step": "",

"completed_steps": [],

"products": [],

"recommendation": ""

}

try:

result = app.invoke(initial_state, config)

print(f"最终结果: {result['recommendation']}")

except InterruptException as e:

print(f"中断了: {e}")

print(f"当前完成步骤: {result.get('completed_steps', []) if 'result' in dir() else []}")

print()

# ========== 第二次执行:从 Checkpoint 恢复 ==========

print("=" * 50)

print("第二次执行:从 Checkpoint 恢复")

print("=" * 50)

# 同一个 thread_id,自动从最近的 Checkpoint 恢复

result = app.invoke(None, config) # 传入 None,表示从存档点继续

print(f"最终结果: {result['recommendation']}")

六、运行结果 / 流程图

运行输出:

复制代码

==================================================

第一次执行:模拟中断

==================================================

[understand] 理解需求: 想买一个打游戏快的笔记本电脑

[search] 搜索商品中...

[compare] 对比商品... (模拟中断点)

中断了: 模拟中断:服务器崩了

==================================================

第二次执行:从 Checkpoint 恢复

==================================================

[compare] 已完成,跳过

[recommend] 推荐: 商品A

最终结果: 强烈推荐 商品A!

可以看到恢复时,compare 检测到已完成就直接跳过了,recommend 从之前保存的 products 继续执行。

七、项目中怎么用

实际场景:

长任务恢复:用户提交一个复杂的数据分析任务,跑了 2 小时后服务器重启。从 Checkpoint 恢复,不用重新跑。

页面刷新保留状态:用户在 AI 助手页面填写了一个长表单,刷新后继续填,不用重新填。

多轮对话恢复:用户和 Agent 对话了 10 轮,中断了。重新打开时从第 10 轮的 Checkpoint 继续。

注意点:

设计幂等的 Node:每个 Node 要么完全成功,要么完全失败,避免中间状态丢失。

分离关键数据和临时数据:Checkpoint 只保存关键数据,减少存储开销。

设置合理的 Checkpoint 过期时间:避免存储无限增长。

八、总结 + 下篇预告

核心要点:

Checkpoint = State 快照,在 Node 执行完成后保存

恢复时传入同一个 thread_id,Agent 自动找到最近的 Checkpoint 继续执行

Checkpoint 让 Agent 不怕中断,用户不用重新等待

存储方式:开发用 MemorySaver,生产用 PostgresSaver

下篇预告:下一篇我们将探讨《Agent 的 Time Travel 是什么?》,理解如何利用 Checkpoint 实现"回到过去"------不是简单恢复,而是像时间旅行一样回到任意之前的状态。

延伸阅读:

LangGraph Checkpoint 文档:

相关推荐

纳尔出装

英雄联盟纳尓到底出什么装备好! 最佳答案你好,出门装:多兰剑+1红顺风核心装备:三相之力+破败。这两件装备是目前属性非常强大,并且也

08-01 分类 365bet官网是多少

复盘拼多多:为什么能持续低价且盈利

拼多多的低价能力,究竟是如何形成的?关于这个问题,或许许多人都在尝试找到答案。而本篇文章里,作者就从「供给-人群-算法-生态-供给」

07-27 分类 best365官网登录入口

世界个人所得税最高的十个国家

声明:世界个人所得税最高的十个国家排行榜,是MAIGOO小编主要根据全球156个国家(地区)个人所得税税率由多到少进行排序,数据主要依据全

09-19 分类 365bet网页版

跨境电商最常用的跨境收款平台有哪些?

随着全球跨境电商行业规模的不断扩大以及迭代速度的加快,跨境电商商家迫切需要更高效率、更低成本的金融支付方案,来保障企业高速发展

08-21 分类 365bet网页版

秦舞阳为什么怂了

秦舞阳为什么怂了? 倒​不是因为秦舞阳姓秦,是秦国逃兵(孙子),不敢刺秦。 秦舞阳​仅凭年轻时杀过人就名声大噪,实则只会花拳绣腿

12-08 分类 365bet网页版