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

最入门的用法,使用 ConversationChainConversationBufferMemory 实现简单的多轮对话:

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

ConversationSummaryMemoryConversationSummaryBufferMemory 需要调用 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 成本控制策略

  1. 监控 Token 消耗:在开发阶段开启 verbose=True,观察每次调用的 Token 用量
  2. 设置告警阈值:当单次调用 Token 超过预期时,触发告警
  3. 超长会话启用摘要:使用 ConversationSummaryBufferMemory 代替 ConversationBufferMemory
  4. 结合语义缓存:对于相似的重复问题,使用缓存避免重复 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年趋势:架构演进方向

  1. LangGraph 全面替代 Legacy Chain

    • ConversationBufferMemory 在 v0.3.1 被弃用
    • v1.0 将完全移除
    • 新项目应直接使用 LangGraph
  2. 三层记忆架构成为主流

    • 短期记忆(Short-term):Checkpointer 管理当前会话状态
    • 长期记忆(Long-term):Store 管理跨会话的用户事实
    • 语义记忆(Semantic):向量数据库存储可检索的历史片段
  3. 专业 Memory 服务兴起

    • LangMem SDK:官方推荐的语义记忆方案
    • Mem0:专注于 Agent 记忆管理,P95 延迟仅 0.2s
    • Zep:支持时间推理的 Memory 服务
  4. 现代应用架构建议

    • 简单多轮对话:使用 ConversationSummaryBufferMemory
    • 复杂 Agent 场景:使用 LangGraph + Checkpointer + 持久化后端
    • 企业级应用:采用三层记忆架构,按需选择专业 Memory 服务

八、总结:选对 Memory,让 AI 应用有温度

LangChain 的 Memory 组件,是连接 LLM 无状态特性与多轮对话需求的桥梁。通过不同的存储和压缩策略,开发者可以根据场景需求,在"记忆完整度"和"Token 消耗"之间找到最佳平衡点。

核心要点回顾:

  1. Memory 本质是对话历史的管理与智能注入——让 LLM 能够"记起"之前聊过的内容
  2. 5种记忆类型各有优劣:Buffer(全量)、Window(窗口)、TokenBuffer(Token限制)、Summary(摘要)、SummaryBuffer(混合)——根据场景选对策略
  3. 现代用法推荐 LCEL + RunnableWithMessageHistory——更灵活、更强大的会话管理方式
  4. 生产环境必须持久化——Redis、PostgreSQL、MongoDB 等方案,按需选择
  5. LangGraph 是未来方向——Legacy Chain 已被弃用,新项目应使用 LangGraph

最后送大家一句话:

选对记忆策略,就是选对了成本与体验的平衡点。用对了 Memory,你的 AI 应用就能从"和陌生人聊天"升级为"和老朋友交流"。


互动话题

你在生产环境中遇到过什么 Memory 相关的坑?比如 Token 爆炸、记忆丢失、或者选错记忆类型导致的效果下降?欢迎在评论区分享你的经历,大家一起避坑。


转载声明:

本文为技术分享文章,如需转载,请标明出处并保持原文内容完整。

参考链接:


相关技术选型建议:

场景 推荐方案
快速原型开发 InMemoryChatMessageHistory
生产环境多会话 Redis + RunnableWithMessageHistory
企业级高可用 PostgreSQL Checkpointer + Store
超长对话 ConversationSummaryBufferMemory
语义检索记忆 VectorStoreRetrieverMemory
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐