06-Mem0 的程序性记忆实现
Mem0 的程序性记忆实现
学习目标
本章分析 Mem0 如何通过 LLM 摘要 Agent 执行历史,构建结构化的程序性记忆。你将了解:
_create_procedural_memory()的触发条件与实现PROCEDURAL_MEMORY_SYSTEM_PROMPT的摘要格式设计- 程序性记忆与普通记忆在存储和检索上的差异
- 程序性记忆在 Agent 恢复上下文场景中的实际应用
前置知识
本章涉及程序性记忆的通用原理,建议先阅读:
下文假设你已理解程序性记忆的基本概念,直接聚焦 Mem0 的具体实现。
项目实践
触发条件
程序性记忆在 Memory.add() 方法中被触发:
# 伪代码if agent_id is not None and memory_type == MemoryType.PROCEDURAL.value: results = self._create_procedural_memory(messages, metadata=processed_metadata)触发条件:
agent_id存在(Agent 场景)memory_type设置为"procedural_memory"
MemoryType 枚举定义了三种类型:
class MemoryType(Enum): SEMANTIC = "semantic_memory" # 语义记忆 EPISODIC = "episodic_memory" # 情景记忆 PROCEDURAL = "procedural_memory" # 程序性记忆摘要流程
_create_procedural_memory() 的实现:
# 伪代码parsed_messages = [ {"role": "system", "content": prompt or PROCEDURAL_MEMORY_SYSTEM_PROMPT}, *messages, # Agent 的执行历史消息 {"role": "user", "content": "Create procedural memory of the above conversation."},]
procedural_memory = self.llm.generate_response(messages=parsed_messages)memory_id = self._create_memory(procedural_memory, {...}, metadata=metadata)流程简洁:
- 将 Agent 执行历史 + 摘要提示词组合为对话
- LLM 生成结构化摘要
- 将摘要作为普通记忆存储(标记
memory_type: "procedural_memory")
摘要提示词设计
PROCEDURAL_MEMORY_SYSTEM_PROMPT 定义了严格的摘要格式:
## Summary of the agent's execution history
**Task Objective**: <总体目标>**Progress Status**: <完成百分比和里程碑>
1. **Agent Action**: <精确描述做了什么> **Action Result**: <原文输出,不改写> **Key Findings**: <关键发现> **Navigation History**: <访问页面历史> **Current Context**: <操作后状态>关键约束:
- 每个步骤的 Action Result 必须原文保留(HTML 片段、JSON 响应、错误消息)
- 步骤按执行顺序编号
- 包含错误信息(完整错误消息和堆栈跟踪)
- 输出只有摘要,不包含额外评论
存储差异
程序性记忆在存储时与普通记忆的区别仅在元数据中:
metadata = {**metadata, "memory_type": MemoryType.PROCEDURAL.value}检索时可通过 memory_type 字段过滤:
m.search("Agent 做了什么", filters={"user_id": "alice", "memory_type": "procedural_memory"})问题与规避
| 问题 | 对策 |
|---|---|
| LLM 摘要时丢失关键输出原文 | 提示词中反复强调”Preserve Every Output” |
| 错误信息被截断 | 要求包含完整错误消息和堆栈跟踪 |
| 摘要过长超出上下文窗口 | 对过长的动作结果进行适度截断 |
| 程序性记忆与普通记忆混淆 | memory_type 元数据区分,可单独过滤 |
设计取舍
为什么程序性记忆独立存储而非附加到普通记忆?
优势:
- 可单独过滤和检索:Agent 恢复上下文时只加载程序性记忆
- 存储格式不同:程序性记忆是长文本摘要,普通记忆是简短事实
- 生命周期不同:程序性记忆随任务结束而固化,普通记忆持续更新
代价:
- 需要额外的
memory_type参数控制 - 普通用户可能不理解程序性记忆的概念
为什么摘要格式是纯文本而非 JSON?
程序性记忆的摘要是自然语言文本(而非结构化 JSON),原因是:
- 摘要需要保留 Agent 输出的原文(HTML、JSON、错误消息),嵌入在文本中更自然
- 检索时通过向量相似度匹配,文本格式更适合
- 结构化的步骤编号和元数据标题提供足够的可解析性
参考来源
- Mem0 论文:arXiv:2504.19413
- Mem0 源码:
mem0/memory/main.py、mem0/configs/prompts.py