LangChain / LangGraph Memory 记忆体系技术文档(作用域判定 · 官方现版本实现 · 工程坑点)

LangChain / LangGraph Memory 记忆体系技术文档(作用域判定 · 官方现版本实现 · 工程坑点)

本文在保留原稿「作用域判定」核心思想的基础上,按 LangChain 官方现版本(0.3+ / 1.0) 重写了实现层。 ⚠️ 原稿第一节列出的 ConversationBufferMemory 等 7 个 Memory 类 已被官方废弃并在 1.0 移除 , 现版本 from langchain.memory import ... 会直接抛 ImportError。详见 §2.4 废弃对照表。


一、核心判定原则(全文纲领,原稿此节完全正确)

短期记忆 / 长期记忆的划分,与底层存储介质无关;判定标准只有业务作用域:是否支持跨会话(cross-session)复用。

类型 作用域 官方对应机制 是否跨会话
短期记忆 绑定单一会话线程(thread_id) Checkpointer ❌ 换 thread_id 即清空
长期记忆 跨多个会话线程(namespace) Store ✅ 新开对话仍可召回
  • 短期记忆 :维持本轮对话上下文。即使持久化入库(如存 PG),也仅供当前 thread 断点续传,不会给全新会话复用。
  • 长期记忆 :新开对话依然可召回;不会一次性全塞进 Prompt,采用按需检索,仅将相关片段注入上下文。

🎯 重要呼应 :原稿这套「按作用域划分、与介质无关」的思想,恰好就是 LangChain 官方新架构的设计哲学 。 官方把持久化明确拆成两套互补系统: - Checkpointers ------ 将线程的图状态持久化为检查点,用于线程内 的短期记忆; - Stores ------ 在图状态之外持久化应用定义的数据,用于跨线程 的长期记忆。 官方原文:"Most applications can use both: checkpointer to track the current thread, store to track persistent information across threads."


二、短期记忆(会话内记忆)

2.1 业务作用与数据特点

保存当前会话上下文,让大模型知晓本轮对话历史、Agent 工具调用过程、上一轮返回结果,是维持单轮对话连贯性的基础。

维度 说明
数据内容 完整对话消息(含 ToolMessage)
注入方式 全量注入 LLM 上下文窗口
约束 受 Token 上限约束,需裁剪/摘要
作用域 单个 thread_id

2.2 现版本官方实现:LangGraph Checkpointer

python 复制代码
from langgraph.checkpoint.memory import InMemorySaver      # 开发
from langgraph.checkpoint.postgres import PostgresSaver    # 生产
from langgraph.graph import StateGraph, MessagesState, START

DB_URI = "postgresql://user:pwd@host:5432/db?sslmode=disable"
with PostgresSaver.from_conn_string(DB_URI) as checkpointer:
    checkpointer.setup()                       # ⚠️ 首次使用必须调用
    graph = builder.compile(checkpointer=checkpointer)

graph.invoke({"messages": [{"role": "user", "content": "hi, I'm Bob"}]},
             {"configurable": {"thread_id": "user-1-thread-a"}})

thread_id 就是会话主键。 同一个 thread_id 续聊,换一个 thread_id 就是全新会话。

2.3 存储介质选型

介质 实现 适用 说明
内存 InMemorySaver(旧名 MemorySaver) 仅开发/测试 进程重启即丢失
SQLite SqliteSaver 本地需持久化的开发 单文件,跨重启
PostgreSQL PostgresSaver / AsyncPostgresSaver 生产多实例首选 多副本共享状态
Redis Redis checkpointer 高频短会话 需自行实现/选型

⚠️ 原稿说「Redis 生产首选」需加限定 :Redis 适合带 TTL 的短会话缓存 ;一旦需要断点续传/人在回路/时间旅行 (LangGraph 的核心能力),必须落到 PG------因为 checkpointer 存的是图状态快照,不是简单消息列表,Redis 做 TTL 自动过期会把未完成流程的状态抹掉。

2.4 ⚠️ 废弃对照表(原稿第一节的 7 个类 → 官方替代)

原稿 Memory 类 现版本状态 官方替代
ConversationBufferMemory v0.3.1 弃用 / 1.0 移除 LangGraph Checkpointer(MemorySaver / PostgresSaver)
ConversationBufferWindowMemory 同上 Checkpointer + 节点内 trim_messages(max_tokens=...)
ConversationTokenBufferMemory 同上 Checkpointer + trim_messages(按 token 显式裁剪)
ConversationSummaryMemory 同上 自建摘要节点:定期摘要并写回 state
ConversationSummaryBufferMemory 同上 摘要节点 + trim_messages(工程推荐组合)
ConversationEntityMemory 同上 Store(语义记忆)+ 实体抽取节点
ConversationKGMemory 同上 图数据库 / Store(外部集成)

关键事实:

复制代码
LangChain 1.0:from langchain.memory import ConversationBufferMemory
→ ImportError(不是 DeprecationWarning!)

这些 legacy 类连同 ConversationChain 一起迁到独立的 langchain-classic 包。

官方迁移一行总结:"History lives in the graph state, not in a memory object."

为什么这套 API 会被淘汰? (值得写进复盘) 每一代 LangChain 记忆方案都耦合在具体编排层上 : BufferMemory → 绑定 ConversationChain;RunnableWithMessageHistory → 绑定 LCEL;Checkpointer → 绑定 LangGraph。 编排层一重构,记忆方案就跟着碎。 这是结构性问题,不是 bug。 → 工程启示:尽量把记忆内容的 schema 与业务语义握在自己手里(PG 表结构),让框架只负责存取,别把记忆长在框架的抽象里。

2.5 短期记忆管理(官方三种手段)

手段 作用 适用
Trim messages 按 token/条数裁剪 通用,最简单
Delete messages 删除指定消息 清理敏感/无效轮次
Summarize messages 老轮次压成摘要 长会话,节省 token

三、长期记忆(跨会话记忆)

3.1 业务作用与数据特点

持久存储跨会话信息,新会话可召回:用户偏好、历史任务经验、业务事实、执行策略。

维度 短期记忆 长期记忆
作用域 单 thread 跨 thread(namespace)
注入方式 全量注入 按需检索,仅命中片段
数据形态 原始消息序列 结构化事实 / 向量片段 / 规则
典型介质 内存 / Redis / PG PG 表 / PGVector / Store

为什么长期记忆必须按需检索而不全塞? 除了 token 成本,还有个硬原因:Lost in the Middle 。研究显示模型的准确率呈 U 形曲线 ------ 相关信息在输入开头或结尾 时准确率最高,埋在中间时急剧下降 。 所以"上下文窗口够大"不等于"可以全塞进去",放对位置、做精选,和容量本身一样重要。

3.2 现版本官方实现:LangGraph Store

python 复制代码
from langgraph.store.memory import InMemoryStore      # 开发
from langgraph.store.postgres import PostgresStore    # 生产

store = InMemoryStore()                        # 或 PostgresStore
namespace = (user_id, "memories")              # ⚠️ 是 tuple,不是字符串

store.put(namespace, str(uuid.uuid4()), {"food_preference": "I like pizza"})
items = store.search(namespace, query="用户喜欢吃什么?", limit=3)

⚠️ 只传 checkpointer 是最常见的架构错误 ------ 那样只得到"持久化的聊天记录", 不会自动得到跨会话的用户知识。两者必须同时配置:

python 复制代码
graph = builder.compile(checkpointer=checkpointer, store=store)

3.3 三类长期记忆(Agent 架构常用分类,原稿分类与官方一致 ✅)

类型 英文 存什么 例子 推荐存储
语义记忆 Semantic 事实、用户偏好 用户习惯简洁回答、技术栈偏好 PG 结构化表(profile,schema 严格)
情景记忆 Episodic 过往任务、历史交互 上次执行的任务、报错与处理过程 PGVector(collection,向量检索)
程序记忆 Procedural 流程、规则、执行策略 Agent 工具调用规范、任务处理步骤 配置表 / 知识库 / 可改写 system prompt

LangMem(LangChain 官方长期记忆 SDK)把这三类都实现了,其中程序记忆(Agent 根据反馈改写自己的 system prompt)是它独有的能力。

3.4 存储介质选型(含集成路径变更)

介质 适用 备注
PostgreSQL 普通表 结构化长记忆:用户偏好、基础配置 工程落地首选
PGVector 情景记忆、历史交互片段 复用现有 PG,无需独立向量库
向量数据库(Chroma / Milvus / Qdrant) 海量片段检索(千万级以上) 中小规模不必引入
Markdown / JSON 文件 仅原型 Demo 生产不推荐:无并发、无多用户管理
图数据库 实体关系、知识图谱 多跳关系场景

⚠️ PGVector 集成路径已变更(原稿未覆盖):

路径 状态
langchain_community.vectorstores.PGVector 已弃用(langchain-community 归档)
langchain_postgres.PGVector 正在被淘汰
✅ langchain_postgres.PGEngine + PGVectorStore 新项目应直接用这个

⚠️ 驱动坑 :langchain-postgres 要求 psycopg3(包名 psycopg) ,不是 psycopg2 也不是 asyncpg。 连接串要写成 postgresql+psycopg://...,安装 psycopg[binary,pool]。 大量旧教程仍用 psycopg2,照抄会直接报错。


四、常见误区澄清

# 误区 正解
1 ❌ 存数据库 = 长期记忆,放内存 = 短期记忆 ✅ 介质不决定记忆类型 。PG 存 thread_id 绑定的会话消息,只用于当前会话断点续传 → 短期记忆 ;PG 存用户偏好,新会话可读 → 长期记忆
2 ❌ 长记忆只能用 MD 文件保存 ✅ MD 仅适合原型。正式工程:结构化长记忆用 PG,历史片段用 PGVector
3 ❌ 配了 checkpointer 就有跨会话记忆了 ✅ 最常见的架构错误 。checkpointer 只管单 thread;跨会话必须另外配 Store
4 ❌ 长期记忆应该全量注入 prompt ✅ 按需检索。全量注入除了 token 成本,还会触发 Lost in the Middle(中间信息准确率骤降)
5 ❌ MemorySaver 可以上生产 ✅ 它是 InMemorySaver,进程重启即失 ;生产用 PostgresSaver
6 ❌ 记忆写在请求同步路径上 ✅ 记忆抽取要放后台(对话结束后异步跑),否则拖慢响应

五、记忆体系坑点清单(工程必读)

5.1 摘要记忆丢失细节(不可逆)

摘要是有损压缩 ,一旦压掉就找不回来。LangMem 官方也点出两难:过度抽取 → 精度下降;抽取不足 → 召回率低。

风险 表现
数字/ID/代码被改写 摘要里"用户提到订单号"丢失了具体单号
时序被压平 "先做了 A 再做了 B" 压成 "做了 A 和 B"
否定被吞 "不要用 MySQL" 压成 "数据库选型"

对策 :关键事实(数字、ID、代码、时间、否定判断)必须结构化入库,摘要只用于压缩"过程性叙述",不能作为唯一事实源。

5.2 向量检索召回错误

坑 说明 对策
相似度 ≠ 相关性 embedding 模型决定召回天花板,语义相近但业务无关会被召回 相似度 + 重要性 + 时效强度(近期/频繁使用加权)组合打分
多跳关系召回不到 「Acme 的负责人是 Dana,Dana 偏好 Slack」------单条片段里没有完整链路,纯向量检索抓不到 引入图结构(实体关系)辅助召回
过滤导致结果不足(over-filtering) 向量检索叠加 WHERE 过滤后,返回条数不够 pgvector 0.8+ 的 iterative index scan (hnsw.iterative_scan)
索引与算子不匹配 用 vector_cosine_ops 建的索引,查询用 L2 距离 → 退化成全表扫描 opclass 与查询算子必须对齐(cosine ↔ <=>)

5.3 记忆冲突与过时(长期记忆第一大坑)

用户偏好会变:第 3 轮说"用 Python",第 47 轮说"改用 TypeScript"------两条都在库里,相似度检索可能返回任意一条,Agent 给出自相矛盾的回答。

⚠️ 注意 2026 年的变化 :Mem0 v2.0.0(2026-04)把抽取改成了单次 ADD-only (一次 LLM 调用抽出新事实直接追加), 不再自动与已有记忆做 UPDATE/DELETE 调和 ;官方去重仅剩精确匹配(MD5) 。 好处是延迟减半、评测分数大涨;代价是记忆库不再自动自纠,矛盾事实会并存。

→ 记忆一致性成了你自己流水线的责任,不再是数据库的能力。必须自建调和机制(定期 LLM 对账 / 版本号 + 失效标记 / 按时间优先)。

5.4 Store 使用坑(官方细节,极易踩)

坑 说明
limit 默认 10,超出静默截断 没有任何溢出信号 。要显式设大或 offset 分页
namespace_prefix 是前缀匹配不是精确匹配 查 ("alice",) 会连 ("alice","memories")、("alice","preferences") 一起返回 → 命名空间污染
默认排序依赖后端实现 PostgresStore 按 updated_at 降序 (最新在前);InMemoryStore 按插入顺序(最新在最后 )→ 不要跨实现依赖顺序,需排序就客户端按 updated_at 排
index=False 存了但搜不到 Store 语义搜索需配置 index={"embed":..., "dims":..., "fields":[...]};不配置或关闭则该条不可被语义检索

5.5 Checkpointer 使用坑

坑 说明
首次必须 checkpointer.setup() PostgresSaver 第一次使用要建表
langgraph dev 可能静默忽略自定义 checkpointer 状态落在内存里,每次热重载销毁 → 你以为有持久化,实际没有
Redis TTL 会抹掉未完成流程 checkpointer 存的是图状态快照,不是消息列表;TTL 过期 = 未完成的 human-in-the-loop 流程丢失

5.6 LangMem 性能坑(直接决定架构)

LangMem 检索延迟可能达到接近 1 分钟级别,且版本尚未到 1.0。

→ 只能放后台异步整理记忆,绝不能放在用户同步请求路径上。 推荐架构:请求路径只读 记忆(PG/PGVector 直查,毫秒级);记忆抽取/整理放后台任务(对话结束后触发)。


六、工程选型建议(本 AG / Agent 项目)

层次 选型 理由
短期会话记忆 PostgresSaver(checkpointer)+ Redis 做热会话缓存 需要断点续传 / 人在回路 → 必须持久化;Redis 只做加速,不唯一持有
结构化长期记忆(用户偏好、配置) PostgreSQL 普通表 schema 严格、可审计、可直接 JOIN
历史任务情景记忆 PGVector(复用现有 PG) 中小规模无需独立向量库;注意用新集成路径 PGVectorStore
记忆抽取链路 后台异步(对话结束后触发) 避免拖慢用户响应;LangMem 延迟高,不能同步用
一致性维护 自建调和流水线(定期对账 / 版本 + 失效标记) 现成库不再自动去重矛盾

落地最小骨架

python 复制代码
# 短期:checkpointer 按 thread_id
# 长期:store 按 (user_id, "memories") namespace
# 两者同时编译进图
checkpointer = PostgresSaver.from_conn_string(DB_URI)
store        = PostgresStore.from_conn_string(DB_URI)   # 语义搜索配 index

graph = builder.compile(checkpointer=checkpointer, store=store)

config = {"configurable": {"thread_id": thread_id, "user_id": user_id}}
result = await graph.ainvoke({"messages": [...]}, config=config)

# 响应返回后再异步触发记忆抽取(不阻塞用户)
asyncio.create_task(extract_and_consolidate_memories(user_id, result["messages"]))

七、精简摘要(可用于 PPT)

LangChain 记忆划分不依赖存储介质,核心看作用域 。短期记忆绑定单一会话线程(thread_id / Checkpointer),维持本轮上下文,可放内存、Redis、PostgreSQL;长期记忆支持跨会话召回(namespace / Store),存储用户偏好与历史任务,可用 PG、PGVector。短期记忆全量注入 Prompt,长期记忆按需检索、仅召回相关片段。

一句话记忆 :Checkpointer 管"这次聊到哪",Store 管"这个用户是谁"。两者都要配。


八、版本与迁移速查

项 结论
ConversationBufferMemory v0.3.1 弃用,1.0 移除 → 迁 langchain-classic 或改用 Checkpointer
ConversationChain / LLMChain 已移除 → LCEL / LangGraph
RunnableWithMessageHistory 自 v0.3 起标记弃用 → 用 Checkpointer
MemorySaver 现名 InMemorySaver,仅开发用
langchain_community.vectorstores.PGVector 已弃用 → langchain_postgres.PGVectorStore
psycopg 驱动 langchain-postgres 需 psycopg3 (postgresql+psycopg://)

检测手段 :pytest -W error::DeprecationWarning ------ 把弃用警告变成测试失败,任何残留的旧模式在上线前就会暴露。

相关推荐
虎鲸不是鱼2 小时前
AI 自动化逆向(六)AI 解一个 9 万条目的资源容器
人工智能·自动化·大模型·ai逆向·自动化逆向
早点睡觉好了2 小时前
LangChain 源码入门 04:Runnable 如何统一调用、批处理、异步与流式接口
python·ai·langchain
丨白色风车丨2 小时前
LangChain Agent 从入门到实战:创建与调用参数全解析
前端·python·langchain
李福春5 小时前
技术思考问题17:上了LangChain框架就等于AI-Agent工程化吗?
大数据·人工智能·langchain·深圳同盟·腾讯云架构师技术同盟·llm应用架构·编排抽象
羞儿5 小时前
【DSH】为什么需要-Harness
人工智能·大模型·harness·认知构建
IT_Octopus10 小时前
【零基础入门 LLM 开发 · Day 13】:LangChain 的对话记忆——Message 对象版
人工智能·python·langchain
半个落月10 小时前
LangChain Agent 中间件实战(上):生命周期、状态、短路与工具包
javascript·langchain
半个落月10 小时前
LangChain Agent 中间件实战(下):DeepAgents文件权限、长期记忆与对话摘要
javascript·langchain
yuanlaile11 小时前
大模型应用层开发实战:从 Prompt 工程到 Dify、私有 RAG、Agent 完整落地总结
prompt·agent·dify·大模型应用开发·llm 应用·prompt 工程