为什么要谈 Agent 记忆
一个只会单轮回答的 LLM 不配叫 Agent。真正能跑长任务、能跨会话保留上下文、能学习用户偏好的 Agent,都绕不开一个核心组件:记忆层。过去一年我们给多个企业客户落地 Agent,踩到的最多的坑不是模型不够强,而是记忆设计错了——要么全塞进 context 导致上下文爆炸,要么无差别用向量检索把精确数据做糊了。
本文把我们沉淀下来的选型框架写出来,供参考。
三种记忆分类
参考认知科学领域的共识,Agent 记忆可以大致分为三类:
Episodic Memory(情景记忆)
用户与 Agent 的具体交互片段。例如"三周前用户问过 Q3 的财报"、"上次会话里用户表达了对 A 方案的偏好"。这类记忆有明确的时间戳、有主体、有事件,适合用事件日志 + 向量检索召回。
Semantic Memory(语义记忆)
从多次交互中抽象出来的稳定知识。例如"用户是一名电力行业的安全管理员"、"公司的报销上限是 500 元"。语义记忆需要去重、合并、偶尔修订,适合用 KV 或图结构管理。
Procedural Memory(程序性记忆)
Agent 自己学会的流程、工具用法、prompt 模板。例如"遇到这类问题先查知识库再调工具"。程序性记忆最容易被忽视,但它决定了 Agent 能不能在运行中自我优化。通常以 prompt 片段或 workflow 配置的形式持久化。
开源实现对比
| 方案 | Episodic | Semantic | Procedural | 自部署难度 | |------|----------|----------|------------|------------| | Mem0 | 向量 + LLM 抽取 | 有合并逻辑 | 弱 | 低 | | Zep | 内建 temporal graph | 内建 | 弱 | 中 | | LangGraph checkpoint | 完整轨迹 | 需自己建 | 强(通过 state) | 低 | | 自研(PG + pgvector) | 自由度最高 | 自由度最高 | 自由度最高 | 高 |
Mem0 的 LLM 抽取适合通用聊天,但企业场景下会遇到"抽得太激进、把业务关键信息改写"的问题。Zep 的 temporal graph 在需要追溯"某个事实是什么时候进入/被修改的"场景下非常强,适合合规要求高的行业。LangGraph checkpoint 本质上是 state 快照,适合编排明确的 workflow,不适合自由聊天。自研方案适合业务语义复杂、审计要求高的场景,但工程投入不小。
YGG 实践建议
- 先分层再选库:把你的业务场景按上述三种记忆拆开,不要用一个"万能向量库"覆盖所有类型。我们在富光项目里最后是 PG 存结构化事实 + Milvus 存历史对话嵌入 + 配置中心存 procedural prompt,三层独立。
- 记忆一定要可观测:任何一次记忆写入、召回、覆盖都要有日志和 trace。调试一个"Agent 记错了用户偏好"的 bug 如果没有 trace,基本只能靠运气。
- 记忆可以是 draft 的:新抽取出来的语义记忆先进 staging,达到一定置信度或得到用户确认后再 promote 到正式层。避免 Agent 把错误信息写死在记忆里。
代码示例:一个最小的分层记忆写入
def write_memory(event, user_id, store):
# 1. 永远先写 episodic(append-only)
store.episodic.append(user_id, event)
# 2. 用 LLM 抽 candidate semantic facts
facts = extract_facts(event.text)
for f in facts:
# 3. 写到 staging,不直接改主库
store.semantic_staging.upsert(user_id, f)
# 4. 异步 job 再从 staging 合并到正式层
# 带冲突检测、保留历史版本
return
注意关键点:主链路永远只写 episodic,semantic 从不同步写。这个约束能帮你在 Agent 误抽取时快速回滚。
延伸阅读
- Mem0 论文 Scalable Long-Term Memory for Production AI Agents (2025)
- Zep 博客 Temporal Knowledge Graphs for Agents
- LangGraph 文档的 Persistence 章节,理解 checkpoint 与 memory 的边界