ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

对话记忆管理实战,BufferMemory、SummaryMemory、EntityMemory对比

2026/8/7 19:17:38 拓冰建站 浏览量
对话记忆管理实战,BufferMemory、SummaryMemory、EntityMemory对比

对话记忆管理实战,BufferMemory、SummaryMemory、EntityMemory对比

上一篇讲了记忆系统的基本概念。这一篇我们深入对话记忆的管理。

对话记忆是Agent最常用的记忆类型。用户和Agent一来一回地聊,上下文怎么维护,历史对话怎么管理,Token怎么控制。这些问题的答案,都在对话记忆策略里。

LangChain提供了好几种对话记忆组件,各有各的特点。我们一个一个看,对比它们的优缺点和适用场景。


ConversationBufferMemory

最简单粗暴的记忆方式。把所有对话原封不动地存起来。

fromlangchain_openaiimportChatOpenAIfromlangchain.memoryimportConversationBufferMemoryfromlangchain.chainsimportConversationChain llm=ChatOpenAI(model="gpt-3.5-turbo",temperature=0)memory=ConversationBufferMemory()conversation=ConversationChain(llm=llm,memory=memory)conversation.invoke("我想学Python")conversation.invoke("Python好学吗")conversation.invoke("有什么好的学习资源")# 查看记忆里存了什么print(memory.buffer)

优点是简单。不需要任何处理,原样存取。信息完整,不会遗漏任何细节。

缺点是Token爆炸。对话长了以后,所有内容都塞进Prompt,Token消耗线性增长。聊到50轮,可能一轮调用就要消耗好几千Token。又慢又贵,还会超出模型的上下文长度限制。

适合场景。短对话,几轮到十几轮。调试和开发阶段,需要看到完整的对话历史。对Token消耗不敏感的场景。


ConversationBufferWindowMemory

滑动窗口策略。只保留最近N轮对话,更早的自动丢弃。

fromlangchain.memoryimportConversationBufferWindowMemory# 只保留最近5轮对话memory=ConversationBufferWindowMemory(k=5)conversation=ConversationChain(llm=llm,memory=memory)foriinrange(10):conversation.invoke(f"这是第{i+1}条消息")# memory里只有最近5轮print(memory.buffer)

优点是Token可控。不管聊多少轮,记忆的大小是固定的。不会出现Token爆炸的问题。

缺点是丢早期信息。用户在第1轮说的信息,到第7轮就忘了。如果早期信息很重要,这个策略就不合适。

适合场景。长对话,但每轮对话相对独立,不需要回溯太远。比如闲聊、简单问答。

k值设多大,看你的场景和模型上下文长度。GPT-3.5上下文4097 Token,k设5到8比较合适。GPT-4上下文更长,k可以设大一点。


ConversationSummaryMemory

摘要策略。定期把旧对话总结成一段摘要,用摘要替代原始对话。

fromlangchain.memoryimportConversationSummaryMemory memory=ConversationSummaryMemory(llm=llm)conversation=ConversationChain(llm=llm,memory=memory)conversation.invoke("我叫张三,在一家互联网公司做后端开发")conversation.invoke("我们公司主要做电商,技术栈是Java和Go")conversation.invoke("我最近想转AI方向,在学Python和机器学习")# 查看摘要print(memory.buffer)# 输出类似:# "用户叫张三,在互联网公司做后端开发,公司主要做电商,# 技术栈Java和Go。最近想转AI方向,在学Python和机器学习。"

三轮对话的内容被压缩成了一段摘要。Token大幅减少,关键信息保留了。

优点是Token省。长对话也能压缩成简短的摘要,不会随对话增长而无限膨胀。

缺点是有信息损失。摘要不可能保留所有细节。具体的措辞、语气、细节信息可能会丢。摘要质量依赖大模型的能力。每次生成摘要也要消耗Token。

适合场景。超长对话,需要保留整体脉络但不需要每句话的细节。客服对话、咨询场景。


ConversationSummaryBufferMemory

混合策略。近期对话保留原文,旧对话变成摘要。两个策略的优点都占了。

fromlangchain.memoryimportConversationSummaryBufferMemory# 设一个Token阈值,超过阈值的旧对话会被摘要memory=ConversationSummaryBufferMemory(llm=llm,max_token_limit=200,# 超过200 Token的旧对话会被压缩)conversation=ConversationChain(llm=llm,memory=memory)foriinrange(20):conversation.invoke(f"消息{i+1}:这是一段对话内容,包含一些信息。")# 近期对话是原文,早期对话是摘要print(memory.buffer)

优点是平衡。近期对话完整保留,细节不遗漏。旧对话压缩成摘要,控制Token。既保留了近期的上下文,又不让Token无限增长。

缺点是实现复杂。需要管理原文和摘要的切换,内部逻辑比较复杂。摘要生成也需要消耗额外的Token。

适合场景。大部分需要多轮对话的场景。既能保持近期上下文的准确性,又能控制总Token量。这是我比较推荐的策略。


ConversationEntityMemory

实体记忆。从对话中提取实体信息,单独存储和维护。

fromlangchain.memoryimportConversationEntityMemory memory=ConversationEntityMemory(llm=llm)conversation=ConversationChain(llm=llm,memory=memory)conversation.invoke("我叫张三,在阿里巴巴做算法工程师")conversation.invoke("我老婆叫李四,她在字节跳动做产品经理")conversation.invoke("我们住在杭州")# 查看实体记忆print(memory.entity_store.store)# 输出类似:# {# "张三": "用户的名字,在阿里巴巴做算法工程师",# "阿里巴巴": "用户工作的公司",# "李四": "用户的妻子,在字节跳动做产品经理",# "字节跳动": "李四工作的公司",# "杭州": "用户居住的城市"# }conversation.invoke("我老婆在哪家公司")# Agent能回答"字节跳动",因为它记住了李四这个实体

优点是结构化。实体信息被提取出来单独存储,不会因为对话变长而丢失。查询特定实体的信息很方便。

缺点是只关注实体。实体之间的复杂关系、时间序列信息、非实体的上下文,它不太好处理。实体提取的质量依赖大模型。

适合场景。需要跟踪人物、地点、组织等实体信息的场景。比如个人助手、客户关系管理。


怎么选

对比一下这几种策略。

策略Token控制信息保留实现难度适合场景
Buffer完整最简单短对话、调试
Window丢早期简单长对话、闲聊
Summary有损失中等超长对话
SummaryBuffer较好近期完整较复杂大部分场景
Entity实体完整中等实体追踪

我的建议是,先用BufferWindowMemory,k设5到10。简单有效,大部分场景够用。

如果对话特别长,换成SummaryBufferMemory。近期原文加远期摘要,兼顾效果和Token。

如果需要追踪用户信息、实体关系,加一层EntityMemory。跟其他策略可以组合使用。

记住,这些策略可以组合。比如同时用WindowMemory管理近期对话,用EntityMemory管理实体信息,用向量数据库做长期记忆。组合使用效果更好。


下一篇讲知识库记忆。怎么把对话中的重要信息提取出来,存入知识库,形成长期记忆。