
在 Agent 框架设计中,记忆模块扮演着至关重要的角色,使得 Agent 不再是无状态的独立个体,而是能够记住过去的交互、经验和知识,从而做出更智能、更连贯的决策和行为。
记忆可能看作 Agent 背后一系列状态组成,对于 Agent 过往记录,不过应该如何组织记忆。

更多视频在 B 站 zidea2015 获取 B站 zidea2015
记忆单元(cell)
记忆细胞是记忆最小的单位,每一个记忆细胞会持有一个 message,并且将其其持有 message 理解和消化,得到该 message 的概要,这个概要用于随后信息之间检索。是否需要对于 message 进行概要,取决两个方面,第一个方面是 message 类型,还有就是 message 的体积,也就是只是针对 user 和 AI 类型并且超过一定大小的 message 才会进行概要(summarize)
你提出的策略,即对用户和 AI 类型且超过一定大小的消息进行概要,是一个在对话记忆系统中实现高效信息检索的有效方法。通过将记忆组织成携带消息的记忆细胞,并对特定类型的长消息进行概要,可以显著提高系统的性能和可扩展性。在实际应用中,需要仔细考虑消息类型的定义、体积阈值的设定以及选择合适的概要方法。
信息损失 概要本质上是一种信息压缩,可能会丢失一些细节或细微差别。需要设计有效的概要方法以最大程度地保留关键信息。 概要质量 概要的质量直接影响后续检索的准确性。需要使用合适的自然语言处理技术来生成高质量的概要。 计算成本 因为现在生成概要是基于大语言模型,所以需要考虑成本。生成概要本身也需要计算资源。需要在概要的收益和成本之间进行权衡。可以通过其他方法来解决概要,例如提取关键词来作为信息匹配。
- 词向量平均 (Word Embedding Averaging)
- 句子/段落嵌入 (Sentence/Paragraph Embeddings)
- 词语移动距离 (Word Mover's Distance, WMD)
- 上下文嵌入相似度 (Contextual Embedding Similarity)
- 生成式评估 (Generative Evaluation - 需要更复杂的设置)
- 基于任务的评估 (Task-based Evaluation)
python
class MemoryCell(BaseModel):
message: BaseMessage
token_size: int
summary: Optional[str]
model_name: Optional[str] = Field(default="deepseek-chat")
memory_id: Optional[str] = Field(default="")
timestamp: float
metadata :Dict[str,Any]
- 这里时间戳(timestamp)是用于计算记忆衰减
- 高效存储和检索,记忆模块需要能够高效地存储大量的记忆数据,并且能够根据需要快速地检索相关信息可以考虑存储该数据类型的数据媒体,然后可以提供 metadata
- 多媒体数据支持是体现在 BaseMessage
- 记忆单元持有一个 BaseMessage 这是一个必填字段,其他字段都是可选字段
- 其他字段初始后自动自动通过计算进行赋值
记忆片段(block)
那么应该如何实现在初始化 MemoryCell(AIMessage(content="写一个函数")),对于其字段进行自动赋值 还有就是如何为 MemoryCell 设置类上属性,也就是所有实例都会共享的属性
python
from typing import Union,List
from pydantic import BaseModel,Field
from .memory_cell import MemoryCell
class MemoryCategory(BaseModel):
name:str = Field(title="记忆类别的名称",examples=['情景记忆'])
title:str
description:str = Field(title="记忆类别的描述")
examples:List[str]
class MemoryBlock(BaseModel):
memory_block_id:str
memory_cells:List[MemoryCell]
memory_entities:List[str]
memory_category:MemoryCategory
生成 message ,以 SystemMessage 触发,然后就是 AIMessage HumanMessage 交互,中间可能穿插 CodeMessage 等其他 message,如何判断截取记忆块
python
def should_extract_memory_block(messages: List[BaseMessage], category_fn: Callable[...,str]) -> bool:
"""
判断是否应该从消息历史中截取记忆块。
Args:
messages: 完整的消息历史列表。
Returns:
True 如果应该截取记忆块,False 否则。
"""
if not messages:
return False
# 检查是否存在以 SystemMessage 开头,并且后续有交互
if not isinstance(messages[0], SystemMessage):
return False
# 遍历消息历史,查找是否包含属于目标 MemoryCategory 的信息
for message in messages:
# 触发条件
result = trigger_category_fn(message)
if result:
return True
return False
触发条件: 首先我们来判断消息记录不为空。然后消息历史以 SystemMessage 开头(表示 Agent 的初始化状态)。在后续的消息中,至少存在一条消息的 additional_kwargs 中包含一个 memory_category 字段,并且该字段是一个 MemoryCategory 实例,其 name 属性与 trigger_category_name 相匹配。 这个函数用于判断是否满足截取记忆块的基本条件。你可以根据更复杂的业务逻辑调整判断标准。
python
def extract_memory_block(messages: List[BaseMessage], category: MemoryCategory) -> Union[MemoryBlock, None]:
pass
对于 extract_memory_block(messages, category) 函数:
目标类别 : 接收完整的消息历史和一个目标 MemoryCategory 实例。 遍历消息: 遍历消息历史中的每一条消息。