前几篇文章我们讲了LangGraph的三大核心概念State、Node、Edge,还亲手写了第一个可运行的Graph。但如果你想做一个真正的对话Agent,会发现缺了点什么——记忆

用户跟你聊了半天,下次进来一问三不知,这体验谁顶得住啊?

用户跟你聊了半天,下次进来一问三不知,这体验谁顶得住啊?

今天我们就从零开始,构建一个带持久化记忆的对话Agent。写完这篇,你就有了一个可以持续对话、记住历史的完整AI助手。


01 | 为什么需要持久化记忆?

先想一个问题:普通的对话系统记忆存在什么问题?

90% 的教程教你的写法是这样的:

// 把所有历史都存在内存里constmessagesBaseMessagefunctionchatmessage: stringpushnewHumanMessageconstawaitinvokepushreturn

这种写法问题很大:

  1. 进程重启就丢了——服务器一重启,所有聊天记录全没了
  2. 多用户没法搞——多个用户聊天,内存混在一起分不清楚
  3. 内存泄漏——聊得越多,数组越长,内存爆炸
  4. 无法回溯——想查看用户上周聊了什么,根本找不到

LangGraph 给我们提供了更好的方案:内置持久化层 + 检查点(Checkpoint)机制


02 | LangGraph 的持久化原理

LangGraph 的持久化核心概念其实很简单:

每一次Graph执行完一个步骤,都会把当前整个State保存到一个 BaseCheckpointSaver 里。下次你接着对话的时候,直接从这里把State恢复出来就行。

用户对话 → 执行Node → 更新State → 保存Checkpoint

                ↓

下次对话 → 恢复Checkpoint → 拿到完整State和历史 → 继续对话

目前 LangGraph.js 提供了几种持久化实现:

实现使用场景持久化
MemorySaver开发测试、单进程内存,重启丢失
FileSystemCheckpointSaver生产单实例、本地开发文件系统,重启保留
PostgresSaver生产多实例、分布式PostgreSQL,真正生产级

我们今天从最简单的 MemorySaver 开始,然后逐步升级到文件持久化。


03 | 第一步:基础对话Agent,不带记忆

先搭个最基础的对话Agent骨架,后面再加记忆:

importChatOpenAIfrom"@langchain/openai"importHumanMessageSystemMessagefrom"@langchain/core/messages"importStateGraphfrom"@langchain/langgraph"importENDfrom"@langchain/langgraph"// 1. 定义State类型typeConversationStatemessagesHumanMessage// 2. 初始化模型constnewChatOpenAImodelName"gpt-4o"temperature0.7// 3. 定义聊天NodeasyncfunctioncallModelstate: ConversationStateconstnewSystemMessage"你是一个友好的AI助手,记得用户跟你说过的话。"constawaitinvokemessagesreturnmessagesmessages// 4. 构建GraphconstnewStateGraphConversationStatechannelsmessagesreducer(prev, next) =>// 添加节点addNode"model"// 添加边——模型调用完就结束addEdge"model"END// 设置入口setEntryPoint"model"// 5. 编译Graphconstcompile

这就是最基础的版本了。但问题是,每次调用都要你自己把所有历史消息拼进去,而且重启就没了。

接下来加记忆。


04 | 第二步:加入内存持久化

LangGraph 提供了 MemorySaver,只需改两行代码就能加上持久化:

importMemorySaverfrom"@langchain/langgraph"// ...前面的代码不变...// 1. 创建一个持久化保存器constnewMemorySaver// 2. 编译的时候传进去constcompilecheckpointer

就这么简单?对,就这么简单!😎

现在怎么使用呢?每次对话你需要传一个 config,里面带上 thread_id——这就是用户的会话ID:

// 用户A第一次说话constconfigurablethread_id"user-a-123"constawaitinvokemessagesnewHumanMessage"你好,我叫张小妹"consolelogmessagesat1content// 你好张小妹!很高兴认识你😊// 过了一会儿,用户A继续说话constawaitinvokemessagesnewHumanMessage"我叫什么来着?"// 使用同一个 thread_idconsolelogmessagesat1content// 你叫张小妹呀,我刚记住呢😉

重点就是:同一个用户用同一个 thread_id。LangGraph 会自动从checkpoint里恢复所有历史消息,你不用自己管。

现在这个版本已经能记住对话了,可惜还是存在内存里,进程重启就丢了。下一步我们搞真正的持久化。


05 | 第三步:文件系统持久化,重启不丢消息

LangGraph.js 从 0.3 版本开始自带了 FileSystemCheckpointSaver,直接就能用:

importFileSystemCheckpointSaverfrom"@langgraph/platform/node"// 替换掉 MemorySaverconstnewFileSystemCheckpointSaver// 保存checkpoint的目录baseDir"./data/checkpoints"// 编译Graph的时候用这个constcompilecheckpointer

使用方式完全不变!还是传 thread_id 就行:

constconfigurablethread_id"user-a-123"constawaitinvokemessagesnewHumanMessage"你好"

原理就是,每个thread_id对应一个文件,每次状态更新都会写入文件。只要硬盘不炸,对话就一直存在。

对于单实例服务来说,这个方案完全够用了,比搞个PostgreSQL简单多了。


06 | 完整可运行代码

把所有代码拼起来,就是一个完整的带文件持久化的对话Agent:

importChatOpenAIfrom"@langchain/openai"importHumanMessageSystemMessageBaseMessagefrom"@langchain/core/messages"importStateGraphENDfrom"@langchain/langgraph"importFileSystemCheckpointSaverfrom"@langgraph/platform/node"importasfrom"fs"// 确保目录存在mkdirSync"./data/checkpoints"recursivetrue// 1. 定义StatetypeConversationStatemessagesBaseMessage// 2. 初始化模型constnewChatOpenAImodelName"gpt-4o"temperature0.7// 3. 聊天NodeasyncfunctioncallModelstate: ConversationStateconstnewSystemMessage"你是一个友好的AI助手,会记住用户说过的每一句话。回答要简洁自然。"constawaitinvokemessagesreturnmessages// 4. 构建GraphconstnewStateGraphConversationStatechannelsmessages// reducer函数把新消息追加到历史后面reducer(prev: BaseMessage[], next: BaseMessage[]) =>addNode"model"addEdge"model"ENDsetEntryPoint"model"// 5. 持久化 + 编译constnewFileSystemCheckpointSaverbaseDir"./data/checkpoints"constcompile// 6. 使用示例asyncfunctionchatthreadId: string, message: stringconstconfigurablethread_idconstawaitinvokemessagesnewHumanMessagereturnmessagesat1contentasstring// 测试一下asyncfunctiontestconsolelogawaitchat"user-1""你好,我是James"consolelogawaitchat"user-1""你还记得我叫什么吗?"consolelogawaitchat"user-2""你好,我是张小妹"consolelogawaitchat"user-2""我叫什么?"testcatchconsoleerror

你直接把这段代码存成 index.ts,装完依赖就能跑:

npm install @langchain/langgraph @langchain/openai @langgraph/platform

tsc index.ts && node index.js


07 | 生产级升级:PostgreSQL 持久化

如果你是多实例部署,或者数据量很大,那文件系统就不够用了。这时候可以用 PostgresSaver

importPostgresSaverfrom"@langchain/langgraph/checkpoint/postgres"importPoolfrom"pg"// 创建连接池constnewPoolconnectionStringenvDATABASE_URL// 创建持久化保存器constnewPostgresSavertableName"langgraph_checkpoints"// 可自定义表名// 初始化表结构(第一次运行需要)awaitinitialize// 编译Graphconstcompile

使用方式还是一样的,完全不用改业务代码。这就是LangGraph设计的精妙之处——持久化实现对业务代码透明,切换实现只需要换一个checkpointer就行


08 | 常见坑点和解决方案

我自己踩过几个坑,给你提个醒:

坑1:State 不能存不能序列化的东西

Checkpoint会把整个State序列化存起来,所以State里不能放函数、Promise、Buffer这些没法JSON序列化的东西。

解决: State只存纯数据,逻辑放Node里。

坑2:reducer 函数一定要正确追加消息

// 正确写法reducer(prev, next) =>// 错误写法(直接覆盖,历史消息丢了)reducer(prev, next) =>

这个错我一开始也犯过,结果就是每次只有最新一条消息,记住不历史…😅

坑3:thread_id 一定要分对用户

同一个用户必须用同一个thread_id,不然就会拿到别人的对话。

最佳实践: thread_id = userId + "-" + conversationId,这样同一个用户不同会话也分开。


总结

今天我们从零搭建了一个带持久化记忆的对话Agent,从内存到文件系统再到PostgreSQL,一步步升级。

核心要点总结一下:

  • LangGraph 的持久化靠 CheckpointSaver,内置了三种实现
  • 只需要在 compile() 的时候传进去,业务代码不用改
  • thread_id 区分不同会话,同一个会话用同一个ID
  • 开发用 MemorySaver,单实例用 FileSystemCheckpointSaver,生产多实例用 PostgresSaver

代码都给你了,直接拿去就能用。下一篇我们讲自定义工具开发,做好了准备,Agent就能调用你自己写的函数了。

学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%免费

在这里插入图片描述

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐