479 lines
17 KiB
Markdown
479 lines
17 KiB
Markdown
# 10. Agent 记忆机制调研与 ZK Data Agent 对比
|
||
|
||
本文整理主流 Agent / AI 产品的记忆实现方式,并对照 ZK Data Agent 当前实现。目标不是判断哪一种“最好”,而是说明不同记忆机制分别解决什么问题,以及为什么我们当前选择“用户记忆 + Skill 使用记忆 + 异步整理队列 + Markdown 可编辑文件”的路线。
|
||
|
||
调研时间:2026-05-19。
|
||
|
||
## 1. 结论摘要
|
||
|
||
主流记忆实现大致分为六类:
|
||
|
||
| 类型 | 代表 | 核心做法 | 适合场景 |
|
||
|------|------|----------|----------|
|
||
| 产品级长期记忆 | ChatGPT Memory | 平台自动保存用户偏好和事实,并在后续对话中注入 | 通用个人助手 |
|
||
| 会话状态记忆 | OpenAI Agents SDK Sessions、AutoGen Memory | 自动保存历史消息或把外部记忆注入上下文 | 线程连续对话 |
|
||
| 文件化项目记忆 | Claude Code `CLAUDE.md`、Claw 基座 memory files | 通过项目/用户级 Markdown 文件向 Agent 注入稳定规则 | 工程项目、团队约定 |
|
||
| 图/向量检索记忆 | LangGraph Store、Mem0、Zep/Graphiti | 抽取事实,存入向量库或知识图谱,按语义检索 | 长期、跨会话、海量事实 |
|
||
| Agent 自主管理记忆 | Letta / MemGPT | Agent 有显式 memory blocks 和 archival memory,可读写管理 | 状态型 Agent、长期角色 |
|
||
| 框架内置任务记忆 | CrewAI | 短期、长期、实体、上下文记忆组合 | 多 Agent 任务协作 |
|
||
|
||
ZK Data Agent 当前更接近:
|
||
|
||
```text
|
||
文件化项目记忆
|
||
+ 产品级用户记忆
|
||
+ Skill 作用域记忆
|
||
+ 异步记忆整理队列
|
||
```
|
||
|
||
它没有优先做向量库或知识图谱,而是选择 Markdown 文件作为最终记忆正文。这个取舍适合当前团队场景:记忆内容需要能被用户看到、编辑、删除,并且要按 Skill 作用域精准注入。
|
||
|
||
## 2. 主流实现机制
|
||
|
||
### 2.1 ChatGPT Memory:产品级个人长期记忆
|
||
|
||
ChatGPT Memory 的核心是平台级用户记忆。它会保存用户偏好、事实和历史对话中有持续价值的信息,并在后续对话中使用。用户可以查看、管理、删除保存的记忆,也可以关闭相关能力。
|
||
|
||
机制特点:
|
||
|
||
- 记忆作用域是用户账号。
|
||
- 由产品后台判断哪些内容值得保存。
|
||
- 注入方式对用户透明,用户看到的是“助手更了解我”。
|
||
- 适合通用个人助手,不适合表达复杂业务流程结构。
|
||
|
||
和我们的关系:
|
||
|
||
ZK Data Agent 的“用户记忆”借鉴了这个方向,但没有把全部记忆做成黑盒。我们把最终正文落到 `user.md`,并在 UI 里允许用户编辑。
|
||
|
||
### 2.2 OpenAI Agents SDK Sessions:会话状态记忆
|
||
|
||
OpenAI Agents SDK 的 Sessions 主要解决“同一个会话线程里自动保留历史上下文”。开发者不需要每轮手动传入完整历史,Session 会保存对话项,并在下一轮运行时自动带上。
|
||
|
||
机制特点:
|
||
|
||
- 更偏 conversation state,而不是长期个人偏好。
|
||
- 适合多轮会话连续执行。
|
||
- 常见实现是 SQLite / SQLAlchemy / 自定义 session backend。
|
||
- 记忆对象主要是消息历史,不是抽象后的长期知识。
|
||
|
||
和我们的关系:
|
||
|
||
ZK Data Agent 也有 session 持久化,但我们把它和“长期记忆”分开:
|
||
|
||
```text
|
||
session.json
|
||
保存当前会话消息、工具调用、产物和运行事件。
|
||
|
||
memory/user.md、memory/skills/*.md
|
||
保存跨会话长期偏好和 Skill 使用经验。
|
||
```
|
||
|
||
这个区分很重要:会话历史服务“恢复当前任务”,长期记忆服务“下次任务更懂用户和业务”。
|
||
|
||
### 2.3 Claude Code / OpenClaw / Claw:文件化项目记忆
|
||
|
||
Claude Code 使用 `CLAUDE.md` 作为项目或用户级记忆文件,常用于保存仓库规则、构建命令、代码风格、项目约定等。OpenClaw / Claw 类 Code Agent 基座通常也会保留这条路线:从全局或工作目录发现记忆文件,并把内容注入上下文。
|
||
|
||
在当前仓库里,对应实现主要是:
|
||
|
||
```text
|
||
src/agent_context.py
|
||
src/session_memory_compact.py
|
||
```
|
||
|
||
其中 `agent_context.py` 负责发现全局和目录级 memory files,`session_memory_compact.py` 负责会话压缩场景下的 session memory 摘要。
|
||
|
||
机制特点:
|
||
|
||
- 记忆是文本文件,天然可读、可版本化。
|
||
- 非常适合工程项目规则和团队约定。
|
||
- 注入通常按目录/项目作用域进行。
|
||
- 记忆更新更多依赖人工维护,而不是完全自动。
|
||
|
||
和我们的关系:
|
||
|
||
ZK Data Agent 继承了“文件化、可编辑、可解释”的优点,但把作用域进一步细分:
|
||
|
||
```text
|
||
user.md
|
||
用户级偏好和稳定习惯。
|
||
|
||
skills/<skill-name>.md
|
||
某个 Skill 的使用经验、踩坑、格式偏好和边界修正。
|
||
```
|
||
|
||
也就是说,我们不是只有“项目记忆”,而是增加了“Skill 记忆”这一层。
|
||
|
||
### 2.4 LangGraph:线程状态 + 长期 Memory Store
|
||
|
||
LangGraph 把 memory 分成 short-term memory 和 long-term memory。短期记忆通常跟 thread 绑定,用来维持一次会话;长期记忆通过 store 按 namespace 保存,可以跨 thread 召回。它还把长期记忆进一步拆成 semantic、episodic、procedural 等类型。
|
||
|
||
机制特点:
|
||
|
||
- thread state 解决会话内上下文。
|
||
- store 解决跨会话长期信息。
|
||
- 支持按 user id / namespace 组织记忆。
|
||
- 长期记忆可以由应用逻辑或 Agent 写入、搜索、更新。
|
||
|
||
和我们的关系:
|
||
|
||
ZK Data Agent 当前没有引入通用 Store / VectorStore,而是用文件系统和 SQLite 队列实现一个轻量版本:
|
||
|
||
```text
|
||
namespace = account_id + memory kind + skill_name
|
||
storage = Markdown files + SQLite queue
|
||
retrieval = user memory always considered, skill memory按启用 Skill 精准注入
|
||
```
|
||
|
||
这比 LangGraph Store 简单,但更直接服务我们当前的 Skill 工作台。
|
||
|
||
### 2.5 Mem0:独立记忆层
|
||
|
||
Mem0 更像一个独立 memory layer。典型链路是:从对话中抽取事实,存入记忆系统;后续根据 query 检索相关记忆,再注入给模型。它强调 add / search / update / delete 这类记忆 API,也支持面向用户、Agent、session 等维度组织。
|
||
|
||
机制特点:
|
||
|
||
- 记忆层和 Agent 框架解耦。
|
||
- 常见存储后端是向量、图或混合检索。
|
||
- 强调自动抽取、去重、更新和语义召回。
|
||
- 适合大规模个性化 Agent 或跨应用记忆服务。
|
||
|
||
和我们的关系:
|
||
|
||
ZK Data Agent 目前没有把记忆做成独立检索服务。原因是我们的高频需求不是“从海量事实里语义搜索”,而是“把少量稳定经验准确注入到对应 Skill”。如果未来 Skill 记忆膨胀,可以在 Markdown 之外增加 Mem0 类似的检索层。
|
||
|
||
### 2.6 Letta / MemGPT:Agent 自主管理内存
|
||
|
||
Letta 延续 MemGPT 思路,把 Agent 看成有长期状态的主体。它通常区分 core memory 和 archival memory:core memory 是短小、常驻上下文的重要信息;archival memory 是更大的外部记忆空间,Agent 可以通过工具读写。
|
||
|
||
机制特点:
|
||
|
||
- Agent 可以主动管理自己的记忆。
|
||
- core memory 常驻,archival memory 需要检索。
|
||
- 适合长期角色 Agent、个人助理、需要自我状态连续性的 Agent。
|
||
- 复杂度更高,需要更强的记忆写入约束和审计。
|
||
|
||
和我们的关系:
|
||
|
||
ZK Data Agent 没有让主 Agent 在执行链路里自由修改记忆。我们把记忆写入放到后台 worker,避免主任务因为记忆整理变慢或出错。这是一个更保守的团队平台取舍。
|
||
|
||
### 2.7 Zep / Graphiti:时间感知知识图谱记忆
|
||
|
||
Zep / Graphiti 代表的是 temporal knowledge graph 路线:从对话或事件中抽取实体和关系,形成带时间属性的知识图谱。它解决的问题不是简单偏好记忆,而是“事实如何随时间变化”“实体关系如何演进”。
|
||
|
||
机制特点:
|
||
|
||
- 记忆结构是实体、关系、事件、时间。
|
||
- 适合复杂事实网络和时间演化。
|
||
- 检索结果可以包含关系路径和上下文。
|
||
- 实现成本和运维复杂度高于 Markdown 或向量检索。
|
||
|
||
和我们的关系:
|
||
|
||
标签边界、业务规则、Skill 使用经验目前更适合文本化规则,不一定需要图谱。但如果未来要做“用户、Skill、数据集、标签、错误类型、修复策略”之间的关系分析,图谱路线会有价值。
|
||
|
||
### 2.8 CrewAI:多 Agent 任务记忆
|
||
|
||
CrewAI 的记忆体系主要服务多 Agent 协作,通常包含 short-term memory、long-term memory、entity memory 和 contextual memory。它关注的是任务过程中多个 Agent 如何共享上下文和持续改进。
|
||
|
||
机制特点:
|
||
|
||
- 和 Crew / Agent / Task 结构绑定。
|
||
- 强调任务协作过程中的上下文复用。
|
||
- 对实体、任务经验有独立组织方式。
|
||
|
||
和我们的关系:
|
||
|
||
ZK Data Agent 当前不是多 Agent 编排优先,而是单个工作台 Agent + Skill 能力包优先。Skill 记忆在某种程度上承担了“任务经验记忆”的角色。
|
||
|
||
### 2.9 AutoGen:Memory 组件注入上下文
|
||
|
||
AutoGen 的 AgentChat 提供 Memory 抽象,可以把 list memory、vector memory 等组件挂到 AssistantAgent 上。运行时 Memory 会根据消息更新上下文,或把检索结果添加到模型输入。
|
||
|
||
机制特点:
|
||
|
||
- Memory 是 Agent 可插拔组件。
|
||
- 可以使用简单列表,也可以接向量检索。
|
||
- 更偏框架扩展点,而不是产品级记忆管理 UI。
|
||
|
||
和我们的关系:
|
||
|
||
ZK Data Agent 的记忆也可以理解为一个可插拔上下文组件,但我们额外做了用户 UI、Skill 作用域和后台队列。
|
||
|
||
## 3. ZK Data Agent 当前实现
|
||
|
||
实现入口:
|
||
|
||
```text
|
||
src/personal_memory.py
|
||
backend/api/server.py
|
||
frontend/app/components/assistant-ui/threadlist-sidebar.tsx
|
||
```
|
||
|
||
### 3.1 存储结构
|
||
|
||
每个账号有独立记忆目录:
|
||
|
||
```text
|
||
.port_sessions/accounts/<account_id>/memory/
|
||
user.md
|
||
skills/
|
||
<skill-name>.md
|
||
memory.db
|
||
```
|
||
|
||
其中:
|
||
|
||
- `user.md`:用户级长期记忆。
|
||
- `skills/<skill>.md`:某个 Skill 的使用记忆。
|
||
- `memory.db`:事件队列、状态和 revision 账本。
|
||
|
||
### 3.2 注入逻辑
|
||
|
||
模型调用前,后端调用:
|
||
|
||
```text
|
||
memory_manager.render_injection(account_id, enabled_skill_names)
|
||
```
|
||
|
||
注入规则:
|
||
|
||
```text
|
||
用户记忆
|
||
账号级,作为长期偏好注入。
|
||
|
||
Skill 使用记忆
|
||
只读取当前启用 Skill 对应的 skills/<skill>.md。
|
||
|
||
冲突优先级
|
||
用户本轮明确要求 > 个性化记忆。
|
||
```
|
||
|
||
这避免了一个常见问题:所有记忆都无差别注入导致上下文污染。
|
||
|
||
### 3.3 生成时机
|
||
|
||
每次交互结束后,后端调用:
|
||
|
||
```text
|
||
memory_manager.enqueue_interaction(...)
|
||
```
|
||
|
||
系统不会每轮同步整理记忆,而是先检测信号:
|
||
|
||
```text
|
||
显式记忆词:
|
||
记住、以后、下次、默认、总是、不要、应该、固定
|
||
|
||
纠错词:
|
||
不对、不是这样、格式错、之前说过、还是不行
|
||
|
||
Skill 经验:
|
||
skill、工具、流程、格式
|
||
|
||
工具经验:
|
||
模型返回的工具参数不是合法 JSON
|
||
```
|
||
|
||
命中后写入 SQLite pending 队列。显式记忆优先级更高。
|
||
|
||
### 3.4 异步整理
|
||
|
||
后台 worker 每 5 秒扫描账号事件,每次最多处理 8 条 pending event:
|
||
|
||
```text
|
||
pending -> processing -> done / failed
|
||
```
|
||
|
||
整理方式:
|
||
|
||
1. 读取已有 `user.md` 和相关 `skills/<skill>.md`。
|
||
2. 把一批事件交给模型做“整理式合并”。
|
||
3. 模型必须输出 JSON:
|
||
|
||
```json
|
||
{
|
||
"user_memory": "完整 Markdown 或空字符串",
|
||
"skill_memories": {
|
||
"skill-name": "完整 Markdown"
|
||
}
|
||
}
|
||
```
|
||
|
||
4. 如果模型输出不可解析,则走 fallback 规则。
|
||
5. 写入 Markdown 文件,并更新 revision。
|
||
|
||
### 3.5 用户可编辑
|
||
|
||
前端左下角“记忆”入口支持:
|
||
|
||
- 查看用户记忆行数。
|
||
- 查看 Skill 记忆列表。
|
||
- 编辑用户记忆。
|
||
- 编辑某个 Skill 记忆。
|
||
- 查看记忆队列状态。
|
||
|
||
管理后台只看队列、用量等统计,不展示其他用户具体记忆内容。
|
||
|
||
## 4. 对比表
|
||
|
||
| 维度 | ChatGPT | Claude Code / OpenClaw | LangGraph / Mem0 / Zep | Letta | ZK Data Agent |
|
||
|------|---------|--------------------|-------------------------|-------|---------------|
|
||
| 主要目标 | 个人助手个性化 | 项目规则注入 | 长期检索记忆 | 状态型长期 Agent | 团队 Skill 工作台 |
|
||
| 记忆粒度 | 用户 | 用户/项目/目录 | 用户/线程/实体/namespace | Agent memory block | 用户 + Skill |
|
||
| 存储形态 | 平台内部 | Markdown 文件 | Store / 向量 / 图 | Core + archival memory | Markdown + SQLite queue |
|
||
| 生成时机 | 产品后台自动 | 多为人工维护 | 自动抽取 / API 写入 | Agent 主动管理 | 交互结束后异步整理 |
|
||
| 检索方式 | 平台决定 | 直接注入文件 | 语义搜索 / 图检索 | Core 常驻 + archival 检索 | 用户记忆 + 当前 Skill 记忆注入 |
|
||
| 可编辑性 | 用户可管理 | 文件可编辑 | 取决于产品/API | 通常需要工具/API | UI 可编辑 Markdown |
|
||
| 适合业务流程沉淀 | 中 | 中 | 高,但工程复杂 | 高,但复杂 | 高,且轻量 |
|
||
| 风险 | 黑盒、难按业务作用域隔离 | 容易依赖人工维护 | 检索和更新复杂 | 主链路复杂度高 | 暂无语义召回和图谱能力 |
|
||
|
||
## 5. 为什么当前方案适合我们
|
||
|
||
### 5.1 我们需要的是 Skill 使用经验,而不只是用户偏好
|
||
|
||
通用记忆多关注“用户是谁、用户喜欢什么”。我们的高频需求更像:
|
||
|
||
```text
|
||
product-data 生成数据时,用户偏好什么确认流程?
|
||
标签大师判断时,哪些边界经常被纠正?
|
||
online-mining-v2 查询线上日志时,哪些字段和表更稳定?
|
||
某个 Skill 写文件时,模型容易踩什么坑?
|
||
```
|
||
|
||
这些经验天然和 Skill 绑定。因此 `skills/<skill>.md` 比单一用户记忆更准确。
|
||
|
||
### 5.2 我们需要可审计、可编辑,而不是完全黑盒
|
||
|
||
团队平台里,记忆不能只存在模型或向量库内部。用户需要能看到:
|
||
|
||
- 记住了什么。
|
||
- 为什么下一次会注入。
|
||
- 哪里可以手动修改。
|
||
- 哪些记忆是用户级,哪些是 Skill 级。
|
||
|
||
Markdown 文件在这点上比纯向量库更直接。
|
||
|
||
### 5.3 主链路不能被记忆整理拖慢
|
||
|
||
数据生成、线上挖掘、标签判断本身就是长任务。记忆整理如果同步放在主链路里,会增加延迟和失败面。
|
||
|
||
当前设计是:
|
||
|
||
```text
|
||
主链路:只读取已有记忆 + 入队事件
|
||
后台:异步整理、合并、失败重试/记录
|
||
```
|
||
|
||
这和团队生产工具的稳定性要求更匹配。
|
||
|
||
### 5.4 Skill 作用域注入能降低上下文污染
|
||
|
||
如果所有记忆每次都注入,模型会被无关偏好干扰。当前只注入启用 Skill 的记忆:
|
||
|
||
```text
|
||
启用 product-data -> 注入 product-data 使用记忆
|
||
启用 label-master -> 注入 label-master 使用记忆
|
||
未启用某 Skill -> 不注入该 Skill 记忆
|
||
```
|
||
|
||
这使记忆更像“能力使用手册的增量补丁”,而不是一坨全局上下文。
|
||
|
||
## 6. 当前不足和后续方向
|
||
|
||
### 6.1 缺少语义召回
|
||
|
||
当前 Skill 记忆是按 Skill 文件整体注入,不做向量检索。如果某个 Skill 记忆变得很长,可能需要:
|
||
|
||
- 按章节拆分。
|
||
- 引入轻量 embedding 检索。
|
||
- 只注入和当前 query 相关的片段。
|
||
|
||
### 6.2 缺少结构化 schema
|
||
|
||
Markdown 易编辑,但不方便做强约束。后续可以让 Skill 记忆同时存在:
|
||
|
||
```text
|
||
human.md
|
||
structured.json
|
||
```
|
||
|
||
其中 Markdown 给人看,JSON 给程序做筛选和校验。
|
||
|
||
### 6.3 缺少记忆质量评估
|
||
|
||
目前能看到队列状态,但还没有系统评估:
|
||
|
||
- 哪些记忆被注入。
|
||
- 注入后是否减少纠错。
|
||
- 哪些记忆过期。
|
||
- 哪些 Skill 记忆导致误导。
|
||
|
||
后续可以把 memory revision 与 session outcome 关联起来。
|
||
|
||
### 6.4 缺少跨用户团队记忆
|
||
|
||
当前是账号级记忆。团队共性经验仍主要沉淀在 Skill 本体里。未来可以区分:
|
||
|
||
```text
|
||
个人 Skill 记忆
|
||
某个用户自己的偏好和使用习惯。
|
||
|
||
团队 Skill 记忆
|
||
多人使用后沉淀的稳定经验,经 review 后合入 Skill。
|
||
```
|
||
|
||
这样可以形成从“个人经验”到“团队 Skill 知识”的晋升路径。
|
||
|
||
## 7. 建议的技术路线
|
||
|
||
短期保持当前架构:
|
||
|
||
```text
|
||
Markdown 可编辑记忆
|
||
SQLite 异步队列
|
||
按 Skill 注入
|
||
UI 可查看可修改
|
||
后台可观测队列
|
||
```
|
||
|
||
中期增强:
|
||
|
||
```text
|
||
记忆片段化
|
||
记忆注入日志
|
||
过期/冲突检测
|
||
记忆质量指标
|
||
```
|
||
|
||
长期可选:
|
||
|
||
```text
|
||
向量检索:解决 Skill 记忆膨胀后的相关片段召回。
|
||
图谱记忆:解决用户、Skill、标签、数据集、错误类型之间的关系分析。
|
||
团队记忆晋升:把多用户共性 Skill 经验 review 后写回 Git Skill。
|
||
```
|
||
|
||
## 8. 资料来源
|
||
|
||
- OpenAI Help:ChatGPT Memory FAQ
|
||
https://help.openai.com/en/articles/8590148-memory-faq
|
||
- OpenAI Agents SDK:Sessions
|
||
https://openai.github.io/openai-agents-python/sessions/
|
||
- Anthropic Claude Code:Memory
|
||
https://docs.anthropic.com/en/docs/claude-code/memory
|
||
- LangChain / LangGraph:Memory concepts
|
||
https://docs.langchain.com/oss/python/concepts/memory
|
||
- Mem0 documentation
|
||
https://docs.mem0.ai/
|
||
- Letta documentation
|
||
https://docs.letta.com/
|
||
- Zep / Graphiti documentation
|
||
https://help.getzep.com/
|
||
- CrewAI Memory concepts
|
||
https://docs.crewai.com/concepts/memory
|
||
- Microsoft AutoGen AgentChat Memory
|
||
https://microsoft.github.io/autogen/dev/user-guide/agentchat-user-guide/memory.html
|
||
- ZK Data Agent 当前实现
|
||
`src/personal_memory.py`、`docs/technical-architecture/05-workspace-memory-observability.md`
|