Postgres Checkpointer 实战:优化数据持久化性能的策略

article/2025/7/2 13:23:48

如果你正在经历一段格外艰难的人生,请允许我祝福你可以从今天开始,邂逅最棒的一年。
——莉兹·克里莫

本文将使用 langgraph-checkpoint-postgres 库,将 Postgres 作为后端来持久化 checkpoint 状态。温馨提示:本文搭配 jupyter-lab 食用更佳。

需求背景

如果您正在使用 LangGraph API,则无需手动实现 checkpointer。API 会自动为您处理 checkpointing。本指南适用于您在自己的自定义服务器中实现 LangGraph 的情况。

1、Checkpointer持久化的核心作用

LangChain框架中Checkpointer持久化的核心价值在于保存和恢复复杂任务的状态。大语言模型(LLM)应用常涉及多步骤链式调用或长时间运行的任务,中断后重新执行成本高昂。

from langchain.checkpoint import FileCheckpointer
checkpointer = FileCheckpointer(file_path="./chat_state.json")

2、中断恢复与连续性保障

对话应用或长期运行流程需要保持上下文一致性。Checkpointer记录链式调用中间状态,在系统崩溃或人工暂停后,可从最后记录点继续执行而非重新开始。典型场景包括:

  • 多轮对话历史保存
  • 分阶段文档处理进度
  • API调用失败后的重试基准点
# 保存状态示例
agent.run("开始分析报告", callbacks=[checkpointer])# 恢复状态示例
loaded_state = checkpointer.load()
agent.resume(loaded_state)

3、实验与调试支持

开发过程中,Checkpointer允许从特定检查点反复测试流程分支。相比每次从头运行,能快速验证特定环节的修改效果,显著提升迭代效率。

# 调试时加载特定检查点
test_state = checkpointer.load_at_step(step=3)
debug_agent(test_state)

4、分布式系统协同

微服务架构中,不同组件可能在不同节点执行。Checkpointer提供的序列化状态可实现:

  • 工作负载重新分配
  • 故障节点任务转移
  • 多个worker协同处理
// 典型检查点数据结构
{"step_id": "analyze_chapter3","artifacts": {"extracted_text": "...","embeddings": [...]},"metadata": {"timestamp": "2023-07-15T08:30:00","version": "llm-v2.3"}
}

5、版本控制与审计追踪

持久化检查点形成不可变的任务历史记录,可用于:

  • 回滚到先前版本
  • 比较不同参数的效果
  • 合规性审计跟踪
# 检查点版本管理
checkpointer.list_versions()  # 返回所有保存的版本
checkpointer.revert(version="20230715_v1") 

6、性能优化手段

选择性持久化能避免重复计算。对于资源密集型操作(如大型文档嵌入),Checkpointer存储中间结果后,后续运行可直接复用。

# 条件性检查点保存
if not checkpointer.exists("doc_embedding"):embeddings = compute_embeddings(text)checkpointer.save("doc_embedding", embeddings)
else:embeddings = checkpointer.load("doc_embedding")
```### Checkpointer持久化的核心作用LangChain框架中Checkpointer持久化的核心价值在于保存和恢复复杂任务的状态。大语言模型(LLM)应用常涉及多步骤链式调用或长时间运行的任务,中断后重新执行成本高昂。```python
from langchain.checkpoint import FileCheckpointer
checkpointer = FileCheckpointer(file_path="./chat_state.json")

7、中断恢复与连续性保障

对话应用或长期运行流程需要保持上下文一致性。Checkpointer记录链式调用中间状态,在系统崩溃或人工暂停后,可从最后记录点继续执行而非重新开始。典型场景包括:

  • 多轮对话历史保存
  • 分阶段文档处理进度
  • API调用失败后的重试基准点
# 保存状态示例
agent.run("开始分析报告", callbacks=[checkpointer])# 恢复状态示例
loaded_state = checkpointer.load()
agent.resume(loaded_state)

8、实验与调试支持

开发过程中,Checkpointer允许从特定检查点反复测试流程分支。相比每次从头运行,能快速验证特定环节的修改效果,显著提升迭代效率。

# 调试时加载特定检查点
test_state = checkpointer.load_at_step(step=3)
debug_agent(test_state)

9、分布式系统协同

微服务架构中,不同组件可能在不同节点执行。Checkpointer提供的序列化状态可实现:

  • 工作负载重新分配
  • 故障节点任务转移
  • 多个worker协同处理
// 典型检查点数据结构
{"step_id": "analyze_chapter3","artifacts": {"extracted_text": "...","embeddings": [...]},"metadata": {"timestamp": "2023-07-15T08:30:00","version": "llm-v2.3"}
}

10、版本控制与审计追踪

持久化检查点形成不可变的任务历史记录,可用于:

  • 回滚到先前版本
  • 比较不同参数的效果
  • 合规性审计跟踪
# 检查点版本管理
checkpointer.list_versions()  # 返回所有保存的版本
checkpointer.revert(version="20230715_v1") 

11、性能优化手段

选择性持久化能避免重复计算。对于资源密集型操作(如大型文档嵌入),Checkpointer存储中间结果后,后续运行可直接复用。

# 条件性检查点保存
if not checkpointer.exists("doc_embedding"):embeddings = compute_embeddings(text)checkpointer.save("doc_embedding", embeddings)
else:embeddings = checkpointer.load("doc_embedding")

一、Docker安装PostgreSQL数据库

# 拉取镜像
sudo docker pull postgres:15

在这里插入图片描述

# 创建本地卷
sudo docker volume create pgdata

数据卷可以在容器之间共享和重用,默认会一直存在,即使容器被删除(docker volume inspect pgdata可查看数据卷的本地位置)。

# 运行一个PostgreSQL数据库实例
sudo docker run --name pgsql -p 5432:5432 -e POSTGRES_PASSWORD=abc123 -v pgdata:/home/sam/postgresql/data --restart=always -d postgres:15

二、pgAdmin访问

https://www.pgadmin.org/download/

#
# Setup the repository
## Install the public key for the repository (if not done previously):
curl -fsS https://www.pgadmin.org/static/packages_pgadmin_org.pub | sudo gpg --dearmor -o /usr/share/keyrings/packages-pgadmin-org.gpg# Create the repository configuration file:
sudo sh -c 'echo "deb [signed-by=/usr/share/keyrings/packages-pgadmin-org.gpg] https://ftp.postgresql.org/pub/pgadmin/pgadmin4/apt/$(lsb_release -cs) pgadmin4 main" > /etc/apt/sources.list.d/pgadmin4.list && apt update'#
# Install pgAdmin
## Install for both desktop and web modes:
sudo apt install pgadmin4# Install for desktop mode only:
sudo apt install pgadmin4-desktop# Install for web mode only: 
sudo apt install pgadmin4-web # Configure the webserver, if you installed pgadmin4-web:
sudo /usr/pgadmin4/bin/setup-web.sh

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

三、安装依赖

pip install -U psycopg psycopg-pool langgraph langgraph-checkpoint-postgres

四、为图定义模型和工具

from pydantic import SecretStr
import osos.environ["OPENAI_BASE_URL"] = "https://api.siliconflow.cn/v1/"
os.environ["OPENAI_API_KEY"] = "sk-xxx"from langchain.chat_models import init_chat_modelmodel = init_chat_model("Qwen/Qwen3-8B", model_provider="openai")
from typing import Literalfrom langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
from langgraph.checkpoint.postgres import PostgresSaver
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver@tool
def get_weather(city: Literal["北京", "上海"]):"""使用该工具获取城市天气信息"""if city == "北京":return "晴天"elif city == "上海":return "多云"else:raise AssertionError("未知的城市")tools = [get_weather]

五、使用同步连接

这将设置一个到数据库的同步连接。同步连接以阻塞方式执行操作,这意味着每个操作都会等待完成,然后才进行下一个操作。DB_URI 是数据库连接 URI,包含连接 PostgreSQL 数据库使用的协议、身份验证以及数据库运行的主机。connection_kwargs 字典定义了数据库连接的附加参数。

DB_URI = "postgresql://postgres:abc123@localhost:5432/postgres?sslmode=disable"
connection_kwargs = {"autocommit": True,"prepare_threshold": 0,
}

1、使用连接池

这管理着一个可重用数据库连接池:

  • 优点:高效利用资源,提高频繁连接的性能
  • 适用于:具有许多短暂数据库操作的应用程序
from psycopg_pool import ConnectionPoolwith ConnectionPool(# Example configurationconninfo=DB_URI,max_size=20,kwargs=connection_kwargs,
) as pool:checkpointer = PostgresSaver(pool)# NOTE: you need to call .setup() the first time you're using your checkpointercheckpointer.setup()graph = create_react_agent(model, tools=tools, checkpointer=checkpointer)config = {"configurable": {"thread_id": "1"}}res = graph.invoke({"messages": [("human", "今天北京天气如何?")]}, config)# 读取历史信息checkpoint = checkpointer.get(config)
res
{'messages': [HumanMessage(content='今天北京天气如何?', additional_kwargs={}, response_metadata={}, id='e5ea0799-173e-4e1b-8940-91e5a164bc64'),AIMessage(content='\n\n', additional_kwargs={'tool_calls': [{'id': '0196d7134c393b91618a7d1b142a4e26', 'function': {'arguments': ' {"city": "北京"}', 'name': 'get_weather'}, 'type': 'function', 'index': 0}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 96, 'prompt_tokens': 165, 'total_tokens': 261, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 88, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Qwen/Qwen3-8B', 'system_fingerprint': '', 'id': '0196d71344be98b7bf1742796c139083', 'service_tier': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run--29759721-c1c2-4e6f-a8b3-e920b91d763b-0', tool_calls=[{'name': 'get_weather', 'args': {'city': '北京'}, 'id': '0196d7134c393b91618a7d1b142a4e26', 'type': 'tool_call'}], usage_metadata={'input_tokens': 165, 'output_tokens': 96, 'total_tokens': 261, 'input_token_details': {}, 'output_token_details': {'reasoning': 88}}),ToolMessage(content='晴天', name='get_weather', id='974cabfa-8742-4257-b836-460dbd17b657', tool_call_id='0196d7134c393b91618a7d1b142a4e26'),AIMessage(content='\n\n今天北京的天气是晴天,阳光明媚,适合外出活动。记得做好防晒措施哦!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 172, 'prompt_tokens': 208, 'total_tokens': 380, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 150, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Qwen/Qwen3-8B', 'system_fingerprint': '', 'id': '0196d7134dc1d2ed7c8e61f6e72ce537', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--835d7789-bdc8-4fa2-96f4-59d4f44c4fd6-0', usage_metadata={'input_tokens': 208, 'output_tokens': 172, 'total_tokens': 380, 'input_token_details': {}, 'output_token_details': {'reasoning': 150}})]}
checkpoint
{'v': 3,'id': '1f032037-78cc-615b-8003-a6736ebdf047','ts': '2025-05-16T03:11:32.048918+00:00','pending_sends': [],'versions_seen': {'agent': {'branch:to:agent': '00000000000000000000000000000004.0.2739958167978239'},'tools': {'branch:to:tools': '00000000000000000000000000000003.0.603242543748743'},'__input__': {},'__start__': {'__start__': '00000000000000000000000000000001.0.013718584308971438'}},'channel_versions': {'messages': '00000000000000000000000000000005.0.11823643751462909','__start__': '00000000000000000000000000000002.0.8037870172415423','branch:to:agent': '00000000000000000000000000000005.0.3650025119425234','branch:to:tools': '00000000000000000000000000000004.0.5015268184742752'},'channel_values': {'messages': [HumanMessage(content='今天北京天气如何?', additional_kwargs={}, response_metadata={}, id='e5ea0799-173e-4e1b-8940-91e5a164bc64'),AIMessage(content='\n\n', additional_kwargs={'tool_calls': [{'id': '0196d7134c393b91618a7d1b142a4e26', 'function': {'arguments': ' {"city": "北京"}', 'name': 'get_weather'}, 'type': 'function', 'index': 0}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 96, 'prompt_tokens': 165, 'total_tokens': 261, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 88, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Qwen/Qwen3-8B', 'system_fingerprint': '', 'id': '0196d71344be98b7bf1742796c139083', 'service_tier': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run--29759721-c1c2-4e6f-a8b3-e920b91d763b-0', tool_calls=[{'name': 'get_weather', 'args': {'city': '北京'}, 'id': '0196d7134c393b91618a7d1b142a4e26', 'type': 'tool_call'}], usage_metadata={'input_tokens': 165, 'output_tokens': 96, 'total_tokens': 261, 'input_token_details': {}, 'output_token_details': {'reasoning': 88}}),ToolMessage(content='晴天', name='get_weather', id='974cabfa-8742-4257-b836-460dbd17b657', tool_call_id='0196d7134c393b91618a7d1b142a4e26'),AIMessage(content='\n\n今天北京的天气是晴天,阳光明媚,适合外出活动。记得做好防晒措施哦!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 172, 'prompt_tokens': 208, 'total_tokens': 380, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 150, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Qwen/Qwen3-8B', 'system_fingerprint': '', 'id': '0196d7134dc1d2ed7c8e61f6e72ce537', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--835d7789-bdc8-4fa2-96f4-59d4f44c4fd6-0', usage_metadata={'input_tokens': 208, 'output_tokens': 172, 'total_tokens': 380, 'input_token_details': {}, 'output_token_details': {'reasoning': 150}})]}}

2、使用单个连接

这创建了一个到数据库的单个专用连接:

  • 优点:使用简单,适用于较长的事务
  • 适用于:具有较少、较长数据库操作的应用程序
from psycopg import Connectionwith Connection.connect(DB_URI, **connection_kwargs) as conn:checkpointer = PostgresSaver(conn)# NOTE: you need to call .setup() the first time you're using your checkpointer# checkpointer.setup()graph = create_react_agent(model, tools=tools, checkpointer=checkpointer)config = {"configurable": {"thread_id": "2"}}res = graph.invoke({"messages": [("human", "今天上海天气如何")]}, config)checkpoint_tuple = checkpointer.get_tuple(config)
checkpoint_tuple
CheckpointTuple(config={'configurable': {'thread_id': '2', 'checkpoint_ns': '', 'checkpoint_id': '1f03203d-ba45-60fc-8003-ef82a83d5b66'}}, checkpoint={'v': 3, 'id': '1f03203d-ba45-60fc-8003-ef82a83d5b66', 'ts': '2025-05-16T03:14:19.975490+00:00', 'pending_sends': [], 'versions_seen': {'agent': {'branch:to:agent': '00000000000000000000000000000004.0.3111923409346694'}, 'tools': {'branch:to:tools': '00000000000000000000000000000003.0.6987713872806675'}, '__input__': {}, '__start__': {'__start__': '00000000000000000000000000000001.0.9943878685247373'}}, 'channel_versions': {'messages': '00000000000000000000000000000005.0.7602821276570259', '__start__': '00000000000000000000000000000002.0.293618470215541', 'branch:to:agent': '00000000000000000000000000000005.0.5778995140285749', 'branch:to:tools': '00000000000000000000000000000004.0.3416019952246956'}, 'channel_values': {'messages': [HumanMessage(content='今天上海天气如何', additional_kwargs={}, response_metadata={}, id='7eadd00c-00ce-49b3-8349-37cf445305e0'), AIMessage(content='\n\n', additional_kwargs={'tool_calls': [{'id': '0196d715ce404add2415fd6212a8973c', 'function': {'arguments': ' {"city": "上海"}', 'name': 'get_weather'}, 'type': 'function', 'index': 0}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 94, 'prompt_tokens': 164, 'total_tokens': 258, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 86, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Qwen/Qwen3-8B', 'system_fingerprint': '', 'id': '0196d715bb9372d38c8a60da334c7fc8', 'service_tier': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run--94765d3d-8b2c-49e3-a006-56b37116bf78-0', tool_calls=[{'name': 'get_weather', 'args': {'city': '上海'}, 'id': '0196d715ce404add2415fd6212a8973c', 'type': 'tool_call'}], usage_metadata={'input_tokens': 164, 'output_tokens': 94, 'total_tokens': 258, 'input_token_details': {}, 'output_token_details': {'reasoning': 86}}), ToolMessage(content='多云', name='get_weather', id='5b8d14c1-dbbf-4a0f-891c-9541d42f9cbc', tool_call_id='0196d715ce404add2415fd6212a8973c'), AIMessage(content='\n\n上海今天天气多云,建议出门可以准备一把小伞,或者看看是否需要搭配外套哦~', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 157, 'prompt_tokens': 208, 'total_tokens': 365, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 134, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Qwen/Qwen3-8B', 'system_fingerprint': '', 'id': '0196d715d09ee98c6f98d1ac52cd503a', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--f0893e0b-f74c-4c7a-98d6-140e974b5454-0', usage_metadata={'input_tokens': 208, 'output_tokens': 157, 'total_tokens': 365, 'input_token_details': {}, 'output_token_details': {'reasoning': 134}})]}}, metadata={'step': 3, 'source': 'loop', 'writes': {'agent': {'messages': [AIMessage(content='\n\n上海今天天气多云,建议出门可以准备一把小伞,或者看看是否需要搭配外套哦~', additional_kwargs={'refusal': None}, response_metadata={'id': '0196d715d09ee98c6f98d1ac52cd503a', 'logprobs': None, 'model_name': 'Qwen/Qwen3-8B', 'token_usage': {'total_tokens': 365, 'prompt_tokens': 208, 'completion_tokens': 157, 'prompt_tokens_details': None, 'completion_tokens_details': {'audio_tokens': None, 'reasoning_tokens': 134, 'accepted_prediction_tokens': None, 'rejected_prediction_tokens': None}}, 'service_tier': None, 'finish_reason': 'stop', 'system_fingerprint': ''}, id='run--f0893e0b-f74c-4c7a-98d6-140e974b5454-0', usage_metadata={'input_tokens': 208, 'output_tokens': 157, 'total_tokens': 365, 'input_token_details': {}, 'output_token_details': {'reasoning': 134}})]}}, 'parents': {}, 'thread_id': '2'}, parent_config={'configurable': {'thread_id': '2', 'checkpoint_ns': '', 'checkpoint_id': '1f03203d-7a6e-6d79-8002-e176fcb372de'}}, pending_writes=[])

3、使用连接字符串

这基于连接字符串创建一个连接:

  • 优点:简单性,封装连接详细信息
  • 适用于:快速设置或连接详细信息以字符串形式提供时
with PostgresSaver.from_conn_string(DB_URI) as checkpointer:graph = create_react_agent(model, tools=tools, checkpointer=checkpointer)config = {"configurable": {"thread_id": "3"}}res = graph.invoke({"messages": [("human", "明天北京天气如何")]}, config)checkpoint_tuples = list(checkpointer.list(config))
checkpoint_tuples
[CheckpointTuple(config={'configurable': {'thread_id': '3', 'checkpoint_ns': '', 'checkpoint_id': '1f032041-deaa-6466-8003-c6fab3893072'}}, checkpoint={'v': 3, 'id': '1f032041-deaa-6466-8003-c6fab3893072', 'ts': '2025-05-16T03:16:11.166003+00:00', 'pending_sends': [], 'versions_seen': {'agent': {'branch:to:agent': '00000000000000000000000000000004.0.5008888481496694'}, 'tools': {'branch:to:tools': '00000000000000000000000000000003.0.2442059679188554'}, '__input__': {}, '__start__': {'__start__': '00000000000000000000000000000001.0.2637731363043043'}}, 'channel_versions': {'messages': '00000000000000000000000000000005.0.8936397767083367', '__start__': '00000000000000000000000000000002.0.7662491731519978', 'branch:to:agent': '00000000000000000000000000000005.0.38094316679119766', 'branch:to:tools': '00000000000000000000000000000004.0.19293298057002828'}, 'channel_values': {'messages': [HumanMessage(content='明天北京天气如何', additional_kwargs={}, response_metadata={}, id='23e2b3c9-22d9-4dc1-a89f-97f72edb7def'), AIMessage(content='\n\n', additional_kwargs={'tool_calls': [{'id': '0196d7177d081ad977161456336fdbac', 'function': {'arguments': ' {"city": "北京"}', 'name': 'get_weather'}, 'type': 'function', 'index': 0}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 158, 'prompt_tokens': 164, 'total_tokens': 322, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 150, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Qwen/Qwen3-8B', 'system_fingerprint': '', 'id': '0196d71774145483ac5bbcd15d13a722', 'service_tier': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run--c3798487-5ba2-4f72-8fed-6cc5c134c28e-0', tool_calls=[{'name': 'get_weather', 'args': {'city': '北京'}, 'id': '0196d7177d081ad977161456336fdbac', 'type': 'tool_call'}], usage_metadata={'input_tokens': 164, 'output_tokens': 158, 'total_tokens': 322, 'input_token_details': {}, 'output_token_details': {'reasoning': 150}}), ToolMessage(content='晴天', name='get_weather', id='689f2cc4-6f78-4802-abe2-cc3ccbec04dc', tool_call_id='0196d7177d081ad977161456336fdbac'), AIMessage(content='\n\n明天北京的天气是晴天,阳光明媚,适合外出活动。记得做好防晒措施哦!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 144, 'prompt_tokens': 207, 'total_tokens': 351, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 122, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Qwen/Qwen3-8B', 'system_fingerprint': '', 'id': '0196d7177e3b7ef7c19e1f3341951fa1', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--45a35256-995f-437d-84ae-8bac88fecc5b-0', usage_metadata={'input_tokens': 207, 'output_tokens': 144, 'total_tokens': 351, 'input_token_details': {}, 'output_token_details': {'reasoning': 122}})]}}, metadata={'step': 3, 'source': 'loop', 'writes': {'agent': {'messages': [AIMessage(content='\n\n明天北京的天气是晴天,阳光明媚,适合外出活动。记得做好防晒措施哦!', additional_kwargs={'refusal': None}, response_metadata={'id': '0196d7177e3b7ef7c19e1f3341951fa1', 'logprobs': None, 'model_name': 'Qwen/Qwen3-8B', 'token_usage': {'total_tokens': 351, 'prompt_tokens': 207, 'completion_tokens': 144, 'prompt_tokens_details': None, 'completion_tokens_details': {'audio_tokens': None, 'reasoning_tokens': 122, 'accepted_prediction_tokens': None, 'rejected_prediction_tokens': None}}, 'service_tier': None, 'finish_reason': 'stop', 'system_fingerprint': ''}, id='run--45a35256-995f-437d-84ae-8bac88fecc5b-0', usage_metadata={'input_tokens': 207, 'output_tokens': 144, 'total_tokens': 351, 'input_token_details': {}, 'output_token_details': {'reasoning': 122}})]}}, 'parents': {}, 'thread_id': '3'}, parent_config={'configurable': {'thread_id': '3', 'checkpoint_ns': '', 'checkpoint_id': '1f032041-92c4-67f1-8002-baf2b9717c21'}}, pending_writes=[]),CheckpointTuple(config={'configurable': {'thread_id': '3', 'checkpoint_ns': '', 'checkpoint_id': '1f032041-92c4-67f1-8002-baf2b9717c21'}}, checkpoint={'v': 3, 'id': '1f032041-92c4-67f1-8002-baf2b9717c21', 'ts': '2025-05-16T03:16:03.207567+00:00', 'pending_sends': [], 'versions_seen': {'agent': {'branch:to:agent': '00000000000000000000000000000002.0.9220065296348962'}, 'tools': {'branch:to:tools': '00000000000000000000000000000003.0.2442059679188554'}, '__input__': {}, '__start__': {'__start__': '00000000000000000000000000000001.0.2637731363043043'}}, 'channel_versions': {'messages': '00000000000000000000000000000004.0.3418660141913067', '__start__': '00000000000000000000000000000002.0.7662491731519978', 'branch:to:agent': '00000000000000000000000000000004.0.5008888481496694', 'branch:to:tools': '00000000000000000000000000000004.0.19293298057002828'}, 'channel_values': {'messages': [HumanMessage(content='明天北京天气如何', additional_kwargs={}, response_metadata={}, id='23e2b3c9-22d9-4dc1-a89f-97f72edb7def'), AIMessage(content='\n\n', additional_kwargs={'tool_calls': [{'id': '0196d7177d081ad977161456336fdbac', 'function': {'arguments': ' {"city": "北京"}', 'name': 'get_weather'}, 'type': 'function', 'index': 0}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 158, 'prompt_tokens': 164, 'total_tokens': 322, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 150, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Qwen/Qwen3-8B', 'system_fingerprint': '', 'id': '0196d71774145483ac5bbcd15d13a722', 'service_tier': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run--c3798487-5ba2-4f72-8fed-6cc5c134c28e-0', tool_calls=[{'name': 'get_weather', 'args': {'city': '北京'}, 'id': '0196d7177d081ad977161456336fdbac', 'type': 'tool_call'}], usage_metadata={'input_tokens': 164, 'output_tokens': 158, 'total_tokens': 322, 'input_token_details': {}, 'output_token_details': {'reasoning': 150}}), ToolMessage(content='晴天', name='get_weather', id='689f2cc4-6f78-4802-abe2-cc3ccbec04dc', tool_call_id='0196d7177d081ad977161456336fdbac')], 'branch:to:agent': None}}, metadata={'step': 2, 'source': 'loop', 'writes': {'tools': {'messages': [ToolMessage(content='晴天', name='get_weather', id='689f2cc4-6f78-4802-abe2-cc3ccbec04dc', tool_call_id='0196d7177d081ad977161456336fdbac')]}}, 'parents': {}, 'thread_id': '3'}, parent_config={'configurable': {'thread_id': '3', 'checkpoint_ns': '', 'checkpoint_id': '1f032041-92c0-6615-8001-6e9be51e90b6'}}, pending_writes=[('7d8bc83b-13ee-3cc6-b8bc-f563a07a74ac', 'messages', [AIMessage(content='\n\n明天北京的天气是晴天,阳光明媚,适合外出活动。记得做好防晒措施哦!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 144, 'prompt_tokens': 207, 'total_tokens': 351, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 122, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Qwen/Qwen3-8B', 'system_fingerprint': '', 'id': '0196d7177e3b7ef7c19e1f3341951fa1', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--45a35256-995f-437d-84ae-8bac88fecc5b-0', usage_metadata={'input_tokens': 207, 'output_tokens': 144, 'total_tokens': 351, 'input_token_details': {}, 'output_token_details': {'reasoning': 122}})])]),CheckpointTuple(config={'configurable': {'thread_id': '3', 'checkpoint_ns': '', 'checkpoint_id': '1f032041-92c0-6615-8001-6e9be51e90b6'}}, checkpoint={'v': 3, 'id': '1f032041-92c0-6615-8001-6e9be51e90b6', 'ts': '2025-05-16T03:16:03.205879+00:00', 'pending_sends': [], 'versions_seen': {'agent': {'branch:to:agent': '00000000000000000000000000000002.0.9220065296348962'}, '__input__': {}, '__start__': {'__start__': '00000000000000000000000000000001.0.2637731363043043'}}, 'channel_versions': {'messages': '00000000000000000000000000000003.0.6752645854463857', '__start__': '00000000000000000000000000000002.0.7662491731519978', 'branch:to:agent': '00000000000000000000000000000003.0.14624747432252805', 'branch:to:tools': '00000000000000000000000000000003.0.2442059679188554'}, 'channel_values': {'messages': [HumanMessage(content='明天北京天气如何', additional_kwargs={}, response_metadata={}, id='23e2b3c9-22d9-4dc1-a89f-97f72edb7def'), AIMessage(content='\n\n', additional_kwargs={'tool_calls': [{'id': '0196d7177d081ad977161456336fdbac', 'function': {'arguments': ' {"city": "北京"}', 'name': 'get_weather'}, 'type': 'function', 'index': 0}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 158, 'prompt_tokens': 164, 'total_tokens': 322, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 150, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Qwen/Qwen3-8B', 'system_fingerprint': '', 'id': '0196d71774145483ac5bbcd15d13a722', 'service_tier': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run--c3798487-5ba2-4f72-8fed-6cc5c134c28e-0', tool_calls=[{'name': 'get_weather', 'args': {'city': '北京'}, 'id': '0196d7177d081ad977161456336fdbac', 'type': 'tool_call'}], usage_metadata={'input_tokens': 164, 'output_tokens': 158, 'total_tokens': 322, 'input_token_details': {}, 'output_token_details': {'reasoning': 150}})], 'branch:to:tools': None}}, metadata={'step': 1, 'source': 'loop', 'writes': {'agent': {'messages': [AIMessage(content='\n\n', additional_kwargs={'refusal': None, 'tool_calls': [{'id': '0196d7177d081ad977161456336fdbac', 'type': 'function', 'index': 0, 'function': {'name': 'get_weather', 'arguments': ' {"city": "北京"}'}}]}, response_metadata={'id': '0196d71774145483ac5bbcd15d13a722', 'logprobs': None, 'model_name': 'Qwen/Qwen3-8B', 'token_usage': {'total_tokens': 322, 'prompt_tokens': 164, 'completion_tokens': 158, 'prompt_tokens_details': None, 'completion_tokens_details': {'audio_tokens': None, 'reasoning_tokens': 150, 'accepted_prediction_tokens': None, 'rejected_prediction_tokens': None}}, 'service_tier': None, 'finish_reason': 'tool_calls', 'system_fingerprint': ''}, id='run--c3798487-5ba2-4f72-8fed-6cc5c134c28e-0', tool_calls=[{'name': 'get_weather', 'args': {'city': '北京'}, 'id': '0196d7177d081ad977161456336fdbac', 'type': 'tool_call'}], usage_metadata={'input_tokens': 164, 'output_tokens': 158, 'total_tokens': 322, 'input_token_details': {}, 'output_token_details': {'reasoning': 150}})]}}, 'parents': {}, 'thread_id': '3'}, parent_config={'configurable': {'thread_id': '3', 'checkpoint_ns': '', 'checkpoint_id': '1f032041-7991-60fc-8000-030f778771d9'}}, pending_writes=[('159b69a7-5acb-ab28-29ce-4091542a3089', 'messages', [ToolMessage(content='晴天', name='get_weather', id='689f2cc4-6f78-4802-abe2-cc3ccbec04dc', tool_call_id='0196d7177d081ad977161456336fdbac')]), ('159b69a7-5acb-ab28-29ce-4091542a3089', 'branch:to:agent', None)]),CheckpointTuple(config={'configurable': {'thread_id': '3', 'checkpoint_ns': '', 'checkpoint_id': '1f032041-7991-60fc-8000-030f778771d9'}}, checkpoint={'v': 3, 'id': '1f032041-7991-60fc-8000-030f778771d9', 'ts': '2025-05-16T03:16:00.565062+00:00', 'pending_sends': [], 'versions_seen': {'__input__': {}, '__start__': {'__start__': '00000000000000000000000000000001.0.2637731363043043'}}, 'channel_versions': {'messages': '00000000000000000000000000000002.0.27439344645254793', '__start__': '00000000000000000000000000000002.0.7662491731519978', 'branch:to:agent': '00000000000000000000000000000002.0.9220065296348962'}, 'channel_values': {'messages': [HumanMessage(content='明天北京天气如何', additional_kwargs={}, response_metadata={}, id='23e2b3c9-22d9-4dc1-a89f-97f72edb7def')], 'branch:to:agent': None}}, metadata={'step': 0, 'source': 'loop', 'writes': None, 'parents': {}, 'thread_id': '3'}, parent_config={'configurable': {'thread_id': '3', 'checkpoint_ns': '', 'checkpoint_id': '1f032041-798f-689c-bfff-9180c905a847'}}, pending_writes=[('b7ff270f-dacb-945c-3ecd-20ba6dec52a4', 'messages', [AIMessage(content='\n\n', additional_kwargs={'tool_calls': [{'id': '0196d7177d081ad977161456336fdbac', 'function': {'arguments': ' {"city": "北京"}', 'name': 'get_weather'}, 'type': 'function', 'index': 0}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 158, 'prompt_tokens': 164, 'total_tokens': 322, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 150, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Qwen/Qwen3-8B', 'system_fingerprint': '', 'id': '0196d71774145483ac5bbcd15d13a722', 'service_tier': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run--c3798487-5ba2-4f72-8fed-6cc5c134c28e-0', tool_calls=[{'name': 'get_weather', 'args': {'city': '北京'}, 'id': '0196d7177d081ad977161456336fdbac', 'type': 'tool_call'}], usage_metadata={'input_tokens': 164, 'output_tokens': 158, 'total_tokens': 322, 'input_token_details': {}, 'output_token_details': {'reasoning': 150}})]), ('b7ff270f-dacb-945c-3ecd-20ba6dec52a4', 'branch:to:tools', None)]),CheckpointTuple(config={'configurable': {'thread_id': '3', 'checkpoint_ns': '', 'checkpoint_id': '1f032041-798f-689c-bfff-9180c905a847'}}, checkpoint={'v': 3, 'id': '1f032041-798f-689c-bfff-9180c905a847', 'ts': '2025-05-16T03:16:00.564439+00:00', 'pending_sends': [], 'versions_seen': {'__input__': {}}, 'channel_versions': {'__start__': '00000000000000000000000000000001.0.2637731363043043'}, 'channel_values': {'__start__': {'messages': [['human', '明天北京天气如何']]}}}, metadata={'step': -1, 'source': 'input', 'writes': {'__start__': {'messages': [['human', '明天北京天气如何']]}}, 'parents': {}, 'thread_id': '3'}, parent_config=None, pending_writes=[('8b412bef-d87d-76d2-05d1-bf7f5a97378c', 'messages', [['human', '明天北京天气如何']]), ('8b412bef-d87d-76d2-05d1-bf7f5a97378c', 'branch:to:agent', None)])]

六、使用异步连接

这将设置一个到数据库的异步连接。异步连接允许非阻塞数据库操作。这意味着应用程序的其他部分可以在等待数据库操作完成的同时继续运行。这在并发场景较高或处理 I/O 密集型操作时特别有用。

1、使用连接池

from psycopg_pool import AsyncConnectionPoolasync with AsyncConnectionPool(# Example configurationconninfo=DB_URI,max_size=20,kwargs=connection_kwargs,
) as pool:checkpointer = AsyncPostgresSaver(pool)# NOTE: you need to call .setup() the first time you're using your checkpointerawait checkpointer.setup()graph = create_react_agent(model, tools=tools, checkpointer=checkpointer)config = {"configurable": {"thread_id": "4"}}res = await graph.ainvoke({"messages": [("human", "明天上海天气如何")]}, config)checkpoint = await checkpointer.aget(config)
checkpoint
{'v': 3,'id': '1f032048-191d-60c4-8003-450932a97415','ts': '2025-05-16T03:18:58.356030+00:00','pending_sends': [],'versions_seen': {'agent': {'branch:to:agent': '00000000000000000000000000000004.0.9476460076898559'},'tools': {'branch:to:tools': '00000000000000000000000000000003.0.5075539263137369'},'__input__': {},'__start__': {'__start__': '00000000000000000000000000000001.0.9870325191514127'}},'channel_versions': {'messages': '00000000000000000000000000000005.0.31782154529391415','__start__': '00000000000000000000000000000002.0.35708852446726413','branch:to:agent': '00000000000000000000000000000005.0.9121909450060119','branch:to:tools': '00000000000000000000000000000004.0.7808599098083274'},'channel_values': {'messages': [HumanMessage(content='明天上海天气如何', additional_kwargs={}, response_metadata={}, id='b2535639-0388-467c-92ad-0c1c2ecde59d'),AIMessage(content='\n\n', additional_kwargs={'tool_calls': [{'id': '0196d719fcb95724c34629d42cfe99e2', 'function': {'arguments': ' {"city": "上海"}', 'name': 'get_weather'}, 'type': 'function', 'index': 0}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 122, 'prompt_tokens': 164, 'total_tokens': 286, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 114, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Qwen/Qwen3-8B', 'system_fingerprint': '', 'id': '0196d719f72bd0bb64ed95e8a578ff06', 'service_tier': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run--a1e1efc4-4634-4b2b-bd15-83586b77de21-0', tool_calls=[{'name': 'get_weather', 'args': {'city': '上海'}, 'id': '0196d719fcb95724c34629d42cfe99e2', 'type': 'tool_call'}], usage_metadata={'input_tokens': 164, 'output_tokens': 122, 'total_tokens': 286, 'input_token_details': {}, 'output_token_details': {'reasoning': 114}}),ToolMessage(content='多云', name='get_weather', id='9b137c50-5685-4d83-8d8a-ae96dc240959', tool_call_id='0196d719fcb95724c34629d42cfe99e2'),AIMessage(content='\n\n明天上海的天气为多云,建议出门可以准备伞具以防突然降雨,并注意防晒。如需了解更详细的天气信息,可以随时告知我!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 284, 'prompt_tokens': 208, 'total_tokens': 492, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 249, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Qwen/Qwen3-8B', 'system_fingerprint': '', 'id': '0196d719fd7b229416116b372cfc23ec', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--dbe5ac72-383f-4fd9-8b08-bb7016649334-0', usage_metadata={'input_tokens': 208, 'output_tokens': 284, 'total_tokens': 492, 'input_token_details': {}, 'output_token_details': {'reasoning': 249}})]}}

2、使用单个连接

from psycopg import AsyncConnectionasync with await AsyncConnection.connect(DB_URI, **connection_kwargs) as conn:checkpointer = AsyncPostgresSaver(conn)graph = create_react_agent(model, tools=tools, checkpointer=checkpointer)config = {"configurable": {"thread_id": "5"}}res = await graph.ainvoke({"messages": [("human", "后天北京天气如何")]}, config)checkpoint_tuple = await checkpointer.aget_tuple(config)
checkpoint_tuple
CheckpointTuple(config={'configurable': {'thread_id': '5', 'checkpoint_ns': '', 'checkpoint_id': '1f03204b-f7ba-617b-8003-8ba829ed9c2d'}}, checkpoint={'v': 3, 'id': '1f03204b-f7ba-617b-8003-8ba829ed9c2d', 'ts': '2025-05-16T03:20:42.229378+00:00', 'pending_sends': [], 'versions_seen': {'agent': {'branch:to:agent': '00000000000000000000000000000004.0.4841987625771813'}, 'tools': {'branch:to:tools': '00000000000000000000000000000003.0.8898034330376885'}, '__input__': {}, '__start__': {'__start__': '00000000000000000000000000000001.0.4325236474012414'}}, 'channel_versions': {'messages': '00000000000000000000000000000005.0.36731613104976735', '__start__': '00000000000000000000000000000002.0.865284452352145', 'branch:to:agent': '00000000000000000000000000000005.0.7688631247355521', 'branch:to:tools': '00000000000000000000000000000004.0.22510220545092896'}, 'channel_values': {'messages': [HumanMessage(content='后天北京天气如何', additional_kwargs={}, response_metadata={}, id='339339d5-2c8d-4f0c-8e39-667f4196c555'), AIMessage(content='\n\n', additional_kwargs={'tool_calls': [{'id': '0196d71bb51b6733bd79c1ee1f261b33', 'function': {'arguments': ' {"city": "北京"}', 'name': 'get_weather'}, 'type': 'function', 'index': 0}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 275, 'prompt_tokens': 165, 'total_tokens': 440, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 267, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Qwen/Qwen3-8B', 'system_fingerprint': '', 'id': '0196d71b77acc177b59cbc50667c0580', 'service_tier': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run--1090c017-5901-41f8-9191-00dee1a7fb9b-0', tool_calls=[{'name': 'get_weather', 'args': {'city': '北京'}, 'id': '0196d71bb51b6733bd79c1ee1f261b33', 'type': 'tool_call'}], usage_metadata={'input_tokens': 165, 'output_tokens': 275, 'total_tokens': 440, 'input_token_details': {}, 'output_token_details': {'reasoning': 267}}), ToolMessage(content='晴天', name='get_weather', id='37a3f432-b07e-4891-9b87-d176b5b5ff75', tool_call_id='0196d71bb51b6733bd79c1ee1f261b33'), AIMessage(content='\n\n北京后天的天气是晴天,适合外出活动,记得做好防晒哦!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 166, 'prompt_tokens': 208, 'total_tokens': 374, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 147, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Qwen/Qwen3-8B', 'system_fingerprint': '', 'id': '0196d71bb7b501e087b3ef82469a46df', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--d4d8be11-920c-430b-8f35-a9da47af3335-0', usage_metadata={'input_tokens': 208, 'output_tokens': 166, 'total_tokens': 374, 'input_token_details': {}, 'output_token_details': {'reasoning': 147}})]}}, metadata={'step': 3, 'source': 'loop', 'writes': {'agent': {'messages': [AIMessage(content='\n\n北京后天的天气是晴天,适合外出活动,记得做好防晒哦!', additional_kwargs={'refusal': None}, response_metadata={'id': '0196d71bb7b501e087b3ef82469a46df', 'logprobs': None, 'model_name': 'Qwen/Qwen3-8B', 'token_usage': {'total_tokens': 374, 'prompt_tokens': 208, 'completion_tokens': 166, 'prompt_tokens_details': None, 'completion_tokens_details': {'audio_tokens': None, 'reasoning_tokens': 147, 'accepted_prediction_tokens': None, 'rejected_prediction_tokens': None}}, 'service_tier': None, 'finish_reason': 'stop', 'system_fingerprint': ''}, id='run--d4d8be11-920c-430b-8f35-a9da47af3335-0', usage_metadata={'input_tokens': 208, 'output_tokens': 166, 'total_tokens': 374, 'input_token_details': {}, 'output_token_details': {'reasoning': 147}})]}}, 'parents': {}, 'thread_id': '5'}, parent_config={'configurable': {'thread_id': '5', 'checkpoint_ns': '', 'checkpoint_id': '1f03204b-e387-6790-8002-719fde470558'}}, pending_writes=[])

3、使用连接字符串

async with AsyncPostgresSaver.from_conn_string(DB_URI) as checkpointer:graph = create_react_agent(model, tools=tools, checkpointer=checkpointer)config = {"configurable": {"thread_id": "6"}}res = await graph.ainvoke({"messages": [("human", "后天上海天气如何")]}, config)checkpoint_tuples = [c async for c in checkpointer.alist(config)]
checkpoint_tuples
[CheckpointTuple(config={'configurable': {'thread_id': '6', 'checkpoint_ns': '', 'checkpoint_id': '1f032050-b6c5-65e0-8001-601198051338'}}, checkpoint={'v': 3, 'id': '1f032050-b6c5-65e0-8001-601198051338', 'ts': '2025-05-16T03:22:49.635980+00:00', 'pending_sends': [], 'versions_seen': {'agent': {'branch:to:agent': '00000000000000000000000000000002.0.8929341257310782'}, '__input__': {}, '__start__': {'__start__': '00000000000000000000000000000001.0.6643697680485742'}}, 'channel_versions': {'messages': '00000000000000000000000000000003.0.721638363372932', '__start__': '00000000000000000000000000000002.0.11953722026997815', 'branch:to:agent': '00000000000000000000000000000003.0.08189810500536276'}, 'channel_values': {'messages': [HumanMessage(content='后天上海天气如何', additional_kwargs={}, response_metadata={}, id='37425ee0-faa6-4c1d-9b7b-a898d52ecc65'), AIMessage(content='\n\n当前工具仅支持查询当前天气情况,无法获取后天天气信息。请问您是否需要了解上海当前的天气状况?或者是否有其他可以协助您的地方?', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 185, 'prompt_tokens': 165, 'total_tokens': 350, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 149, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Qwen/Qwen3-8B', 'system_fingerprint': '', 'id': '0196d71d96afa5548e5dfd9b7fe02261', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--edad30f3-8032-480f-8303-e339ac63dfa0-0', usage_metadata={'input_tokens': 165, 'output_tokens': 185, 'total_tokens': 350, 'input_token_details': {}, 'output_token_details': {'reasoning': 149}})]}}, metadata={'step': 1, 'source': 'loop', 'writes': {'agent': {'messages': [AIMessage(content='\n\n当前工具仅支持查询当前天气情况,无法获取后天天气信息。请问您是否需要了解上海当前的天气状况?或者是否有其他可以协助您的地方?', additional_kwargs={'refusal': None}, response_metadata={'id': '0196d71d96afa5548e5dfd9b7fe02261', 'logprobs': None, 'model_name': 'Qwen/Qwen3-8B', 'token_usage': {'total_tokens': 350, 'prompt_tokens': 165, 'completion_tokens': 185, 'prompt_tokens_details': None, 'completion_tokens_details': {'audio_tokens': None, 'reasoning_tokens': 149, 'accepted_prediction_tokens': None, 'rejected_prediction_tokens': None}}, 'service_tier': None, 'finish_reason': 'stop', 'system_fingerprint': ''}, id='run--edad30f3-8032-480f-8303-e339ac63dfa0-0', usage_metadata={'input_tokens': 165, 'output_tokens': 185, 'total_tokens': 350, 'input_token_details': {}, 'output_token_details': {'reasoning': 149}})]}}, 'parents': {}, 'thread_id': '6'}, parent_config={'configurable': {'thread_id': '6', 'checkpoint_ns': '', 'checkpoint_id': '1f032050-7351-6c98-8000-f62e8b117b4f'}}, pending_writes=[]),CheckpointTuple(config={'configurable': {'thread_id': '6', 'checkpoint_ns': '', 'checkpoint_id': '1f032050-7351-6c98-8000-f62e8b117b4f'}}, checkpoint={'v': 3, 'id': '1f032050-7351-6c98-8000-f62e8b117b4f', 'ts': '2025-05-16T03:22:42.563181+00:00', 'pending_sends': [], 'versions_seen': {'__input__': {}, '__start__': {'__start__': '00000000000000000000000000000001.0.6643697680485742'}}, 'channel_versions': {'messages': '00000000000000000000000000000002.0.6541960891137211', '__start__': '00000000000000000000000000000002.0.11953722026997815', 'branch:to:agent': '00000000000000000000000000000002.0.8929341257310782'}, 'channel_values': {'messages': [HumanMessage(content='后天上海天气如何', additional_kwargs={}, response_metadata={}, id='37425ee0-faa6-4c1d-9b7b-a898d52ecc65')], 'branch:to:agent': None}}, metadata={'step': 0, 'source': 'loop', 'writes': None, 'parents': {}, 'thread_id': '6'}, parent_config={'configurable': {'thread_id': '6', 'checkpoint_ns': '', 'checkpoint_id': '1f032050-7350-6dcc-bfff-46d64947994f'}}, pending_writes=[('6ea05cff-f255-2cd4-0e99-0f0637eb2a63', 'messages', [AIMessage(content='\n\n当前工具仅支持查询当前天气情况,无法获取后天天气信息。请问您是否需要了解上海当前的天气状况?或者是否有其他可以协助您的地方?', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 185, 'prompt_tokens': 165, 'total_tokens': 350, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 149, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'Qwen/Qwen3-8B', 'system_fingerprint': '', 'id': '0196d71d96afa5548e5dfd9b7fe02261', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--edad30f3-8032-480f-8303-e339ac63dfa0-0', usage_metadata={'input_tokens': 165, 'output_tokens': 185, 'total_tokens': 350, 'input_token_details': {}, 'output_token_details': {'reasoning': 149}})])]),CheckpointTuple(config={'configurable': {'thread_id': '6', 'checkpoint_ns': '', 'checkpoint_id': '1f032050-7350-6dcc-bfff-46d64947994f'}}, checkpoint={'v': 3, 'id': '1f032050-7350-6dcc-bfff-46d64947994f', 'ts': '2025-05-16T03:22:42.562806+00:00', 'pending_sends': [], 'versions_seen': {'__input__': {}}, 'channel_versions': {'__start__': '00000000000000000000000000000001.0.6643697680485742'}, 'channel_values': {'__start__': {'messages': [['human', '后天上海天气如何']]}}}, metadata={'step': -1, 'source': 'input', 'writes': {'__start__': {'messages': [['human', '后天上海天气如何']]}}, 'parents': {}, 'thread_id': '6'}, parent_config=None, pending_writes=[('225c6741-b759-049f-51cd-496b6230b72d', 'messages', [['human', '后天上海天气如何']]), ('225c6741-b759-049f-51cd-496b6230b72d', 'branch:to:agent', None)])]

七、数据表

从数据库中可以看到 checkpointer 创建的 4 张表

在这里插入图片描述

参考文档

  • https://github.langchain.ac.cn/langgraph/how-tos/persistence_postgres/

http://www.hkcw.cn/article/YrnCjAPNKm.shtml

相关文章

【清晰教程】利用Git工具将本地项目push上传至GitHub仓库中

Git 是一个分布式版本控制系统,由 Linus Torvalds 创建,用于有效、高速地处理从小到大的项目版本管理。GitHub 是一个基于 Git 的代码托管平台,提供了额外的协作和社交功能,使项目管理更加高效。它们为项目代码管理、团队协作和持…

雷达目标起伏特性简析

目录 一、五种起伏模型辨析 二、数学模型 一、五种起伏模型辨析 在《雷达搜索状态下的脉冲积累雷达方程-CSDN博客》中提到雷达方程模型是假定是非起伏目标,即目标RCS是稳定的,然而在真实的雷达搜索目标的过程中,目标的RCS总是变化的&#xf…

差分与共模的相互转化:

差分与共模的相互转化: 理想情况下,如果在差分对接收端,两个单端信号完全对称,即幅度相同、翻转方向相反、边沿对齐,那么共模信号将是恒定的电平,如图8-21a所示。但是实际中两个单端信号不可能完全对称,比如…

python-pptx去除形状默认的阴影

文章目录 效果原理1. 阴影继承机制解析2. XML层操作细节3. 注意事项 扩展应用1. 批量去除阴影2. 复合效果控制 效果 右边这个是直接添加一个形状。可以看到它会默认被赋予一个阴影。 然而,这个东西在特定的场合,其实是我们所不需要的。 那怎么把这个阴…

使用pydantic-i18n将fastapi的接口返回消息翻译成中文

使用fastapi时,发现接口报错的结果是英文的,自己的英语水平不太行,就想能不能翻译成中文,发现果然有办法。 先看结果: 实现方法: 参考链接pydantic-i18n PyPI 首先执行如下代码获取原有的英文翻译字典 …

说一说SAP系统从Non-Unicode到Unicode的演化

当前的 SAP 系统基本上都是 Unicode 系统。然而,在 SAP 的发展过程中,最初并不是 Unicode 系统,而是 Non-Unicode 系统。 1. 什么是 Non-Unicode 和 Unicode? Non-Unicode 系统: 在 Non-Unicode 系统中,字符…

特朗普马斯克发表“分手感言” 称赞成就与未来合作

5月30日,美国总统特朗普与美国企业家、政府效率部负责人埃隆马斯克在白宫召开新闻发布会。会上,特朗普对马斯克领导的“政府效率部”所取得的成绩表示赞赏,称该部门聘请了计算机领域的杰出人才。特朗普还提到,政府将致力于推动“政府效率部”削减政府开支政策的永久化。他指…

特朗普称将把进口钢铁关税提高至50% 加强行业保护

当地时间5月30日,美国总统特朗普宣布将进口钢铁的关税从25%提高至50%。美国白宫当天在社交媒体上发布公告,表示此举是为了进一步保护美国钢铁行业免受外国和不公平竞争的影响,并指出新的关税政策将从下周开始实施。特朗普曾于2月10日签署行政命令,对所有进口至美国的钢铁和…

警方:跳进兵马俑坑男子有精神疾病 警情通报发布

5月31日凌晨3点15分,新浪微博账号@平安临潼发布了一则警情通报。责任编辑:zhangxiaohua

5月全国各地经济社会发展观察 高质量发展新图景绘就

5月,万物繁茂。消费新动能持续涌动、夏粮生产力保丰收、就业岗位挖潜扩容、城市更新提升民生福祉……一派充满生机的高质量发展新图景在神州大地不断绘就。临近端午小长假,北京的宋女士这几天正忙着订火车票和酒店,准备利用假期去河南游玩。她说:“想去看石窟、吃水席,还要…

白皮精读:70页 2025 基于数据空间的金融数据可信流通研究报告【附全文阅读】

该报告聚焦金融数据可信流通,基于数据空间理念,分析全球及我国金融数据流通现状与挑战,提出包含典型场景、关键角色、流通模式及技术方案的可信流通框架,并通过中信银行、工银金租等多个实践案例验证其可行性。报告指出当前面临法…

【解决办法】Git报错error: src refspec main does not match any.

在命令行中使用 Git 进行 git push -u origin main 操作时遇到报错error: src refspec main does not match any。另一个错误信息是:error: failed to push some refs to https://github.com/xxx/xxx.git.这是在一个新设备操作时遇到的问题,之前没有注意…

聊聊在大模型推理强化学习中熵机制上的探索

原文首发:https://mp.weixin.qq.com/s/M-KqQWVI-Z7kYXvgD4WeHw 在RL训练LLM的过程中,普遍存在模型entropy迅速下降/性能迅速饱和的现象。这导致模型过度自信,进而削弱其探索能力,最终限制了性能的进一步提升。 我们通过广泛的实验…

基于地理特征金字塔的层次化AI定位方案:从人脑推理到卫星图谱的跨尺度匹配

基于地理特征金字塔的层次化AI定位方案:从人脑推理到卫星图谱的跨尺度匹配 一、仿生推理框架:从人脑定位逻辑到AI层次化建模 1.1 人类视觉定位的认知机制 神经科学研究表明,人类定位遵循"三级推理链": 宏观特征锚定&…

马哈蒂尔:中国不会轻易被美国击败,或将成世界第一强国

马来西亚前总理马哈蒂尔5月30日在东京出席“日经新闻”主办的“亚洲的未来”年度论坛时发表讲话,表示中国不会轻易被美国击败,并且看起来将成为世界第一强国。他认为,鉴于美国日趋保守的政策取向,美国将无法阻止中国的发展势头。马哈蒂尔批评了特朗普的关税政策,称其让美国…

汽车价格战再起 20多万的车14万卖 真降价还是假套路?

近期,汽车市场出现了一系列低价促销活动,如吉利帝豪标价2.99万元、奇瑞瑞虎3x售价3.49万元以及比亚迪海豹直降5.3万元。这些价格吸引了大量关注,但背后隐藏着一些套路。比亚迪于5月23日推出“限时一口价”促销活动后,吉利、奇瑞和凯迪拉克等品牌迅速跟进。然而,记者在走访…

原县委书记花上千万建10个厕所被查 豪华公厕引争议

刚摘掉深度贫困县帽子的通榆县,时任县委书记李德明就斥资上千万元建造了10个豪华水冲公厕。日前,吉林省纪委监委公开通报了4起形式主义、官僚主义典型问题,其中提到李德明搞劳民伤财的“形象工程”。2023年,他升任省农业农村厅厅长,直至2025年1月主动投案。李德明主政的通…

UHF RFID无源标签的芯片供电原理

作为无源物联网技术中最基础的一环,UHF RFID无源标签已经被广泛用于商超零售、物流仓储、图书档案、防伪溯源等量非常大的应用领域,仅2021年度,全球出货量就超过200亿。在实际应用中UHF RFID无源标签的芯片是究竟依靠什么来供电的呢? UHF RFID无源标签供电特点 1.借助无线…

C++?多态!!!

一、引言 众所周知,C有三大特性,它们分别是封装、继承和多态,在之前的文章中已经详细介绍过封装和继承了,今天我们将一起学习多态相关的知识,如果还想了解封装、继承相关的知识,可以跳转到以下链接&#xf…

耿爽回应美方抹黑:完全不可接受 反对无端指责和政治操弄

中国常驻联合国副代表耿爽在安理会审议向乌克兰提供武器问题时发言指出,战场上武器数量不断增加只会加剧对抗、延长战火。自俄乌冲突爆发以来,中方一直呼吁冲突当事方尽快停火止战。遗憾的是,乌克兰危机仍在持续,平民伤亡人数不断增加,令人深感痛心和忧虑。在当前俄乌双方…