持久化记忆SQLite

要把数据真正"落盘"(Persist to Disk),我们需要将 Checkpointer 从内存替换为真正的数据库。

对于本地轻量级落盘,SQLite 是最完美的首选方案。而在真实的生产环境中,如果面临高并发诉求,这套 Checkpointer 机制也可以直接桥接至 MySQL 进行持久化,或是利用 Redis 作为高速状态缓存。

我们先来看最快落地的 SQLite 落盘方案,只需要简单修改几行代码即可完成!


🛠️ 实现数据落盘(持久化到 SQLite)

LangGraph 官方提供了一个专门用于 SQLite 持久化的独立扩展包。

步骤一:安装依赖

打开你的终端,在虚拟环境中安装 SQLite 的 Checkpoint 包:

复制代码
pip install langgraph-checkpoint-sqlite
步骤二:修改后端的图编译逻辑 (test6.py)

打开你的 test6.py,拉到最底部构建图的地方。我们需要用 SqliteSaver 替换掉 MemorySaver

1. 修改头部的导入:

复制代码
# 删掉这行:from langgraph.checkpoint.memory import MemorySaver

# 替换为:
import sqlite3
from langgraph.checkpoint.sqlite import SqliteSaver

2. 修改图编译逻辑:

复制代码
# ==========================================
# 之前的旧代码:
# memory = MemorySaver()
# graph = builder.compile(checkpointer=memory, interrupt_before=["tester"])
# ==========================================

# 现在的落盘新代码:
# 建立与本地 SQLite 数据库文件的连接(如果文件不存在会自动创建)
# check_same_thread=False 是为了兼容 Streamlit 的多线程渲染机制
db_conn = sqlite3.connect("skills_creator_state.db", check_same_thread=False)
memory = SqliteSaver(db_conn)

graph = builder.compile(
    checkpointer=memory,
    interrupt_before=["tester"]
)
print(">>> Skills Creator 智能体引擎启动完毕!(状态已持久化至 SQLite)\n")

🧠 架构升级后的神奇效果

仅仅改动这几行代码,你的系统就发生了质的飞跃:

  1. 多端状态同步 :当你在本地项目文件夹里运行程序后,会多出一个名为 skills_creator_state.db****的文件。这就是你所有的图状态数据。
  2. "断电重启"级别的恢复 :你可以试着在 Streamlit 页面上发起一个任务,当它走到"等待人工审核"挂起时,你直接在终端里把服务关掉(Kill 进程)。然后你重新启动 streamlit run app.py。你会发现,只要你的 thread_id 没有变,页面依然会停留在等待你审核的那个瞬间,生成的代码一行都没有丢!
  3. 历史记录的永久化 :你前端写的那个"历史任务"侧边栏,原本刷新后历史就清空了。现在,只要你利用 LangGraph 的 graph.get_state_history(config) 方法去查询底层的 SQLite,你可以随时把一个月前 AI 帮你写的代码完完整整地捞出来。

相关问题解答:

❓ 疑问一:没有设计字段和类型,数据是怎么存进去的?

你的直觉很准,我们确实没有写类似于 CREATE TABLE 这样的 SQL 语句,也没有定义 current_code 是 TEXT、iteration_count 是 INT。

这里的秘密在于LangGraph 的自动建表与"序列化(Serialization)"机制

  • 自动建表(Auto-Migration) :当你执行 SqliteSaver(db_conn) 的时候,LangGraph 引擎会在底层悄悄执行建表语句。它会默认创建几个核心表(比如 checkpointscheckpoint_writes 等)。
  • 黑盒存储(BLOB / JSON 序列化) :在数据库里,LangGraph 并没有把你定义的 SkillsCreatorState 拆解成几十个零散的列(Column)。相反,它把整个大字典(包含了代码、报错、聊天记录等所有状态)压缩并序列化成了一坨 JSON 字符串或二进制数据(BLOB)
  • 按需解包:每次流转到下一个节点时,引擎把这坨数据从数据库里完整地掏出来,反序列化成 Python 字典交给你;节点运行完,再把更新后的字典重新序列化,覆盖写回数据库。

所以,底层数据库并不关心你的 State 里面具体装了什么,它只负责安全地保存这个"包裹"。


❓ 疑问二:只有一个 .db 文件,所有人的数据是不是全混在一起了?

答案是: 数据确实都在同一个物理文件里,但它们绝对不会混在一起,彼此是严格隔离的!

在多租户系统(Multi-tenant Architecture)中,把数据存在同一个库甚至同一张表里是非常常见的做法。保证数据不串线的核心保安,就是你代码里写的那个 thread_id

我们来看看底层的隔离逻辑是怎样的:

  • 数据库的主键隔离 :在那张自动生成的 checkpoints 表里,最核心的一个字段就是 thread_id
  • 前端的唯一标识 :在你的 app.py 中,你写了 st.session_state.thread_id = str(uuid.uuid4())。这意味着,每一个打开你网页的用户,都会获得一个全球唯一的不重复 ID (比如 task_a1b2c3d4...)。
  • 精准提取 :当 A 用户点击"生成"时,你把 config={"configurable": {"thread_id": "A的ID"}} 传给了图引擎。引擎生成的底层 SQL 类似于:SELECT * FROM checkpoints WHERE thread_id = 'A的ID'。它只会提取 A 用户的专属包裹。
  • 互不干扰 :B 用户同一时间也在用,他的查询条件是 WHERE thread_id = 'B的ID'。哪怕他们同时存取同一个 .db 文件,因为这把"钥匙"不同,A 永远看不到 B 的代码,B 也影响不到 A 的报错信息。

这就好比一栋拥有无数个带锁储物柜的巨大仓库(.db 文件)。虽然都在一个仓库里,但每个人只有自己那个柜子的钥匙(thread_id)。


相关推荐
yanghuashuiyue17 小时前
langchain技术栈研究
langchain
YuanDaima204819 小时前
LangChain基础配置与对话模型实战
人工智能·python·langchain·大模型·智能体·langgraph
Flying pigs~~19 小时前
基于Deepseek大模型API完成文本分类预测功能
java·前端·人工智能·python·langchain·deepseek
花千树-01020 小时前
5分钟用 Java 构建你的第一个 AI 应用
java·人工智能·spring boot·langchain·aigc·ai编程
二十一_21 小时前
炸了!Claude Code 51万行源码全部泄露,我已经拿到了完整代码
前端·langchain·claude
老王熬夜敲代码1 天前
LangGraph的状态
开发语言·langchain
QC·Rex1 天前
从零到部署:构建生产级 AI Agent 的完整指南
人工智能·langchain·agent·rag·工具调用·人工智能体·生产部署
陆业聪1 天前
字节跳动开源 DeerFlow 2.0 源码拆解:14层Middleware、Sub-Agent并发编排和结构化记忆是怎么做的
人工智能·langchain·aigc·agent
java资料站1 天前
第03章:LangChain使用之Model I/O
microsoft·langchain