AI Agent Harness Engineering 的记忆系统:短期记忆与长期记忆的实现
本文将按照以下结构展开:首先,我们将介绍AI Agent记忆系统的基本概念和理论基础;然后,我们将深入探讨短期记忆和长期记忆的实现技术;接着,我们将通过一个完整的案例研究,展示如何将这些技术应用到实际项目中;最后,我们将总结要点,并展望AI Agent记忆系统的未来发展方向。在深入探讨短期记忆和长期记忆的实现之前,我们首先需要理解AI Agent记忆系统的基本概念。存储经验:保存与环境交互过程中产
AI Agent Harness Engineering 的记忆系统:短期记忆与长期记忆的实现
摘要/引言
你是否曾经想过,如果人工智能能够像人类一样记忆和学习,那将会是怎样的情景?在科幻电影中,我们经常看到拥有完美记忆的AI角色,它们能够回忆起每一个细节,从过去的经历中学习,并根据这些记忆做出决策。如今,这不再仅仅是科幻想象——随着AI Agent技术的快速发展,构建具有复杂记忆系统的人工智能实体正在成为现实。
问题陈述
在构建能够执行复杂任务、与环境持续交互的AI Agent时,记忆系统是一个核心挑战。人类的记忆系统精巧而复杂,分为感觉记忆、短期记忆和长期记忆,每种记忆都有其独特的特点和作用。而对于AI Agent来说,如何设计和实现一个高效、灵活且可扩展的记忆系统,使其能够存储、检索和利用信息,仍然是一个亟待解决的难题。
传统的AI系统往往缺乏有效的记忆机制,它们在处理任务时往往只能依赖当前的输入,而无法有效地利用过去的经验。这使得它们在处理需要长期规划、上下文理解和持续学习的任务时表现不佳。
核心价值
本文将深入探讨AI Agent记忆系统的设计与实现,特别是短期记忆和长期记忆的工作原理和技术方案。通过阅读本文,你将:
- 理解人类记忆系统与AI记忆系统的类比与区别
- 掌握短期记忆和长期记忆的核心概念和实现技术
- 学习如何设计一个完整的AI Agent记忆系统架构
- 获取可实践的代码示例和实现细节
- 了解记忆系统在实际AI Agent应用中的最佳实践
无论你是AI研究者、工程师,还是对这一领域感兴趣的技术爱好者,本文都将为你提供宝贵的见解和实用的指导。
文章概述
本文将按照以下结构展开:首先,我们将介绍AI Agent记忆系统的基本概念和理论基础;然后,我们将深入探讨短期记忆和长期记忆的实现技术;接着,我们将通过一个完整的案例研究,展示如何将这些技术应用到实际项目中;最后,我们将总结要点,并展望AI Agent记忆系统的未来发展方向。
正文
一、AI Agent记忆系统概述
核心概念
在深入探讨短期记忆和长期记忆的实现之前,我们首先需要理解AI Agent记忆系统的基本概念。AI Agent的记忆系统可以被定义为一种结构化的信息存储和检索机制,它使Agent能够:
- 存储经验:保存与环境交互过程中产生的信息
- 检索知识:在需要时快速访问相关信息
- 学习适应:基于过去的经验改进行为和决策
- 保持连贯:在长时间交互中保持上下文的一致性
与人类记忆类似,AI Agent的记忆系统也可以按照信息存储的时长和特点进行分类。通常,我们将其分为以下几个层次:
- 感觉记忆:极短时间内保存原始感知数据
- 短期记忆:短时间内保存有限容量的信息
- 长期记忆:长时间保存几乎无限容量的信息
这种分类方式借鉴了认知心理学中的记忆模型,但在AI实现中,我们需要根据技术特点进行调整和优化。
问题背景
AI Agent记忆系统的研究受到了多个领域的启发和影响,包括认知心理学、神经科学、计算机科学和人工智能等。让我们简要回顾一下这个领域的发展背景:
认知心理学视角:
早在20世纪60年代,认知心理学家Atkinson和Shiffrin就提出了记忆的多存储模型,将记忆分为感觉记忆、短期记忆和长期记忆三个阶段。这一模型为后来AI记忆系统的设计提供了重要的理论基础。
神经科学视角:
神经科学研究表明,人类大脑中的海马体在记忆形成和巩固过程中起着关键作用,而大脑皮层则负责长期记忆的存储。这些发现启发了AI研究者设计类似的记忆巩固机制。
AI发展视角:
早期的AI系统,如专家系统,采用符号化的知识表示和推理方式,但缺乏灵活的记忆机制。随着深度学习的兴起,神经网络显示出了强大的模式识别能力,但在长期记忆和推理方面仍有局限。近年来,结合神经网络和外部记忆结构的研究成为热点,如记忆网络、神经图灵机等。
问题描述
设计和实现AI Agent的记忆系统面临着多个挑战:
- 容量与效率的平衡:记忆系统需要能够存储大量信息,同时又要保证检索的效率
- 信息的组织与索引:如何有效地组织记忆内容,使得相关信息能够被快速找到
- 记忆的更新与遗忘:如何处理新信息的加入,以及何时移除不再重要的信息
- 上下文理解与关联:如何理解信息之间的关联,并在适当的情境中唤起相关记忆
- 泛化与抽象:如何从具体经验中提取抽象知识,以便在新情境中应用
这些挑战相互关联,需要我们在设计记忆系统时综合考虑。
AI Agent记忆系统的概念结构与核心要素组成
一个完整的AI Agent记忆系统通常包含以下核心要素:
- 记忆存储:负责信息的物理或逻辑存储
- 记忆编码:将感知信息转换为可存储的表示形式
- 记忆索引:创建高效的索引结构,便于信息检索
- 记忆检索:根据当前情境和需求,查找相关信息
- 记忆更新:添加新信息,修改现有信息,或移除过时信息
- 记忆巩固:将短期记忆转换为长期记忆的过程
- 记忆遗忘:选择性地清除不重要的信息,避免记忆过载
这些要素相互作用,共同构成了一个功能完整的记忆系统。在接下来的章节中,我们将详细探讨短期记忆和长期记忆的具体实现方式。
二、短期记忆的实现
核心概念
短期记忆(Short-Term Memory, STM)是AI Agent记忆系统中的一个关键组件,它负责在短时间内保存和处理有限容量的信息。在认知心理学中,短期记忆有时也被称为工作记忆,强调其在信息处理中的积极作用。
对于AI Agent而言,短期记忆具有以下核心特点:
- 有限容量:只能同时保存有限数量的信息项
- 短暂保持:信息在没有复述的情况下只能保持较短时间
- 活跃处理:与当前任务和推理过程紧密关联
- 易受干扰:新信息的进入容易导致旧信息的丢失
短期记忆在AI Agent中起着至关重要的作用,它是连接感知、推理和行动的桥梁,使Agent能够在处理复杂任务时保持上下文的连贯性。
短期记忆的数学模型
为了更好地理解和实现短期记忆,我们可以借助一些数学模型来描述其特性。以下是几个常用的模型:
1. 缓冲器模型
短期记忆可以被建模为一个固定大小的缓冲器,新信息进入时,旧信息可能会被挤出:
Mt={[It,Mt−1[0..N−2]]if ∣Mt−1∣=N[It,Mt−1]otherwiseM_t = \begin{cases} [I_t, M_{t-1}[0..N-2]] & \text{if } |M_{t-1}| = N \\ [I_t, M_{t-1}] & \text{otherwise} \end{cases}Mt={[It,Mt−1[0..N−2]][It,Mt−1]if ∣Mt−1∣=Notherwise
其中,MtM_tMt表示时刻ttt的记忆状态,ItI_tIt表示时刻ttt的输入,NNN表示缓冲器的容量。
2. 激活衰减模型
这个模型认为记忆项具有不同的激活水平,激活水平随时间衰减,当激活水平低于阈值时,记忆项就会被遗忘:
ai(t)=ai(t0)⋅e−λ(t−t0)+∑t′∈Tiδ(t−t′)a_i(t) = a_i(t_0) \cdot e^{-\lambda(t-t_0)} + \sum_{t' \in T_i} \delta(t-t')ai(t)=ai(t0)⋅e−λ(t−t0)+t′∈Ti∑δ(t−t′)
其中,ai(t)a_i(t)ai(t)表示记忆项iii在时刻ttt的激活水平,λ\lambdaλ表示衰减率,TiT_iTi表示记忆项iii被重新激活的时刻集合,δ\deltaδ表示脉冲函数。
3. 相似性干扰模型
这个模型考虑了记忆项之间的相互干扰,相似的记忆项会相互影响:
ri=si∑jsj+βr_i = \frac{s_i}{\sum_j s_j + \beta}ri=∑jsj+βsi
其中,rir_iri表示记忆项iii的可检索性,sis_isi表示记忆项iii与当前线索的相似性,β\betaβ表示干扰参数。
这些数学模型为我们实现短期记忆提供了理论指导,我们可以根据具体应用场景选择合适的模型或进行组合。
短期记忆的算法实现
基于上述模型,我们可以设计多种短期记忆的实现算法。以下是几种常用的算法:
1. 队列(FIFO)算法
这是最简单的短期记忆实现方式,使用先进先出队列来存储信息:
这种方法实现简单,但缺乏灵活性,没有考虑信息的重要性。
2. 最近最少使用(LRU)算法
LRU算法会根据信息的使用情况来决定保留哪些信息,最近使用过的信息更有可能被保留:
LRU算法在很多场景下都表现良好,但它只考虑了使用时间,没有考虑信息的重要性。
3. 基于激活度的算法
这种算法为每个记忆项分配一个激活度,根据激活度来决定记忆的保留和检索:
基于激活度的算法更加灵活,可以综合考虑多种因素,但实现也更复杂。
短期记忆的Python实现
让我们通过Python代码来实现一个基于激活度的短期记忆系统:
import time
import numpy as np
from typing import List, Dict, Any, Tuple
class ShortTermMemory:
def __init__(self, capacity: int = 10, decay_rate: float = 0.05,
threshold: float = 0.1, similarity_weight: float = 0.3):
"""
初始化短期记忆系统
参数:
capacity: 记忆容量上限
decay_rate: 激活度衰减率
threshold: 遗忘阈值
similarity_weight: 相似性对激活度的影响权重
"""
self.capacity = capacity
self.decay_rate = decay_rate
self.threshold = threshold
self.similarity_weight = similarity_weight
self.memories: List[Dict[str, Any]] = [] # 存储记忆项
self.last_update = time.time() # 上次更新时间
def _compute_similarity(self, item1: Any, item2: Any) -> float:
"""
计算两个记忆项之间的相似度
参数:
item1: 第一个记忆项
item2: 第二个记忆项
返回:
相似度分数(0-1之间)
"""
# 这里简化处理,实际应用中可以使用更复杂的相似度计算方法
# 如余弦相似度、编辑距离等
if isinstance(item1, str) and isinstance(item2, str):
# 对于字符串,计算Jaccard相似度
set1 = set(item1.lower().split())
set2 = set(item2.lower().split())
if not set1 or not set2:
return 0.0
return len(set1.intersection(set2)) / len(set1.union(set2))
elif isinstance(item1, (int, float)) and isinstance(item2, (int, float)):
# 对于数值,计算归一化距离
max_val = max(abs(item1), abs(item2), 1e-10)
return 1.0 - abs(item1 - item2) / max_val
else:
# 其他类型,直接比较是否相等
return 1.0 if item1 == item2 else 0.0
def _decay_activations(self):
"""衰减所有记忆项的激活度"""
current_time = time.time()
time_delta = current_time - self.last_update
for memory in self.memories:
# 指数衰减
memory['activation'] *= np.exp(-self.decay_rate * time_delta)
self.last_update = current_time
def add(self, content: Any, metadata: Dict[str, Any] = None) -> int:
"""
添加新的记忆项
参数:
content: 记忆内容
metadata: 额外的元数据
返回:
新记忆项的索引
"""
self._decay_activations() # 先进行衰减
# 计算新记忆项与现有记忆项的相似度,并更新相关记忆的激活度
max_similarity = 0.0
for memory in self.memories:
similarity = self._compute_similarity(content, memory['content'])
if similarity > 0.1: # 只有相似度足够高时才影响
memory['activation'] += similarity * self.similarity_weight
max_similarity = max(max_similarity, similarity)
# 初始化新记忆项的激活度
initial_activation = 1.0 - max_similarity * 0.5 # 避免重复内容
# 创建新记忆项
new_memory = {
'content': content,
'metadata': metadata or {},
'activation': initial_activation,
'timestamp': time.time()
}
# 添加到记忆列表
self.memories.append(new_memory)
# 如果超出容量,移除激活度最低的项
if len(self.memories) > self.capacity:
self._remove_lowest_activation()
# 移除激活度低于阈值的项
self._forget_below_threshold()
return len(self.memories) - 1
def retrieve(self, query: Any, top_k: int = 5) -> List[Tuple[Any, float, Dict[str, Any]]]:
"""
根据查询检索相关记忆
参数:
query: 查询内容
top_k: 返回的最大结果数
返回:
记忆内容、激活度和元数据的列表
"""
self._decay_activations() # 先进行衰减
# 计算查询与每个记忆项的匹配度
results = []
for memory in self.memories:
similarity = self._compute_similarity(query, memory['content'])
# 综合考虑相似度和激活度
relevance = similarity * 0.7 + memory['activation'] * 0.3
results.append((memory['content'], relevance, memory['metadata']))
# 按相关性排序
results.sort(key=lambda x: x[1], reverse=True)
return results[:top_k]
def _remove_lowest_activation(self):
"""移除激活度最低的记忆项"""
if self.memories:
min_idx = min(range(len(self.memories)), key=lambda i: self.memories[i]['activation'])
del self.memories[min_idx]
def _forget_below_threshold(self):
"""移除激活度低于阈值的记忆项"""
self.memories = [m for m in self.memories if m['activation'] >= self.threshold]
def get_all(self) -> List[Dict[str, Any]]:
"""获取所有记忆项(用于调试)"""
self._decay_activations()
return sorted(self.memories, key=lambda x: x['activation'], reverse=True)
def clear(self):
"""清空所有记忆"""
self.memories = []
这个实现包含了短期记忆的核心功能,包括添加记忆、检索记忆、激活度衰减和遗忘机制。在实际应用中,我们可以根据具体需求对其进行扩展和优化。
短期记忆的实际应用场景
短期记忆在AI Agent中有许多实际应用场景:
- 对话系统:在多轮对话中,短期记忆可以帮助系统理解上下文,记住之前的对话内容。
- 任务规划:在执行复杂任务时,短期记忆可以保存中间步骤和子目标。
- 状态跟踪:在与环境交互过程中,短期记忆可以跟踪环境状态的变化。
- 实时决策:在需要快速决策的场景中,短期记忆可以提供最近的相关信息。
例如,在一个客服对话系统中,短期记忆可以用来记住用户最近提到的问题、偏好和需求,从而提供更加个性化和连贯的服务。
三、长期记忆的实现
核心概念
长期记忆(Long-Term Memory, LTM)是AI Agent记忆系统中负责长期存储信息的组件。与短期记忆相比,长期记忆具有以下特点:
- 大容量:能够存储几乎无限量的信息
- 持久性:信息可以长期保存,甚至永久保存
- 结构化:信息通常以某种结构化的方式组织
- 联想性:信息之间存在关联,可以通过联想检索
在认知心理学中,长期记忆通常被进一步分为陈述性记忆(关于事实和事件的记忆)和程序性记忆(关于如何做事情的记忆)。在AI Agent中,我们可以借鉴这种分类,但也需要根据技术特点进行调整。
长期记忆的知识表示
长期记忆的一个关键问题是如何表示和组织知识。以下是几种常用的知识表示方法:
1. 语义网络
语义网络使用节点和边来表示概念和它们之间的关系:
语义网络直观易懂,适合表示分类学知识和简单关系,但在处理复杂逻辑和不确定性时有局限。
2. 框架/脚本
框架(Frame)是一种结构化的知识表示方法,用于表示典型情境和对象:
# 简化的框架表示示例
restaurant_frame = {
"name": "Restaurant",
"slots": {
"name": {"type": "str", "required": True},
"cuisine": {"type": "str", "required": True},
"location": {"type": "tuple", "required": False},
"price_range": {"type": "int", "constraint": "1-5", "required": False},
"menu": {"type": "list", "required": False}
},
"default_values": {
"price_range": 3
},
"relations": {
"is_a": "Business",
"sells": "Food",
"has_part": ["Kitchen", "Dining_Area"]
}
}
脚本(Script)是框架的一种扩展,用于表示事件序列:
# 简化的脚本表示示例
restaurant_script = {
"name": "Eating_at_Restaurant",
"scene": "Restaurant",
"roles": ["Customer", "Waiter", "Cook", "Cashier"],
"props": ["Menu", "Table", "Food", "Check", "Money"],
"events": [
"Entering",
"Seating",
"Ordering",
"Waiting",
"Eating",
"Paying",
"Leaving"
],
"entry_conditions": [
"Customer is hungry",
"Customer has money"
],
"results": [
"Customer is not hungry",
"Customer has less money",
"Restaurant has more money"
]
}
框架和脚本适合表示结构化知识和典型情境,但在处理灵活性和例外情况时可能不够。
3. 本体
本体(Ontology)是一种更加正式和结构化的知识表示方法,它定义了概念、关系和公理:
本体具有严格的逻辑基础,适合知识共享和推理,但构建和维护成本较高。
4. 向量嵌入
随着深度学习的发展,向量嵌入(Vector Embedding)成为一种流行的知识表示方法:
embed:X→Rd\text{embed}: \mathcal{X} \rightarrow \mathbb{R}^dembed:X→Rd
其中,X\mathcal{X}X是输入空间,Rd\mathbb{R}^dRd是ddd维向量空间。
向量嵌入将各种类型的信息(文本、图像、音频等)映射到连续的向量空间中,使得相似的信息在向量空间中距离较近。这种表示方法非常适合语义检索和相似度计算。
长期记忆的数学模型
长期记忆的数学模型通常关注知识的组织、存储和检索。以下是几个重要的模型:
1. 联想记忆模型
联想记忆模型基于赫布学习规则(Hebb’s Rule),强调同时激活的神经元之间的连接会增强:
Δwij=η⋅ai⋅aj\Delta w_{ij} = \eta \cdot a_i \cdot a_jΔwij=η⋅ai⋅aj
其中,Δwij\Delta w_{ij}Δwij是神经元iii和jjj之间连接权重的变化,η\etaη是学习率,aia_iai和aja_jaj分别是神经元iii和jjj的激活水平。
Hopfield网络是一种经典的联想记忆模型,它可以存储和检索模式:
E=−12∑i,jwijsisj+∑iθisiE = -\frac{1}{2} \sum_{i,j} w_{ij} s_i s_j + \sum_i \theta_i s_iE=−21i,j∑wijsisj+i∑θisi
其中,EEE是能量函数,wijw_{ij}wij是连接权重,sis_isi是神经元状态,θi\theta_iθi是阈值。
2. 向量空间模型
向量空间模型将每个记忆项表示为一个向量,通过计算向量之间的相似度来进行检索:
sim(v⃗i,v⃗j)=v⃗i⋅v⃗j∥v⃗i∥∥v⃗j∥\text{sim}(\vec{v}_i, \vec{v}_j) = \frac{\vec{v}_i \cdot \vec{v}_j}{\|\vec{v}_i\| \|\vec{v}_j\|}sim(vi,vj)=∥vi∥∥vj∥vi⋅vj
其中,sim\text{sim}sim是余弦相似度,v⃗i\vec{v}_ivi和v⃗j\vec{v}_jvj是两个向量。
近年来,随着深度学习的发展,我们可以使用神经网络来学习高质量的向量表示,如Word2Vec、GloVe、BERT等。
3. 图神经网络模型
图神经网络(Graph Neural Networks, GNNs)可以处理图结构的数据,非常适合表示和推理结构化知识:
hv(k+1)=σ(Wk∑u∈N(v)hu(k)∣N(v)∣+Bkhv(k))\mathbf{h}_v^{(k+1)} = \sigma\left(\mathbf{W}_k \sum_{u \in \mathcal{N}(v)} \frac{\mathbf{h}_u^{(k)}}{|\mathcal{N}(v)|} + \mathbf{B}_k \mathbf{h}_v^{(k)}\right)hv(k+1)=σ Wku∈N(v)∑∣N(v)∣hu(k)+Bkhv(k)
其中,hv(k)\mathbf{h}_v^{(k)}hv(k)是节点vvv在第kkk层的表示,N(v)\mathcal{N}(v)N(v)是节点vvv的邻居,Wk\mathbf{W}_kWk和Bk\mathbf{B}_kBk是参数矩阵,σ\sigmaσ是激活函数。
长期记忆的算法实现
长期记忆的实现需要考虑存储、索引、检索和更新等多个方面。以下是几种关键算法:
1. 向量索引算法
对于向量嵌入表示的记忆,我们需要高效的索引算法来支持最近邻搜索:
不同的索引算法有不同的优缺点,我们需要根据数据规模和查询需求进行选择。
2. 记忆巩固算法
记忆巩固是将短期记忆转换为长期记忆的过程:
记忆巩固算法可以帮助AI Agent选择性地保存重要信息,避免记忆过载。
3. 知识图谱构建与推理算法
对于结构化知识,我们可以使用知识图谱来表示和推理:
知识图谱可以支持复杂的推理查询,但构建和维护成本较高。
长期记忆的Python实现
让我们通过Python代码来实现一个基于向量嵌入和知识图谱的长期记忆系统:
import numpy as np
import networkx as nx
from typing import List, Dict, Any, Tuple, Optional
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import faiss # 用于高效向量检索
import json
class LongTermMemory:
def __init__(self, embedding_dim: int = 300, use_faiss: bool = True):
"""
初始化长期记忆系统
参数:
embedding_dim: 向量嵌入维度
use_faiss: 是否使用FAISS进行高效检索
"""
self.embedding_dim = embedding_dim
self.use_faiss = use_faiss
# 向量记忆部分
self.vector_memories: List[Dict[str, Any]] = []
self.vectorizer = TfidfVectorizer(max_features=embedding_dim) # 简化的嵌入方法
self.embedding_matrix: Optional[np.ndarray] = None
self.faiss_index: Optional[faiss.Index] = None
# 知识图谱部分
self.kg = nx.DiGraph()
# ID映射
self.next_id = 0
def _get_embedding(self, text: str) -> np.ndarray:
"""
获取文本的向量嵌入
参数:
text: 输入文本
返回:
向量嵌入
"""
if not self.vector_memories:
# 没有记忆时,返回随机向量
return np.random.randn(1, self.embedding_dim)
# 简单的TF-IDF嵌入
texts = [m['content'] for m in self.vector_memories] + [text]
tfidf_matrix = self.vectorizer.fit_transform(texts)
return tfidf_matrix[-1].toarray()
def _update_vector_index(self):
"""更新向量索引"""
if not self.vector_memories:
return
# 更新嵌入矩阵
texts = [m['content'] for m in self.vector_memories]
tfidf_matrix = self.vectorizer.fit_transform(texts)
self.embedding_matrix = tfidf_matrix.toarray()
# 更新FAISS索引(如果使用)
if self.use_faiss:
self.faiss_index = faiss.IndexFlatL2(self.embedding_dim)
self.faiss_index.add(self.embedding_matrix.astype('float32'))
def add_vector_memory(self, content: str, metadata: Dict[str, Any] = None,
source: str = "observation") -> int:
"""
添加向量记忆
参数:
content: 记忆内容
metadata: 额外的元数据
source: 记忆来源
返回:
记忆ID
"""
memory_id = self.next_id
self.next_id += 1
# 创建记忆项
memory = {
'id': memory_id,
'content': content,
'metadata': metadata or {},
'source': source,
'timestamp': None, # 这里可以添加时间戳
'access_count': 0,
'importance': 0.5 # 初始重要性
}
self.vector_memories.append(memory)
self._update_vector_index()
return memory_id
def retrieve_vector_memory(self, query: str, top_k: int = 5,
threshold: float = 0.0) -> List[Dict[str, Any]]:
"""
检索向量记忆
参数:
query: 查询文本
top_k: 返回的最大结果数
threshold: 相似度阈值
返回:
相关记忆列表
"""
if not self.vector_memories:
return []
query_embedding = self._get_embedding(query)
if self.use_faiss and self.faiss_index is not None:
# 使用FAISS进行检索
distances, indices = self.faiss_index.search(
query_embedding.astype('float32'), min(top_k * 2, len(self.vector_memories))
)
# 转换为相似度分数
similarities = 1 / (1 + distances[0])
# 准备结果
results = []
for idx, sim in zip(indices[0], similarities):
if sim >= threshold and len(results) < top_k:
memory = self.vector_memories[idx].copy()
memory['similarity'] = sim
memory['access_count'] += 1 # 更新访问计数
results.append(memory)
return results
else:
# 使用简单的余弦相似度
similarities = cosine_similarity(query_embedding, self.embedding_matrix)[0]
# 排序并返回结果
result_indices = np.argsort(similarities)[::-1]
results = []
for idx in result_indices:
if similarities[idx] >= threshold and len(results) < top_k:
memory = self.vector_memories[idx].copy()
memory['similarity'] = similarities[idx]
memory['access_count'] += 1 # 更新访问计数
results.append(memory)
return results
def add_kg_entity(self, entity_id: str, entity_type: str,
attributes: Dict[str, Any] = None) -> bool:
"""
添加知识图谱实体
参数:
entity_id: 实体ID
entity_type: 实体类型
attributes: 实体属性
返回:
是否成功添加
"""
if entity_id in self.kg:
# 实体已存在,更新属性
if attributes:
for key, value in attributes.items():
self.kg.nodes[entity_id][key] = value
return False
# 添加新实体
self.kg.add_node(entity_id, type=entity_type, **(attributes or {}))
return True
def add_kg_relation(self, subject_id: str, object_id: str,
relation_type: str, attributes: Dict[str, Any] = None) -> bool:
"""
添加知识图谱关系
参数:
subject_id: 主体实体ID
object_id: 客体实体ID
relation_type: 关系类型
attributes: 关系属性
返回:
是否成功添加
"""
# 确保实体存在
if subject_id not in self.kg:
self.add_kg_entity(subject_id, "Unknown")
if object_id not in self.kg:
self.add_kg_entity(object_id, "Unknown")
# 添加关系
self.kg.add_edge(subject_id, object_id, type=relation_type, **(attributes or {}))
return True
def query_kg(self, query: Dict[str, Any]) -> List[Dict[str, Any]]:
"""
查询知识图谱
参数:
query: 查询条件
返回:
查询结果
"""
# 简化的查询实现
results = []
# 根据查询类型执行不同的查询
if 'entity_type' in query:
# 查询特定类型的实体
for node, attrs in self.kg.nodes(data=True):
if attrs.get('type') == query['entity_type']:
results.append({
'type': 'entity',
'id': node,
'attributes': attrs
})
if 'relation_type' in query:
# 查询特定类型的关系
for u, v, attrs in self.kg.edges(data=True):
if attrs.get('type') == query['relation_type']:
results.append({
'type': 'relation',
'subject': u,
'object': v,
'attributes': attrs
})
if 'subject' in query and 'relation' in query:
# 查询特定主体和关系的客体
subject = query['subject']
relation = query['relation']
for u, v, attrs in self.kg.edges(data=True):
if u == subject and attrs.get('type') == relation:
results.append({
'type': 'entity',
'id': v,
'attributes': self.kg.nodes[v]
})
return results
def consolidate_memory(self, short_term_memories: List[Dict[str, Any]],
importance_threshold: float = 0.6):
"""
巩固记忆,将短期记忆转换为长期记忆
参数:
short_term_memories: 短期记忆列表
importance_threshold: 重要性阈值
"""
for stm in short_term_memories:
# 简单的重要性评估
importance = stm.get('activation', 0.5) # 使用激活度作为重要性指标
# 可以添加更多的重要性评估因素
# 例如:新奇性、情绪价值、与目标的相关性等
if importance >= importance_threshold:
# 添加到向量记忆
content = str(stm.get('content', ''))
metadata = stm.get('metadata', {})
metadata['importance'] = importance
metadata['original_activation'] = stm.get('activation', 0.5)
memory_id = self.add_vector_memory(content, metadata, source="consolidation")
# 尝试提取知识图谱信息(简化处理)
# 在实际应用中,可以使用更复杂的信息抽取技术
if 'entities' in metadata:
for entity in metadata['entities']:
self.add_kg_entity(entity['id'], entity.get('type', 'Unknown'))
# 添加与记忆的关系
self.add_kg_relation(f"memory_{memory_id}", entity['id'], "mentions")
def save(self, filepath: str):
"""
保存长期记忆到文件
参数:
filepath: 文件路径
"""
data = {
'vector_memories': self.vector_memories,
'kg_nodes': dict(self.kg.nodes(data=True)),
'kg_edges': [(u, v, d) for u, v, d in self.kg.edges(data=True)],
'next_id': self.next_id
}
with open(filepath, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
def load(self, filepath: str):
"""
从文件加载长期记忆
参数:
filepath: 文件路径
"""
with open(filepath, 'r', encoding='utf-8') as f:
data = json.load(f)
# 加载向量记忆
self.vector_memories = data['vector_memories']
self.next_id = data['next_id']
# 重建知识图谱
self.kg = nx.DiGraph()
for node, attrs in data['kg_nodes'].items():
self.kg.add_node(node, **attrs)
for u, v, attrs in data['kg_edges']:
self.kg.add_edge(u, v, **attrs)
# 更新向量索引
self._update_vector_index()
这个实现结合了向量记忆和知识图谱,提供了长期记忆的基本功能,包括添加记忆、检索记忆、记忆巩固和知识图谱操作。在实际应用中,我们可以使用更先进的嵌入方法(如BERT、Sentence-Transformers等)和更强大的图数据库(如Neo4j)来增强系统的能力。
长期记忆的实际应用场景
长期记忆在AI Agent中有广泛的应用场景:
- 用户建模:记住用户的偏好、习惯和历史行为,提供个性化服务
- 领域知识库:存储特定领域的事实知识,支持问答和推理
- 经验学习:保存过去的成功和失败经验,用于改进未来的决策
- 实体和关系记忆:记住现实世界中的实体及其关系,支持常识推理
- 任务记忆:记住过去执行过的任务和步骤,用于迁移学习
例如,在一个个人助理AI Agent中,长期记忆可以记住用户的日程安排、喜欢的餐厅、朋友的生日等信息,从而提供更加智能化的服务。
四、短期记忆与长期记忆的交互
核心概念
短期记忆和长期记忆并不是孤立工作的,它们之间存在着密切的交互。这种交互对于AI Agent的认知能力至关重要,类似于人类记忆系统中工作记忆与长期记忆的协同工作。
短期记忆与长期记忆的交互主要体现在以下几个方面:
- 编码与存储:短期记忆中的信息经过编码后可以存储到长期记忆中
- 检索与激活:长期记忆中的信息可以被检索并激活到短期记忆中
- 巩固与转化:通过复述和联想,短期记忆可以转化为长期记忆
- 上下文关联:当前情境(短期记忆)可以作为线索,帮助检索相关的长期记忆
理解这种交互机制对于设计高效的AI Agent记忆系统至关重要。
记忆交互的数学模型
我们可以用数学模型来描述短期记忆和长期记忆之间的交互:
1. 激活扩散模型
激活扩散模型描述了信息如何在记忆系统中传播和激活:
ai(t+1)=ai(t)+∑j∈N(i)wij⋅aj(t)−λ⋅ai(t)a_i(t+1) = a_i(t) + \sum_{j \in \mathcal{N}(i)} w_{ij} \cdot a_j(t) - \lambda \cdot a_i(t)ai(t+1)=ai(t)+j∈N(i)∑wij⋅aj(t)−λ⋅ai(t)
其中,ai(t)a_i(t)ai(t)是记忆项iii在时刻ttt的激活度,N(i)\mathcal{N}(i)N(i)是记忆项iii的邻居,wijw_{ij}wij是连接权重,λ\lambdaλ是衰减率。
2. 记忆转移模型
记忆转移模型描述了信息在短期记忆和长期记忆之间的转移:
ΔMstm=E−C+R\Delta M_{stm} = E - C + RΔMstm=E−C+R
ΔMltm=C−F\Delta M_{ltm} = C - FΔMltm=C−F
其中,EEE是从环境进入短期记忆的信息,CCC是从短期记忆转移到长期记忆的信息,RRR是从长期记忆检索到短期记忆的信息,FFF是从长期记忆中遗忘的信息。
记忆交互的算法实现
以下是实现短期记忆和长期记忆交互的关键算法:
1. 记忆编码与巩固算法
2. 基于上下文的记忆检索算法
完整记忆系统的Python实现
现在,让我们将短期记忆和长期记忆结合起来,实现一个完整的记忆系统:
import time
from typing import List, Dict, Any, Optional
import numpy as np
# 假设我们已经有了之前定义的ShortTermMemory和LongTermMemory类
class UnifiedMemorySystem:
def __init__(self, stm_capacity: int = 10, stm_decay_rate: float = 0.05,
ltm_embedding_dim: int = 300, consolidation_threshold: float = 0.7,
retrieval_trigger: float = 0.5):
"""
初始化统一记忆系统
参数:
stm_capacity: 短期记忆容量
stm_decay_rate: 短期记忆衰减率
ltm_embedding_dim: 长期记忆嵌入维度
consolidation_threshold: 记忆巩固阈值
retrieval_trigger: 检索触发阈值
"""
# 初始化短期记忆
self.stm = ShortTermMemory(
capacity=stm_capacity,
decay_rate=stm_decay_rate
)
# 初始化长期记忆
self.ltm = LongTermMemory(
embedding_dim=ltm_embedding_dim
)
# 参数设置
self.consolidation_threshold = consolidation_threshold
self.retrieval_trigger = retrieval_trigger
# 上下文状态
self.current_context = {}
self.last_retrieval_time = 0
def perceive(self, content: Any, metadata: Dict[str, Any] = None,
importance: float = 0.5):
"""
感知并处理新信息
参数:
content: 感知内容
metadata: 额外的元数据
importance: 重要性评分
"""
#
更多推荐

所有评论(0)