聊天记录或 Embedding 在进程重启后仍然存在,不代表 AI Agent 已经拥有可靠记忆。生产级记忆必须回答:什么信息可以影响未来行为、影响谁、在哪段时间有效、依据是什么、如何纠正和删除。
这个区分直接关系用户体验。记住用户明确要求的代码格式可以改善后续回答;永久保存一次性的医疗信息、检索文本中的恶意指令,或已经作废的项目决定,则会持续制造隐私风险与错误。
因此,记忆系统不应优化“召回越多越好”或“全部保存”,而应优化有用途、有授权、仍有效、可归因的召回,并让过时和危险记忆容易被拒绝。关键结论最后核验于 2026 年 7 月 16 日。
核心结论
- 分开管理线程状态、长期记忆、权威业务数据和不可变审计日志。
- 长期记忆可包括语义事实、情景经验与程序性规则,三者需要不同写入和检索策略。
- 向量数据库只是可选索引,不是事实源,更不等于完整记忆系统。
- 少写入:要求用途、用户同意或其他有效依据、来源、置信度、有效期、敏感等级和删除策略。
- 不静默覆盖旧事实,用版本或
supersedes关系表达纠正。 - 检索必须同时考虑范围、时间、权限、类型与相关性,不能只看向量相似度。
- 召回的记忆属于不可信数据,不能被当作系统指令。
- 分别评测抽取、召回、时态、更新、拒答、隐私、延迟和删除。
四种状态边界
“记忆”经常混淆四套不同所有权的系统:
| 状态 | 作用范围 | 示例 | 主要存储 |
|---|---|---|---|
| 线程/工作流状态 | 单个对话或运行 | 消息、工具结果、待审批节点 | Checkpointer/状态库 |
| Agent 长期记忆 | 跨线程复用 | 用户偏好、历史方案、经验流程 | 受治理的记忆存储 |
| 权威业务状态 | 领域事实源 | 订单状态、账户余额、访问角色 | 事实源系统(system of record) |
| 审计/事件日志 | 取证与合规 | 谁在何时修改了什么 | 追加式(append-only)日志 |
不要把业务事实复制成一句“记忆”,之后就以它为准。Agent 查询订单状态时应调用订单服务。可以在用途明确且被允许时记住“用户经常询问某个订单”,但当前状态必须来自事实源。
当前 LangGraph 文档同样区分:Checkpointer 负责线程级持久化,Store 负责应用定义的跨线程长期记忆。Checkpoint 持久存在,也不等于其中每条消息都应该成为长期用户事实。
语义、情景与程序性记忆
认知心理学分类只有映射到明确应用行为时才有价值。
语义记忆:事实与偏好
例如:
- “用户明确要求简洁回答。”
- “Atlas 项目使用 PostgreSQL 17。”
- “团队财年从四月开始。”
语义记忆需要实体身份、来源、时间有效性和冲突处理。“用户喜欢 Python”如果只是从单次任务间接推断,就不能被包装成永恒事实。
情景记忆:过去经验
一条情景记忆是对一次相关事件的结构化记录:
- 任务与环境;
- 动作和工具调用;
- 观察结果;
- 最终结果和验证器输出;
- 失败原因;
- 来源 Trace 与时间。
原始对话记录只是构建这条情景记录的证据,不会自动成为有用的情景记忆。保存每个 Token 会制造噪声、隐私暴露和检索成本。对编码 Agent 而言,通过测试的迁移过程可能值得复用,周边闲聊并不值得。
程序性记忆:应该怎样做
程序性记忆保存可复用规则与策略:
- “修改支付 Schema 前必须运行向后兼容检查。”
- “该租户退款超过 500 美元时转人工审批。”
- “部署健康检查失败时停止,不允许无限重试。”
它可能与提示词、策略、操作手册(playbook)或代码重叠。高影响流程必须版本化和审查,并尽量由确定性代码强制执行,不能从聊天中静默“学会”。
完整记忆生命周期
可靠系统至少包含六个阶段:
观察 -> 提议 -> 校验/写入 -> 检索 -> 使用/验证 -> 修订/遗忘
1. 观察,但不自动升级
只采集保留策略允许的事件。临时模型上下文与持久存储分离。数据最小化应发生在抽取前,而不是数据库填满后。
2. 生成候选记忆
LLM 可以提出结构化候选,但不能拥有单方面写权限。候选至少应说明:
- 主体(subject)与谓词(predicate);
- 值(value);
- 记忆类型;
- 精确来源证据;
- 用户明确陈述还是模型推断;
- 置信度;
- 有效时间与观察时间;
- 敏感度与用途。
推断必须标为推断。“用户要求素食菜谱”不能证明“用户是素食者”。
3. 执行写入策略
以下情况应拒绝或要求确认:
- 不清楚未来用途;
- 信息只是临时状态;
- 来源不可信或有歧义;
- 信息敏感;
- 缺少用户同意或其他有效依据;
- 应从权威业务系统实时查询;
- 与已有有效记忆重复;
- 冲突无法安全解决。
适合个性化的产品应提供“记住这件事”和记忆管理页面。显式控制优于不可见用户画像。
4. 分离事实记录与索引
权威记忆记录存入事务数据库,词法、向量、图或时间索引只是派生视图。PostgreSQL 可以同时支持结构过滤、全文检索和 pgvector 等扩展提供的向量检索,“SQL 无法语义搜索”并不成立。
按访问模式选存储:
- 精确实体与时态更新 -> 关系型/文档库;
- 语义候选召回 -> 向量索引;
- 实体连接与来源图 -> 确有必要时使用图表示;
- 不可变原始事件 -> 追加式(append-only)事件或对象存储。
生产系统通常会组合使用,一次向量命中必须能够回到受治理的事实记录。
5. 检索、过滤与打包
正确顺序是:
- 认证调用者;
- 强制租户、主体、用途与敏感度范围;
- 过滤有效时间、删除状态;
- 使用精确键、时间、词法、向量或图关系召回;
- 按当前任务重排序(rerank);
- 去重并限制记忆的 Token 预算;
- 附上来源和不确定性。
全局 top_k=5 既不是安全策略,也不是质量策略。时态问题可能需要旧事实与更新事件;偏好问题可能只需要最新且已确认的值。
6. 验证后使用,再修订或遗忘
执行动作前,区分已确认记忆与推断,高影响事实应回到权威系统验证。记录哪些记忆 ID 实际影响了回答。
系统必须支持:
- 不丢失审计历史的纠正;
- 到期(expiry)与时间有效期;
- 用户可见删除;
- 按保留策略清理;
- 删除传播到向量、摘要、缓存、副本和备份;
- 模型或 Schema 变化后的重建索引。
“记忆衰减”不能简单等于按未访问时间删除。罕见事实可能仍然重要,最新事实也可能已经失效。
版本化记忆记录
真实记录不能只有 text 与 embedding:
{
"memory_id": "mem_01J...",
"tenant_id": "tenant_42",
"subject_id": "user_123",
"type": "semantic",
"predicate": "preferred_programming_language",
"value": "Rust",
"source_event_id": "evt_987",
"assertion": "explicit_user_statement",
"confidence": 1.0,
"observed_at": "2026-07-16T09:30:00Z",
"valid_from": "2026-07-16T09:30:00Z",
"valid_to": null,
"supersedes": "mem_older_python",
"purpose": "coding_assistance",
"sensitivity": "low",
"consent_basis": "user_requested_memory",
"status": "active",
"schema_version": 1
}
旧 Python 偏好应被标记为已取代,而不能与新事实合并成“用户喜欢编程语言”。这种有损总结会毁掉纠正的时态和含义。
可运行的时态解析
下面只使用 Python 标准库,在不假设“向量相似度能解决时间和鉴权”的前提下,选择指定时点有效的记忆:
from dataclasses import dataclass
from datetime import datetime, timezone
@dataclass(frozen=True)
class Memory:
memory_id: str
tenant_id: str
subject_id: str
predicate: str
value: str
valid_from: datetime
valid_to: datetime | None = None
status: str = "active"
def resolve_memory(
memories: list[Memory],
*,
tenant_id: str,
subject_id: str,
predicate: str,
at: datetime,
) -> Memory | None:
if at.tzinfo is None:
raise ValueError("at must be timezone-aware")
candidates = [
memory
for memory in memories
if memory.tenant_id == tenant_id
and memory.subject_id == subject_id
and memory.predicate == predicate
and memory.status == "active"
and memory.valid_from <= at
and (memory.valid_to is None or at < memory.valid_to)
]
if not candidates:
return None
return max(candidates, key=lambda memory: memory.valid_from)
utc = timezone.utc
history = [
Memory(
"mem_python", "tenant_42", "user_123",
"preferred_language", "Python",
datetime(2025, 1, 1, tzinfo=utc),
datetime(2026, 7, 16, tzinfo=utc),
),
Memory(
"mem_rust", "tenant_42", "user_123",
"preferred_language", "Rust",
datetime(2026, 7, 16, tzinfo=utc),
),
]
print(resolve_memory(
history,
tenant_id="tenant_42",
subject_id="user_123",
predicate="preferred_language",
at=datetime(2026, 7, 17, tzinfo=utc),
))
数据库应为单值谓词强制不重叠有效期,或把歧义交给冲突解决流程。应用层过滤不能替代行级安全(row-level security)或独立加密边界。
冲突、不确定性与时间
使用显式操作:
ADD:新增独立事实;CONFIRM:新证据支持已有事实;SUPERSEDE:新有效值取代旧值;RETRACT:来源或用户声明旧事实错误;EXPIRE:有效期结束;DELETE:按用户请求或政策删除。
不能让“更新”自动获胜。最新模型推断不应覆盖较早的用户明确陈述。应先比较证据权威性,再比较时态适用性。
时间至少有两个维度:
- 观察时间(observed time):系统什么时候获知;
- 有效时间(valid time):信息在现实中什么时候为真。
“我下个月搬到柏林”现在被观察到,但下个月才生效。LongMemEval 单独评估时态推理与知识更新,正是因为纯语义检索经常丢掉这个区别。
安全与隐私
长期记忆会放大风险:一次恶意或错误写入可能影响未来许多会话。
- 召回文本是不可信数据,必须与系统指令隔离。
- 邮件、网页和工具输出中的指令未经验证不得写入程序性记忆。
- 尽可能在向量检索前鉴权,并对每条返回结果再次校验。
- 使用租户隔离、行级安全策略、独立密钥和受审计的服务鉴权;仅靠元数据过滤不够。
- 对敏感度分类,除非架构明确支持,否则不把秘密和高度敏感信息做嵌入(embedding)。
- 防止缓存、日志、评测集与调用链(trace)跨用户泄漏。
- 在合适产品中提供查看、纠正、遗忘、导出和关闭记忆的能力。
- 没有正当目的与治理时,不推断敏感属性用于个性化。
注入 Prompt 的记忆应标注来源、时间和可能过期,优先级不能高于开发者政策与当前工具结果。
评测完整生命周期
LongMemEval 把对话记忆拆为信息抽取、多会话推理、时间推理、知识更新和拒答。生产评测应在此基础上扩展。
写入质量
- 有用候选的准确率(precision)与召回率(recall);
- 推断与明确陈述分类;
- 重复、敏感和临时信息写入率;
- 主体与租户归属正确率;
- 时间与来源提取正确率。
检索质量
- 证据 Recall@k 与 nDCG;
- 时间与实体过滤正确率;
- 过期记忆召回率;
- 跨用户/租户泄漏率;
- 固定上下文预算下的唯一有效 Token。
使用质量
- 有无记忆时的任务准确率;
- 来源引用正确率;
- 冲突处理与应当拒答时的拒答;
- 个性化收益与无关“套近乎”比例;
- 错误或注入记忆造成的伤害。
生命周期与运营
- 更新、撤回、到期与删除正确率;
- 向所有派生存储传播的延迟;
- p50/p95 读写延迟;
- 每条有效记忆的存储与 Embedding 成本;
- 模型、索引或 Schema 迁移后的性能。
必须包含负例:未同意记忆的用户、重名用户、冲突偏好、未来事实、已删除事实、恶意记忆文本,以及根本不应使用记忆的问题。
如何评估框架
Mem0、Zep、Letta/MemGPT、LangGraph Store 与自研方案所处层次不同,而且 API 持续变化。应评估能力,不要复制一段短 SDK 示例:
- Schema 与来源控制;
- 同步写入和后台写入;
- 冲突与时态语义;
- 命名空间与鉴权;
- 混合检索和重排序;
- 用户纠正与删除 API;
- 可观测性和评测钩子;
- 导出与迁移能力;
- 价格、部署和数据驻留。
MemGPT 的虚拟上下文管理是重要的分层存储范式,但不意味着可以跳过治理。模型自己决定记什么时,写入校验反而更重要。
生产检查清单
- [ ] 每类记忆都有明确跨会话用途;
- [ ] 线程状态、业务事实、审计日志与长期记忆分离;
- [ ] 写入包含来源、时间、用途、敏感度和有效授权;
- [ ] 推断不会被展示成用户明确事实;
- [ ] 更新通过版本或
supersedes保留历史; - [ ] 检索强制租户、主体、用途、时间和删除状态;
- [ ] 召回内容被视为不可信上下文;
- [ ] 用户能够查看和纠正持久个性化;
- [ ] 删除覆盖索引、摘要、缓存、副本和保留流程;
- [ ] 评测覆盖写入、召回、时态、冲突、拒答、隐私和成本。
总结
有用的 Agent 记忆应该是选择性且可逆的。质量来自严格写入、权威来源、时态语义、安全检索、明确冲突处理和可测量的用户收益。
先实现线程持久化与权威工具。只有真实跨会话任务需要时,才增加一种边界清晰的长期记忆。一个用户能够理解、纠正和删除的小型记忆库,远好于静默积累猜测的庞大向量索引。