将让Agent越来越智能、高效和人性化。随着人工智能技术的不断发展,Agent(智能代理)将具备以下特点:1. **智能水平提升**:Agent将具备更强的学习能力,能够通过大数据分析和机器学习不断优化自身算法,提高决策准确性和预测能力。2. **效率提高

摘要:引言 从本质上来说,AI Agent 仍然是一种工具。但与软件工程领域中的其他工具不同,我们对 AI Agent 怀有更高、也更复杂的期待。这种期待源于 AI 能力的加持——我们希望它不仅仅提升效率,而是真正解放生产力。 在这一愿景下,&a
引言 从本质上来说,AI Agent 仍然是一种工具。但与软件工程领域中的其他工具不同,我们对 AI Agent 怀有更高、也更复杂的期待。这种期待源于 AI 能力的加持——我们希望它不仅仅提升效率,而是真正解放生产力。 在这一愿景下,"长期记忆"成为关键能力之一。它的意义在于,让 Agent 不再只是被动执行指令,而是能够在持续交互中逐渐变得更智能、更贴近使用者,甚至越来越"懂我"。 在《AI Agent 的记忆系统:从必要性到工程实践》一文中,我们已经系统阐述了 Agent 记忆的分类及其作用。本文则进一步聚焦其中的长期记忆能力,尝试从工程实践的角度展开具体落地方案。 在正式展开之前,先简单回顾一下长期记忆与短期记忆的区别。 短期记忆:存储会话中产生的各类消息,包括用户输入、模型回复、工具调用及其结果等。这些消息直接参与模型推理,实时更新。当消息累积导致上下文窗口超出限制时,需要通过压缩、卸载、摘要等上下文工程策略进行处理。 长期记忆:Agent 在多次交互与会话之间持久化存储信息的系统。它相当于智能体的"个人档案"或"知识库",用于保留需要跨会话记忆的关键信息,如用户偏好、重要事实、从历史会话中积累的经验与知识等。其核心目标是实现个性化和持续学习。 Agent 长期记忆的工程实现,核心可以归结为两个基本问题: 如何维护长期记忆 —— 包括长期记忆的新增、更新与删除; 如何使用长期记忆 —— 即在实际推理与决策过程中,如何高效、准确地检索与注入相关记忆。 围绕这两个问题,我们需要首先明确长期记忆的存储载体。在当前主流的工程实践中,长期记忆通常依赖两类基础设施:VectorStore(向量数据库) 与 GraphStore(图数据库)。接下来,我们将从这两种载体的特性与适用场景出发,逐步展开长期记忆的工程化实现方式。 以下内容我们将结合mem0进行说明,github地址:https://github.com/mem0ai/mem0 一、长期记忆的载体 1.1 VectorStore:语义检索的基石 向量数据库是当前长期记忆最主流的存储载体。其核心思路是:将文本信息通过 Embedding 模型转换为高维向量,存储在专门的向量索引结构中。检索时,将查询语句同样转换为向量,通过余弦相似度或内积等度量方法,找出语义最相近的记忆条目。 这种方式的优势非常直接——语义相似即可命中。即便用户的表述与存储时的措辞完全不同,只要语义接近,向量检索就能找到对应的记忆。例如,Agent 存储了"用户不喜欢辣食",当下次对话中用户问到餐厅推荐时,即便没有提及"辣",Agent 也能从向量空间中召回这条偏好。 常见的 VectorStore 选型包括: 方案 特点 适用场景 Chroma 轻量级,易集成,支持本地持久化 本地开发、小规模部署 Qdrant 高性能,支持丰富的过滤条件 生产环境,记忆量较大 Pinecone 全托管,开箱即用 快速原型、云端部署 pgvector PostgreSQL 扩展,与关系数据融合 已有 PG 栈的团队 Faiss 极致性能,适合批量检索 离线分析、大规模召回 向量数据库的局限同样明显:它擅长处理孤立事实,但对于实体间关系的表达能力较弱。"张三是李四的上司"和"李四喜欢咖啡"对向量数据库而言没有本质差异,它无法自然地表达和利用实体之间的关联结构。这正是图数据库要解决的问题。 1.2 GraphStore:关系知识的天然载体 图数据库将知识以节点(Node)和边(Edge) 的形式组织,节点代表实体(人、地点、事件等),边代表实体间的关系。这种结构天然适合表达复杂的关联信息。 以 mem0 的 Graph Memory 实现为例,当 Agent 处理"Alice 在 GraphConf 2025 上认识了 Bob"这条信息时: 向量数据库:将这句话嵌入为一个向量,语义检索时可以找到它; 图数据库:提取出 Alice、Bob、GraphConf 2025 三个节点,以及 MET_AT 关系边,形成结构化的知识图谱。 后续当用户问"Alice 认识哪些人?"时,图数据库可以直接沿着边遍历,精确返回所有相关节点,而不依赖语义相似度的模糊召回。 mem0 的 Graph Memory 架构如下: Conversation → Extraction LLM → VectorStore (embeddings) ↓ GraphStore (nodes & edges) Query → VectorSearch → Candidate Memories → Graph traversal → Contextual Relations 两者并行工作:向量检索负责语义召回,图遍历补充关系上下文,最终合并返回给 Agent。 GraphStore 的接入示例(以 Neo4j 为例): from mem0 import Memory config = { "graph_store": { "provider": "neo4j", "config": { "url": "neo4j+s://<your-instance>.databases.neo4j.io", "username": "neo4j", "password": "your-password", } } } memory = Memory.from_config(config) 目前 mem0 支持的图数据库后端包括 Neo4j、Memgraph、Amazon Neptune 和 Kuzu(嵌入式),可以按部署环境灵活选择。 1.3 两者的核心差异 维度 VectorStore GraphStore 存储单元 文本片段 + 向量 节点 + 边 + 属性 检索方式 语义相似度搜索 关系遍历 + 模式匹配 擅长场景 偏好、事实、陈述性知识 人物关系、事件脉络、多跳推理 部署复杂度 低 中高 典型问题类型 "用户喜欢什么?" "Alice 认识谁?谁参加了哪个会议?" 值得注意的是,以上仅是工程上常见的实现方式,实际应用中可能因具体需求而异。在我们此前对 OpenClaw 的分析《OpenClaw 入门指南:从原理到实战》就发现,其长期记忆是以本地 MEMORY.md 文档的形式存储的——简单直接。这告诉我们,不应拘泥于形式,而应根据实际需要合理评估,有时候最朴素的方案反而是最合适的。 二、如何维护长期记忆? 确定了存储载体,接下来的核心问题是:如何让记忆库保持准确、及时、不冗余。 长期记忆的维护本质上是一个持续的 CRUD 过程:新信息到来时新增,信息发生变化时更新,矛盾信息出现时删除。听起来简单,但在实际 Agent 交互中,判断"这条信息是新增还是更新"并不容易。 2.1 维护策略:规则 + LLM vs 纯 LLM 目前主流的维护策略有两种路径: 路径一:规则 + LLM 判断 设定一些明确的规则,例如"情感倾向明显的表达优先存储"、"重要度评分超过阈值才触发写入",在规则过滤之后再交由 LLM 做最终判断。这种方式可控性强,适合有明确记忆策略的产品场景。 路径二:完全交给 LLM 直接将当前对话和已有记忆库交给 LLM,让它自行判断应该 ADD、UPDATE、DELETE 还是 NONE。这种方式更灵活,能处理更复杂的边界情况。 我个人更倾向于后者。既然我们选择了使用 AI,就应该充分信任 AI 的判断力。在《AI Agent 的记忆系统:从必要性到工程实践》一文中对 Cursor 记忆系统的解析中也发现,Cursor 正是采用了这种"完全交给 LLM"的方式。 mem0 将这种灵活性通过 Custom Update Memory Prompt 开放给开发者,允许用户自定义 LLM 的决策逻辑。 2.2 记忆的新增(ADD) 当会话产生了新的、尚未存储的信息时,触发 ADD 操作。mem0 的信息提取流程分为两步: 信息抽取:通过 LLM 从对话中提取关键事实、偏好、决策等信息片段; 冲突检测:与现有记忆进行比对,确认是否为全新信息。 from mem0 import Memory m = Memory() messages = [ {"role": "user", "content": "我计划下个月去东京旅行。"}, {"role": "assistant", "content": "好的,我会记住这个计划,方便后续提供相关建议。"} ] result = m.add(messages, user_id="alice") 执行完毕后,mem0 会自动从对话中抽取"用户计划下个月去东京旅行"这一事实,写入向量存储,同时(如果启用了图存储)在图中创建 Alice → PLANS_TO_VISIT → Tokyo 的关系边。 infer=True 是默认行为,也是推荐做法——让 LLM 决定哪些信息值得存储,而不是盲目地把所有对话都塞进记忆库。 2.3 记忆的更新(UPDATE) 更新是维护中最复杂的操作。当新信息与已有记忆描述的是同一件事,但内容有所变化时,需要更新而非新增。 以 mem0 的 Custom Update Memory Prompt 为例,它通过结构化的 LLM 决策来处理这个问题: UPDATE_MEMORY_PROMPT = """你是一个智能记忆管理器,负责控制系统的记忆。 你可以执行四种操作:(1) 新增记忆 (2) 更新记忆 (3) 删除记忆 (4) 不做变更 比较新获取的事实与现有记忆。对于每条新事实,决定是否: - ADD:作为新条目添加 - UPDATE:更新现有记忆条目 - DELETE:删除现有记忆条目 - NONE:不做变更(事实已存在或不相关) """ 更新场景示例: 旧记忆:[{"id": "0", "text": "用户喜欢奶酪披萨"}] 新事实:["用户喜欢鸡肉披萨和奶酪披萨"] 决策结果: { "memory": [{ "id": "0", "text": "用户喜欢鸡肉披萨和奶酪披萨", "event": "UPDATE", "old_memory": "用户喜欢奶酪披萨" }] } 有两个细节值得关注:保留原始 ID,确保历史追溯链路不断;记录 old_memory,方便审计与 Debug。 2.4 记忆的删除(DELETE) 当新信息与已有记忆产生直接矛盾时,触发 DELETE。这是记忆库保持"当前真实"的关键机制。 旧记忆:[{"id": "1", "text": "用户喜欢奶酪披萨"}] 新事实:["用户不喜欢奶酪披萨"] 决策结果: { "memory": [{ "id": "1", "text": "用户喜欢奶酪披萨", "event": "DELETE" }] } 矛盾信息不应被"更新"掩盖,而应被删除——因为这不是一次"说法变化",而是一次"事实反转"。LLM 需要能准确区分这两种情形。 三、如何使用长期记忆? 维护好的记忆库,只有在被有效利用时才体现价值。"如何使用长期记忆"的本质,是在正确的时机,把正确的记忆注入到 LLM 的上下文中。 3.1 检索流程全貌 mem0 的检索流水线如下: 用户查询 ↓ 查询改写(Query Rewrite) ↓ 向量检索(Vector Search) ↓ 重排序(Reranking) ↓ 注入上下文 每一步都在为最终结果的精准度做贡献,不能随意省略。 3.2 为什么需要查询改写(Query Rewrite)? 用户在对话中的表达往往不适合直接作为检索 Query。以一个具体例子说明: 用户问:"帮我推荐一家今晚吃饭的地方。" 这句话直接丢给向量检索,能命中什么?最可能返回的是"用户曾经去过某家餐厅"或"用户提到过晚饭"——而真正有用的记忆是"用户不吃辣"、"用户偏好日式料理"、"用户对花生过敏"。 查询改写的作用,就是将用户的原始表达转化为更适合记忆检索的语义查询。例如将上述问题扩展为:"用户的饮食偏好"、"用户的食物禁忌"、"用户过往的餐厅偏好",分别独立检索,再合并结果。 这一步通常由一个轻量的 LLM 调用完成,成本可控,但对检索质量的提升非常显著。 3.3 为什么需要重排序(Reranking)? 向量检索基于余弦相似度(最常见),返回的是"语义最近"的结果,但"语义最近"≠"最相关"。 举一个典型的反例。用户问:"我学过哪些编程语言?",记忆库中存储了以下四条: A "用户认为学好编程最重要的是多实践" B "用户大学读的是计算机专业,辅修数学" C "用户掌握 Python、Java 和 Go,目前主力使用 Go" D "用户不喜欢前端开发" 向量检索按余弦相似度排序后,假设结果可能是:A(0.88)> B(0.85)> C(0.79)> D(0.74)。 原因并不难理解:A 里"学好编程"和 B 里"计算机专业"与查询中"学过"和"编程语言"的向量表示高度重叠,而 C 虽然是这道题的直接答案,但措辞不同,语义向量反而排第三。 如果此时 limit=2,用到的记忆就只有 A 和 B,真正的答案 C 被截断丢掉了。 Reranking 的作用正在于此:它在向量召回之后引入另一个模型(通常是交叉编码器 Cross-Encoder),将查询和每条记忆作为一对输入,整体评估其语义相关性,而不是分别计算各自的向量再做比较。经过精排,C 会被推到第一位,A 和 B 反而被压后。 Reranking 前后的排序对比: 排名 向量检索(召回阶段) Reranking(精排后) 1 A - "学好编程最重要的是多实践" C - "掌握 Python、Java 和 Go" 2 B - "大学读计算机专业" B - "大学读计算机专业" 3 C - "掌握 Python、Java 和 Go" D - "不喜欢前端开发" 4 D - "不喜欢前端开发" A - "学好编程最重要的是多实践" 在 mem0 中,开启 Reranking 只需一个参数: results = m.search( "推荐一部今晚适合看的电影", user_id="alice", rerank=True, limit=5 ) 两阶段检索(向量召回 + Reranking 精排)是当前 RAG 领域的主流范式,在记忆检索场景同样适用,也是 mem0 官方推荐的使用方式。 3.4 其他优化策略 除了改写和 Reranking,还有几种常见的检索优化手段: ① 相关度阈值过滤(Threshold Filtering) 只返回相似度分数超过阈值的记忆条目,避免将不相关的记忆注入上下文,干扰 LLM 推理。 results = m.search( "用户的饮食偏好", user_id="alice", threshold=0.7 # 只返回相似度 > 0.7 的记忆 ) ② 元数据过滤(Metadata Filtering) 为记忆条目附加结构化元数据,检索时通过过滤条件缩小候选范围,提高精度同时降低延迟。 # 写入时携带元数据 m.add(messages, user_id="alice", metadata={"category": "food_preference"}) # 检索时按类别过滤 results = m.search( "用户喜欢吃什么", user_id="alice", filters={"categories": {"contains": "food_preference"}} ) ③ 图关系增强(Graph-Enhanced Retrieval) 对于涉及实体关系的查询,启用图存储可以在向量召回的基础上补充关系上下文,使 Agent 对复杂关联有更完整的认知。 results = m.search( "Alice 认识哪些人?", user_id="demo-user", enable_graph=True ) # results["results"] 包含向量召回的记忆 # results["relations"] 包含图数据库返回的关系信息 ④ 多路检索合并(Multi-Query Retrieval) 对一个用户请求生成多个不同角度的检索 Query,分别独立检索后合并去重。这在用户问题较模糊或涉及多个维度时特别有效。 以"帮我安排下周的学习计划"为例,这是一个需要综合多维度上下文才能回答好的问题。如果只用原始问题检索,很可能只能命中"用户提到过学习"之类的泛化记忆。 正确做法是先将其拆解为多个语义明确的子查询: from mem0 import Memory m = Memory() user_query = "帮我安排下周的学习计划" # 将原始问题拆解为多个子查询,覆盖不同维度 sub_queries = [ "用户的学习目标和方向", "用户每天的可用时间和作息习惯", "用户目前的学习进度", "用户偏好的学习方式", ] # 分别检索,去重合并 all_memories = [] seen_ids = set() for q in sub_queries: results = m.search(q, user_id="alice", limit=3) for mem in results["results"]: if mem["id"] not in seen_ids: all_memories.append(mem) seen_ids.add(mem["id"]) # all_memories 包含从四个角度召回、去重后的完整上下文 四路检索分别可能命中: 子查询1 → "用户目标是通过 AWS 认证考试"、"用户想深入学习分布式系统" 子查询2 → "用户工作日晚上有 1-2 小时空余"、"用户周末可以学习半天" 子查询3 → "用户已经看完了第 3 章,卡在第 4 章的实验上" 子查询4 → "用户更喜欢边做项目边学,不喜欢纯看书" 将这些记忆合并注入上下文,Agent 才能给出真正贴合用户实际情况的学习计划,而不是完全自由发挥、脱离实际需要的结果。 结语 长期记忆是 AI Agent 从"工具"走向"伙伴"的关键一步。 本文围绕长期记忆的两个核心工程问题展开:存储载体的选择(VectorStore vs GraphStore),以及记忆的维护(ADD/UPDATE/DELETE)与检索(改写 + 向量召回 + Reranking)。 核心逻辑就是:把合适的信息存在合适的地方,在合适的时机以合适的方式取出来。这句话说起来平平无奇,但其中每一个步,都是工程上多次实践后的结晶。 在如何维护长期记忆这个问题上,我更倾向于信任 LLM 的判断——无论是记忆维护时的 ADD/UPDATE/DELETE 决策,还是检索时的查询改写,LLM 的灵活性远超硬编码规则。当然,"信任 AI"并不意味着放任不管,有审计、有监控、可干预,才能使我们设计出一个更安全、可靠的Agent。 Agent 的“懂你”,从来不是一蹴而就的。 它不是某个模型参数的瞬间跃迁,而是一次次交互之后,一条条记忆沉淀下来的结果。 而我们作为工程师,要做的并不是赋予它“理解”的幻觉,而是为这种长期积累的过程搭建稳固的地基—— 让记忆可存储、可演化、可调用, 让“越来越懂你”不再只是愿景,而成为一种可以被工程化实现的能力。