我和我的 AI Agent(3)记忆模块设计上花了不少心思,看看记忆细胞和记忆片段是如何设计以及实现的

github项目

在 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 实例。 遍历消息: 遍历消息历史中的每一条消息。

相关推荐
0x2111 小时前
[论文阅读]REPLUG: Retrieval-Augmented Black-Box Language Models
论文阅读·人工智能·语言模型
GeekABC1 小时前
FastAPI系列06:FastAPI响应(Response)
开发语言·python·fastapi·web
fen_fen2 小时前
Python3:Jupyter Notebook 安装和配置
ide·python·jupyter
JOYCE_Leo162 小时前
一文详解卷积神经网络中的卷积层和池化层原理 !!
人工智能·深度学习·cnn·卷积神经网络
float_六七2 小时前
Python语言基础知识详解:分支结构控制语句
python
声声codeGrandMaster2 小时前
django之优化分页功能(利用参数共存及封装来实现)
数据库·后端·python·django
Johny_Zhao3 小时前
OpenStack 全套搭建部署指南(基于 Kolla-Ansible)
linux·python·信息安全·云计算·openstack·shell·yum源·系统运维
27669582923 小时前
海关 瑞数 后缀分析 rs
java·python·rs·瑞数·海关·瑞数后缀·后缀生成
~央千澈~3 小时前
对鸿蒙 Next 系统“成熟论”的深度剖析-优雅草卓伊凡
人工智能