AI Agent 长期记忆设计指南(存储架构与检索方案全拆解)

把会话窗口当记忆用是 Agent 一个常见的设计误区——上下文窗口是有限、昂贵、不可扩展的。长期记忆必须落到外部存储里,常见做法是”向量库 + 知识图谱 + 事件日志”三层架构,配合 RAG(Retrieval-Augmented Generation)按需召回。在企业客服 Agent 上线第一周就翻车后,我把记忆层从”塞上下文”改成”外部持久化 + 智能检索”,跨会话用户偏好命中率显著提升。下面把记忆分层、存储选型、检索策略拆开讲清。

一、为什么上下文窗口撑不起长期记忆

很多人第一版 Agent 会把历史对话”全塞进 prompt”——遇到核心用户用了 3 个月,prompt 长度轻松突破 10 万 token。这条路有三个硬伤:

  • 成本:每轮推理按 token 计费,10 万 token 的 prompt 调用一次主流大模型,费用是几百 token 的几十倍。
  • 延迟:长 prompt 拉长 prefill 阶段,首 token 延迟从毫秒级跳到秒级。
  • 衰减:上下文超长后模型会出现”迷失中段”问题,关键事实被淹没在噪声中。

Mem0 在 LOCOMO 基准上的公开数据:使用托管长期记忆模块的 Agent,回复准确率比”context-stuffing”提升 26%,token 消耗下降超过 90%。这组数据不是营销话术——它精确刻画了”长期记忆外置”对成本与质量的双重收益。

二、长期记忆的分层架构

成熟的 Agent 长期记忆通常分四层,每层解决不同问题:

  1. 工作记忆(Working Memory):当前会话的上下文,由上下文窗口承担。会话结束即释放。
  2. 情景记忆(Episodic Memory):历史事件和操作记录,按时间序列存储。回答”上周用户问了什么”这类问题靠它。
  3. 语义记忆(Semantic Memory):抽象出的事实、概念、用户偏好,以知识库或结构化文档形式存在。
  4. 程序记忆(Procedural Memory):可复用的执行模式,例如”对技术用户用代码示例,对非技术用户用类比”。

四层不是非此即彼,生产系统通常四层都用。MemGPT、LangGraph、Letta 等框架已经在工程上把这四层做成了”分层记忆栈”。

三、存储选型:向量库、知识图谱、事件日志

不同类型的记忆需要不同的存储。下面是各层对应的存储选型与典型产品。

3.1 向量库(语义记忆主力)

向量库存储高维 embedding,支持相似度检索。主流选项分两类:

  • 托管型:Pinecone。企业级 SLA,免运维,按存储和 QPS 计费。
  • 开源型:Weaviate(混合检索强)、Milvus(大规模场景)、Chroma(轻量、本地友好)、Qdrant(Rust 写、延迟稳)、FAISS(Meta 出,库而非服务)。

选型核心考量是规模与运维能力。10 万级向量、本地开发用 Chroma/FAISS 够用;千万级以上、跨区域高可用,Pinecone 或 Milvus 更稳。

3.2 知识图谱(结构化推理)

向量相似检索搞不定多跳推理(”用户工作的城市附近有哪些餐厅”),这种关系查询必须靠图:

  • Neo4j:老牌成熟图数据库,Cypher 查询语言生态完整。
  • Memgraph:高性能、兼容 Cypher,适合实时分析。
  • Graphiti / Zep:专门为时序知识图谱设计,记录实体关系随时间的演变。
  • GraphRAG:Microsoft 出,把图谱检索融入 RAG 流程。

知识图谱的强项是”实体-关系-时间”三元组的精确查询;弱项是写入慢、构建成本高。常见组合是:向量库放原始记忆、知识图谱放结构化洞察。

3.3 事件日志(审计与回放)

事件日志负责”不可篡改的真相源”。LangGraph checkpoint、PostgreSQL + Kafka、EventStoreDB 都能做。事件日志的用途不是检索,是审计、调试和回放——一旦 Agent 出问题,可以从日志中精确还原某一步的状态。

记忆层 存储类型 典型产品 检索方式
语义记忆 向量库 Pinecone / Milvus / Chroma Embedding 相似度
结构化关系 知识图谱 Neo4j / Zep / Graphiti Cypher / 图查询
时序事件 事件日志 Kafka + PostgreSQL / LangGraph checkpoint 时间窗口 + 字段过滤
会话级 关系数据库 PostgreSQL 主键查询

四、检索策略:把记忆喂回 Prompt

存好之后,怎么取回是核心问题。

4.1 RAG 三步走

  1. 查询向量化:用户 query 用同一 embedding 模型转成向量。
  2. 向量检索:在向量库中找出 top-K 最相关的记忆块。
  3. 重排与注入:用重排模型(cross-encoder)过滤噪声,剩余记忆块拼到 prompt 的 system 段。

4.2 混合检索

纯向量检索在精确关键词、专有名词上容易漏检。混合检索把”语义相似度 + 关键词匹配 + 元数据过滤”叠起来:

  • 语义检索:找”概念相关”的内容。
  • 关键词检索(BM25):找”字面相关”的内容。
  • 元数据过滤:按时间、来源、标签做硬约束。

Pinecone、Weaviate 都内置混合检索 API。生产经验是:先 metadata 过滤缩小候选集,再做向量检索——又快又准。

4.3 Memory-First 架构

传统 RAG 是”先检索外部文档 → 生成”。Memory-First 反过来:先查 Agent 自己的长期记忆,命中就不再调外部 RAG,节省延迟与 API 成本。这种架构对”个性化”场景尤其有效——用户偏好等私有记忆几乎肯定在内部,外部文档反而是噪声源。

五、四层记忆栈的工程实践

给一段最简化的 LangGraph 长期记忆示例代码,演示工作记忆 + 长期记忆如何配合:

from langgraph.graph import StateGraph
from langgraph.checkpoint.postgres import PostgresSaver
from langgraph.store.memory import InMemoryStore

# 短期记忆:checkpointer 负责跨 step 状态持久化
checkpointer = PostgresSaver.from_conn_string("postgresql://...")

# 长期记忆:InMemoryStore 负责跨 thread 持久化(生产换 Redis 或 PG)
store = InMemoryStore()

builder = StateGraph(dict)
# ... 添加节点 ...
graph = builder.compile(
    checkpointer=checkpointer,
    store=store,
)

# 跨会话检索用户偏好
def retrieve_user_context(state, config, *, store):
    user_id = config["configurable"]["user_id"]
    facts = store.search(("facts", user_id), query="preferences")
    episodes = store.search(("episodes", user_id), query="resolved", limit=5)
    return {"user_facts": facts, "episodes": episodes}

效果上,checkpointer 保证单次对话的 step 之间状态可恢复;store 保证跨 session 的”事实”和”事件”可查询。两层配合就是”短期可断点续跑、长期可历史追溯”的最小可行实现。

工程上有几条经验值得记:

  • 块大小(chunking):文档别整篇存,按”语义完整的段落/小节”切,控制在 200~500 token 一块。整篇存会大幅降低检索精度。
  • 元数据丰富度:每块都附 source、date、author、topic_tag 标签,过滤检索场景必备。
  • 去重与摘要:定期合并相似记忆、淘汰长期未访问的项,防止向量库膨胀拖累检索质量。
  • 写权限隔离:长期记忆里的敏感字段要做脱敏和访问控制,Agent 记忆被攻击的后果比模型本身被攻击更严重。

到这里,长期记忆的”为什么 / 存什么 / 怎么存 / 怎么取”就闭环了。

常见问题(FAQ)

Q1:上下文窗口能解决长期记忆吗?

不能。窗口有限且昂贵;超过约 32K 后模型注意力会显著衰减。

Q2:向量库和知识图谱必须二选一吗?

不必。生产环境常做”向量存原文 + 图存结构化关系”的混合架构。

Q3:记忆更新频率怎么定?

按事件触发写入,定期做合并/摘要;高频小更新会导致向量库膨胀。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 qiqicto@qq.com 举报,一经查实,本站将立刻删除。
赞 (0)
赵其鑫的头像赵其鑫管理团队

相关推荐

返回顶部