langchain从入门到精通(四十二)——全面剖析之Memory
1. Memory模块的设计意义
1.1 不借助LangChain情况下,我们如何实现大模型的记忆能力?
import openai
from openai import OpenAI
openai.api_key = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
openai.api_base="https://dashscope.aliyuncs.com/compatible-mode/v1"
llm = OpenAI(api_key=openai.api_key ,base_url=openai.api_base)
def chat_with_model(prompt, model="qwen-plus"):# 步骤一:定义一个可以接收用户输入的变量promptmessages = [{"role": "system", "content": "你是一位乐于助人的AI小助手"},{"role": "user", "content": prompt}]# 步骤二:定义一个循环体:while True:# 步骤三:调用OpenAI的GPT模型APIresponse = llm.chat.completions.create(model=model,messages=messages)# 步骤四:获取模型回答answer = response.choices[0].message.contentprint(f"模型回答: {answer}")# 询问用户是否还有其他问题user_input = input("您还有其他问题吗?(输入退出以结束对话): ")if user_input == "退出":break# 步骤五:记录用户回答messages.append({"role": "user", "content": user_input})messages.append({"role": "assistant", "content": answer})print(messages)
调用可
chat_with_model("你好")
告诉模型相关信息,模型会记忆
模型回答: 你好呀!有什么我可以帮你的吗?😊
[{'role': 'system', 'content': '你是一位乐于助人的AI小助手'}, {'role': 'user', 'content': '你好'}, {'role': 'user', 'content': ''}, {'role': 'assistant', 'content': '你好呀!有什么我可以帮你的吗?😊'}]
模型回答: 你好呀!有什么我可以帮你的吗?😊
[{'role': 'system', 'content': '你是一位乐于助人的AI小助手'}, {'role': 'user', 'content': '你好'}, {'role': 'user', 'content': ''}, {'role': 'assistant', 'content': '你好呀!有什么我可以帮你的吗?😊'}, {'role': 'user', 'content': '我是陈真'}, {'role': 'assistant', 'content': '你好呀!有什么我可以帮你的吗?😊'}]
模型回答: 你好,陈真!很高兴认识你~有什么问题或者需要帮助的吗?😊
这种形式是最简单的一种让大模型具备上下文知识的一种存储方式,任何记忆的基础都是所有聊天交互的历史记录。即使这些不全部直接使用,也需要以某种形式存储。保留一个聊天消息列表还是相当简单,一个非常简单的记忆模块可以只返回每次运行的最新消息。稍微复杂一点的记忆模块需要返回过去 K 条消息的简洁摘要。更复杂的可能会从存储的消息中提取实体,并且仅返回有关当前运行中引用的实体的信息。而我们论述的这些复杂情况,在应用开发中往往才是我们真正要用到。所以一个理想的开发状态是:因为每个应用程序对于如何查询记忆会有不同的要求,那我们要做到既可以轻松地使用简单的记忆模块,还能够在需要时灵活地扩展高度定制化的自定义记忆模块。
LangChain就针对上述情况,基于它的开发规范和设计理念,构建了一些可以直接使用的Memory
工具,用于存储聊天消息的一系列集成,同时,也支持我们去自定义相关的Memory
模块,从而适配到应用开发的各个场景中。
Memory
作为存储记忆数据的一个是抽象模块,其作为一个独立模块使用是没有任何意义的,因为本质上它的定位就是一个存储对话数据的空间。先抛开其内部实现的复杂性,我们可以回想一下:在定义链路的时候,每个链的内部都会根据其接收到的输入去定义其核心执行逻辑,比如在链内如何去调用外部工具,如何解析返回的数据格式等。其中链接收到的输入,可以直接来自用户,同时,也可以来自Memory
模块。所以在这个过程中,一个链如果接入了Memory
模块,其内部会与Memory
模块进行两次交互:
- 收到用户输入之后,执行核心逻辑之前,链会读取
Memory
模块,拿到对应的数据,与用户输入的Prompt放在一起,执行接下来的逻辑。 - 执行核心逻辑之后,返回响应之前,链会将这个过程中产生的信息,写入
Memory
模块,以便在其他场景下能够引用到这些记忆数据。
2. 如何自定义Memory模块
2.1 自定义Memory的API实现
步骤1:先看API:https://api.python.langchain.com/en/latest/langchain_api_reference.html#module-langchain.memory
步骤2:再看源码:langchain/libs/core/langchain_core/memory.py
```python
class BaseMemory(Serializable, ABC):"""Chains 中记忆的抽象基类。记忆指的是 Chains 中的状态。记忆可用于存储关于 Chains 过去执行的信息,并将该信息注入到未来执行的 Chains 输入中。例如,对于对话 Chains,记忆可用于存储对话并自动将其添加到未来模型提示中,以便模型具有必要的上下文来连贯地响应最新的输入。"""# 下面是一些必须由子类实现的方法:# 定义一个属性,任何从BaseMemory派生的子类都需要实现此方法。# 此方法应返回该记忆类将添加到链输入的字符串键。@property@abstractmethoddef memory_variables(self) -> List[str]:"""此记忆类将添加到链输入的字符串键列表。"""# 定义一个抽象方法。任何从BaseMemory派生的子类都需要实现此方法。# 此方法基于给定的链输入返回键值对。@abstractmethoddef load_memory_variables(self, inputs: Dict[str, Any]) -> Dict[str, Any]:"""根据链的文本输入返回键值对。"""# 定义一个抽象方法。任何从BaseMemory派生的子类都需要实现此方法。# 此方法将此链运行的上下文保存到内存。@abstractmethoddef save_context(self, inputs: Dict[str, Any], outputs: Dict[str, str]) -> None:"""将此链运行的上下文保存到记忆中。"""# 定义一个抽象方法。任何从BaseMemory派生的子类都需要实现此方法。# 此方法清除内存内容。@abstractmethoddef clear(self) -> None:"""清除记忆内容。"""
自定义记忆模块,先导入BaseMemory
并对其进行子类化。需要的具体类和模块如下:
from langchain_core.messages import HumanMessage, AIMessage, BaseMessage
from pydantic import Field
from dataclasses import field class InputStoreMemory(BaseMemory):chat_history: List[BaseMessage] = Field(default_factory=list)def __init__(self, **kwargs):super().__init__(**kwargs)@propertydef memory_variables(self) -> List[str]:return ["chat_history"]def load_memory_variables(self, inputs: Dict[str, Any]) -> Dict[str, Any]:return {"chat_history": self.chat_history}def save_context(self, inputs: Dict[str, Any], outputs: Dict[str, Any]) -> None:user_input = inputs.get("input") or ""ai_output = outputs.get("text") or outputs.get("output") or ""self.chat_history.append(HumanMessage(content=user_input))self.chat_history.append(AIMessage(content=ai_output))def clear(self) -> None:self.chat_history.clear()input_memory = InputStoreMemory()
input_memory.save_context({"input": "你好,我是小智"}, {"output": " "})
加载记忆
input_memory.load_memory_variables({})
得到结果
input_memory.load_memory_variables({})
继续存储信息
input_memory.save_context({"input": "我正在学习AI大模型课程。"}, {"output": " "})
加载信息
input_memory.load_memory_variables({})
{'desc': '你好,我是小智\n我正在学习AI大模型课程。'}
自定义的Memory接入LangChain
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate,MessagesPlaceholder
from langchain.chains import LLMChain
openai.api_key = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
openai.api_base="https://dashscope.aliyuncs.com/compatible-mode/v1"
# 实例化一个模型
llm = ChatOpenAI(model_name="qwen-plus",api_key=openai.api_key ,base_url=openai.api_base)# qwen-plus# 实例化一个模版
from langchain_core.prompts import ChatPromptTemplatechat_template = ChatPromptTemplate.from_messages([("system", "你是一位乐于助人的 AI 小助手,请记住用户说过的话,并基于这些内容做出自然、富有记忆感的回应。"),MessagesPlaceholder(variable_name="chat_history"), ("human", "{input}")
])chat_chain = LLMChain(llm=llm, prompt=chat_template,memory=InputStoreMemory(),verbose=True)
chat_chain.invoke({"input":"你好,请你介绍一下你自己。"})
chat_chain.invoke({"input":"我是小智"})
chat_chain.invoke({"input":"我是谁呀,请你告诉我我的名字"})
chat_chain.invoke({"input":"我每天都在服务同学"})
chat_chain.invoke({"input":"现在你知道我每天都在做什么吗?"})
> Entering new LLMChain chain...
Prompt after formatting:
System: 你是一位乐于助人的 AI 小助手,请记住用户说过的话,并基于这些内容做出自然、富有记忆感的回应。
Human: 你好,请你介绍一下你自己。
AI: 你好呀!很高兴认识你~我是Qwen,一个热爱学习、乐于助人的AI小伙伴。我特别喜欢和人类朋友们交流,可以陪你聊天、帮你写作,甚至还能写代码呢!虽然我还在不断学习和成长中,但我会认真对待每一次对话,希望能成为你值得信赖的好伙伴。不知道你今天想和我聊些什么呢?🌟
Human: 我是小智
AI: 你好,小智!我是Qwen,很高兴认识你~🌟 我是一个喜欢学习和帮助他人的AI小伙伴。我们可以一起聊天、写作,甚至一起写代码呢!希望我们能成为好朋友,有什么需要帮忙的尽管告诉我哦~
Human: 我是谁呀,请你告诉我我的名字
AI: 你叫小智,是刚刚和我打招呼的新朋友呀!✨ 我还特意记下了你的名字,希望没有记错呢~小智,今天想和我聊些什么?或者需要我帮忙做些什么吗?
Human: 我每天都在服务同学
AI: 小智,听起来你是一个非常热心、乐于助人的人呢!每天服务同学一定很充实吧?😊
你是学生组织的成员吗?还是作为志愿者在帮助大家呢?我很好奇你的工作内容,也想了解一下你帮助同学时发生的有趣故事~
如果你遇到什么需要帮忙的地方,比如整理信息、写文案,或者规划服务计划,我也可以陪你一起完成哦!💪
Human: 现在你知道我每天都在做什么吗?> Finished chain.
3. 自定义支持实体识别的Memory
3.1 spacy工具安装
针对上述需求描述,我们补充两个知识点:首先,实体识别(Named Entity Recognition, NER)是自然语言处理(NLP)中的一个经典任务,其目的是从文本中识别出有特定意义的实体,例如人名、地点、组织机构名、时间表达式、数量、货币值等。实体识别通常作为信息提取、问答系统、内容摘要、语义搜索等应用的基础。其次,对于如何从一个文本中提取出具体的实体,我们要借助一个可以做实体识别的深度学习模型,该模型,我们选择从Python的一个spacy
库中下载。
spacy官网:https://spacy.io/
spaCy
是一个开源的自然语言处理(NLP)库,提供了一些高性能的语言处理功能,适用于Python。主要用于文本分析和处理任务,包括但不限于词性标注、命名实体识别(NER)、句法依赖分析、句子边界检测等。使用spaCy
库,需要在当前环境下安装其依赖包,执行如下代码:
pip install --upgrade --quiet spacy
! python -m spacy download zh_core_web_sm
Collecting zh-core-web-sm==3.8.0Downloading https://github.com/explosion/spacy-models/releases/download/zh_core_web_sm-3.8.0/zh_core_web_sm-3.8.0-py3-none-any.whl (48.5 MB)---------------------------------------- 0.0/48.5 MB ? eta -:--:------------------------------------------ 0.0/48.5 MB ? eta -:--:--- -------------------------------------- 1.3/48.5 MB 6.1 MB/s eta 0:00:08-- ------------------------------------- 2.9/48.5 MB 7.0 MB/s eta 0:00:07--- ------------------------------------ 4.5/48.5 MB 7.7 MB/s eta 0:00:06--- ------------------------------------ 4.5/48.5 MB 7.7 MB/s eta 0:00:06--- ------------------------------------ 4.5/48.5 MB 7.7 MB/s eta 0:00:06--- ------------------------------------ 4.5/48.5 MB 7.7 MB/s eta 0:00:06--- ------------------------------------ 4.5/48.5 MB 7.7 MB/s eta 0:00:06--- ------------------------------------ 4.5/48.5 MB 7.7 MB/s eta 0:00:06--- ------------------------------------ 4.5/48.5 MB 7.7 MB/s eta 0:00:06--- ------------------------------------ 4.5/48.5 MB 7.7 MB/s eta 0:00:06---- ----------------------------------- 5.2/48.5 MB 2.2 MB/s eta 0:00:20----- ---------------------------------- 6.8/48.5 MB 2.6 MB/s eta 0:00:16------ --------------------------------- 8.4/48.5 MB 3.0 MB/s eta 0:00:14------ --------------------------------- 8.4/48.5 MB 3.0 MB/s eta 0:00:14------ --------------------------------- 8.4/48.5 MB 3.0 MB/s eta 0:00:14------ --------------------------------- 8.4/48.5 MB 3.0 MB/s eta 0:00:14------ --------------------------------- 8.4/48.5 MB 3.0 MB/s eta 0:00:14------ --------------------------------- 8.4/48.5 MB 3.0 MB/s eta 0:00:14------ --------------------------------- 8.4/48.5 MB 3.0 MB/s eta 0:00:14------- -------------------------------- 8.7/48.5 MB 2.0 MB/s eta 0:00:20-------- ------------------------------- 10.2/48.5 MB 2.3 MB/s eta 0:00:17
...Successfully installed spacy-pkuseg-1.0.1 zh-core-web-sm-3.8.0
✔ Download and installation successful
You can now load the package via spacy.load('zh_core_web_sm')
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...
3.2 自定义实力识别功能逻辑实现
import openai
from openai import OpenAI
openai.api_key = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
openai.api_base="https://dashscope.aliyuncs.com/compatible-mode/v1"
# qwen-plus
llm = OpenAI(api_key=openai.api_key ,base_url=openai.api_base)
# 导入依赖包
import spacy# 实例化模型。
nlp = spacy.load("zh_core_web_sm")# 构建一条输入文本
text = "2014年9月,马云在杭州发起了世界互联网大会。这一事件标志着中国在全球互联网发展中的积极参与。"# 执行
doc = nlp(text)# 查看实体识别结果
doc.ents
(2014年9月, 杭州, 中国)
例子2:
text = "随后,2015年11月,腾讯公司在深圳发布了微信支付功能,进一步推动了中国数字经济的发展"
doc = nlp(text)
doc.ents
(2015年11月, 腾讯公司, 深圳, 中国)
例子3:
text = "与此同时,字节跳动的产品——抖音,在2016年成为中国年轻人中的热门应用,为内容创造者提供了展示才华的平台。"
doc = nlp(text)
doc.ents
(2016年, 中国)
from langchain.chains import LLMChain
from langchain.schema import BaseMemory
from pydantic import BaseModel
from typing import Any, Dict, Iterable, List, Optional
class SpacyEntityMemory(BaseMemory, BaseModel):"""存储实体信息的记忆类。"""# 定义一个字典来存储实体的信息。entities: dict = {}# 定义一个 Key,作用是将有关实体的信息传递到提示符:memory_keymemory_key: str = "entities"# 清除全部的实体信息def clear(self):self.entities = {}@propertydef memory_variables(self) -> List[str]:"""定义提供给提示符的变量。"""return [self.memory_key]def load_memory_variables(self, inputs: Dict[str, Any]) -> Dict[str, str]:"""Load the memory variables, in this case the entity key."""# 获取输入文本doc = nlp(inputs[list(inputs.keys())[0]])# 提取关于实体的已知信息(如果存在的话)。entities = [self.entities[str(ent)] for ent in doc.ents if str(ent) in self.entities]# 返回要放在上下文中的实体的组合信息。return {self.memory_key: "\n".join(entities)}def save_context(self, inputs: Dict[str, Any], outputs: Dict[str, str]) -> None:"""将此对话中的上下文保存到缓冲区。"""# 获取输入文本text = inputs[list(inputs.keys())[0]]# 运行spacy,从输入文本中提取关键的信息doc = nlp(text)# 对于提到的每个实体,将此信息保存到字典中。for ent in doc.ents:ent_str = str(ent) # 如果实体信息已经存在,将当前文本(text)追加到这个实体键下已有的文本后面,每个文本之间用换行符\n分隔。# 示例:{'2014年9月': '2014年9月,马云在杭州发起了世界互联网大会。这一事件标志着中国在全球互联网发展中的积极参与。', \# '马云': '2014年9月,马云在杭州发起了世界互联网大会。这一事件标志着中国在全球互联网发展中的积极参与。', # '杭州': '2014年9月,马云在杭州发起了世界互联网大会。这一事件标志着中国在全球互联网发展中的积极参与。', # '中国': '2014年9月,马云在杭州发起了世界互联网大会。这一事件标志着中国在全球互联网发展中的积极参与。'}if ent_str in self.entities:self.entities[ent_str] += f"\n{text}"else:# 如果实体不存在,则在self.entities字典中以这个实体字符串ent_str为键,当前文本text为值,创建一个新的键值对。self.entities[ent_str] = text
在上述Memory
的实现逻辑中,定义entities
作为存储记忆数据的变量。其中,save_context
的逻辑是:针对输入的文本,使用zh_core_web_sm
模型去做实体识别,如果该实体的Key
在entities
已经存在,将当前文本text
追加到这个实体Key
下已有的文本后面,每个文本之间用换行符\n
分隔。如果实体不存在,则在entities
字典中以这个实体字符串为Key
,当前文本text
为值,创建一个新的键值对。其示例如下:
输入:'2014年9月,马云在杭州发起了世界互联网大会。这一事件标志着中国在全球互联网发展中的积极参与。识别到的实体:2014年9月、 马云、杭州存储到`SpacyEntityMemory`类中`entities`字典的信息是:- '2014年9月': '2014年9月,马云在杭州发起了世界互联网大会。这一事件标志着中国在全球互联网发展中的积极参与。',
- '马云': '2014年9月,马云在杭州发起了世界互联网大会。这一事件标志着中国在全球互联网发展中的积极参与。',
- '杭州': '2014年9月,马云在杭州发起了世界互联网大会。这一事件标志着中国在全球互联网发展中的积极参与。'
load_memory_variables
的代码逻辑是:先对输入的文本使用zh_core_web_sm
模型去做实体识别,然后去查entities
是否存在这个Key
,如果存在,把这个Key
对应的内容读取出来,作为上下文信息。示例如下:
输入:'那天,我正好去游玩,碰到了马云识别到的实体: 马云去`SpacyEntityMemory`类中`entities`字典的中找到下面内容,作为上下文信息:- '马云': '2014年9月,马云在杭州发起了世界互联网大会。这一事件标志着中国在全球互联网发展中的积极参与。',
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model_name="qwen-plus",api_key=openai.api_key ,base_url=openai.api_base)
from langchain.prompts.prompt import PromptTemplatetemplate = """以下是人类和AI之间的友好对话。AI很健谈,并提供了大量来自其上下文的具体细节。如果AI不知道某个问题的答案,它会真诚地说不知道。如果相关,你会得到人类提到的实体的信息。相关实体信息:
{entities}对话:
人类: {input}
AI:"""prompt = PromptTemplate(input_variables=["entities", "input"], template=template)SpacyMemory = SpacyEntityMemory(memory_key="entities")
spacy_chain = LLMChain(llm=llm, prompt=prompt, memory=SpacyMemory, # 接入Memory 模块verbose=True)
4. LangChain内置的Memory模块
当然可以,以下是对 LangChain 内置 Memory 模块的完整、深入讲解,包括每种 Memory 类型的核心参数、适用场景、优缺点等,适合用于学习材料、开发文档或项目选型依据。
4.1 ConversationBufferMemory
✅ 主要作用:
保存从会话开始到当前的完整历史对话消息文本,并将其插入 prompt 中,适用于简洁场景。
⚙️ 参数说明:
参数 | 类型 | 说明 |
---|---|---|
memory_key | str | Prompt 占位符的字段名,默认为 "history" |
input_key /output_key | str | 输入与输出字段名,默认是 "input" 和 "output" |
return_messages | bool | 若设为 True ,返回消息对象(适用于 Chat 模型) |
chat_memory | BaseChatMemory | 底层聊天存储结构 |
👍 优点:
- 实现最简单、使用方便
- 可自动累积所有的上下文
👎 缺点:
- 当对话过长时,prompt 会变得庞大,容易超出 token 限制
- 无摘要或压缩,效率低
✅ 使用示例:
from langchain.memory import ConversationBufferMemorymemory = ConversationBufferMemory(return_messages=True)# 与 ConversationChain 搭配:
from langchain.chains import ConversationChain
conversation = ConversationChain(llm=ChatOpenAI(),memory=memory
)
4.2 ConversationBufferWindowMemory
✅ 主要作用:
仅保留最近N 轮消息(一个滑动窗口),控制 token 长度,适合高频对话。
⚙️ 参数说明:
参数 | 类型 | 说明 |
---|---|---|
k | int | 保留最近的 k 轮会话,默认 5 |
memory_key | str | Prompt 中的字段名 |
return_messages | bool | 同上 |
input_key /output_key | str | 同上 |
👍 优点:
- 避免 prompt 膨胀,性能更高
- 控制上下文大小,节省成本
👎 缺点:
- 旧对话被丢弃,长期依赖上下文的任务不合适
- 无摘要、不可回溯全局语义
4.3 ConversationSummaryMemory
✅ 主要作用:
通过 LLM 对历史对话进行摘要提炼,只保留浓缩语义内容作为上下文。
⚙️ 参数说明:
参数 | 类型 | 说明 |
---|---|---|
llm | BaseLanguageModel | 执行摘要的语言模型 |
memory_key | str | Prompt 插入字段(如 “summary”) |
buffer | str | 内部存储的摘要缓存 |
chat_memory | BaseChatMemory | 存储历史 |
predict_new_summary() | 方法 | 每轮调用后更新摘要 |
👍 优点:
- 节省 token,适合长对话
- 模型能保留上下文大意而不丢失重要信息
👎 缺点:
- 摘要可能丢失细节
- 对摘要质量依赖 LLM 表现
- 需要额外的 OpenAI 费用
✅ 示例:
from langchain.memory import ConversationSummaryMemory
from langchain.chat_models import ChatOpenAImemory = ConversationSummaryMemory(llm=ChatOpenAI(temperature=0),memory_key="summary"
)
4.4 ConversationEntityMemory
✅ 主要作用:
识别并记录对话中出现的**命名实体(如人物、地点、事件)**及其联想内容,为特定实体提供记忆。
⚙️ 参数说明:
参数 | 类型 | 说明 |
---|---|---|
llm | BaseLanguageModel | 提取实体及其关系 |
memory_key | str | 默认为 "entities" |
entity_cache | Dict[str, str] | 本地记录的实体与描述 |
k | int | 每次检索最大实体数(可选) |
👍 优点:
- 对实体(角色)信息建立独立记忆
- 适合剧情剧本、客服场景、个性化助手
- 记住多个不同实体的背景知识
👎 缺点:
- 架构复杂,依赖实体抽取准确性
- 不适合无明确实体的轻量任务
4.5 ConversationKGMemory
✅ 主要作用:
以知识图谱格式保存对话中提到的实体及其属性/关系,支持图谱推理。
⚙️ 参数说明:
参数 | 类型 | 说明 |
---|---|---|
llm | BaseLanguageModel | 抽取三元组(实体、属性、值) |
knowledge_store | Dict[str:Set[str]] | 内存中的简化图谱结构 |
memory_key | str | 默认是 "knowledge" |
👍 优点:
- 知识结构化,适合复杂问答
- 可储存规则、关系、类别等
👎 缺点:
- 对 LLM 图谱抽取准确性要求高
- 实际图谱能力有限制(非全功能图数据库)
4.6 VectorStoreRetrieverMemory
✅ 主要作用:
使用**向量数据库(如 FAISS、Chroma)**将每轮对话向量化,并启用语义检索历史片段。
⚙️ 参数说明:
参数 | 类型 | 说明 |
---|---|---|
retriever | BaseRetriever | 检索器对象,如 FAISSRetriever |
memory_key | str | 默认是 "history" |
input_key | str | 输入字段名 |
search_kwargs | dict | 控制多少条匹配内容 |
👍 优点:
- 极大压缩 context,语义检索精准相关历史
- 可支持长期记忆
👎 缺点:
- 需要构建和维持向量数据库
- 无法自动总结信息,只能检索
✅ 示例:
from langchain.vectorstores import FAISS
vectorstore = FAISS.load_local(...)memory = VectorStoreRetrieverMemory(retriever=vectorstore.as_retriever())
4.7 ZepMemory
(第三方集成)
✅ 主要作用:
与 Zep 服务集成,用于统一的云端对话历史和搜索管理。
⚙️ 参数说明:
参数 | 类型 | 说明 |
---|---|---|
session_id | str | 对话唯一标识 |
zep_client | ZepClient | 云端客户端 |
memory_key | str | Prompt 插入字段 |
👍 优点:
- 具备长期记忆、搜索、摘要等综合能力
- 云端可支持多用户、多设备
👎 缺点:
- 依赖外部服务,需要网络与 API Key
- 不适合完全数据本地部署的场景
📊 总结对比一览表
Memory 名称 | 保留方式 | 节省 Token | 结构化支持 | 适用场景 |
---|---|---|---|---|
ConversationBufferMemory | 纯文本历史 | ❌ | 否 | 简洁 demo、多轮 Q&A |
ConversationBufferWindowMemory | N 条消息 | ✅ | 否 | Token 控制场景 |
ConversationSummaryMemory | 动态摘要 | ✅✅ | 否 | 长对话摘要 |
ConversationEntityMemory | 实体槽位 | ✅✅ | 是(半结构化) | 多角色、知识跟踪 |
ConversationKGMemory | 知识图谱 | ✅✅ | 是(结构化) | 数据问答、任务规划 |
VectorStoreRetrieverMemory | 语义检索 | ✅✅✅ | 是(检索) | 知识库型问答 |
ZepMemory | 云端服务 | ✅✅✅ | 是(增强) | 多人多端支持 |