Zep:时间知识图谱驱动的智能体记忆架构——让 AI 真正"记住"你

论文标题: Zep: A Temporal Knowledge Graph Architecture for Agent Memory
机构: Zep AI
作者: Preston Rasmussen, Pavlo Paliychuk, Travis Beauvais, Jack Ryan, Daniel Chalef
论文链接: https://arxiv.org/abs/2501.13956

🎯 一句话总结

Zep 提出了一种基于时间感知知识图谱的智能体记忆架构,通过 Graphiti 引擎动态维护对话和业务数据中的实体、事实及其时间线,在 LongMemEval 基准上实现了 18.5% 的准确率提升,同时将响应延迟降低了 90%,上下文 token 消耗从 115k 压缩到 1.6k。


📖 问题背景:为什么 RAG 还不够?

想象这样一个场景:你和 AI 助手聊了三个月,期间提过自己换了工作、搬了家、新交了女朋友。某天你问它:"我现在在哪家公司上班?"它大概率会一脸茫然,或者给你一个三个月前的答案。

这不是 AI “健忘”,而是现有架构的根本缺陷。基于 Transformer 的大语言模型有两个天然短板:

  1. 上下文窗口有限:即便是 GPT-4 Turbo 的 128k 上下文,也装不下几个月的对话历史
  2. 知识截止日期:预训练数据有时效性,模型不知道你昨天发生了什么

RAG(检索增强生成)是目前最流行的补救方案。核心思路很简单:把外部知识切成文档块,向量化后存进数据库,用户提问时检索相关内容塞进 prompt。这套方案对静态知识库(产品手册、法律条文、技术文档)效果不错,但企业级智能体面对的是另一种挑战——动态演化的对话记忆

RAG 在动态场景下的三大痛点

问题类型 具体表现 根本原因
知识过时 用户说"我上周换了新工作",但检索出的仍是旧公司信息 传统 RAG 无法追踪事实的时间有效性
实体混淆 “小王”、“王经理”、"老王"被当成三个不同的人 缺乏实体解析(Entity Resolution)机制
关系丢失 知道张三和李四都是用户的朋友,但不知道他们俩也是朋友 向量检索只能捕捉语义相似性,无法建模关系
时序混乱 分不清"上周的会议"和"去年的会议" 文档块丢失了原始的时间上下文

MemGPT:记忆管理的先行者

MemGPT 是第一个系统性解决 LLM 记忆问题的工作。它的核心洞察非常精妙:把 LLM 类比成操作系统,用虚拟内存的思路管理上下文窗口

┌────────────────────────────────────────────────────────────────────────┐
│                    MemGPT vs Zep 架构对比                               │
├────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  MemGPT 架构 (类操作系统)              Zep 架构 (知识图谱)               │
│  ═══════════════════════              ══════════════════════            │
│                                                                         │
│  ┌─────────────────────┐              ┌─────────────────────┐          │
│  │    Main Context     │              │    Query Engine     │          │
│  │    (CPU 缓存)        │              │    (检索管道)        │          │
│  │  当前对话 + 核心信息  │              │  搜索→重排→构造     │          │
│  └──────────┬──────────┘              └──────────┬──────────┘          │
│             │                                    │                      │
│             │ function call                      │ graph query          │
│             │ (调页)                             │ (图查询)             │
│             ▼                                    ▼                      │
│  ┌─────────────────────┐              ┌─────────────────────┐          │
│  │   Recall Memory     │              │  Semantic Subgraph  │          │
│  │   (内存)            │              │  (语义实体子图)      │          │
│  │  最近对话历史        │              │  实体 + 关系 + 时间  │          │
│  └──────────┬──────────┘              └──────────┬──────────┘          │
│             │                                    │                      │
│             │ search                             │ extraction           │
│             ▼                                    ▼                      │
│  ┌─────────────────────┐              ┌─────────────────────┐          │
│  │  Archival Memory    │              │  Episode Subgraph   │          │
│  │  (硬盘)             │              │  (情节子图)          │          │
│  │  历史对话 + 文档     │              │  原始对话数据        │          │
│  └─────────────────────┘              └─────────────────────┘          │
│                                                                         │
│  核心差异:                                                              │
│  • MemGPT: 文本块检索,无结构                                            │
│  • Zep: 实体-关系图谱,有时间维度                                        │
│                                                                         │
└────────────────────────────────────────────────────────────────────────┘

图0:MemGPT 与 Zep 架构对比。MemGPT 用分层存储管理文本,Zep 用知识图谱组织结构化知识。

具体来说,MemGPT 维护了一个分层存储结构:

  • 核心记忆(Main Context):当前对话窗口,相当于 CPU 缓存
  • 归档记忆(Archival Memory):历史对话和外部知识,相当于硬盘
  • 召回记忆(Recall Memory):最近的对话历史,相当于内存

当上下文窗口不够用时,LLM 可以通过 function call 主动"调页"——把不重要的信息写入归档,把需要的信息从归档读取出来。这个设计让 MemGPT 在 Deep Memory Retrieval 基准上达到了 93.4% 的准确率,远超递归摘要(35.3%)等传统方法。

但 MemGPT 有个根本局限:它本质上还是在做文本检索,只是检索策略更智能了。它无法建模实体之间的关系,也无法追踪事实随时间的演变。

Zep 的核心洞察

Zep 的作者们意识到:与其把记忆当成"文档检索"问题,不如把它当成"知识图谱构建"问题

对话不只是一堆文本,而是充满了结构化信息:

  • 实体:人物(张三)、地点(北京)、组织(腾讯)、概念(机器学习)
  • 关系:朋友、同事、喜欢、讨厌、居住在、就职于
  • 时间:过去(“三年前”)、现在(“目前”)、将来(“下周”)

如果能把这些结构化信息提取出来,存进知识图谱,检索时就能回答"张三上个月推荐的那家餐厅叫什么"这种复杂问题——这需要同时理解"张三"这个实体、"推荐"这个关系、以及"上个月"这个时间约束。


🧠 核心方法:Graphiti——时间感知的知识图谱引擎

Zep 的核心是 Graphiti,一个专为 LLM 智能体设计的时间感知知识图谱引擎。它的记忆系统是一个动态知识图谱 G=(N,E,ϕ)\mathcal{G}=(\mathcal{N}, \mathcal{E}, \phi)G=(N,E,ϕ),其中 N\mathcal{N}N 是节点集合,E\mathcal{E}E 是边集合,ϕ:E→N×N\phi:\mathcal{E}\to\mathcal{N}\times\mathcal{N}ϕ:EN×N 是关联函数。

这个图谱由三层子图构成,形成一个从原始数据到高层抽象的层次结构:

┌─────────────────────────────────────────────────────────────────────────┐
│                      Zep 三层知识图谱架构                                  │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  第三层:社区子图 (Community Subgraph) $\mathcal{G}_c$           │   │
│  │  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐         │   │
│  │  │ 工作相关    │    │ 兴趣爱好    │    │ 家庭生活    │         │   │
│  │  │ 社区摘要    │    │ 社区摘要    │    │ 社区摘要    │         │   │
│  │  └──────┬──────┘    └──────┬──────┘    └──────┬──────┘         │   │
│  └─────────┼─────────────────┼─────────────────┼─────────────────┘   │
│            │                 │                 │                      │
│            ▼                 ▼                 ▼                      │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  第二层:语义实体子图 (Semantic Entity Subgraph) $\mathcal{G}_s$ │   │
│  │                                                                  │   │
│  │    [张三] ──WORKS_FOR──▶ [腾讯]                                  │   │
│  │      │                     │                                     │   │
│  │      │ IS_FRIEND           │ LOCATED_IN                          │   │
│  │      ▼                     ▼                                     │   │
│  │    [李四] ◀──LIKES───── [深圳]                                   │   │
│  │      │                                                           │   │
│  │      │ RECOMMENDS                                                │   │
│  │      ▼                                                           │   │
│  │    [海底捞]                                                      │   │
│  │                                                                  │   │
│  │    每条边带有四个时间戳:t'_created, t'_expired, t_valid, t_invalid │   │
│  └──────────────────────────────┬───────────────────────────────────┘   │
│                                 │                                       │
│                                 ▼                                       │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  第一层:情节子图 (Episode Subgraph) $\mathcal{G}_e$             │   │
│  │                                                                  │   │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐        │   │
│  │  │ 消息 1   │  │ 消息 2   │  │ 消息 3   │  │ 消息 N   │        │   │
│  │  │ t=09:00  │─▶│ t=09:05  │─▶│ t=09:10  │─▶│ t=...    │        │   │
│  │  │ 用户说   │  │ 助手回复 │  │ 用户说   │  │ ...      │        │   │
│  │  └──────────┘  └──────────┘  └──────────┘  └──────────┘        │   │
│  │                                                                  │   │
│  │  保留原始对话数据,支持引用溯源                                   │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

图1:Zep 三层知识图谱架构示意图。从底向上依次是情节子图(原始数据)、语义实体子图(结构化知识)、社区子图(高层抽象)。

第一层:情节子图(Episode Subgraph)Ge\mathcal{G}_eGe

情节子图是"原始记忆"层,存储未经加工的输入数据。每条消息、每段文本、每个 JSON 对象都作为一个情节节点(Episode Node)保存下来。

为什么要保留原始数据?三个原因:

  1. 非损失存储:后续的实体/关系提取可能有遗漏或错误,保留原始数据可以随时回溯
  2. 引用溯源:当 LLM 给出一个回答时,可以追溯到原始对话,提供引用和出处
  3. 审计合规:企业场景需要保留完整的交互记录

每个情节节点包含三个关键字段:

  • 内容:原始文本/JSON
  • 发言者:消息的来源(用户、助手、系统)
  • 参考时间戳 treft_{ref}tref:消息发送的时间点

treft_{ref}tref 非常重要。当用户说"我下周四有个会议"时,系统需要知道"现在"是什么时候,才能正确解析"下周四"的具体日期。这是 Graphiti 处理相对时间表达的基础。

情节边 Ee\mathcal{E}_eEe 连接情节节点和它们提取出的语义实体,建立了从原始数据到结构化知识的双向索引。

第二层:语义实体子图(Semantic Entity Subgraph)Gs\mathcal{G}_sGs

语义实体子图是"概念记忆"层,存储从情节中提取的结构化知识。它包含两类元素:

实体节点(Entity Nodes):代表对话中提到的人物、地点、组织、概念等。每个实体节点包含:

  • 名称:实体的规范名称(如"张三")
  • 摘要:对实体的简短描述(如"AI 研究员,曾就职于腾讯")
  • 嵌入向量:用于语义检索的 1024 维向量

事实边(Fact Edges):代表实体之间的关系。每条边包含:

  • 关系类型:如 WORKS_FORIS_FRIENDS_WITHRECOMMENDS
  • 事实描述:关系的详细说明(如"张三和李四是 2020 年在腾讯认识的同事")
  • 四个时间戳:这是 Zep 的核心创新,下面详细说明
实体提取与消歧

实体提取是个经典的 NLP 问题,但在对话场景下有特殊挑战:同一个人可能有多种称呼。用户可能在不同时候说"我老板"、“王总”、“老王”,这三个指的可能是同一个人。

Zep 的解决方案是混合检索 + LLM 消歧的两阶段流程:

┌────────────────────────────────────────────────────────────────────────┐
│                    实体提取与消歧流程                                    │
├────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  输入消息: "我老板王总推荐了一家餐厅"                                    │
│       │                                                                 │
│       ▼                                                                 │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  Stage 1: 实体提取 (LLM)                                         │   │
│  │  提取实体: ["我老板", "王总", "餐厅"]                              │   │
│  └──────────────────────────────┬──────────────────────────────────┘   │
│                                 │                                       │
│                                 ▼                                       │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  Stage 2: 候选检索                                               │   │
│  │  ┌─────────────────┐    ┌─────────────────┐                     │   │
│  │  │  向量相似度搜索  │    │  全文搜索        │                     │   │
│  │  │  找语义相似实体  │    │  找名称匹配实体  │                     │   │
│  │  └────────┬────────┘    └────────┬────────┘                     │   │
│  │           │                      │                               │   │
│  │           └──────────┬───────────┘                               │   │
│  │                      ▼                                           │   │
│  │           候选实体: ["王经理", "老王", "王总监"]                   │   │
│  └──────────────────────────────┬──────────────────────────────────┘   │
│                                 │                                       │
│                                 ▼                                       │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  Stage 3: LLM 消歧判断                                           │   │
│  │                                                                  │   │
│  │  Prompt: "王总" 和 "王经理" 是同一个人吗?                         │   │
│  │  Context: 之前的对话历史                                          │   │
│  │                                                                  │   │
│  │  LLM 输出:                                                       │   │
│  │  {                                                               │   │
│  │    "is_duplicate": true,                                         │   │
│  │    "merged_name": "王总 (王经理)",                                │   │
│  │    "uuid": "existing-entity-uuid"                                │   │
│  │  }                                                               │   │
│  └──────────────────────────────┬──────────────────────────────────┘   │
│                                 │                                       │
│                                 ▼                                       │
│                     更新图谱:合并实体节点                               │
│                                                                         │
└────────────────────────────────────────────────────────────────────────┘

图1.5:实体提取与消歧流程。两阶段设计结合了检索效率和判断精度。

这个设计的好处是:向量检索和全文检索各有所长(前者捕捉语义相似性,后者捕捉词汇重叠),两者结合能提高召回率;最终用 LLM 做高精度判断,避免误合并。

论文中还提到使用了 reflexion 技术 来减少幻觉——这是一种让 LLM "自我反思"的方法,先生成初步答案,再检查答案是否合理,不合理就修正。

事实提取与去重

事实提取的流程类似:

  1. 给定实体列表和对话上下文,用 LLM 提取实体间的关系
  2. 为每条关系生成嵌入向量
  3. 同一实体对的现有边中检索相似边
  4. 用 LLM 判断是否是重复事实

注意第 3 步的约束:只在同一实体对的边中搜索。这大大减少了搜索空间,避免把"张三喜欢篮球"和"李四喜欢篮球"误判为重复。

双时间模型:Zep 的杀手锏

这是 Graphiti 最核心的创新。传统知识图谱是"静态快照"——它告诉你张三是李四的同事,但不告诉你什么时候开始、什么时候结束、什么时候这条信息被记录下来。

Zep 为每条事实边维护四个时间戳,形成两条独立的时间线:

┌────────────────────────────────────────────────────────────────────────┐
│                        双时间模型 (Bi-temporal Model)                    │
├────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│   事务时间线 T' (Transaction Time) ─ 系统视角                           │
│   ════════════════════════════════════════════════════════════════▶    │
│   │                                                                     │
│   │  t'_created                           t'_expired                   │
│   │  (系统记录时间)                        (系统失效时间)                 │
│   │      │                                     │                        │
│   │      ▼                                     ▼                        │
│   │  ┌───────────────────────────────────────────┐                     │
│   │  │        事实在数据库中存在的时间段           │                     │
│   │  └───────────────────────────────────────────┘                     │
│                                                                         │
│   有效时间线 T (Valid Time) ─ 现实世界视角                               │
│   ════════════════════════════════════════════════════════════════▶    │
│   │                                                                     │
│   │  t_valid                               t_invalid                   │
│   │  (事实生效时间)                         (事实失效时间)                │
│   │      │                                     │                        │
│   │      ▼                                     ▼                        │
│   │  ┌───────────────────────────────────────────┐                     │
│   │  │        事实在现实世界中为真的时间段         │                     │
│   │  └───────────────────────────────────────────┘                     │
│                                                                         │
└────────────────────────────────────────────────────────────────────────┘

图2:双时间模型示意图。事务时间线追踪系统操作,有效时间线追踪现实世界事实的生命周期。

时间线 时间戳 语义 用途
事务时间线 T′T'T tcreated′t'_{created}tcreated 系统记录这条事实的时间 数据库审计
texpired′t'_{expired}texpired 系统删除/失效这条事实的时间 数据库审计
有效时间线 TTT tvalidt_{valid}tvalid 这条事实在现实中生效的时间 时间推理
tinvalidt_{invalid}tinvalid 这条事实在现实中失效的时间 时间推理

举个具体例子

用户在 2024 年 1 月 15 日说:“我上周从腾讯离职了,现在在 OpenAI 工作。”

系统会创建两条边:

┌────────────────────────────────────────────────────────────────────────┐
│                     知识更新示例:工作变更                                │
├────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  用户输入 (2024-01-15): "我上周从腾讯离职了,现在在 OpenAI 工作"         │
│                                                                         │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  边1(新创建): 用户 ─[工作于]─▶ OpenAI                          │   │
│  │  ├── t'_created = 2024-01-15  (系统记录时间)                    │   │
│  │  ├── t_valid = 2024-01-08     (事实生效时间,"上周"推算)         │   │
│  │  └── t_invalid = NULL         (事实仍然有效)                    │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  边2(被更新): 用户 ─[工作于]─▶ 腾讯                            │   │
│  │  ├── t'_created = 2023-06-01  (系统当初记录的时间)              │   │
│  │  ├── t'_expired = 2024-01-15  (系统现在标记失效)                │   │
│  │  ├── t_valid = 2020-07-01     (事实当初生效的时间)              │   │
│  │  └── t_invalid = 2024-01-07   (事实失效,新边生效前一天)         │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  时间线可视化:                                                          │
│                                                                         │
│  2020-07     2023-06     2024-01-07  2024-01-08  2024-01-15            │
│     │           │            │           │           │                  │
│     ├───────────┼────────────┤           │           │                  │
│     │  腾讯工作期 (有效)      │           │           │                  │
│     │           │            │           │           │                  │
│     │           │            │           ├───────────┼──────────▶       │
│     │           │            │           │  OpenAI 工作期 (有效)        │
│     │           │            │           │           │                  │
│     │           ├────────────┼───────────┼───────────┤                  │
│     │           │ 腾讯边在数据库中存在期   │ 失效      │                  │
│                                                                         │
└────────────────────────────────────────────────────────────────────────┘

图3:知识更新示例。当用户说"换工作"时,系统同时创建新边并使旧边失效,保留完整的历史记录。

这个双时间模型借鉴自数据库领域的 Temporal Database 理论,已经有几十年的研究历史。Zep 的贡献是把它引入 LLM 智能体记忆场景,并设计了相应的提取和更新机制。

冲突检测与边失效

当新信息与旧事实矛盾时,系统如何处理?

Zep 的策略是新信息优先:用 LLM 识别语义冲突的边,然后自动使旧边失效。具体流程:

1. 提取新事实边
2. 检索同一实体对的现有边
3. 用 LLM 判断是否存在矛盾
4. 如果矛盾,且时间有重叠:
   └── 设置旧边的 t_invalid = 新边的 t_valid - 1

为什么优先信任新信息?因为在对话场景下,用户刚说的话更可能反映当前状态。当然,这个假设不是 100% 正确的(用户可能在回忆过去),但作为启发式规则,它在大多数情况下是合理的。

第三层:社区子图(Community Subgraph)Gc\mathcal{G}_cGc

社区子图是"全局理解"层,通过社区检测算法把紧密相连的实体聚类成群组。

为什么需要社区?两个原因:

  1. 全局查询:当用户问"最近我们讨论了哪些话题"时,需要一个高层视角
  2. 上下文补充:检索单个实体时,可以顺带提供它所属社区的背景信息

每个社区节点包含:

  • 成员列表:属于这个社区的实体节点
  • 摘要:用 LLM 生成的社区描述
  • 关键词名称:用于检索的关键词集合
社区检测算法的选择

GraphRAG 使用 Leiden 算法做社区检测,这是一种基于模块度优化的高质量算法。但 Zep 选择了标签传播算法(Label Propagation),原因是:

Leiden 的问题:每次图谱更新后,需要重新运行完整的社区检测,计算开销大。

标签传播的优势:支持增量更新。当新增一个节点时,只需要:

  1. 查看新节点的邻居属于哪些社区
  2. 投票选出归属社区(少数服从多数)
  3. 更新社区摘要

这个增量更新策略是一个工程上的 trade-off:检测质量可能略逊于 Leiden,但延迟和成本大大降低。论文承认,随着时间推移,增量更新的社区会逐渐偏离完整运行的结果,因此需要定期做全量刷新。


🔍 记忆检索:三步走的检索管道

有了知识图谱,下一步是如何高效检索。Zep 的检索系统可以形式化表示为一个函数 f:S→Sf: S \to Sf:SS,它接受文本查询 α\alphaα,返回格式化的上下文 β\betaβ

整个过程分三步:f(α)=χ(ρ(φ(α)))=βf(\alpha) = \chi(\rho(\varphi(\alpha))) = \betaf(α)=χ(ρ(φ(α)))=β

┌────────────────────────────────────────────────────────────────────────┐
│                    Zep 记忆检索管道 (Memory Retrieval Pipeline)          │
├────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│   用户查询 α                                                             │
│   "张三上个月推荐的餐厅是哪家?"                                          │
│        │                                                                │
│        ▼                                                                │
│   ┌────────────────────────────────────────────────────────────────┐   │
│   │  Step 1: 搜索 (Search) φ                                        │   │
│   │  ┌──────────────┐ ┌──────────────┐ ┌──────────────┐            │   │
│   │  │ φ_cos        │ │ φ_bm25       │ │ φ_bfs        │            │   │
│   │  │ 语义相似度    │ │ 全文搜索     │ │ 图遍历       │            │   │
│   │  │ (向量检索)   │ │ (关键词匹配) │ │ (关系扩展)   │            │   │
│   │  └──────┬───────┘ └──────┬───────┘ └──────┬───────┘            │   │
│   │         │                │                │                     │   │
│   │         └────────────────┼────────────────┘                     │   │
│   │                          ▼                                      │   │
│   │                   候选结果集合                                   │   │
│   └──────────────────────────┬─────────────────────────────────────┘   │
│                              │                                          │
│                              ▼                                          │
│   ┌────────────────────────────────────────────────────────────────┐   │
│   │  Step 2: 重排序 (Rerank) ρ                                      │   │
│   │                                                                 │   │
│   │  ┌─────────┐  ┌─────────┐  ┌─────────────┐  ┌──────────────┐   │   │
│   │  │ RRF     │  │ MMR     │  │ Episode-    │  │ Cross-       │   │   │
│   │  │ 融合排序 │  │ 多样性  │  │ mentions    │  │ encoder      │   │   │
│   │  │         │  │ 排序    │  │ 频率排序    │  │ 精排         │   │   │
│   │  └────┬────┘  └────┬────┘  └──────┬──────┘  └──────┬───────┘   │   │
│   │       └────────────┴───────────────┴───────────────┘            │   │
│   │                          │                                      │   │
│   │                          ▼                                      │   │
│   │                   Top-K 精选结果                                 │   │
│   └──────────────────────────┬─────────────────────────────────────┘   │
│                              │                                          │
│                              ▼                                          │
│   ┌────────────────────────────────────────────────────────────────┐   │
│   │  Step 3: 构造 (Construct) χ                                     │   │
│   │                                                                 │   │
│   │  <FACTS>                                                        │   │
│   │  - 张三推荐了海底捞 (2024-01-15 - present)                       │   │
│   │  - 张三和李四是同事 (2020-01-01 - present)                       │   │
│   │  </FACTS>                                                       │   │
│   │                                                                 │   │
│   │  <ENTITIES>                                                     │   │
│   │  - 张三: AI研究员,腾讯员工                                       │   │
│   │  - 海底捞: 火锅连锁餐厅                                          │   │
│   │  </ENTITIES>                                                    │   │
│   └──────────────────────────┬─────────────────────────────────────┘   │
│                              │                                          │
│                              ▼                                          │
│                        上下文 β                                         │
│                   (格式化文本,送入 LLM)                                  │
│                                                                         │
└────────────────────────────────────────────────────────────────────────┘

图4:Zep 记忆检索管道。搜索阶段追求高召回,重排序阶段提高精确率,构造阶段格式化输出。

Step 1: 搜索(Search,φ\varphiφ

搜索阶段的目标是高召回——尽可能多地找出候选节点和边。Zep 实现了三种互补的搜索方法:

搜索方法 符号 捕捉的相似性 实现基础 适用场景
余弦语义相似度 φcos\varphi_{cos}φcos 语义相似 向量数据库 “美食推荐” 匹配 “餐厅建议”
BM25 全文搜索 φbm25\varphi_{bm25}φbm25 词汇相似 Lucene 精确匹配人名、专有名词
广度优先遍历 φbfs\varphi_{bfs}φbfs 上下文相似 图遍历 找出与核心实体相关的周边信息

三种方法各有所长:

  • 语义搜索能处理同义词和近义表达,但对专有名词效果差
  • 全文搜索对精确匹配很好,但无法处理语义变体
  • 图遍历能发现间接关联,是知识图谱特有的优势

图遍历的威力:假设用户问"张三推荐的那家餐厅",但图谱里"餐厅"节点的名称是"海底捞",向量相似度可能不高。但如果"张三"节点有一条"推荐"边指向"海底捞",图遍历就能通过关系边找到它。

Zep 还支持种子节点遍历:以最近对话中提到的实体为起点做 BFS,这样可以优先返回与当前话题相关的信息。

Step 2: 重排序(Rerank,ρ\rhoρ

搜索阶段追求召回率,可能返回几十上百个候选结果。重排序阶段的目标是提高精确率——把最相关的结果排到前面。

Zep 提供了多种重排序策略:

重排器 原理 优点 缺点
RRF 融合多个排序列表的倒数排名 简单高效 不考虑语义
MMR 最大边际相关性,平衡相关性和多样性 避免冗余 需要调参
Episode-mentions 按实体在对话中被提及的频率排序 捕捉重要性 可能偏向高频词
Node distance 按图距离(到查询核心的跳数)排序 保持上下文聚焦 可能错过远距离关联
Cross-encoder 用 LLM 对每个候选打分 最高精度 计算成本高

在实际使用中,通常先用轻量级方法(RRF、MMR)做初筛,必要时再用 Cross-encoder 做精排。

Step 3: 构造(Construct,χ\chiχ

最后一步是把检索到的节点和边格式化成 LLM 可读的文本。Zep 使用的模板如下:

FACTS and ENTITIES represent relevant context to the current conversation.

These are the most relevant facts and their valid date ranges.
If the fact is about an event, the event takes place during this time.
format: FACT (Date range: from - to)

<FACTS>
{facts}
</FACTS>

These are the most relevant entities
ENTITY_NAME: entity summary

<ENTITIES>
{entities}
</ENTITIES>

注意两个设计细节:

  1. 事实带时间范围:这让 LLM 能正确回答时间敏感问题。比如"张三现在在哪工作"和"张三以前在哪工作"需要不同的答案。

  2. 实体带摘要:摘要提供了实体的背景信息,帮助 LLM 理解上下文。


🧪 实验评估

论文在两个基准上评估了 Zep:DMR(Deep Memory Retrieval)和 LongMemEval。

┌────────────────────────────────────────────────────────────────────────┐
│                      两个评估基准对比                                    │
├────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  DMR (Deep Memory Retrieval)          LongMemEval                       │
│  ═══════════════════════════          ═══════════                       │
│                                                                         │
│  • 来源: MemGPT 团队                  • 来源: 学术界                     │
│  • 对话数: 500 段                     • 对话数: 若干                     │
│  • 每段消息: ~60 条                   • 每段消息: ~115,000 tokens        │
│  • 问题类型: 单轮事实检索             • 问题类型: 6 类复杂问题            │
│  • 难度: ⭐⭐                         • 难度: ⭐⭐⭐⭐⭐                   │
│                                                                         │
│  问题类型分布 (LongMemEval):                                             │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                  │   │
│  │  single-session-user      ████████████████  用户在单会话中说的    │   │
│  │  single-session-assistant ████████████      助手在单会话中回复的  │   │
│  │  single-session-preference████████          用户表达的偏好        │   │
│  │  multi-session            ██████████████    跨多个会话的信息      │   │
│  │  knowledge-update         ████████          被更新后的信息        │   │
│  │  temporal-reasoning       ██████████████    需要时间推理          │   │
│  │                                                                  │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  为什么 LongMemEval 更有价值?                                           │
│  • 115k tokens 超出大多数模型的有效处理范围                              │
│  • 6 类问题覆盖真实企业场景                                              │
│  • 时间推理和知识更新是 RAG 的痛点                                       │
│                                                                         │
└────────────────────────────────────────────────────────────────────────┘

图5:两个评估基准对比。DMR 基准较简单,LongMemEval 更贴近真实企业场景。

实验设置

模型选择

  • 嵌入和重排序:BGE-m3(BAAI)
  • 图构建:GPT-4o-mini
  • 响应生成:GPT-4o-mini 和 GPT-4o

对比基线

  • Full-context:把完整对话历史塞进上下文窗口
  • Conversation Summaries:对每个会话生成摘要
  • Recursive Summarization:递归合并摘要
  • MemGPT:当前 SOTA 的 LLM 记忆系统

DMR 基准:小试牛刀

Deep Memory Retrieval 是 MemGPT 团队提出的基准,包含 500 段多会话对话,每段约 5 个会话、60 条消息。每段对话配一个问答对用于评估。

实验结果

记忆方法 模型 准确率
Recursive Summarization GPT-4-turbo 35.3%
Conversation Summaries GPT-4-turbo 78.6%
MemGPT GPT-4-turbo 93.4%
Full-conversation GPT-4-turbo 94.4%
Zep GPT-4-turbo 94.8%
Conversation Summaries GPT-4o-mini 88.0%
Full-conversation GPT-4o-mini 98.0%
Zep GPT-4o-mini 98.2%

Zep 在两个模型上都取得了最佳成绩,但领先幅度很小(0.2%~0.4%)。

作者的自我批评非常诚实:DMR 这个基准太简单了。60 条消息轻松塞进现代 LLM 的上下文窗口,Full-context 基线就能达到 94%+。基准的问题还包括:

  • 问题都是简单的单轮事实检索
  • 部分问题表述模糊(如"favorite drink to relax with"在对话中从未被这样表述)
  • 无法反映真实企业场景的复杂性

LongMemEval 基准:真正的考验

LongMemEval 是一个更具挑战性的基准,对话平均长度达到 115,000 tokens——这已经超出了大多数模型的有效处理范围。

基准包含六类问题:

  • single-session-user:单会话中用户提到的信息
  • single-session-assistant:单会话中助手提供的信息
  • single-session-preference:单会话中表达的偏好
  • multi-session:跨多个会话的信息
  • knowledge-update:信息被更新后的正确答案
  • temporal-reasoning:需要时间推理的问题

整体结果

记忆方法 模型 准确率 延迟 延迟 IQR 上下文 Tokens
Full-context GPT-4o-mini 55.4% 31.3s 8.76s 115k
Zep GPT-4o-mini 63.8% 3.20s 1.31s 1.6k
Full-context GPT-4o 60.2% 28.9s 6.01s 115k
Zep GPT-4o 71.2% 2.58s 0.684s 1.6k

这组数据非常亮眼:

  • 准确率提升 15.2%~18.5%:说明知识图谱能更精准地提取关键信息
  • 延迟降低 90%:从 ~30 秒降到 ~3 秒,对用户体验至关重要
  • Token 消耗降低 98%:从 115k 降到 1.6k,直接影响 API 成本

按问题类型细分(使用 GPT-4o):

问题类型 Full-context Zep 变化
single-session-preference 20.0% 56.7% +184%
single-session-assistant 94.6% 80.4% -17.7%
temporal-reasoning 45.1% 62.4% +38.4%
multi-session 44.3% 57.9% +30.7%
knowledge-update 78.2% 83.3% +6.5%
single-session-user 81.4% 92.9% +14.1%

实验结果分析

Zep 的优势领域

  1. 偏好问题(+184%):这类问题需要理解用户的喜好偏向,知识图谱可以把"我喜欢X"这类表述提取为显式的关系边
  2. 时间推理(+38.4%):双时间模型的直接收益,Full-context 需要 LLM 自己从长文本中理清时间线
  3. 多会话(+30.7%):跨会话信息整合是知识图谱的强项,向量检索很难做到

Zep 的劣势领域

  1. 单会话助手问题(-17.7%):这是个值得关注的异常。我的猜测是:助手回复往往包含详细的步骤说明、代码片段、长篇解释,这些内容在提取成知识图谱时会丢失细节。比如用户问"你之前给我写的那段代码是什么",图谱可能只记录了"助手提供了一段 Python 代码",但代码本身需要从原始情节中检索。

GPT-4o-mini vs GPT-4o 的差异

  • 在 knowledge-update 问题上,GPT-4o-mini 使用 Zep 反而轻微下降(-3.36%),而 GPT-4o 有 6.52% 提升
  • 这说明理解 Zep 的时间标注格式需要一定的模型能力,能力不足的模型可能被复杂的时间信息搞糊涂

消融实验的缺失

论文没有提供消融实验,这是一个遗憾。我们无法知道:

  • 三层图谱结构各自贡献了多少?
  • 双时间模型相比单时间模型有多大提升?
  • 不同检索方法(向量、全文、图遍历)的相对贡献是多少?

💡 技术亮点与局限

三大亮点

1. 双时间模型的务实引入

双时间模型不是什么新理论,Temporal Database 领域研究了几十年。但 Zep 的贡献是:

  • 设计了从自然语言中提取时间信息的 prompt
  • 实现了基于 LLM 的冲突检测和边失效机制
  • 把数据库理论和 LLM 应用巧妙结合

这种"把经典方法引入新场景"的研究思路值得学习。

2. 工程导向的系统设计

论文花了不少篇幅讨论延迟、token 成本这些工程指标:

  • 选择标签传播而非 Leiden,为了支持增量更新
  • 限制实体/边去重的搜索范围,减少计算复杂度
  • 使用预定义 Cypher 查询而非 LLM 生成,保证 schema 一致性

这些设计决策说明作者团队有实际的生产经验,而不只是在刷 benchmark。

3. 层次化的图谱结构

从情节到实体到社区的三层结构,对应了人类记忆的心理学模型:

  • 情节记忆(Episodic Memory):具体事件的记忆
  • 语义记忆(Semantic Memory):概念和关系的知识
  • 图式(Schema):高层的组织结构

这种设计不仅有理论支撑,也便于在不同粒度上进行检索。

三大局限

1. 单会话助手问题的性能下降

论文坦承这个问题,但没有给出清晰解释。这可能是知识图谱表示能力的固有缺陷——并非所有信息都适合图结构。长篇代码、详细步骤、结构化数据,这些内容在"压缩"成三元组时会丢失关键细节。

可能的解决方向

  • 对长内容保留原文引用,不只存摘要
  • 使用混合架构,对不同类型内容采用不同存储策略

2. 缺少与其他 GraphRAG 方法的对比

论文只对比了 MemGPT 和 Full-context,但 GraphRAG、LightRAG、HippoRAG 这些近期的图增强 RAG 工作呢?它们同样使用知识图谱,直接对比能更清楚地展示 Zep 的独特价值。

作者在结论中提到这是未来工作方向,但对读者来说,这种对比在当前就很有价值。

3. 图构建成本的黑箱

提取实体、关系、时间都需要 LLM 调用。一条消息可能需要调用 3-5 次 LLM:

  • 实体提取 1 次
  • 实体消歧 N 次(N = 候选实体数)
  • 关系提取 1 次
  • 关系消歧 M 次
  • 时间提取 K 次(K = 关系数)

论文没有详细分析这个成本。在高频对话场景(如客服机器人),图构建可能成为瓶颈。

可能的优化方向

  • 使用更小的专用模型做提取任务
  • 批量处理多条消息
  • 异步构建,不阻塞响应

🔮 深度思考与启发

记忆的本质是什么?

这篇论文让我重新思考"AI 记忆"的本质。传统 RAG 把记忆当成"信息检索"问题:存储文本,检索文本。但人类的记忆远不止于此:

  • 我们会关联信息(张三喜欢篮球 + 李四喜欢篮球 → 他们可能合得来)
  • 我们会更新信息(张三换工作了 → 之前的工作信息"过期"了)
  • 我们会抽象信息(一堆对话 → “我们在讨论旅行计划”)

知识图谱天然支持这些操作。实体和关系支持关联,时间戳支持更新,社区支持抽象。这可能是比向量检索更适合记忆的表示方式。

时间感知是被低估的方向

大多数 RAG 研究都在卷相关性排序:用更好的嵌入模型、更复杂的重排器、更精细的分块策略。但很少有人关注时间维度。

然而现实世界的信息天然带时间属性:

  • 新闻:今天的比昨天的更重要
  • 偏好:最近表达的比一年前的更准确
  • 状态:工作、住址、关系都会变化

Zep 的双时间模型提供了一个不错的框架,但还有很多可以探索的方向:

  • 时间衰减:旧信息的权重随时间降低
  • 时间聚合:按时间段组织和检索信息
  • 时间预测:基于历史模式推测未来状态

结构化 vs 非结构化的权衡

知识图谱的优势是结构化,但结构化也是把双刃剑。

结构化的好处

  • 支持复杂查询(“张三在腾讯工作期间推荐的餐厅”)
  • 显式的实体消歧
  • 可解释的推理路径

结构化的代价

  • 信息损失(详细内容被压缩成三元组)
  • 提取错误(LLM 可能漏提或错提)
  • 构建成本(需要大量 LLM 调用)

理想的系统可能是混合架构

  • 用知识图谱存储结构化信息(实体、关系、时间)
  • 用原始文档存储非结构化信息(详细内容)
  • 检索时结合两者

Zep 的情节子图已经朝这个方向走了一步,但可以做得更彻底。


🔧 工程落地建议

如果你正在考虑为自己的智能体产品引入记忆功能,这里是一些实践建议:

场景评估

场景特征 推荐方案
短对话(< 100 条消息) Full-context,简单直接
中等对话(100-1000 条消息) MemGPT 或简单 RAG
长对话 + 需要时间推理 Zep/Graphiti 类方案
长对话 + 需要跨会话关联 Zep/Graphiti 类方案
高频对话(每秒多条消息) 需要仔细评估图构建成本

成本优化策略

  1. 分层处理:不是每条消息都值得完整处理。可以先用轻量级模型判断消息是否包含有价值的信息,只对重要消息做完整的实体/关系提取。

  2. 延迟构建:图构建可以异步进行,不必阻塞用户响应。用户发消息后立即返回答案(用 Full-context 或简单 RAG),后台慢慢更新图谱。

  3. 模型选择:用 GPT-4o-mini 而非 GPT-4o 做图构建,成本差 10 倍以上。

  4. 批量处理:如果消息来得快,可以攒一批一起处理,减少 LLM 调用次数。

评估指标

除了准确率,还要关注:

  • 延迟:用户能接受的等待时间(通常 < 5 秒)
  • Token 成本:每次查询消耗的 token 数
  • 构建成本:每条消息的图构建成本
  • 存储成本:图谱的存储空间

📚 相关工作

系统/论文 核心思路 与 Zep 的关系
MemGPT/Letta 用操作系统虚拟内存思路管理 LLM 上下文 Zep 的直接竞争对手和比较基准
GraphRAG 用知识图谱增强 RAG,引入社区检测和摘要 Zep 社区子图的灵感来源
LightRAG 轻量级 GraphRAG,强调低延迟 与 Zep 的检索方法有相似之处
AriGraph 区分情节记忆和语义记忆的图谱架构 Zep 双子图设计的灵感来源
Reflexion LLM 自我反思减少幻觉 Zep 实体提取使用的技术

📝 总结

Zep 展示了时间感知知识图谱在智能体记忆领域的巨大潜力。通过三层图谱结构(情节→实体→社区)和双时间模型(事务时间+有效时间),它在处理长对话、复杂时间推理、知识更新、跨会话关联等企业级任务时表现出色。

在 LongMemEval 基准上,Zep 实现了:

  • 准确率提升 18.5%
  • 延迟降低 90%
  • Token 消耗降低 98%

但系统也有明显的局限:单会话助手问题性能下降、缺少与其他 GraphRAG 方法的对比、图构建成本不透明。

对于正在构建智能体产品的团队,Zep 提供了一个比纯文本检索更强大的记忆框架。是否采用取决于你的场景特征:如果对话很长、需要时间推理、有跨会话关联需求,值得一试;如果只是短对话,Full-context 可能更简单高效。

核心启示:记忆不只是信息检索,更是知识的结构化组织。时间是信息的重要维度,值得在系统设计中显式建模。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐