LangChain 的 Memory 组件:基本使用、常用场景教学及企业项目落地
LangChain 的 Memory 组件:基本使用、常用场景教学及企业项目落地

文章目录
前言:你的 AI 为什么总是"失忆"?
你遇到过这种情况吗?
用户刚告诉 AI 助手"我喜欢喝拿铁,加一份浓缩",结果聊了几句关于天气的话题,再问"推荐一款适合我的咖啡",AI 斩钉截铁地回答:“您可以试试我们的美式咖啡,清爽提神。”
这不是 AI 在故意气你,而是大语言模型(LLM)本质上就是一个"只有7秒记忆的金鱼"——每一次 API 调用都是独立的,模型根本不知道你们之前聊过什么。
再比如,你做一个客服机器人,用户聊到第10轮时突然冒出一句"刚才说的那个订单",然后你的系统就开始装傻:“不好意思,能麻烦您再说一下订单号吗?”
又或者,你辛辛苦苦做了一个多轮对话的 AI 应用,结果用户第二天打开,发现所有的聊天记录全没了——程序重启 = 历史清零。
这些场景,相信只要做过 AI 应用的开发者,或多或少都踩过坑。问题的根源很简单:LLM 没有内置的记忆能力,而多轮对话、个性化服务、智能客服等场景又强依赖上下文连续性。
不借助外部记忆组件,模型每次都像第一次见到用户。用户需要反复重复背景信息,体验极差。而如果手动拼接所有历史消息,Token 会线性膨胀,API 费用更是失控式增长。
核心矛盾就是:LLM 的无状态特性,与应用需要上下文连续性之间,存在不可调和的矛盾。
那么,有没有一种优雅的方式来解决这个问题?
答案就是 LangChain 的 Memory 组件。
在接下来的文章中,我会手把手带你从零掌握 LangChain Memory:从基础概念、5种核心记忆类型对比,到现代 LCEL 风格的 RunnableWithMessageHistory 用法,再到生产环境持久化实战。内容很干,建议先收藏再慢慢消化。
一、痛点解决方案:Memory 组件登场
LangChain Memory 组件正是为解决"LLM 无状态"与"应用需要上下文"之间的矛盾而生。
你可以把 Memory 理解成一个外置的记忆中枢——它自动保存对话历史,智能注入到每次 Prompt 中,让模型能够"记起"之前聊过的内容。
Memory 的本质,就是对话历史的管理与智能注入。通过不同的存储和压缩策略,让模型既能记住关键信息,又不会因为历史过长导致 Token 耗尽。
用一个生活场景来比喻:
LLM 本身就像一个只有7秒记忆的金鱼,每次聊天都像第一次见到你。而 Memory 组件,就像给金鱼配了一本日记本。你告诉金鱼的事情它虽然记不住,但日记本会帮你记着,下次金鱼需要知道什么的时候,就去翻翻日记本。
又或者,你可以把 Memory 想象成餐厅服务员的小本本:
客人说"我不吃香菜,记得帮我挑出来",服务员在小本本上画了个叉。客人走了两圈去选菜,再回来时服务员翻开本本一看:“哦对,这位客人不吃香菜。”——Memory 就是那个小本本。
二、深入理解 Memory:核心概念与工作原理
2.1 Memory 到底是什么?
在 LangChain 的语境下,Memory 是一个用于在 Chain 或 Agent 多次调用之间持久化状态的机制。这个状态通常是对话历史,但也可以是任何需要跨步骤保留的信息。
从架构层面看,Memory 组件在每次对话流程中扮演着承上启下的角色:
用户输入
↓
从 Memory 中读取历史记录
↓
组装成完整 Prompt(含历史上下文)
↓
调用 LLM
↓
将本轮对话保存回 Memory
整个流程自动完成,开发者只需要配置好 Memory 类型,剩下的事情 LangChain 会帮你处理。
2.2 核心接口:BaseMemory
所有 Memory 类型都继承自 BaseMemory 抽象基类,其核心方法只有三个:
# 1. 读取记忆,返回包含历史的字典
load_memory_variables(inputs: Dict[str, Any]) -> Dict[str, Any]
# 2. 保存本轮对话的用户输入和 AI 回复
save_context(inputs: Dict[str, Any], outputs: Dict[str, Any]) -> None
# 3. 清空所有记忆
clear() -> None
这三个方法揭示了 Memory 的核心工作流程:在 Chain 执行前,通过 load_memory_variables 将记忆注入到本次输入中;执行后,通过 save_context 将本轮交互保存。整个过程对开发者是透明的。
2.3 最底层:ChatMessageHistory
在 Memory 之上,还有一层更基础的抽象:ChatMessageHistory。
ChatMessageHistory 是最底层的历史存储单元,本质就是一个消息列表,提供了保存用户消息、AI 消息,以及获取所有消息的便捷方法。
from langchain_core.chat_history import InMemoryChatMessageHistory
history = InMemoryChatMessageHistory()
history.add_user_message("你好,我叫小明")
history.add_ai_message("你好小明,很高兴认识你!")
print(history.messages)
# [HumanMessage(content='你好,我叫小明'), AIMessage(content='你好小明,很高兴认识你!')]
ConversationBufferMemory 实际上就是对 ChatMessageHistory 的一层封装——它负责调用底层的消息历史存储,同时实现 BaseMemory 接口,让记忆可以无缝集成到 Chain 中。
三、五种记忆类型横向对比:选对策略,事半功倍
LangChain 提供了多种记忆机制,不同类型各有优劣,适用场景也不同。下面我会逐一讲解,并通过对比表格帮你快速选型。
3.1 ConversationBufferMemory(全量缓冲记忆)
这是最简单、最直接的形式——把用户和 AI 之间的所有对话历史按原样存储。
工作原理:
- 每次对话后,Memory 自动保存用户输入和 AI 回复
- 下一次对话时,将完整的对话历史注入到 Prompt 中
- 简单粗暴,保留了所有细节
适用场景:
- 短对话(建议不超过20轮)
- 对精度要求极高的应用,不能丢失任何细节
- 开发调试阶段
优点:
- 实现简单,容易理解
- 信息最完整,不会遗漏任何细节
- 模型能访问所有历史上下文
缺点:
- 随着对话变长,Token 消耗量爆炸式增长
- 一个100轮的对话可能消耗数万 Token
- 最终可能超过模型的上下文限制
- API 费用会让人肉疼
生活案例:
把每天聊天的内容一字不落全部抄在本子上。本子越来越厚,翻起来越来越慢,而且你抄的速度永远赶不上说话的速度。
3.2 ConversationBufferWindowMemory(滑动窗口记忆)
为了解决全量记忆的 Token 爆炸问题,滑动窗口记忆出场了。它只保留最近 K 轮的对话,更早的对话会被丢弃。
核心参数:
k:控制保留的对话轮数(注意:1轮 = 1次用户输入 + 1次AI回复 = 2条消息)
适用场景:
- 长期运行的机器人
- 只需要近期上下文的场景
- 客服场景,用户问题通常和最近对话相关
优点:
- Token 消耗可控,保持稳定
- 实现简单,行为可预测
- 适合"近期信息最重要"的场景
缺点:
- 早期的重要信息会被永久丢弃
- 无法支持跨长周期的复杂推理
- 选错 K 值可能导致关键信息丢失
生活案例:
在本子上贴便利贴,只记最近3条消息,写满就撕掉最旧的那张。简单高效,但如果你一个月前说过"我下个月要出差",等聊到下个月时,这个信息早就被撕掉了。
3.3 ConversationTokenBufferMemory(基于 Token 的记忆)
与窗口记忆类似,但截断依据不再是轮数,而是 Token 数量。
核心参数:
max_token_limit:当历史对话的 Token 数量超过这个限制时,自动截断最旧的内容
适用场景:
- 严格预算控制的应用
- 需要精准控制成本的场景
- Token 直接等于钱钱的场景
优点:
- 能更精准地控制成本
- 不受对话长度影响,始终保持 Token 在可控范围内
- 适合成本敏感型应用
缺点:
- 截断时机不可预测(取决于消息长度)
- 可能切断正在讨论的话题
- 行为比窗口记忆更难调试
生活案例:
便利贴不是按"几张"来算,而是按"用了多少墨水"。墨水用完了就撕掉最旧的,不管话题聊到哪了。
3.4 ConversationSummaryMemory(摘要记忆)
摘要记忆采用了完全不同的思路——不是存储原始对话,而是用 LLM 持续生成对话摘要,用摘要作为记忆。
工作原理:
- 每次对话后,调用 LLM 对历史进行压缩总结
- 保存的是摘要而非原始对话
- Token 消耗保持稳定,不会随对话轮数线性增长
适用场景:
- 超长对话(数百轮)
- 只需要关键信息,不需要细节的场景
- 需要跨越很长时间保持上下文的场景
优点:
- Token 消耗稳定,不随对话增长
- 能保留长时间跨度的上下文
- 适合信息密度不高的闲聊场景
缺点:
- 每次保存都要额外调用 LLM 进行摘要,产生额外成本
- 摘要过程有信息损耗,细节可能丢失
- 摘要质量依赖 LLM 能力
- 对于细节要求高的场景不适用
生活案例:
不是记原话,而是每天用一句话总结今天聊了什么。比如"今天聊了买咖啡的事,用户喜欢拿铁"。简单高效,但如果你想回顾"用户当时具体说了什么味道的描述",对不起了,只有摘要。
3.5 ConversationSummaryBufferMemory(摘要缓冲记忆)——推荐场景首选
这是最智能、最实用的一种方式,结合了全量缓冲和摘要记忆的优点。
工作原理:
- 保留最近几轮的原始对话,保证近期信息的完整性
- 将更早之前的对话内容进行智能摘要,保留核心要点
- 当 Token 超过
max_token_limit时,触发摘要压缩
核心参数:
max_token_limit:控制触发摘要的 Token 阈值- 需要传入一个 LLM 用于生成摘要
优点:
- 近期对话保持完整细节
- 远期对话通过摘要保留核心信息
- Token 消耗可控且稳定
- 平衡了精度和成本
缺点:
- 实现相对复杂
- 摘要过程仍有轻微信息损耗
- 需要额外配置 LLM
生活案例:
最近3天的对话完整抄在本子上;一个月前的对话只保留摘要——“用户那段时间在聊咖啡,后来转去聊旅游了”。既有细节又有全局视野。
3.6 五种记忆类型横向对比速查表
| 记忆类型 | 存储内容 | 触发截断条件 | Token 控制 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|---|---|
| Buffer | 全部历史 | 无 | 差 | 细节完整,实现简单 | Token 爆炸,无法用于长对话 | 短对话(<20轮),高精度需求 |
| Window | 最近K轮 | 轮数达到K | 好 | 稳定可预测,实现简单 | 早期信息永久丢失 | 客服机器人,只需要近期上下文 |
| TokenBuffer | 最近N Token | Token超限 | 极好 | 精准成本控制 | 截断时机不可预测 | 严格预算控制,成本敏感型 |
| Summary | 摘要 | 无(始终摘要) | 极好 | Token最稳定 | 细节丢失,额外摘要成本 | 超长对话(100+轮),信息密度低 |
| SummaryBuffer | 近期细节+远期摘要 | Token超限 | 好 | 近期全量+远期摘要 | 实现复杂,有轻微损耗 | 复杂长任务,推荐作为默认选择 |
选型口诀:
- 短且全量 → Buffer
- 轮数固定 → Window
- 长会话且要压缩 → Summary
- 近详远略且可控长度 → SummaryBuffer(综合最优解)
四、实战教学:从基础到进阶,手把手带你上手
4.1 环境准备
首先安装 LangChain 核心库及相关依赖:
pip install langchain langchain-openai langchain-core
4.2 基础用法:ConversationChain + ConversationBufferMemory
最入门的用法,使用 ConversationChain 和 ConversationBufferMemory 实现简单的多轮对话:
from langchain.chat_models import ChatOpenAI
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationChain
import os
os.environ["OPENAI_API_KEY"] = "your-api-key"
# 1. 初始化模型
llm = ChatOpenAI(model="gpt-4o", temperature=0.7)
# 2. 创建 Memory 实例
memory = ConversationBufferMemory(
memory_key="history", # Prompt 中历史变量的名称
return_messages=True # 返回 Message 对象列表,而非字符串
)
# 3. 创建对话链
conversation = ConversationChain(
llm=llm,
memory=memory,
verbose=True # 开启后可在控制台看到完整的 Prompt 构建过程
)
# 4. 开始多轮对话
print(conversation.predict(input="你好,我叫小明"))
print(conversation.predict(input="我今天想学 LangChain"))
print(conversation.predict(input="你还记得我的名字吗?"))
运行后,你应该能看到 AI 正确记住了你的名字。开启 verbose=True 后,控制台会打印出完整的 Prompt 内容,你可以观察到历史消息是如何被注入的。
调试技巧:
如何查看当前 Memory 中保存了什么?
# 查看当前记忆内容
print(memory.load_memory_variables({}))
输出类似:
{'history': [HumanMessage(content='你好,我叫小明'),
AIMessage(content='你好小明!'),
HumanMessage(content='我今天想学 LangChain'),
AIMessage(content='LangChain 是...')]}
4.3 进阶用法:LCEL 风格 + RunnableWithMessageHistory
从 LangChain v0.3 开始,官方推荐使用 LCEL (LangChain Expression Language) 风格来构建应用。RunnableWithMessageHistory 是现代化用法,支持:
- 与 LCEL 链无缝集成
- 通过
session_id管理多个会话,实现会话隔离 - 支持 Redis、PostgreSQL 等持久化后端
完整代码示例:
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_core.chat_history import InMemoryChatMessageHistory
from langchain_core.chat_history import BaseChatMessageHistory
from langchain_openai import ChatOpenAI
# 1. 定义模型
llm = ChatOpenAI(model="gpt-4o", temperature=0.7)
# 2. 定义 Prompt(关键:添加 MessagesPlaceholder)
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个友好的 AI 助手,名字叫小 Lang。"),
MessagesPlaceholder(variable_name="history"), # 历史消息会注入到这里
("human", "{input}") # 用户当前输入
])
# 3. 构建 LCEL 链
chain = prompt | llm
# 4. 定义会话历史存储(这里用内存,生产环境用 Redis)
store = {}
def get_session_history(session_id: str) -> BaseChatMessageHistory:
"""根据 session_id 获取对应的聊天历史"""
if session_id not in store:
store[session_id] = InMemoryChatMessageHistory()
return store[session_id]
# 5. 用 RunnableWithMessageHistory 包装链
chain_with_history = RunnableWithMessageHistory(
runnable=chain,
get_session_history=get_session_history,
input_messages_key="input",
history_messages_key="history"
)
# 6. 调用链(通过 config 指定 session_id)
config = {"configurable": {"session_id": "user_xiaoming_001"}}
response = chain_with_history.invoke(
{"input": "你好,我叫小明"},
config=config
)
print(response.content)
response = chain_with_history.invoke(
{"input": "我今天想学 Python 编程"},
config=config
)
print(response.content)
response = chain_with_history.invoke(
{"input": "你还记得我叫什么名字吗?"},
config=config
)
print(response.content)
关键参数说明:
| 参数 | 说明 |
|---|---|
runnable |
被包装的 LCEL 链 |
get_session_history |
函数,根据 session_id 返回对应的 ChatMessageHistory |
input_messages_key |
用户当前输入在字典中的 key |
history_messages_key |
Prompt 中历史消息占位符的变量名 |
会话隔离原理:
不同 session_id 的对话完全独立,互不干扰:
# 小明的会话
config_xiaoming = {"configurable": {"session_id": "user_xiaoming_001"}}
chain_with_history.invoke({"input": "我叫小明"}, config=config_xiaoming)
# 小红的会话(完全独立的历史)
config_xiaohong = {"configurable": {"session_id": "user_xiaohong_002"}}
chain_with_history.invoke({"input": "我是小红"}, config=config_xiaohong)
# 验证会话隔离
print(store["user_xiaoming_001"].messages) # 只有小明的对话
print(store["user_xiaohong_002"].messages) # 只有小红的对话
五、常用场景列举:Memory 能做什么?
5.1 智能客服机器人
这是 Memory 最经典的应用场景。客服机器人需要记住用户的:
- 订单号、退换货诉求
- 产品偏好、购买记录
- 已处理的问题进度
使用 ConversationSummaryBufferMemory,既能记住用户的完整诉求,又不会因为对话过长导致 Token 爆炸。
5.2 个性化 AI 助手
让 AI 记住用户的姓名、职业、兴趣爱好,提供定制化建议。比如:
- 用户说"我是一名后端工程师"
- AI 后续的回答都会结合这个背景
- 告别"你是什么职业"这种重复性的废话
5.3 RAG 知识库问答
在 ConversationalRetrievalChain 中,Memory 用于将新问题与对话历史合并,生成完整的查询语句:
# 伪代码示例
# 1. 用户问:"关于那个问题,官方文档是怎么说的?"
# 2. Memory 提供历史上下文:"用户之前在讨论XXX问题"
# 3. 合并后生成检索查询:"官方文档中关于XXX的说明"
# 4. 从向量数据库检索相关文档
# 5. 返回有针对性的答案
没有 Memory,RAG 就无法处理"那个问题"这种指代性提问。
5.4 会议纪要与长会话管理
对于客服记录、访谈总结等长会话场景,使用 ConversationSummaryBufferMemory 自动压缩对话,保留关键结论,适合:
- 客服会话回顾
- 用户访谈记录
- 长时间的技术讨论总结
5.5 多轮任务引导
典型场景如订票助手:
- 第一轮:记住出发地"北京"
- 第二轮:记住目的地"上海"
- 第三轮:记住时间偏好
- 第四轮:综合所有信息完成订票
没有 Memory,订票助手每次都要用户重复所有信息,体验极差。
六、生产环境避坑指南
6.1 新手最容易踩的6个 Memory 陷阱
陷阱1:忘记设置 return_messages=True
# 错误:返回的是字符串拼接,ChatModel 可能无法正确处理
memory = ConversationBufferMemory() # 默认 return_messages=False
# 正确:返回 Message 对象列表,更适合 ChatModel
memory = ConversationBufferMemory(return_messages=True)
陷阱2:混淆 memory_key
Prompt 中的变量名必须与 Memory 的 memory_key 一致:
# Memory 定义
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
# Prompt 必须匹配
prompt = ChatPromptTemplate.from_messages([
MessagesPlaceholder(variable_name="chat_history"), # 必须与 memory_key 一致
("human", "{input}")
])
陷阱3:多会话隔离失效
常见问题:生产环境中,用户每次请求的 session_id 都不同,导致历史无法累积。
# 错误:每次请求都是新的 session_id
config = {"configurable": {"session_id": str(uuid.uuid4())}} # 每次都不同!
# 正确:使用稳定的用户标识
config = {"configurable": {"session_id": user_id}} # 基于用户ID,确保稳定
陷阱4:Token 爆炸导致费用失控
使用 ConversationBufferMemory 保存全部对话,用户聊了180轮后单次调用约40,000 Token,API 费用一个月涨了8倍。
解决方案: 使用 ConversationSummaryBufferMemory 并设置合理的 max_token_limit:
memory = ConversationSummaryBufferMemory(
llm=llm,
max_token_limit=2000, # 超过2000 Token 就触发摘要
return_messages=True
)
陷阱5:程序重启后记忆丢失
默认的 ConversationBufferMemory 存储在内存中,程序重启即丢失。
解决方案: 使用持久化存储(见下一节)。
陷阱6:Summary 时使用错误的 LLM
ConversationSummaryMemory 和 ConversationSummaryBufferMemory 需要调用 LLM 生成摘要。如果使用与主对话不同的廉价模型,可能导致摘要质量下降。
# 建议:使用同级别模型生成摘要,保证质量
summary_llm = ChatOpenAI(model="gpt-4o-mini", temperature=0) # 可以用稍微便宜的模型
memory = ConversationSummaryBufferMemory(
llm=summary_llm, # 用于生成摘要
max_token_limit=2000
)
6.2 不同 LLM 的 Token 限制与 Memory 调优
| 模型 | 上下文窗口 | 推荐 Memory 类型 | Window K值建议 | TokenBuffer 限制建议 |
|---|---|---|---|---|
| GPT-4o | 128K | SummaryBuffer | - | 8000-10000 |
| GPT-4o-mini | 128K | SummaryBuffer | - | 8000-10000 |
| Claude 3.5 | 200K | SummaryBuffer | - | 10000-15000 |
| Claude 3 Haiku | 200K | SummaryBuffer | - | 10000-15000 |
6.3 成本控制策略
- 监控 Token 消耗:在开发阶段开启
verbose=True,观察每次调用的 Token 用量 - 设置告警阈值:当单次调用 Token 超过预期时,触发告警
- 超长会话启用摘要:使用
ConversationSummaryBufferMemory代替ConversationBufferMemory - 结合语义缓存:对于相似的重复问题,使用缓存避免重复 LLM 调用
七、企业级实战:持久化与架构演进
7.1 为什么需要持久化?
默认的 Memory 实现都存储在内存中,存在以下问题:
- 程序重启 = 历史清零
- 无法支持跨进程、跨机器的会话共享
- 服务器宕机 = 用户丢失会话状态
- 无法满足数据合规要求(如保存对话日志)
生产环境必须将记忆持久化到外部存储。
7.2 持久化方案对比
| 存储方案 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| Redis | 高并发、低延迟要求 | 毫秒级读写,支持 TTL | 需要额外运维 |
| PostgreSQL | 企业级应用、高可靠要求 | 事务支持、功能丰富 | 相对较慢 |
| MongoDB | 文档型数据、灵活 schema | 易于使用 | 16MB 单文档限制 |
| SQLite | 小型单机应用 | 零配置、文件级持久化 | 不适合高并发 |
7.3 Redis 持久化实战
使用 RedisChatMessageHistory 实现对话历史的 Redis 持久化:
from langchain.memory import ConversationBufferMemory
from langchain_community.chat_message_histories import RedisChatMessageHistory
# 配置 Redis 连接
SESSION_ID = "user_12345_session_001"
REDIS_URL = "redis://localhost:6379/0"
# 1. 创建基于 Redis 的消息历史存储
message_history = RedisChatMessageHistory(
session_id=SESSION_ID,
url=REDIS_URL,
)
# 2. 创建 Memory,绑定到持久化的消息历史
memory = ConversationBufferMemory(
chat_memory=message_history, # 关键:指定持久化的 chat_memory
memory_key="chat_history",
return_messages=True
)
# 3. 在 Chain 中使用
# ... 正常创建 ConversationChain
# 4. 程序重启后,历史依然存在
message_history_restored = RedisChatMessageHistory(
session_id=SESSION_ID, # 使用相同的 session_id
url=REDIS_URL
)
memory_restored = ConversationBufferMemory(
chat_memory=message_history_restored,
memory_key="chat_history",
return_messages=True
)
Redis 持久化选项:
生产环境建议开启 Redis 的持久化机制:
# redis.conf 配置示例
# RDB 模式:定期快照
save 900 1 # 15分钟内1个key变化则保存
save 300 10 # 5分钟内10个key变化则保存
save 60 10000 # 1分钟内10000个key变化则保存
# AOF 模式:记录每个写操作(推荐)
appendonly yes
appendfsync everysec # 每秒同步,性能与持久化兼顾
7.4 LangGraph Checkpointer:企业级记忆管理
从 LangChain v0.3 开始,ConversationBufferMemory 已被标记为 deprecated(弃用),LangChain 正在将 Memory 能力向 LangGraph 迁移。
LangGraph 提供了更强大的记忆管理方案:Checkpointer + Store。
Checkpointer(短期记忆):
from langgraph.checkpoint.postgres import PostgresSaver
from langgraph.graph import StateGraph, MessagesState, START
DB_URI = "postgresql://postgres:postgres@localhost:5442/postgres?sslmode=disable"
# 使用 PostgresSaver 作为 Checkpointer
with PostgresSaver.from_conn_string(DB_URI) as checkpointer:
checkpointer.setup() # 首次使用需要初始化数据库表
builder = StateGraph(MessagesState)
builder.add_node("call_model", call_model)
builder.add_edge(START, "call_model")
builder.set_finish_point("call_model")
graph = builder.compile(checkpointer=checkpointer)
# 通过 thread_id 实现会话隔离
config = {"configurable": {"thread_id": "user_12345"}}
# 调用时会自动保存状态到 PostgreSQL
graph.invoke(
{"messages": [{"role": "user", "content": "你好,我叫小明"}]},
config=config
)
Store(长期记忆):
Checkpointer 只能管理单线程(单会话)内的状态。如果需要在不同会话之间共享用户偏好等信息,需要使用 Store:
from langgraph.store.postgres import PostgresStore
# Store 用于跨会话的长期记忆
store = PostgresStore.from_conn_string(DB_URI)
# 用户偏好存储(跨所有会话共享)
await store.aflat_put(
namespace=("user_preferences", user_id),
key="coffee_preference",
value={"type": "latte", "extra_shot": True}
)
# 任何会话都可以读取这个偏好
preference = await store.aget(
namespace=("user_preferences", user_id),
key="coffee_preference"
)
7.5 2026年趋势:架构演进方向
-
LangGraph 全面替代 Legacy Chain
ConversationBufferMemory在 v0.3.1 被弃用- v1.0 将完全移除
- 新项目应直接使用 LangGraph
-
三层记忆架构成为主流
- 短期记忆(Short-term):Checkpointer 管理当前会话状态
- 长期记忆(Long-term):Store 管理跨会话的用户事实
- 语义记忆(Semantic):向量数据库存储可检索的历史片段
-
专业 Memory 服务兴起
- LangMem SDK:官方推荐的语义记忆方案
- Mem0:专注于 Agent 记忆管理,P95 延迟仅 0.2s
- Zep:支持时间推理的 Memory 服务
-
现代应用架构建议
- 简单多轮对话:使用
ConversationSummaryBufferMemory - 复杂 Agent 场景:使用 LangGraph + Checkpointer + 持久化后端
- 企业级应用:采用三层记忆架构,按需选择专业 Memory 服务
- 简单多轮对话:使用
八、总结:选对 Memory,让 AI 应用有温度
LangChain 的 Memory 组件,是连接 LLM 无状态特性与多轮对话需求的桥梁。通过不同的存储和压缩策略,开发者可以根据场景需求,在"记忆完整度"和"Token 消耗"之间找到最佳平衡点。
核心要点回顾:
- Memory 本质是对话历史的管理与智能注入——让 LLM 能够"记起"之前聊过的内容
- 5种记忆类型各有优劣:Buffer(全量)、Window(窗口)、TokenBuffer(Token限制)、Summary(摘要)、SummaryBuffer(混合)——根据场景选对策略
- 现代用法推荐 LCEL + RunnableWithMessageHistory——更灵活、更强大的会话管理方式
- 生产环境必须持久化——Redis、PostgreSQL、MongoDB 等方案,按需选择
- LangGraph 是未来方向——Legacy Chain 已被弃用,新项目应使用 LangGraph
最后送大家一句话:
选对记忆策略,就是选对了成本与体验的平衡点。用对了 Memory,你的 AI 应用就能从"和陌生人聊天"升级为"和老朋友交流"。
互动话题
你在生产环境中遇到过什么 Memory 相关的坑?比如 Token 爆炸、记忆丢失、或者选错记忆类型导致的效果下降?欢迎在评论区分享你的经历,大家一起避坑。
转载声明:
本文为技术分享文章,如需转载,请标明出处并保持原文内容完整。
参考链接:
- LangChain Memory 官方文档
- LangGraph Checkpointer 官方文档
- RunnableWithMessageHistory 教程
- Redis 作为 Agent Memory 解决方案
- LangChain Memory 类型深度对比
相关技术选型建议:
| 场景 | 推荐方案 |
|---|---|
| 快速原型开发 | InMemoryChatMessageHistory |
| 生产环境多会话 | Redis + RunnableWithMessageHistory |
| 企业级高可用 | PostgreSQL Checkpointer + Store |
| 超长对话 | ConversationSummaryBufferMemory |
| 语义检索记忆 | VectorStoreRetrieverMemory |
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)