尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Agent长期记忆实战:用Mem0搭建跨会话智能助手

Agent长期记忆实战:用Mem0搭建跨会话智能助手 一个典型的尴尬场景用户昨天刚在自动化助手对话中详细描述了自己的技术栈、希望每天几点收到日报、当前项目的核心指标。今天打开新会话助手像第一次见面一样把同样的问题又问了一遍。这类问题的根源不是模型不够聪明而是 Agent 缺少“长期记忆”。大模型的上下文窗口再大也只相当于工作记忆一旦会话结束这些信息就会丢失。真正让 Agent 从“会聊天”走向“能办事”的是 Augmenting Long-Term Memory——把关键信息从对话中抽取出来存进可以跨会话检索的记忆系统并在合适时机自动更新和遗忘。这篇文章不打算停留在概念层面。我会从开发者视角拆解Agent 长期记忆到底解决什么问题主流方案 Mem0、Letta、Zep 分别是什么思路并用一个可运行的 Mem0 示例演示如何给 Agent 接入最基础也最常用的长期记忆能力。如果你正在做 LLM 应用、智能助手、客服机器人或任何需要跨会话保持状态的系统这篇文章值得收藏备用。1. 这篇文章真正要解决的问题1.1 三种典型的“失忆”场景第一类是客服与工单场景。用户在周一提交了一个技术工单周二回来问“上个工单处理到哪一步了”。如果 Agent 没有长期记忆它需要用户重新描述一遍问题、重复提供订单号、再次说明之前已经确认过的信息。这种体验不是“智能”而是“健忘”。第二类是个人助手场景。用户说过“我喜欢简洁的回答”“我主要用 Python 和 PyTorch”“我周五下午通常有会”。这些偏好如果无法跨会话保留用户每次使用都需要重新交代背景助手永远停留在“初次见面”的状态价值大打折扣。第三类是长期项目场景。Agent 负责一个持续时间很长的任务比如素材调研、竞品跟踪、代码库维护。项目进行到第 N 轮对话时早期已经确定的技术选型、决策理由、边界条件会随着上下文滚动而慢慢被挤出窗口。最后模型给出的结论可能和几天前自己确认过的方案互相矛盾。这三个场景的共同点是什么它们需要记住的不是一段临时聊天记录而是可以从交互历史中提取出来、在未来继续发挥作用的信息单元。1.2 传统方案的边界在哪里很多人第一反应是“把对话历史都存下来下一次塞进 prompt”。这个方案在轮次少的时候能用但存在三个问题token 成本快速上升、长历史中关键信息被淹没、跨会话数据没有结构化的读取方式。第二种做法是给每个用户缓存最近 N 轮对话。这能解决同一个会话里面上下文丢失的问题却解决不了跨 session 的偏好、事实和项目状态。缓存本质上是“短期记忆”的扩展不是“长期记忆”。第三种做法是 RAG。RAG 适合检索外部知识库、文档、网页内容它解决的是“模型不知道的信息”问题而长期记忆要解决的是“模型曾经知道但后来忘了”的问题。两者有关联但不能画等号。1.3 适合阅读本文的读者如果你正在做以下事情这篇文章对你会很有帮助开发智能客服、搭建个人知识助手、实现带记忆的 Agent 工作流、设计多轮对话系统或者只是好奇“Agent 怎么记住用户”。我默认你了解基本的 Python 编程和大模型 API 调用但不要求你之前接触过专门记忆框架。2. 长期记忆的基础概念与记忆周期2.1 三个记忆层级可以把 Agent 的记忆理解为一个三层结构。第一层是工作记忆也就是模型当前上下文窗口里能看到的内容。窗口越大能同时处理的临时信息越多但它是易失的一旦请求结束或被弹出窗口就会丢失。第二层是会话记忆它服务于同一个会话内部的连续性通常用滑动窗口、摘要压缩或短期缓存实现。当前大多数对话应用的“记忆增强”其实只做到了这一层。第三层是长期记忆它负责保存跨会话仍然有效的用户偏好、事实、事件和状态。长期记忆通常存储在外部的向量数据库、键值存储或图数据库中需要时再检索回上下文。本文说的 Augmenting Long-Term Memory指的就是这个层级的构建与增强。2.2 长期记忆保存什么应用开发中长期记忆可以进一步细分记忆类型说明示例事实记忆用户提供的确定性偏好或属性用户使用 Java 开发工作语言是中文情景记忆发生过的事件或交互历史上周三用户提交了订单退款申请程序记忆任务执行流程和约束项目要求先写测试再提交代码状态记忆正在进行中的任务状态推荐系统开发进度为 70%正在做 A/B 测试不同记忆类型的存储方式不同。事实记忆适合放入结构化或向量化记录情景记忆往往带时间属性程序记忆可能更接近一套规则状态记忆则需要支持反复更新。一个合格的长期记忆框架不应该把所有内容一股脑塞进同一个文本字段。2.3 记忆的生命周期长期记忆不是“写进去就完事”它有完整的生命周期。编码阶段系统从原始对话中抽取值得长期保留的信息。存储阶段为这些信息建立索引、元数据和向量表示。检索阶段在需要时根据当前用户问题召回相关记忆。更新与遗忘阶段当事实发生变化或用户明确要求删除时修正或移除旧记忆。记忆工程中大量的问题不在“存储”而在“编码”和“更新”什么信息值得存、什么时候该更新旧记忆、什么时候该遗忘这些判断直接影响记忆系统的质量。如果任何一句闲聊都被记住记忆库很快就会充满噪音检索阶段反而召不回真正重要的内容。3. 三种主流技术方案Mem0、Letta、Zep3.1 Mem0面向开发者的记忆层Mem0 的定位是给 Agent 提供一个“记忆层”。它的核心思路是从用户对话中提取可以长期保存的事实性记忆写入向量存储并通过 LLM 判断新增、更新或删除。它的工作方式大致可以概括为当用户说了一句话Mem0 会尝试从里面抽取可记忆的信息然后在已有记忆中查找是否信息冲突或重复。如果存在相似旧记忆就触发更新如果没有就新增一条记忆。查询时用户的一句话会被转换成向量去向量库中召回语义相近的记忆条目。Mem0 对开发者的价值在于接入简单。它有比较清晰 Python API可以按 user 或 agent 维度隔离记忆也支持 Qdrant、pgvector 等多种向量存储。它比较适合希望快速给 Agent 加上记忆能力又不打算从零设计抽取逻辑的团队。3.2 LettaMemGPT模拟操作系统的虚拟上下文Letta 的前身是 MemGPT它的设计灵感来自操作系统虚拟内存。模型上下文窗口很小那就把记忆分成“主存”和“外部存储”主存里放 core memory包含 persona、human 等固定模块外部存储放 archival memory 和 recall memory也就是可以无限增长的历史记录和知识。Letta 的特别之处在于模型自己通过函数调用管理记忆。系统根据 token 压力或任务需求触发“把旧记忆写入外部存储”“把重要记忆加载回上下文”“更新 core memory 中的某一段信息”等操作。这种设计把记忆管理变成了 Agent 的一项自主能力而不是由外部脚本固定执行。它更适合想深入探索 Agent 自主记忆行为、研究上下文自动化管理的开发者。代价是概念和配置更复杂学习曲线比 Mem0 陡峭。3.3 Zep企业级时间感知记忆Zep 的特点是面向生产环境把时序信息和知识图谱结合。它能把一段对话转成易于检索的记忆事实同时保留事件发生的时间顺序让 Agent 可以询问“用户上个月提过哪些需求”这类带时间约束的问题。Zep 在事件类记忆上更自然因为它有明确的 graph memory 概念可以捕捉实体之间的关系。对于企业知识助手、客户服务系统这类需要追溯历史、分析关系、做时间过滤的场景Zep 的方向更合适。当然它的部署和运维成本也高于 Mem0 的最小接入方案。3.4 怎么选从公开资料和社区使用情况看方案选择主要取决于场景复杂度。方案记忆组织方式突出能力适合场景上手成本Mem0记忆条目 向量检索抽取、更新、删除自动化个人助手、客服系统、轻量 Agent低Letta记忆块 虚拟上下文模型自主管理上下文研究型 Agent、复杂自主任务高Zep事件 向量 知识图谱时间感知、关系记忆企业级客服、知识管理平台中高如果你只是想先跑通一个带记忆的 Agent建议从 Mem0 开始如果你已经在做复杂 Agent 系统需要深入理解记忆如何融入模型行为可以研究 Letta如果你们有企业级数据和合规要求Zep 值得评估。4. 实操准备与核心配置4.1 环境准备长期记忆方案的上手实验不需要太重的环境。本文示例选用 Mem0因为它的最小接入路径最短。建议环境如下操作系统Windows、macOS、Linux 均可Python建议 3.10 及以上版本示例用到新版类型标注LLM APIOpenAI 兼容接口的 Key也可以按自身情况选择官方支持的模型向量存储本地测试可以不额外启动服务生产环境推荐 Qdrant、pgvector 等先创建虚拟环境并安装依赖python -m venv .venv source .venv/bin/activate # Windows 使用 .venv\Scripts\activate pip install mem0ai需要注意Mem0 的包名在不同阶段可能有变化。如果安装失败可以尝试pip install mem0具体包名和版本以官方文档为准。项目中不要追求最新版本而忽略接口变化建议锁定版本号并在团队内部统一。4.2 初始化记忆对象最小环境下只需要配置 LLM 和 Embedding 模型。Mem0 需要 LLM 来完成记忆抽取和更新判断需要 Embedding 模型来完成记忆条目的向量化。# 文件路径examples/memory_init.py import os from mem0 import Memory os.environ[OPENAI_API_KEY] your-openai-api-key config { llm: { provider: openai, config: { model: gpt-4o-mini, temperature: 0.1, }, }, embedder: { provider: openai, config: { model: text-embedding-3-small, }, }, } m Memory.from_config(config) print(memory init ok)这里有两个关键点。第一temperature 设低一些让记忆抽取更稳定第二embedding 模型要和向量检索的语义空间一致实际项目中更换 embedding 模型后旧向量索引通常需要重新生成。如果你在本地测试不一定需要配置 vector_store默认会使用本地向量索引。生产环境建议显式配置分布式向量库方便扩展和备份。5. 完整示例用 Mem0 给 Agent 增加长期记忆5.1 基础记忆操作下面是一个覆盖写入、检索、查看、更新、删除的最小示例。请注意Mem0 的接口在版本升级后可能有变化代码中的参数和返回字段以你安装的官方版本为准。# 文件路径examples/memory_basic.py from mem0 import Memory m Memory() # 1) 写入记忆 m.add( 用户希望每天上午 9 点收到技术日报并且喜欢简洁的中文摘要。, user_idzhangsan, metadata{source: onboarding, time: 2025-06-01}, ) # 2) 检索记忆 result m.search( 用户希望什么时间收到日报, user_idzhangsan, limit3, ) print(search result:, result) # 3) 查看该用户全部记忆 all_memories m.get_all(user_idzhangsan) print(all memories:, all_memories) # 4) 更新记忆 # memory_id 来自 add / search / get_all 返回结果 m.update(memory_idxxx, data用户希望每天上午 8 点收到技术日报) # 5) 删除记忆 m.delete(memory_idxxx)这段代码展示了记忆的基本生命周期。需要特别说明的是更新操作实际项目中很少直接手写 memory_id而是在写入新信息时先 search 已有记忆判断是否存在同一事实再决定是新增还是更新。这一步可以自动完成也是 Mem0 的核心价值之一。5.2 把记忆封装成一个 Agent 工具真实场景中记忆操作不应该散落在业务代码里。更好的方式是把记忆封装成 Agent 的基础工具类让模型和上层业务统一通过这个类存取记忆。# 文件路径examples/agent_with_memory.py from mem0 import Memory class MemoryAgent: def __init__(self, user_id: str): self.user_id user_id self.memory Memory() def remember(self, content: str, metadata: dict | None None): 把一条值得长期保留的信息写入记忆库。 return self.memory.add( content, user_idself.user_id, metadatametadata or {}, ) def recall(self, query: str, limit: int 5) - list[str]: 根据当前问题召回相关的历史记忆。 result self.memory.search( query, user_idself.user_id, limitlimit, ) return [item[memory] for item in result.get(results, [])] def clear(self): 清空当前用户的全部记忆适合测试或用户主动重置。 memories self.memory.get_all(user_idself.user_id) for item in memories.get(results, []): self.memory.delete(item[id]) if __name__ __main__: agent MemoryAgent(user_idzhangsan) agent.remember(用户正在开发一个推荐系统偏好 Python 和 PyTorch。) agent.remember(用户今天提到希望把推荐结果延迟控制在 200ms 以内。) retrieved agent.recall(这个项目用什么语言和框架) for text in retrieved: print(recall:, text)需要注意不同版本get_all返回字段可能不同有的版本返回results有的版本返回memories具体以官方文档为准。5.3 在对话流程中接入记忆一个常见的接入模式是用户提问前先根据问题召回相关记忆模型回答后再从用户消息中抽取并写入新的记忆。伪代码流程如下# 文件路径examples/chat_with_memory.py def handle_user_message(agent: MemoryAgent, user_message: str): # 1. 召回与当前问题相关的历史记忆 related_memories agent.recall(user_message) # 2. 组装上下文把记忆注入系统提示 system_prompt 你是用户的长期助手。以下是与本次问题相关的历史记忆\n system_prompt \n.join(related_memories) # 3. 调用大模型生成回答实际项目使用你自己的 LLM 客户端 # reply llm.chat(system_prompt, user_message) # 4. 从用户消息中抽取值得长期保留的信息 agent.remember(user_message) return system_prompt这里真正容易踩坑的地方是不要把召回的几十条记忆全部塞进 prompt。记忆注入数量要控制只保留最相关的 3 到 5 条否则不仅浪费 token还可能让模型被无关记忆干扰。6. 运行结果与效果验证6.1 预期输出运行第一个示例examples/memory_basic.py后search 结果大致会返回一个 JSON结构类似{ results: [ { id: 6f7b0b1e-xxxx-xxxx-xxxx-xxxxxxxxxxxx, memory: 用户希望每天上午 9 点收到技术日报并且喜欢简洁的中文摘要。, event: ADD, score: 0.87 } ], meta: {} }score表示当前问题与记忆条目的语义相似度通常越高越相关。event字段表示这条记忆最近一次发生的事件类型可能包括新增、更新、删除、检索等。6.2 验证方法第一步确认写入成功。运行python examples/memory_basic.py观察add是否返回包含id的输出。没有返回 id说明写入链路有问题通常先检查 API Key 和模型权限。第二步验证语义检索。换一种措辞再查询一次比如把“用户希望什么时间收到日报”改成“日报发送时间偏好是什么”。如果两种问法都能召回同一条记忆说明 embedding 和向量检索工作正常。如果召回不到优先调整查询表述或检查 embedding 模型是否正确加载。第三步验证更新与删除。调用update修改数据再search查看是否返回新内容调用delete后再search确认旧记忆不再出现。更新逻辑是长期记忆系统的核心测试时要格外关注。第四步验证跨会话能力。关闭 Python 进程重新启动一个新的进程再构建同一个user_id的MemoryAgent调用recall。如果还能召回之前的记忆说明数据确实持久化到了外部存储而不是只保存在内存里。6.3 失败的后续排查顺序如果运行失败第一步看异常信息第二步看 API Key 是否正确第三步确认网络能访问模型服务地址第四步确认向量库连接是否正常。需要强调的是生产环境中这些配置都不应该在代码中硬编码而是通过环境变量或密钥管理服务注入。7. 常见问题与排查思路问题现象可能原因排查方式解决方案添加记忆时报 401 或 403LLM 或 Embedding 的 API Key 无效、模型权限不足检查环境变量、API 控制台用量和权限更换有效 Key确认账号有对应模型访问权限检索不到相关记忆查询表述和写入时的语义差异太大或 limit 太小打印召回结果尝试换一种问法调整 limit 和相似度阈值保持查询语义与记忆内容一致记忆内容出现明显错误抽取阶段的 LLM 判断不准查看 add 返回的新增记忆文本拆分更小的事实片段补充 metadata对关键事实加入人工校验同一事实被反复写入写入前缺少去重逻辑或更新判断不触发查看 get_all 结果中的重复项写入前先 search 同一主题命中已有的高相似记忆时转为更新上下文长度仍然爆炸召回的长期记忆没有控制数量和会话历史混在一起检查系统提示和注入逻辑只注入 top 3 到 5 条记忆会话历史用摘要压缩不要全文保留敏感数据被写入记忆库缺乏脱敏、权限控制和清理机制审查记忆库内容和日志对 PII 脱敏按用户隔离数据加密存储提供用户主动删除入口这些问题的共性在于长期记忆系统如果只解决“存得下”和“查得回”它只是数据管道的延伸真正决定成败的是抽取质量、更新判据和边界控制。8. 长期记忆工程的最佳实践8.1 按用户、Agent、会话分层隔离记忆数据必须支持多维度隔离。同一套系统可能服务多个用户也可能一个用户使用多个 Agent。建议至少用user_id和agent_id区分必要时加入session_id代表一次业务会话。查询和写入都要显式传递身份标识防止数据串号。8.2 元数据先行每条记忆都要带上来源、时间、置信度等元数据。来源用于追溯时间用于事件回看和衰减计算置信度用于系统判断是否值得写入长期记忆。没有元数据的记忆库最后会变成一团无法解释的黑盒。8.3 控制检索阈值召回结果不是越多越好。给相似度分数设置一个合理下限过滤掉低相关条目设置一个合理的 top_k 上限控制注入 prompt 的 token 成本。对高价值任务可以多轮查询后合并结果而不是把整库结果都扔给模型。8.4 更新优先于新增长期记忆系统最怕重复。推荐流程是写入前先搜索已有记忆中是否有同一主体、同一属性的高相似条目。如果有走更新流程保留原始来源并记录更新时间如果没有才走新增流程。这样记忆库会越来越精炼而不是越来越臃肿。8.5 给用户遗忘的权利Regulation 与隐私要求越来越严格产品上也要给用户提供“查看我的记忆”“修改我的记忆”“删除我的记忆”的入口。即使不涉及合规要求这个能力对系统质量也有帮助用户主动清除过时记忆后Agent 下一次的表现通常会明显变好。8.6 建立记忆评测集很多团队上线了记忆功能但没有定义“怎么样才算记住”。建议准备一组标准任务用户偏好记忆、跨会话召回、重复信息去重、事实变更更新、主动遗忘。每一次功能迭代用同一组任务回归测试用召回准确率和任务成功率衡量系统是否在变好。8.7 注意安全边界记忆库里装的往往是用户隐私数据安全等级高于普通日志。生产环境建议做到传输加密、存储加密、最小权限访问、访问审计、定期清理。不要在代码和日志中打印完整记忆内容不要在演示中暴露真实用户数据。9. 总结与后续学习方向从上面的方案和代码示例可以得出一个判断Augmenting Long-Term Memory 的核心不是“把历史文本存进向量库”而是围绕记忆生命周期建立起一套抽取、存储、检索、更新、遗忘的工程链路。记住哪些信息、何时更新、何时遗忘比“有没有记忆系统”更重要。如果你正在做 Agent 项目建议先别急着上复杂框架。用今天这个最小链路跑通“写入-召回-更新”你就能快速看清长期记忆的核心瓶颈在哪里。它通常出现在抽取质量、检索阈值、重复去重和用户遗忘触发条件上而不是在向量数据库的选型上。下一阶段可以研究两个方向一是读 Letta 的 memory block 设计理解模型自主管理上下文的思路二是调研 Zep 的时间感知与图谱记忆看能否满足企业级场景。无论走哪条路最终都要回到一个问题你的 Agent 知道自己该记住什么、该忘掉什么吗这个问题的答案决定了记忆系统是 Agent 的加分项还是新的负担。
返回列表