跳转到内容

02-Mem0 的 LLM 对话记忆提取提示词设计

Mem0 的 LLM 对话记忆提取提示词设计

学习目标

本章分析 Mem0 如何将精心设计的 LLM 提示词作为记忆提取的”大脑”。你将了解:

  • ADDITIVE_EXTRACTION_PROMPT 的结构与设计原则
  • 提示词如何防止”First Topic Dominance”等提取陷阱
  • 时间锚定、数值精确、禁止泛化等质量约束的实现方式
  • 12 个 Few-Shot 示例各自解决的问题

前置知识

本章涉及 LLM 结构化提取的通用原理,建议先阅读:

下文假设你已理解 LLM 提取的基本概念,直接聚焦 Mem0 的提示词设计细节。

项目实践

提示词的层次结构

ADDITIVE_EXTRACTION_PROMPT 位于 mem0/configs/prompts.py,约 900+ 行,分为以下层次:

区块行数约内容
ROLE30角色定义、提取范围(用户+助手消息)
INPUTS806 种输入类型的定义(新消息、摘要、已有记忆等)
GUIDELINES - 提取范围120从用户/助手消息中提取什么的详细规则
GUIDELINES - 质量标准200上下文丰富、时间锚定、数值精确、禁止泛化等
GUIDELINES - 完整性规则100禁止捏造、禁止隐式推断、禁止回显提取等
GUIDELINES - 记忆链接30linked_memory_ids 的链接条件
EXAMPLES35012 个 Few-Shot 示例
CHECKLIST30输出前的完整性检查清单
OUTPUT FORMAT30输出 JSON 格式定义

关键设计原则

1. 角色定义:“Memory Extractor”

# ROLE
You are a Memory Extractor — a precise, evidence-bound processor
responsible for extracting rich, contextual memories from conversations.
Your sole operation is ADD.

“Memory Extractor” 定位明确:不是对话助手,不是总结器,是精确的证据绑定处理器。“Sole operation is ADD” 强调只做添加,不做更新/删除。

2. 提取范围:从两种角色提取

- User messages: Personal facts, preferences, plans, experiences
- Assistant messages: Specific recommendations, plans created,
information researched, solutions provided

Mem0 明确允许从助手消息中提取信息——这与传统”只从用户消息提取”不同。助手提供的推荐、创建的方案、研究的信息同样值得记忆。

但有限制条件:

  • 不回显:助手重复用户已说的话,不提取
  • 不提取元评论:助手对自己能力的描述,不提取

3. 禁止泛化:具体细节必须保留

这是提示词中最强调的规则之一:

"promoted to assistant manager" → KEEP "assistant manager", NOT "manager"
"drove a Ferrari 488 GTB" → KEEP "Ferrari 488 GTB", NOT "sports car"
"scored 3 goals in the semifinal" → KEEP "3 goals in the semifinal", NOT "several goals"

Mem0 认为”用模糊类别替代具体细节”是最严重的提取错误——因为具体细节正是用户搜索时用的关键词。

4. 时间锚定:Observation Date vs Current Date

Observation Date: 2022-01-16 # 对话实际发生的日期
Current Date: 2026-02-18 # 今天的系统日期
"recently" → 基于 Observation Date 解析为 "early January 2022"
NOT "early February 2026"

这是一个微妙但关键的设计:如果用户在 2022 年说”我最近读了 X”,而系统在 2026 年检索,“recently” 必须解析为 2022 年 1 月,而非 2026 年 2 月。

5. “First Topic Dominance” 防护

# CRITICAL: Exhaustive Extraction Checklist
1. Have you extracted at least one memory from EVERY distinct topic?
2. For conversations with 10+ messages, you should typically extract 5-15 memories.
If you have fewer than 3, re-read the conversation.
3. Re-read each user message individually.

在输出前强制 LLM 做完整性检查:每个话题是否都提取了?10+ 条消息的对话如果只提取了 2-3 条记忆,几乎肯定遗漏了信息。

12 个 Few-Shot 示例解决的问题

示例解决的问题
1. 多话题提取一条消息包含 3 个话题(职业、餐厅、怀孕),分别提取
2. 助手推荐提取从助手回复中提取推荐内容
3. 空结果纯问候对话,无信息可提取
5. 去重用户重复说同一件事,跳过
6. 多维度提取职业 + 娱乐偏好 + 学习资源,分别提取
7. 历史 Observation Date”recently” 基于历史日期解析
8. 文档内容提取用户分享案例,提取内容而非”用户分享了文档”
9. 结构化数据D&D 怪物属性,保留所有数值
10. 记忆链接新记忆关联已有记忆 UUID
11. 长对话多话题5 条消息 5 个话题,每个都提取
12. 多说话者从”assistant”角色中提取真实人名分享的事实

动态提示词构建器

generate_additive_extraction_prompt() 函数将静态模板与动态输入组合:

# 伪代码
prompt = "\n\n".join([
f"## Summary\n{_format_summary(summary)}",
f"## Last k Messages\n{_format_conversation_history(last_k_messages)}",
f"## Recently Extracted Memories\n{_serialize_memories(recently_extracted)}",
f"## Existing Memories\n{_serialize_memories(existing_memories)}",
f"## New Messages\n{_format_new_messages(new_messages)}",
f"## Observation Date\n{observation_date}",
f"## Current Date\n{current_date}",
f"## Custom Instructions\n{custom_instructions}", # 可选
"# Output:",
])

过去消息内容超过 300 字符时自动截断(PAST_MESSAGE_TRUNCATION_LIMIT = 300),防止 prompt 过长。

问题与规避

问题对策
提示词过长消耗大量 Token对历史消息做 300 字符截断;Existing Memories 只传 top-10
LLM 忽略”禁止泛化”指令Few-Shot 示例中反复强调具体→泛化的错误案例
LLM 回显提取提示词中明确”No Echo Extraction”规则 + Few-Shot 示例
输出 JSON 格式错误response_format={"type": "json_object"} + 代码块解析回退

设计取舍

为什么提示词 900+ 行而非精简?

优势

  • 12 个 Few-Shot 示例覆盖了几乎所有常见提取场景
  • 完整性检查清单显著降低”first topic dominance”问题
  • Mem0 基准测试提升(LoCoMo +20 分)证明效果显著

代价

  • 提示词本身消耗大量 Token
  • 每次 add() 调用都携带完整提示词,成本较高
  • 提示词修改需要重新验证所有 Few-Shot 示例

替代方案:小型提取模型

可以使用微调的小型模型(如 BERT-based NER)替代 LLM 提取。Mem0 选择了 LLM 方案,原因是:

  • 提取规则灵活变化,微调模型难以快速适应
  • LLM 理解上下文和歧义的能力远超 NER 模型
  • 提示词可迭代,模型需要重新训练

参考来源

  • Mem0 论文:arXiv:2504.19413
  • Mem0 提示词源码:mem0/configs/prompts.py