返回知识库
🧠

Dawn AI 记忆系统架构

4-Layer Event-Driven Memory Architecture

4
Memory Layers
7
Pipeline Steps
1024d
Embedding
Spring
Tech Stack
💡

什么是 Dawn AI 记忆系统?

CORE CONCEPTS

Dawn AI 的记忆系统是一个四层事件驱动架构,为 AI Agent 提供从短期工作记忆到长期用户画像的完整记忆生命周期管理。核心设计理念:

🎯
每次对话不应是「失忆」的——Agent 需要记住过去、理解现在、预判未来。四层分离确保每一层都有独立的存储引擎和生命周期策略,而非单一向量库兜底。
🏗️

四层分离

Working → Pending → Episodic → Profile,每层有独立的存储引擎和生命周期策略,各司其职。

事件驱动

消息写入不阻塞响应。Summarization、Consolidation、Reflection 三阶段通过 Spring Event 解耦,任何一步失败不影响用户体验。

🔄

用进废退

记忆重要性随时间指数衰减,被检索则刷新权重。低重要性记忆在 180 天后自动清除,reflection 类记忆豁免驱逐。

🏗️

系统架构

ARCHITECTURE

Dawn AI 采用四层分层架构:L1 Working Memory 处理实时对话,L2 Pending Queue 批量积累,L3 Episodic Memory 向量持久化,L4 User Profile 提炼用户人格。每层独立存储,逐层向上流动。

Dawn AI 四层记忆架构
👤
L4 User Profile
Redis Hash · 30天 TTL · System Prompt 注入
ReflectionWorker 提炼
📚
L3 Episodic Memory
PGVector · HNSW 索引 · 1024d cosine · 指数衰减
Consolidation 写入
📥
L2 Pending Queue
Redis List · 批量触发 · batch-size=5 · 100字摘要
批次积累触发
📝
L1 Working Memory
Redis List · 20条滑动窗口 · 2h TTL · 降级到本地缓存
降级策略:Redis 不可用时回退到本地 ConcurrentHashMap;LLM 不可用时 importance 固定为 0.3。Atomic RENAME 确保 pending queue 排空原子性,保证数据安全。
🗂️

记忆层级

MEMORY LAYERS

四层记忆各司其职,从实时对话缓存到长期人格画像,逐层提炼:

📝 L1 工作记忆(Working Memory)

类似人类的「工作记忆」,存储当前会话中的实时对话历史。

📌
典型场景:用户在对话中提到「我正在处理一个紧急 bug」,工作记忆会记住这个上下文,但 2 小时后自动过期。
L1 Working Memory 配置
存储引擎    Redis List (降级: ConcurrentHashMap)
Key         ai:session:{sessionId}
窗口大小    20 条消息滑动窗口
TTL         2 小时
原子性      Atomic RENAME 确保 pending 排空
写入时机    每次用户消息到达时实时写入

📥 L2 待处理队列(Pending Queue)

批量积累消息,达到阈值后触发 LLM 摘要,是连接 L1 和 L3 的桥梁。

🔑
关键机制:每 5 条消息(测试环境 3 条)触发一次 SummarizationRequestEvent,LLM 将对话压缩为约 100 字的精炼摘要。
L2 Pending Queue 配置
存储引擎    Redis List (:pending 后缀)
Key         ai:session:{sessionId}:pending
批次大小    默认 5 条 (测试环境 3 条)
摘要输出    约 100 字精炼摘要
触发事件    SummarizationRequestEvent
TTL         2 小时

📚 L3 情景记忆(Episodic Memory)

Dawn AI 的核心长期记忆层——基于向量嵌入的语义记忆,支持模糊匹配和概念关联。

💡
两种记忆类型:summary(重要性 0.5)来自 LLM 摘要,reflection(重要性 0.9)来自 ReflectionWorker 的高阶提炼。搜索「旅行偏好」能匹配到「喜欢去海边度假」,因为两者在语义空间中相近。
L3 Episodic Memory 配置
存储引擎    PostgreSQL + pgvector 扩展
索引类型    HNSW (余弦距离)
Embedding   1024 维向量
元数据      type / sessionId / importance / createdAt / lastAccessedAt
衰减公式    importance *= 0.5^(days/30),下限 0.01
驱逐条件    importance < 0.1 AND age > 180天 (reflection 豁免)

👤 L4 用户画像(User Profile)

从长期记忆中提炼的用户人格特征,注入 System Prompt 让模型「记住」用户是谁。

🔑
设计意图:让模型「记住」用户是谁,而非记住用户说了什么。Profile 以结构化 key-value 对形式注入 System Prompt,每次对话都生效,不占用检索配额。
L4 User Profile 配置
存储引擎    Redis Hash
Key         ai:profile:{userId}
TTL         30 天
数据来源    ReflectionWorker 从长期记忆中提取
输出格式    约 200 字用户人格特征
注入方式    结构化 key-value → System Prompt
⚙️

事件驱动流水线

PIPELINE

当用户发送消息时,Dawn AI 内部执行以下7 步事件驱动处理流程

1

📥 消息写入

用户消息到达,调用 addMessage 写入 Redis List。消息进入 L1 Working Memory 的 20 条滑动窗口,实时可读。

2

📊 批量积累

消息同时写入 L2 Pending Queue(:pending 后缀)。当积累达到 batch-size=5 条时,触发下一步摘要流程。

3

🧠 LLM 摘要

触发 SummarizationRequestEventMemorySummarizer 将 5 条消息压缩为约 100 字的精炼摘要。LLM 不可用时 importance 降级为 0.3。

4

💾 向量持久化

MemoryConsolidator 将摘要写入 PGVector,生成 1024 维 embedding,建立 HNSW 索引。记忆类型标记为 summary,初始重要性 0.5。

5

🔄 计数触发

使用 CAS(Compare-And-Swap)原子计数器追踪摘要次数。当计数达到 reflection-threshold 时,触发长期反思流程。

6

🔮 长期反思

ReflectionWorker 从多条 summary 中提炼高阶认知,生成约 200 字的用户人格特征。类型标记为 reflection,重要性 0.9,永不淘汰。

7

👤 画像注入

用户人格特征写入 L4 Redis Hash,以结构化 key-value 对形式注入下次对话的 System Prompt。模型每次都能感知用户身份。

🔀

记忆生命周期

LIFECYCLE

Dawn AI 的记忆不是「写了就忘」,而是有完整的生命周期管理——用进废退,模拟人类记忆的自然遗忘曲线。

📉
指数衰减:importance *= 0.5^(days/30) —— 30 天衰减到 50%,60 天衰减到 25%,90 天衰减到 12.5%。下限 0.01,避免完全归零。
🔄
访问刷新:每次检索命中时更新 lastAccessedAt,被检索的记忆权重重置。真正实现了「用进废退」的效果——常用的记忆保持活跃,不用的自然褪色。
🗑️
自动驱逐:importance < 0.1age > 180天 时,记忆被自动清除。每日 03:00 执行驱逐任务,03:30 执行衰减任务。
🛡️
Reflection 豁免:type=reflection 的记忆永不淘汰。这类记忆代表 LLM 对用户的深层理解(importance=0.9),生成成本高、价值密度大、数量有限(由 CAS 计数器控制频率)。
💾

存储架构

BACKENDS

四层记忆各有独立的存储引擎,Redis 处理热数据,PGVector 承载长期语义记忆:

Layer 存储 技术 TTL
L1 Working Redis List ai:session:{id} 2h
L2 Pending Redis List ai:session:{id}:pending 2h
L3 Episodic PostgreSQL pgvector HNSW, cosine, 1024d 由驱逐管理
L4 Profile Redis Hash ai:profile:{id} 30d
⚖️

与其他记忆方案对比

COMPARISON
特性 Dawn AI mem0 Hindsight
记忆层数 4层 2层 4类
向量存储 PGVector Qdrant / Chroma 专用向量DB
热存储 ✅ Redis ❌ 无 ❌ 无
事件驱动 ✅ Spring Event ⚠️ 同步API ⚠️ 同步
重要性衰减 ✅ 指数衰减 ❌ 无 ❌ 无
反思机制 ✅ CAS计数触发 ❌ 无 ✅ 心智模型
知识图谱 ❌ 无 ✅ NLP实体链接 ✅ 内置图谱
因果推理 ❌ 无 ❌ 无 ✅ 因果链追踪
用户画像 ✅ 独立L4 ⚠️ 嵌入长期记忆 ✅ 内置
技术栈 Java / Spring Python / FastAPI Python
🏆
选择建议:如果需要「生产就绪、简洁可控」的记忆系统,Dawn AI 是最佳选择;如果需要「开箱即用、NLP 实体链接」,选择 mem0;如果需要「因果推理、知识图谱」的深度记忆,考虑 Hindsight。
🚀

演进路线

ROADMAP
🔴

NLP 实体抽取

在摘要阶段提取人物、地点、项目等实体,写入元数据。参考 mem0 新算法思路,无需图数据库即可支持实体级查询。

高优
🔴

动态重要性评分

当前 summary 固定 0.5、LLM 降级固定 0.3,应改为基于内容的动态评分。情绪强烈的对话、包含决策的内容应获得更高权重。

高优
🟡

时间推理能力

在检索时考虑事件发生的时间顺序,支持「上周讨论的方案」「最近的决定」等时间敏感查询。

中优
🟡

多信号检索融合

将单一向量检索扩展为语义 + 关键词 + 实体的多路召回,参考 mem0 的混合检索策略,提升查全率。

中优
🟢

跨会话模式检测

聚合多用户的记忆数据,识别通用行为模式和偏好趋势,用于产品层面的洞察。

低优
🟢

记忆压缩合并

当多条 summary 语义高度重叠时,自动合并以减少存储和检索噪音。需要引入相似度阈值和 LLM 合并策略。

低优
🔬

设计决策

TRADE-OFFS

每一个架构决策背后都有明确的权衡考量:

🤔
为什么选择指数衰减而非固定过期?
固定过期(TTL)无法区分「有用但不常用」和「无用且不常用」的记忆。指数衰减公式 0.5^(days/30) 模拟人类记忆的遗忘曲线——30 天衰减到一半,60 天衰减到 25%。配合访问刷新机制,被检索的记忆权重重置,实现了「用进废退」的效果。
🛡️
为什么 Reflection 记忆豁免驱逐?
Reflection 是 LLM 从多条 summary 中提炼的高阶认知,代表了对用户的深层理解。这类记忆的生成成本高(需要 LLM 推理)、价值密度大(importance=0.9),且数量有限(由 CAS 计数器控制生成频率),因此不参与常规驱逐。
为什么用 Spring Event 而非消息队列?
Summarization → Consolidation → Reflection 的管线本质上是单用户、顺序敏感的操作链。Spring Event 的 @Async 注解足够解耦各阶段,且无需引入 Kafka/RabbitMQ 等外部依赖。对于中小规模部署,这是复杂度和可靠性的最优平衡点。
👤
为什么 Profile 注入 System Prompt 而非检索?
用户画像(「喜欢简洁回答」「资深后端工程师」)是全局性上下文,每次都应生效。如果作为检索结果,可能因语义不匹配而遗漏。注入 System Prompt 确保模型每次对话都能感知用户身份,且不占用检索配额。

快速了解

QUICK REFERENCE
Dawn AI Memory Pipeline — 伪代码概览
// 消息到达时的完整处理流程

ON user_message:
  // Step 1-2: 写入 L1 + L2
  L1.WorkingMemory.push(message)     // Redis List, 20条窗口, 2h TTL
  L2.PendingQueue.push(message)      // Redis List, 批量积累

  // Step 3: 批次触发摘要
  IF L2.PendingQueue.size() >= batch_size:
    PUBLISH SummarizationRequestEvent
    summary = LLM.summarize(L2.drain())  // ~100字压缩

    // Step 4: 向量持久化
    L3.EpisodicMemory.store(
      embedding = embed(summary),     // 1024d, HNSW
      type = "summary",
      importance = 0.5
    )

    // Step 5-6: CAS 计数 → 反思
    counter = CAS_increment(reflection_counter)
    IF counter >= reflection_threshold:
      profile = ReflectionWorker.reflect(recent_summaries)
      L3.store(profile, type="reflection", importance=0.9)

      // Step 7: 画像注入
      L4.UserProfile.update(profile)  // Redis Hash, 30d TTL
      // → 注入下次 System Prompt

// 定时任务
CRON "0 0 3 * * *":  evict(importance < 0.1 && age > 180d)
CRON "0 30 3 * * *": decay(importance *= 0.5 ^ (days/30))
ON  retrieval_hit:     refresh(lastAccessedAt)  // 用进废退
🔗

相关资源

RESOURCES