Files
sundynix-agentix/memory_industry_analysis.md
T
2026-06-19 22:18:54 +08:00

9.5 KiB
Raw Blame History

生产级 AI Agent 长期记忆 — 行业主流方案

行业共识:四层记忆架构

2025 年以来,行业在长期记忆上已经形成了四层分类共识(模仿认知科学):

类型 内容 生命周期
L1 工作记忆 当前对话的上下文窗口 会话内
L2 短期/情景记忆 近期对话摘要、事件日志 数小时 ~ 数天
L3 语义记忆 提炼出的事实、偏好、知识 持久(可衰减)
L4 程序记忆 学到的行为规则、约束、SOP 持久

sundynix-agentix 当前只覆盖了 L1context window+ L2history+ L3 的最简形态(KV profile)。


四大主流方案详解

1️⃣ OpenAI ChatGPT — "Dreaming" 机制

思路:不靠向量检索,靠后台异步合成摘要

用户对话 → 结束后异步触发 "Dreaming"
    ↓
分析历史 → 合成/更新 Memory Summary(结构化事实列表)
    ↓
下次对话 → 整个 Memory Summary 注入 context window

架构特点

  • 存储:结构化事实列表(非向量),存为 user-scoped 文档
  • 写入:后台异步 "Dreaming" 进程,周期性回顾历史、合成偏好
  • 读取全量注入 context window(不做检索,依赖结构化摘要足够紧凑)
  • 治理:自动失效旧记忆("traveling to Singapore" → "went to Singapore"),用户可查看/编辑/删除
  • 不用 RAG:刻意避免向量检索的延迟和复杂度,用轻量摘要替代

Note

sundynix-agentix 的方案与 ChatGPT 早期版本(2024.4 Saved Memories)非常接近——都是逐轮 LLM 抽取 + 全量注入。 ChatGPT 后来演进到 Dreaming 是因为发现逐轮抽取会导致"记忆腐烂"noisy/stale),需要周期性整理合并


2️⃣ Mem0 — 行业最主流的记忆中间件

思路:三阶段流水线 + 混合存储。被认为是当前事实上的行业标准

对话消息 → Extract → Consolidate → Store
                                        ↓
                            ┌───────────┴───────────┐
                        Vector Store          Graph Store (Mem0g)
                        (语义检索)             (关系推理)
                                        ↓
查询时 → Retrieve (语义相似 + 图谱关联) → 注入 prompt

三阶段流水线

阶段 做什么 关键区别
Extract LLM 从对话中抽取结构化事实和关系 类似 sundynix 的 extractMemory
Consolidate LLM 将新事实与已有记忆对账,输出 ADD / UPDATE / DELETE / NOOP ⚠️ sundynix 缺失这一层
Store 分别写入 Vector Store + Graph Store + KV Store sundynix 只有 KV

Consolidate 是核心差异

已有记忆: "用户喜欢 Vue"
新抽取:   "用户说最近在学 React,打算迁移"

Mem0 Consolidate → UPDATE: "用户从 Vue 迁移到 React"
sundynix        → 如果 key 不同 → 两条并存("前端框架:Vue" + "技术学习:React"
                  如果 key 恰好相同 → 覆盖(但依赖 LLM 用同一个 key,不可控)

检索方式

  • 不是全量注入,而是用当前 query embedding 做 top-K 语义检索
  • 同时走 Graph Store 做关系关联检索("用户在 X 公司" → 关联出 "X 公司用 Go 技术栈"
  • 大幅减少 token 浪费

3️⃣ Letta(原 MemGPT)— 操作系统式自管理记忆

思路Agent 像操作系统一样自己管理自己的内存层级。

┌─────────────────────────────────────────┐
│  Context Window ("RAM")                  │
│  ┌─────────┐  ┌──────────┐  ┌─────┐    │
│  │ System   │  │ Recall   │  │User │    │
│  │ Prompt   │  │ Memory   │  │Msg  │    │
│  │(可编辑)  │  │(检索结果) │  │     │    │
│  └─────────┘  └──────────┘  └─────┘    │
└─────────────┬───────────────────────────┘
              │ Agent 主动调用内存管理工具
              ↓
┌─────────────────────────────────────────┐
│  Archival Memory ("Disk")  — 向量存储    │
│  Agent 可以 search / insert / delete     │
└─────────────────────────────────────────┘

关键设计

  • Agent 自己决定什么时候存记忆(不是外部异步抽取)
  • Agent 自己决定什么时候查记忆(通过 tool call)
  • System prompt 是可编辑的Agent 可以修改自己的"人格"和"核心记忆"
  • Archival Memory 是无限的向量存储,Agent 按需检索

与 sundynix 的对比sundynix 是外部驱动(orchestrator 异步抽取),Letta 是 Agent 自驱动。


4️⃣ Zep / Graphiti — 双时态知识图谱

思路:面向时间敏感场景,用图谱追踪事实的时间演变。

对话/文档 → Graphiti 引擎 → 三层子图:
    ├─ Episode 子图:原始事件(无损保留,带时间戳)
    ├─ Semantic Entity 子图:提取的实体和关系(语义检索)
    └─ Community 子图:实体聚类(高层概览)

双时态模型(Bi-temporal

每条事实记录两个时间维度:

维度 含义 示例
Valid Time 事实在现实中为真的时间 "2024-01 ~ 2025-03 用户在 A 公司"
Ingestion Time 系统何时发现这个事实 "2025-04 从对话中得知"
2024-01: 用户说 "我在 A 公司做后端"
2025-03: 用户说 "我上个月从 A 离职了"

Zep 存储:
  (用户) -[就职于]-> (A公司)  valid: 2024-01 ~ 2025-02, invalidated_at: 2025-03
  (用户) -[离职于]-> (A公司)  valid: 2025-03 ~

普通 KV 存储:
  公司: A公司  →  被覆盖为空,或两条矛盾并存
  • 可以回答"用户去年这个时候在做什么?"
  • 旧事实失效但不删除,保留完整时间线
  • 企业级场景(合规、审计、保单变更)的首选

对比总览

维度 sundynix 现状 ChatGPT Mem0 Letta Zep
存储 PG 扁平 KV 结构化文档 Vector + Graph + KV Vector (Archival) 双时态知识图谱
抽取 逐轮 LLM 抽取 后台周期 Dreaming Extract 阶段 Agent 自主存储 Graphiti 引擎
去重/合并 exact key match Dreaming 合成 Consolidate (ADD/UPDATE/DELETE) Agent 自管理 双时态失效
检索 全量注入 全量注入(紧凑摘要) 语义 top-K + 图谱关联 Agent 主动搜索 语义 + 时间 + 图谱
时间维度 有(自动过时) 双时态
遗忘 自动 DELETE 操作 Agent 决定 失效不删
用户控制 查看/编辑/删除 有 API 有 API 有 API
复杂度 ★☆☆☆☆ ★★☆☆☆ ★★★☆☆ ★★★★☆ ★★★★★

sundynix-agentix 的差距与改造路线

与行业标准(Mem0 模式)的 3 个关键差距

flowchart LR
    A["1. 缺 Consolidate 层<br/>无法 ADD/UPDATE/DELETE<br/>只有盲目 upsert"] --> D["记忆腐烂<br/>冗余/过时/矛盾"]
    B["2. 全量注入<br/>不做相关性检索"] --> E["token 浪费<br/>噪声干扰"]
    C["3. 无时间/置信度<br/>维度"] --> F["无法遗忘<br/>无法区分强弱偏好"]

建议改造路线(利用已有基础设施)

项目已有 Milvus + Neo4j + Postgres,完全可以不引入新依赖,渐进实现 Mem0 级别的能力:

Phase 1 — 加 Consolidate 层(改 memory_extract.go,约 50 行)

把现在的 "抽取 → 盲目 upsert" 改为 "抽取 → LLM 对账 → 决策执行":

// 现在的流程:
fresh := filterNewPrefs(parsePrefs(txt), existing)  // exact match 去重
for _, p := range fresh {
    o.upsertMemory(ctx, uid, p.Key, p.Value)  // 盲 upsert
}

// 改为 Mem0 式 Consolidate
// 1. 把新抽取 + 已有画像一起交给 LLM
// 2. LLM 输出操作列表:[{op:"ADD/UPDATE/DELETE", key, value, reason}]
// 3. 按操作执行

Phase 2 — 按需检索代替全量注入(复用 Milvus,改 compile.go

// 现在 (compile.go:27-31):全量注入
if rc.Profile != "" {
    sys.WriteString("\n\n关于当前用户的已知信息:\n")
    sys.WriteString(rc.Profile)  // 全部偏好
}

// 改为:memory_get 传入 queryMilvus 语义检索 top-5 相关偏好
// memory store 存偏好时同时 embedding → Milvus memory collection
// 读取时用 query embedding → top-K → 只注入相关的

Phase 3 — 图谱记忆(复用 Neo4j)

memory_upsert 时同时写入 Neo4j
  (User:uid) -[偏好 {key, since, confidence}]-> (Value:value)

检索时可以做关系推理:
  "用户的公司" → "公司的技术栈" → 关联出相关偏好

Tip

最务实的改造优先级Phase 1Consolidate> Phase 2(语义检索)> Phase 3(图谱)。 Phase 1 改动最小(只改 memory_extract.go 的抽取 prompt 和处理逻辑), 但效果最显著——直接解决记忆腐烂这个最大的 Day-2 问题。