技术原理核心
技术研究 记忆模型 遗忘曲线
AI Agent 记忆管理机制的深度技术分析,包括遗忘曲线模型和权重调整策略
人类记忆模型借鉴
艾宾浩斯遗忘曲线
德国心理学家赫尔曼·艾宾浩斯(Hermann Ebbinghaus)在 1885 年提出了著名的遗忘曲线理论,描述了人类记忆随时间衰减的规律:
遗忘曲线公式:
R = e^(-t/S)
其中:
- R: 记忆保留率 (Retention),0-1 之间的值
- t: 时间 (Time),从学习时刻到现在的时间间隔
- S: 记忆强度 (Strength),取决于初始学习深度
- e: 自然常数 ≈ 2.718
关键发现:
- 20 分钟后:保留率降至 58%
- 1 小时后:保留率降至 44%
- 1 天后:保留率降至 33%
- 1 周后:保留率降至 25%
- 1 月后:保留率降至 20%
但对 AI 记忆系统的启示:
- 指数衰减:记忆权重应随时间呈指数下降,而非线性
- 可强化性:每次”复习”(重新访问)会提升记忆强度 S
- 个体差异:不同记忆内容的初始强度 S 应不同
现代记忆理论补充
| 理论 | 核心观点 | AI 系统借鉴 |
|---|---|---|
| 工作记忆模型 | 短期记忆容量有限 (7±2 个组块) | 设置短期记忆容量上限 |
| 双重编码理论 | 语义 + 情景双重编码更牢固 | 记忆应包含内容和上下文 |
| 扩散激活理论 | 相关概念相互关联 | 建立记忆之间的图结构 |
| 提取诱导遗忘 | 提取某些记忆会抑制相关记忆 | 检索时应动态调整权重 |
记忆权重调整机制
核心权重公式
基于遗忘曲线理论,我们提出以下记忆权重计算模型:
def calculate_memory_weight(memory, current_time):
"""
计算记忆的当前权重
参数:
memory: 记忆对象,包含 created_at, last_accessed, access_count, base_importance
current_time: 当前时间戳
返回:
0-1 之间的权重值
"""
# 时间衰减因子
time_delta = current_time - memory.created_at # 秒
decay_rate = 0.0001 # 每小时衰减率,可根据场景调整
time_weight = math.exp(-decay_rate * time_delta / 3600)
# 访问频率增强因子
access_boost = min(math.log(memory.access_count + 1) / 5, 0.5)
# 近期访问加成 (7 天内)
recency_bonus = 0.2 if (current_time - memory.last_accessed) < 7 * 86400 else 0
# 基础重要性 (由内容决定,0-1)
base_importance = memory.base_importance
# 综合权重
weight = base_importance * (time_weight + access_boost + recency_bonus)
return min(max(weight, 0), 1) # 限制在 0-1 范围内
权重组成分析
最终权重 = 时间权重 × 基础重要性 + 访问增强 + 近期加成
各因子详解:
1. 时间权重 (Time Weight): 0.0 - 1.0
- 指数衰减:exp(-λt)
- λ (衰减率):可配置,典型值 0.0001/小时
- 1 天后:≈0.92, 7 天后:≈0.67, 30 天后:≈0.30
2. 基础重要性 (Base Importance): 0.0 - 1.0
- 由内容类型决定:
* 用户明确指令:1.0
* 项目核心设计:0.8-0.9
* 一般对话:0.3-0.5
* 闲聊:0.1-0.2
3. 访问增强 (Access Boost): 0.0 - 0.5
- log(访问次数 + 1) / 5
- 10 次访问:+0.24, 100 次访问:+0.46
4. 近期加成 (Recency Bonus): 0.0 或 0.2
- 7 天内访问过:+0.2
- 否则:+0.0
动态权重调整场景
| 场景 | 权重变化 | 说明 |
|---|---|---|
| 新记忆创建 | 权重 = 基础重要性 | 初始状态 |
| 记忆被检索 | 权重 × 1.2, last_accessed 更新 | 强化效应 |
| 用户明确标记重要 | 基础重要性 = 1.0 | 永久高优 |
| 用户明确删除 | 权重 = 0 | 软删除 |
| 记忆过期 (>90 天) | 权重自然衰减至<0.1 | 允许遗忘 |
记忆提取优先级策略
分层检索架构
┌─────────────────────────────────────────────────────────┐
│ 查询请求 │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ 第一层:核心记忆层 (权重 > 0.8) │
│ - 全量检索,必返回 │
│ - 用户画像、项目核心设计、关键决策 │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ 第二层:活跃记忆层 (0.5 < 权重 ≤ 0.8) │
│ - 语义检索,Top-K 返回 │
│ - 近期对话、进行中的任务 │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ 第三层:长期记忆层 (0.2 < 权重 ≤ 0.5) │
│ - 仅当查询相关时返回 │
│ - 历史项目、旧对话 │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ 第四层:归档层 (权重 ≤ 0.2) │
│ - 默认不检索,仅显式查询时返回 │
│ - 过期信息、已废弃设计 │
└─────────────────────────────────────────────────────────┘
检索优先级算法
def retrieve_memories(query, memory_store, token_budget=50000):
"""
基于优先级的记忆检索
策略:
1. 按层级顺序检索
2. 每层内按权重降序
3. token 预算用尽时停止
"""
results = []
tokens_used = 0
# 定义层级
layers = [
('core', 0.8, 1.0), # 核心层
('active', 0.5, 0.8), # 活跃层
('long_term', 0.2, 0.5), # 长期层
('archive', 0.0, 0.2) # 归档层
]
for layer_name, min_w, max_w in layers:
# 获取该层记忆
layer_memories = memory_store.filter_by_weight(min_w, max_w)
# 按权重排序
layer_memories.sort(key=lambda m: m.weight, reverse=True)
# 对非核心层进行语义过滤
if layer_name != 'core':
layer_memories = semantic_filter(query, layer_memories, top_k=20)
# 逐个添加,直到 token 预算用尽
for memory in layer_memories:
if tokens_used + memory.token_count > token_budget:
return results # 预算用尽,返回
results.append(memory)
tokens_used += memory.token_count
return results
Token 预算分配策略
| 记忆层 | 预算占比 | 典型 tokens | 说明 |
|---|---|---|---|
| 核心层 | 40% | 20K | 必须保留 |
| 活跃层 | 35% | 17.5K | 主要检索区 |
| 长期层 | 20% | 10K | 按需检索 |
| 归档层 | 5% | 2.5K | 兜底 |
系统架构设计
整体架构图
graph TB
subgraph 用户交互层
A[用户查询] --> B[Query Parser]
B --> C[意图识别]
end
subgraph 记忆管理层
C --> D{记忆检索器}
D --> E[核心记忆库]
D --> F[活跃记忆库]
D --> G[长期记忆库]
D --> H[归档记忆库]
E --> I[权重计算引擎]
F --> I
G --> I
H --> I
I --> J[时间衰减模块]
I --> K[访问统计模块]
I --> L[重要性评估模块]
end
subgraph 存储层
E --> M[(向量数据库)]
F --> M
G --> M
H --> N[(冷存储])
end
subgraph 后台任务
O[定时权重更新] --> J
P[记忆压缩任务] --> G
Q[归档清理任务] --> H
end
style E fill:#ff6b6b
style F fill:#feca57
style G fill:#48dbfb
style H fill:#c8d6e5
核心组件说明
| 组件 | 职责 | 技术选型 |
|---|---|---|
| Query Parser | 解析用户查询,提取关键信息 | LLM + 规则引擎 |
| 记忆检索器 | 执行分层检索策略 | 自定义算法 |
| 权重计算引擎 | 实时计算记忆权重 | 公式计算 |
| 向量数据库 | 存储记忆嵌入向量 | Pinecone/Milvus/Weaviate |
| 定时权重更新 | 批量更新所有记忆权重 | Cron Job |
| 记忆压缩任务 | 将长期记忆摘要压缩 | LLM 摘要 |
数据流示例
用户提问: "我们项目的认证模块是怎么设计的?"
1. Query Parser 解析:
- 主题:认证模块 (authentication)
- 意图:设计思路查询
- 时间范围:不限
2. 记忆检索 (token 预算=50K):
核心层 (20K):
✓ 项目架构设计文档 (8K tokens, weight=0.95)
✓ 认证模块决策记录 (5K tokens, weight=0.92)
✓ 用户安全需求 (3K tokens, weight=0.88)
活跃层 (17.5K):
✓ 最近认证相关讨论 (6K tokens, weight=0.72)
✓ OAuth 实现代码片段 (4K tokens, weight=0.68)
✓ JWT 配置讨论 (3K tokens, weight=0.65)
长期层 (10K):
✓ 早期认证方案探索 (5K tokens, weight=0.35)
✓ 已废弃的 SAML 方案 (4K tokens, weight=0.28)
归档层 (2.5K):
- 无相关内容
3. 组装上下文,调用 LLM 生成回答
配置参数建议
memory_config:
# 衰减配置
decay:
rate: 0.0001 # 每小时衰减率
half_life: 168 # 半衰期 (小时) ≈ 7 天
min_weight: 0.01 # 最小权重
# 层级阈值
layers:
core_min: 0.8
active_min: 0.5
long_term_min: 0.2
# Token 预算
budget:
total: 50000
core_ratio: 0.4
active_ratio: 0.35
long_term_ratio: 0.2
archive_ratio: 0.05
# 强化配置
reinforcement:
access_boost_max: 0.5
recency_window: 168 # 7 天 (小时)
recency_bonus: 0.2
本节要点
- 遗忘曲线为时间衰减提供了数学基础:R = e^(-t/S)
- 记忆权重由时间衰减、基础重要性、访问频率、近期访问共同决定
- 分层检索确保高权重内容优先,同时保留低权重内容的可访问性
- Token 预算按层级分配,核心记忆占 40%,活跃记忆占 35%
- 系统架构包含查询解析、检索器、权重引擎、向量存储四大核心组件