Memory

Memory 概述

为什么需要 Memory

大多数的大模型应用程序都会有一个会话接口,允许我们进行多轮的对话,并有一定的上下文记忆能力。

但实际上,模型本身是 不会记忆 任何上下文的,只能依靠用户本身的输入去产生输出。

如何实现记忆功能呢?

实现这个记忆功能,就需要 额外的模块 去保存我们和模型对话的上下文信息,然后在下一次请求时,把所有的历史信息都输入给模型,让模型输出最终结果。

而在 LangChain 中,提供这个功能的模块就称为 Memory(记忆) ,用于存储用户和模型交互的历史信
息。

什么是 Memory

Memory,是 LangChain 中用于多轮对话中保存和管理上下文信息(比如文本、图像、音频等)的组件。它让应用能够记住用户之前说了什么,从而实现对话的上下文感知能力,为构建真正智能和上下文感知的链式对话系统提供了基础。

在这里插入图片描述

不使用 Memory 模块,如何拥有记忆?

通过 messages 变量,不断地将历史的对话信息追加到对话列表中,以此让大模型具备上下文记忆能力。

from langchain_core.messages import AIMessage
from langchain_core.prompts import ChatPromptTemplate
from langchain_ollama import ChatOllama

chat_model = ChatOllama(
    model="qwen3:0.6b"
)

prompt_template = ChatPromptTemplate.from_messages(
    [
        ("system", "你是一个AI助手"),
        ("human", "帮用户解决问题")
    ]
)

response = chat_model.invoke(prompt_template.invoke({}))

# 将新的结果,通过 .messages.append 添加到消息模版中
prompt_template.messages.append(AIMessage(content=response.content))

Memory 模块的设计思路

如何设计 Memory 模块?

  • 层次 1(最直接的方式):保留一个聊天消息列表
  • 层次 2(简单的新思路):只返回最近交互的 k 条消息
  • 层次 3(稍微复杂一点):返回过去 k 条消息的简洁摘要
  • 层次 4(更复杂):从存储的消息中提取实体,并且仅返回有关当前运行中引用的实体的信息

Memory 模块的使用

ChatMessageHistory

ChatMessageHistory 是一个用于存储和管理对话消息的基础类,它直接操作消息对象(如 HumanMessage, AIMessage 等),是其它记忆组件的底层存储工具

在 API 文档中,ChatMessageHistory 还有一个别名类:InMemoryChatMessageHistory;导包时,需使用:from langchain_community.chat_message_histories import ChatMessageHistory

特点

  • 纯粹是消息对象的“存储器”,与记忆策略(如缓冲、窗口、摘要等)无关。
  • 不涉及消息的格式化(如转成文本字符串)
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_ollama import ChatOllama

chat_model = ChatOllama(
    model="qwen3:0.6b"
)

# 实例化
history = ChatMessageHistory()

# 添加相关信息进行存储
history.add_user_message("你好")
history.add_ai_message("很高兴认识你")
history.add_user_message("帮我计算1+2=?")

# print(history.messages) # [HumanMessage(content='你好', additional_kwargs={}, response_metadata={}), AIMessage(content='很高兴认识你', additional_kwargs={}, response_metadata={})]

# 对接大模型
response = chat_model.invoke(history.messages)
print(response.content)

ConversationBufferMemory

ConversationBufferMemory 是一个基础的对话记忆(Memory)组件,专门用于按原始顺序存储的对话历史。

适用场景

对话轮次较少、依赖完整上下文的场景(如简单的聊天机器)

特点

  • 完整存储对话历史
  • 简单无裁剪无压缩
  • 与 Chains/Models 无缝集成
  • 支持两种返回格式(通过 return_messages 参数控制输出格式)
    • return_messages=True 返回消息对象列表(List[BaseMessage]
    • return_messages=False(默认)返回拼接的纯文本字符串
from langchain.memory import ConversationBufferMemory

# 实例化
memory = ConversationBufferMemory(
    return_messages=True
)
# 存储相关的消息
memory.save_context(
    inputs={"input": "你好,我是wifi"},  # key是什么不重要,只要是inputs的内容都是human,outputs的都是ai
    outputs={"output": "很高兴认识你"},
)
memory.save_context(
    inputs={"input": "帮我回答一下1+2=?"},
    outputs={"output": "3"},
)
# 获取存储的信息
# 方式1:通过load_memory_variables,返回的是字典,key为history
memory.load_memory_variables({}) # history的内容为字符串,return_messages=False
memory.load_memory_variables({}) # history的内容为消息列表,return_messages=True
# 方式2:通过chat_memory
memory.chat_memory.messages

结合大模型、提示词模版使用

from langchain.chains.llm import LLMChain
from langchain.memory import ConversationBufferMemory
from langchain_core.prompts import PromptTemplate
from langchain_ollama import ChatOllama

chat_model = ChatOllama(
    model="qwen3:0.6b"
)

prompt_template = PromptTemplate.from_template(
    template="""
        你可以与人类对话。
        当前对话: {history}
        人类问题: {question} # memory输出的key为history
        回复:
    """
)

memory = ConversationBufferMemory(
    # memory_key="chat_history", # 可以设置memory的key,在上面的history就可以换成chat_history
)

chain = LLMChain(llm=chat_model, memory=memory, prompt=prompt_template)
chain.invoke({"question": "你好,我是wifi"})
response = chain.invoke({"question": "我的名字是什么呢"})
print(response) # 这里就可以获取到记忆中的名字了

ConversationChain

ConversationChain 实际上是对 ConversationBufferMemoryLLMChain 进行了封装,并且提供一个默认格式的提示词模版(我们也可以不用),从而简化了初始化 ConversationBufferMemory 的步骤。

将下面的代码:

memory = ConversationBufferMemory()
chain = LLMChain(llm=chat_model, memory=memory, prompt=prompt_template)

转化为:

chain = ConversationChain(llm=chat_model, prompt=prompt_template)

ConversationBufferWindowMemory

在了解了 ConversationBufferMemory 记忆类后,我们知道它能无限将历史对话信息填充到 History 中,为大模型提供上下文背景。但这会导致内存占用大,且消耗的 token 非常多;此外,每个大模型都有最大输入 Token 限制。

我们发现,过久远的对话数据往往对当前轮次的问答无有效信息,LangChain 给出的解决方案是:ConversationBufferWindowMemory 模块。该记忆类会保存一段时间内对话交互的列表,仅使用最近 K 个交互,避免缓存区过大。

特点

  • 适合长对话场景。
  • 与 Chains/Models 无缝集成
  • 支持两种返回格式(通过 return_messages 参数控制输出格式)
    • return_messages=True 返回消息对象列表(List[BaseMessage]
    • return_messages=False(默认)返回拼接的纯文本字符串
from langchain.memory import ConversationBufferWindowMemory

memory = ConversationBufferWindowMemory(k=2)

memory.save_context({"input": "你好"}, {"output": "怎么了"})
memory.save_context({"input": "你是谁"}, {"output": "我是AI助手"})
memory.save_context({"input": "你的生日是哪天?"}, {"output": "我不清楚"})
print(memory.load_memory_variables({})) # {'history': 'Human: 你是谁\nAI: 我是AI助手\nHuman: 你的生日是哪天?\nAI: 我不清楚'}

ConversationTokenBufferMemory

ConversationTokenBufferMemory 是 LangChain 中一种基于 Token 数量控制 的对话记忆机制。如果字符数量超出指定数目,它会切掉这个对话的早期部分,以保留与最近的交流相对应的字符数量。

特点

  • Token 精准控制
  • 原始对话保留

原理

在这里插入图片描述

示例:

这里进行 token 转换,需要提前安装transformers包:uv pip install transformers

from langchain.memory import ConversationTokenBufferMemory
from langchain_ollama import ChatOllama

llm = ChatOllama(model="qwen3:0.6b")

memory = ConversationTokenBufferMemory(
    llm=llm,
    max_token_limit=30 # 设置token上限,默认2000
)
memory.save_context({"input": "你好吗?"}, {"output": "我很好,谢谢!"})
memory.save_context({"input": "今天天气如何?"}, {"output": "晴天,25度"})

print(memory.load_memory_variables({})) # {'history': 'Human: 今天天气如何?\nAI: 晴天,25度'}

ConversationSummaryMemory

前面的方式存在问题:全部保存对话太浪费资源,而按对话条数token截断,又无法兼顾内存节省与对话质量,因此推出了 ConversationSummaryMemory、ConversationSummaryBufferMemory。

ConversationSummaryMemory 是 LangChain 中一种智能压缩对话历史的记忆机制,它通过大语言模型(LLM)自动生成对话内容的精简摘要,而非存储原始对话文本。

内部通过调用大模型,将消息内容给大模型生成摘要信息

这种记忆方式特别适合长对话和需要保留核心信息的场景。

特点

  • 摘要生成
  • 动态更新
  • 上下文优化

原理

在这里插入图片描述

基本使用:

from langchain.memory import ConversationSummaryMemory
from langchain_ollama import ChatOllama

llm = ChatOllama(model="qwen3:0.6b")

memory = ConversationSummaryMemory(llm=llm)
memory.save_context({"input": "你好吗?"}, {"output": "我很好,谢谢!"})
memory.save_context({"input": "今天天气如何?"}, {"output": "晴天,25度"})

print(memory.load_memory_variables({})) # {'history': 'New summary:  \nThe human asks if AI is good. AI responds that AI helps humans reach their full potential.'}

ConversationSummaryMemory.from_messages 使用:

from langchain.memory import ConversationSummaryMemory
from langchain_ollama import ChatOllama
from langchain_community.chat_message_histories import ChatMessageHistory

llm = ChatOllama(model="qwen3:0.6b")

history = ChatMessageHistory()
history.add_user_message("你好,你是谁")
history.add_ai_message("我是wifi")

memory = ConversationSummaryMemory.from_messages(
    llm=llm,
    # 是生成摘要的原材料 保留完整对话,供必要时回溯。当新增对话时,LLM需要结合原始历史生成新摘要
    chat_memory=history,
)
print(memory.load_memory_variables({}))
# {'history': 'New summary:  \nThe human asks, "What do you think AI is?"  \nAI: "I am a WiFi."  \n\nNew summary:  \nThe human asks, "What do you think AI is?" AI: "I am a WiFi."'}
print(memory.chat_memory.messages)
# [HumanMessage(content='你好,你是谁', additional_kwargs={}, response_metadata={}), AIMessage(content='我是wifi', additional_kwargs={}, response_metadata={})]

ConversationSummaryBufferMemory

ConversationSummaryBufferMemory 是 LangChain 中一种混合型记忆机制,它结合了 ConversationBufferMemory(完整对话记录)和 ConversationSummaryMemory(摘要记忆)的优点,在保留最近对话原始记录的同时,对较早的对话内容进行智能摘要

特点

  • 保留最近 N 条原始对话:确保最新交互的完整上下文
  • 摘要较早历史:对超出缓冲区的旧对话进行压缩,避免信息过载
  • 平衡细节与效率:既不会丢失关键细节,又能处理长对话

原理

在这里插入图片描述

from langchain.memory import ConversationSummaryBufferMemory
from langchain_ollama import ChatOllama

llm = ChatOllama(model="qwen3:0.6b")

memory = ConversationSummaryBufferMemory(
    llm=llm,
    max_token_limit=50,
    return_messages=True
)

ConversationEntityMemory(了解)

ConversationEntityMemory 是一种基于实体的对话记忆机制,它能够智能地识别、存储和利用对话中出现的实体信息(如人名、地点、产品等)及其属性/关系,并结构化存储,使 AI 具备更强的上下文理解和记忆能力。

好处:解决信息过载问题

  • 长对话中大量冗余信息会干扰关键事实记忆
  • 通过对实体摘要,可以压缩非重要细节(如删除寒暄等,保留价格/时间等硬性事实)

应用场景
在医疗等高风险领域,必须用实体记忆确保关键信息(如过敏史)被 100%准确识别和拦截。

例如:

  • 使用 ConversationSummaryMemory
"患者主诉头痛和高血压(140/90),正在服用阿司匹林。患者对青霉素过敏。三天后头痛未缓解,建议更换止痛药。"
  • 使用 ConversationEntityMemory
{
  "症状": "头痛",
  "血压": "140/90",
  "当前用药": "阿司匹林(无效)",
  "过敏药物": "青霉素"
}

对比:ConversationSummaryMemory 和 ConversationEntityMemory

维度 ConversationSummaryMemory ConversationEntityMemory
自然语言文本(一段话) 结构化字典(键值对)
下游如何利用信息 需大模型“读懂”摘要文本,如果 AI 的注意力集中在“头痛”和“换药”上,可能会忽略过敏提示(尤其是摘要较长时) 无需依赖模型的“阅读理解能力”,直接通过字段名(如过敏药物)查询
防错可靠性 低(依赖大模型的注意力) 高(通过代码强制检查)
推荐处理 可以试试阿莫西林(一种青霉素类药) 完全避免推荐过敏药物

ConversationKGMemory(了解)

ConversationKGMemory 是一种基于**知识图谱(Knowledge Graph)**的对话记忆模块,它比 ConversationEntityMemory 更进一步,不仅能识别和存储实体,还能捕捉实体之间的复杂关系,形成结构化的知识网络。

特点

  • 知识图谱结构:将对话内容转化为(头实体, 关系, 尾实体)的三元组形式
  • 动态关系推理

需要安装networkx

VectorStoreRetrieverMemory(了解)

VectorStoreRetrieverMemory 是一种基于向量检索的先进记忆机制,它将对话历史存储在向量数据库中,通过语义相似度检索相关信息,而非传统的线性记忆方式。每次调用时,就会查找与该记忆关联最高的 k 个文档。

对于上面几种方法(存储在内存中的),VectorStoreRetrieverMemory 存储在向量数据库中,做到了持久化

适用场景
这种记忆特别适合需要长期记忆和语义理解的复杂对话系统。

原理

在这里插入图片描述

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐