Files
zk-data-agent/docs/technical-architecture/10-memory-research.md
T
2026-05-20 15:53:06 +08:00

479 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 / MemGPTAgent 自主管理内存
Letta 延续 MemGPT 思路,把 Agent 看成有长期状态的主体。它通常区分 core memory 和 archival memorycore 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 AutoGenMemory 组件注入上下文
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 HelpChatGPT Memory FAQ
https://help.openai.com/en/articles/8590148-memory-faq
- OpenAI Agents SDKSessions
https://openai.github.io/openai-agents-python/sessions/
- Anthropic Claude CodeMemory
https://docs.anthropic.com/en/docs/claude-code/memory
- LangChain / LangGraphMemory 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`