新闻详情

新闻详情

首页 / 资讯中心 / 详情

AI Agent记忆系统设计:Memory Provider核心模式与实战

发布时间:2026/9/28 14:59:57来源:尧图网络
AI Agent记忆系统设计:Memory Provider核心模式与实战
做AI Agent的兄弟应该都有过类似的体验模型明明很强但一聊长就“失忆”用户上一轮说的事下一轮就忘了来回掰扯几轮之后用户耐心直接归零。我自己在给一个客服型Agent接记忆能力的时候对比了Hermes、Mem0、Honcho、Hindsight这四个名字很像的记忆方案最后发现一个有意思的事——它们的API设计和数据流几乎长在同一个骨架上。今天就把我对Memory Provider的实战拆解以及它们为什么都这样设计的原因一次说清楚。这篇文章适合两类人一类是正在做Agent应用、被上下文窗口折磨得头疼的开发者另一类是想自己设计记忆模块但不知道从哪里下手的架构师。我不会只讲概念会把核心接口、写入读取链路、触发时机、召回方式这些可落地的东西都摊开讲最后还会给一段可以抄的Python实现。1. Memory Provider 到底在解决什么问题1.1 上下文窗口是Agent记忆的“天花板”所有大模型的上下文窗口都是有限的哪怕现在有支持128K甚至更长窗口的模型也不能真的把所有历史对话一股脑塞进去。原因很直接Token费用会随对话长度指数起飞推理时间会越拉越长而且长上下文里的关键信息往往被淹没在无关内容里模型的注意力反而会分散。我做过一个简单测试把十轮客服对话全部拼接进Prompt结果模型对第一轮提到的订单号记忆准确率只有不到60%而同样内容单独检索出来再放进去准确率能到90%以上。这就引出了Memory Provider的核心价值它不是让模型“记住”全部内容而是提供一个外部记忆系统让Agent在需要的时候主动去查。就像人不会把每天发生的所有事都刻在脑子里但遇到相关场景时能回忆起关键细节。上下文窗口是短期工作记忆的容量上限而Memory Provider就是补上长期记忆这块短板。1.2 记忆的三种层级工作记忆、情景记忆、语义记忆我在设计记忆系统时习惯把Agent的记忆分成三个层级对应认知科学里对记忆的分类方法。第一层是工作记忆就是当前正在进行的对话上下文通常保留最近几轮原始消息即可。第二层是情景记忆记录过去发生的具体事件和对话片段比如“用户上周三反馈过登录超时”。第三层是语义记忆是提炼出来的事实、偏好、规则比如“用户偏好简洁回复”“用户所在城市是上海”。Hermes、Mem0这些方案表面看各不相同但它们的数据模型都离不开这三个层级。有的方案侧重情景记忆直接存储对话片段并建立索引有的方案侧重语义记忆会从对话中抽取实体和关系。真正好的Memory Provider不会只存储一种而是让情景记忆和语义记忆互为补充用情景片段支撑细节用语义记忆支撑推理。为什么都要这么分层因为单纯存储原始对话会导致召回时关键事实被噪声干扰而单纯存储结构化实体又会丢失上下文语感两者结合才稳妥。1.3 为什么不能用Prompt硬拼一个记忆系统你可能觉得既然模型本身很聪明那每次把历史记录格式化塞进Prompt不就行了表面上看确实是最快路径但只要你做过两轮以上真实用户对话就会发现这条路根本走不通。首先是成本问题假设每轮用户消息500字助手回复800字保留20轮的话单是历史就得塞进26000字上下文长期运行费用非常可观。其次是准确性问题模型对长篇上下文的中间和末尾部分感知更强早期的关键信息很容易被“冲淡”。更重要的是硬拼方案完全没有“记忆管理”概念。你没法对记忆做增删改查没法设置有效期没法按相关性排序更没法在多个会话之间共享记忆。而Memory Provider本质上是一个带索引、带检索、带更新策略的存储层它让记忆成为Agent可以用标准接口操作的一等公民。所以我一直跟团队说不要把记忆写死在Prompt模板里要把记忆做成一个独立的服务。2. 四个主流记忆方案的设计密码2.1 Hermes消息级别的轻量记忆先声明一下我这里讨论的Hermes是指作为Memory Provider出现的轻量级记忆模块不是网上那个同名开源大模型。Hermes的设计思路非常朴素把每一条用户消息和助手回复都按“消息”为单位存入记忆库每条消息带角色、时间戳、会话ID。检索时按相关度和时间贴近度把相关消息捞出来拼成一个“记忆片段”塞进Prompt。它的优点是好理解、易集成整个库只需要一张消息表和一套向量索引。缺点是缺少对信息的提炼原样存储的消息里经常混着寒暄、语气词、无关内容召回时容易把噪声也带出来。如果你只是做一个个人助理类DemoHermes这种方案完全够用因为它最接近“给Agent配一个对话记录本”的直觉。2.2 Mem0以实体为中心的长期记忆Mem0是目前社区讨论度最高的Memory Provider之一它的核心思路是把记忆从“消息”提升到“实体”。系统会从对话中抽取用户提到的偏好、任务状态、人物关系等整理成实体和属性例如“用户张三偏好简洁回复最近任务申请退款”。每个实体可以有创建时间、更新时间、重要度记忆库本质上变成了一张动态维护的知识图谱或结构化表。这种设计最大的好处是可以做到定点更新。比如用户中途改了口说“其实我喜欢更详细的回复”系统只需要更新“偏好”这个实体的值而不需要追溯之前的对话。Mem0还提供了管理API支持人工干预记忆可以被人工确认、删除或修改这在合规场景很重要。我实际体验下来Mem0对客服、销售、CRM这类需要长期跟踪用户信息的场景相当契合因为它的数据模型天然支持“用户画像”这种高层抽象。2.3 Honcho面向多Agent对话的“对话记忆”Honcho这个名字听起来很特别它的定位也更偏向对话场景本身。它不只是记录“谁说了什么”还会维护对话中多个参与者之间的互动关系。比如在客服场景里有用户和AI助手在协作场景里可能有多个Agent协作Honcho会给每个参与者建立独立的记忆上下文并记录他们之间的对话图。Honcho对我印象最深的是它强调“re-contextualization”也就是每次对话前都会基于当前参与者身份和历史互动生成一个动态的“对话背景”。举个例子同一个用户上午和下午分别来咨询Honcho能让下午的AI自动想起上午聊到的方案而且不会把另一个用户的记忆串进来。它的设计体现了多用户多会话隔离的重要性这也是我一直强调的点记忆Provider不能只做一个全局大仓库必须按用户、会话、角色做好边界。2.4 Hindsight事后回顾式摘要记忆Hindsight这个方案的名字就已经说明了一半它是用“后见之明”来生成记忆。具体做法是不在对话进行中逐条插入记忆而是等一段对话结束后调用大模型对这段对话做一次回顾提炼出发生了什么、用户表达了什么偏好、有没有遗留的任务然后把这些摘要作为结构化记忆存起来。这很像我们人类在一天结束后躺在床上回忆今天开会说了什么再决定哪些事情值得记住。这种事后摘要思路有几个明显好处第一减少写入频率对话过程不打断主流程性能开销低第二生成的记忆质量更高因为它有全局视角能看到整个对话的起承转合第三天然支持“遗忘”因为摘要本身就是一种信息压缩无关细节会被自动丢弃。代价是如果需要实时回忆中间某个细节可能因为摘要粒度太粗而丢失。Hindsight让我意识到记忆Provider可以引入一个“总结器”角色而不仅仅是存储和索引。2.5 对比表四个方案共享了哪些核心元素为了更直观地看它们的共性我把四个方案的几个关键维度放在一张表里方案记忆粒度主要触发时机存储重点召回方式Hermes消息级实时每轮原始消息片段向量时间加权检索Mem0实体级实时抽取更新实体属性/关系图结构化查询语义检索Honcho会话/参与者级对话开始前和结束后参与者关系与互动上下文按参与者身份重构建Hindsight摘要级对话结束后批量生成LLM提炼的结构化摘要摘要检索细节回查看完这张表你会发现四者根本的差异只在记忆粒度和触发时机而底层都依赖三件事内容提取、向量化存储、相关性召回。这恰恰说明Memory Provider的标准化程度远比我们想象得高也意味着我们可以提炼出一套通用的实现范式。3. 核心设计模式拆解为什么这些方案殊途同归3.1 写读分离异步管道是标配四个方案里除了消息级的Hermes可能在边写边读其他几个都把写入和读取拆成了独立的两条链路。写入链路负责从对话流中提取记忆、生成向量、写入存储读取链路负责根据当前用户问题生成检索条件、召回记忆、重排、拼接Prompt。这两条链路不共享同一份代码往往还跑在不同的触发点上。为什么都要这么做因为写入和读取的性能目标完全不同。写入希望低入侵最好在后台异步完成不要阻塞对话响应读取希望低延迟必须在几百毫秒内完成召回。如果把它们混在一起比如每来一条消息就同步抽取一次实体并查询一次记忆库那么Agent的每次响应都会被拖慢而且容易因为异常导致对话中断。所以我在设计自己的Memory Provider时第一件事就是把写入管道和读取管道彻底解耦写入走异步队列读取走同步接口。3.2 记忆需要“分层缓存”没有谁只用一个库你会发现这些方案表面上都叫“长期记忆”但实际上没有一个方案是只用一个全局数据库从头存到尾的。Hermes会先保存最近几轮消息在工作上下文中然后才把更老的消息向量化到长期库Mem0会把最近对话里的临时实体短暂保存在内存里等确认了再合并到持久化实体表中Honcho每次会话开始时就从长期存储里恢复对话背景Hindsight则先把整段对话存进暂存区等结束后再异步生成摘要。这个设计可以类比成CPU的L1/L2/L3缓存工作记忆是最热的数据直接放Prompt短期记忆是最近几天的高频数据放在快速存储里长期记忆是经过提炼的冷数据放慢速但容量大的存储。为什么非要分这么多层因为成本和召回质量的平衡点在中间。如果所有记忆都走向量库召回最简单但是每次调用都要多一次网络IO和向量计算如果所有记忆都塞进Prompt又回到了成本爆炸的老路。折中方案就是把“最近几轮”和“历史关键信息”分开处理只有需要时才去翻长期记忆。3.3 混合召回语义检索时间衰减关键词过滤很多刚开始做记忆系统的人以为记忆召回就是给用户当前query做一个向量检索取top5塞进Prompt就完事了。实际跑过之后会发现纯向量召回效果非常不稳定有的是因为embedding模型对名词实体不敏感有的是因为语义相近但上下文角色不对导致把A用户的记忆串到B用户身上。成熟的Memory Provider在召回时都会做混合策略第一路是语义向量召回通过embedding算相似度第二路是关键词/实体验配把用户问题里的实体名、商品名、订单号直接到索引里匹配第三路是时间衰减通常会给记忆一个时间权重越近的记忆分数越高。最后用线性加权把这些分数融合起来。比如我常用的打分公式大致是final_score 0.5 * semantic_score 0.3 * entity_match_score 0.2 * recency_score。这个权重需要根据场景调客服场景里实体匹配权重可以调高而闲聊场景里语义相似度更重要。3.4 结构化提取与自然语言摘要并存为什么几乎每个方案最后都选择既存结构化数据又存自然语言摘要因为两种形式各有不可替代性。结构化数据适合精确查询和更新比如“用户的收货城市变了”这种操作在实体表里改一个字段就行自然语言摘要适合模糊回忆和全局概括比如“用户对我们的售后流程感到不满”这种信息没法彻底拆成字段。以Mem0为代表的实体型方案会把核心事实抽成结构化实体但也保留原始对话片段作为佐证以Hindsight为代表的摘要型方案主要用自然语言摘要但会把摘要里的关键实体单独抽出建立索引。我自己在实现时会设计两种存储一张实体表用于精确查询一个向量库用于摘要召回。写入时先抽取实体再生成一段摘要两者都存读取时再把两部分合并到一起作为记忆上下文。这也就是为什么这四个方案在外观上差异很大内部却越来越像的原因。4. 实战从零手写一个可用的Memory Provider4.1 抽象接口设计不要一上来就选型很多人一上来就急着选Mem0还是Hindsight我建议先自己抽象一套接口把选型推迟到后面。因为无论是哪个现成方案底层都逃不过写入、召回、删除、更新这四类操作。我先定义一个MemoryProvider的基类只暴露最小必要接口。from abc import ABC, abstractmethod from typing import Optional, List, Dict class MemoryProvider(ABC): abstractmethod def add_memory(self, content: str, metadata: Optional[Dict] None, memory_type: str episodic) - str: 写入一条记忆返回记忆ID pass abstractmethod def search_memory(self, query: str, top_k: int 5, filters: Optional[Dict] None) - List[Dict]: 根据query召回相关记忆 pass abstractmethod def update_memory(self, memory_id: str, new_content: str, metadata: Optional[Dict] None) - None: 更新一条记忆的内容 pass abstractmethod def delete_memory(self, memory_id: str) - None: 删除一条记忆 pass为什么要这样设计接口因为在Agent主循环里你只关心“把这段对话记下来”和“根据当前问题取出记忆”并不关心底层是向量库、SQL数据库还是简单的JSON文件。这样设计之后你可以从最简单的文件存储版本起步等数据量大了再平滑替换成Mem0或自己用向量库实现。4.2 写入链路提取过滤入库写入链路是整个Memory Provider里最容易失控的部分如果每轮对话都调大模型提取记忆成本会瞬间失控。所以我总结了一个低成本高覆盖的写入策略先判断这段对话里是否有值得长期记忆的信息再决定是否触发提取。def extract_memories(conversation: List[Dict]) - List[Dict]: # 用LLM判断哪些信息值得记忆用户偏好、事实、任务、重要事件 # 这里省略具体prompt正常会返回 [{content, memory_type, importance}, ...] prompt f 你是一个记忆提取器。下面是一段对话请提取值得长期记忆的信息。 只提取可验证的事实和明确的用户偏好不要提取寒暄和情绪化内容。 每条记忆给出内容、类型(episodic/semantic)和重要度(1-10)。 对话内容 {conversation} raw llm_call(prompt) memories parse_llm_result(raw) return [m for m in memories if m[importance] 6]过滤规则也很重要。我加的规则包括不存超过500字的原始内容不存纯语气词输出不存任何临时状态如“用户正在输入中”。写入时把同一条记忆的向量embedding生成好同时存原始文本和metadatametadata里必须有session_id和timestamp方便未来做隔离和衰减。异步化处理就是把整个提取过程丢进一个任务队列Agent主循环只负责把对话原文暂存到临时缓冲区等对话间隔期再统一提取。4.3 读取链路查询改写混合召回排序读取链路的质量直接影响Agent的回答质量。这里我会先做一个小小的查询改写把用户的原始问题转成一组检索词包括问题本身、命中的实体、用户ID、当前会话状态。比如用户说“我之前那个订单怎么样了”检索词就应该是“订单状态用户ID最近订单”而不是整句话原样去向量库碰运气。def search_memory(self, query: str, top_k: int 5, filters: Optional[Dict] None) - List[Dict]: # 1. 查询改写生成多个候选检索键 retrieval_queries [query] if filters and user_id in filters: # 会把查询和用户id拼成一条带过滤条件的查询 retrieval_queries.append(f{query} user_id:{filters[user_id]}) all_hits [] for q in retrieval_queries: hits vector_store.search(q, top_ktop_k * 2, wherefilters) all_hits.extend(hits) # 2. 合并去重按 score 排序 all_hits dedup_and_sort(all_hits) return all_hits[:top_k]召回之后我通常还会再让一个快速分类器过滤掉与当前任务无关的记忆比如用户问售后时不要返回和闲聊娱乐相关的内容。这一步可做可不做但如果你的Agent经常串味加这个过滤非常有效。排序完成后把记忆按固定模板拼接到Prompt里格式一般是“相关信息\n- 记忆内容\n- 时间xxx\n- 来源xxx”。4.4 集成进Agent主循环把Memory Provider接到Agent里其实只需要改三个位置对话开始前读取对话结束后写入每轮处理时拼接记忆上下文。下面是一段最小可运行示例。from custom_memory import SimpleMemoryProvider memory SimpleMemoryProvider() def agent_run(user_message: str, history: List[Dict]) - str: # 1. 读取长期记忆保留最近3轮工作记忆 relevant_memories memory.search_memory(user_message, top_k5) recent_window history[-3:] memory_text \\n.join( f- {mem[content]} (时间:{mem[timestamp]}) for mem in relevant_memories ) # 2. 组装Prompt prompt f 你是智能客服。这是与用户相关的长期记忆 {memory_text} 这是最近几轮对话 {recent_window} 用户当前问题{user_message} response call_llm(prompt) # 3. 对话暂存到缓冲区由异步写入器定期提取记忆 memory.buffer_message(user, user_message) memory.buffer_message(assistant, response) return response这段代码最关键的地方在于“最近3轮工作记忆长期记忆混合”。我试过只加长期记忆不加最近对话模型经常答非所问因为有些信息依赖前文的指代我也试过只保留最近对话不加长期记忆用户两周前表达过的偏好全丢。混合之后效果最稳。4.5 小规模评测没有记忆和有记忆的差距我在一个模拟客服数据集上简单测过效果连续对话十轮第一轮用户说“我可能会申请商品退款请用邮件通知我”后续轮次里用户突然说“退款的事请联系我邮箱”。没有记忆的Agent完全不知道“联系我邮箱”的邮箱地址是什么只能套话让用户再提供一次而加了Memory Provider的Agent能自动提取“退款需邮件通知”这个偏好语义在后面对话中直接调用邮件发送逻辑。最终没有记忆的版本任务完成率只有35%有记忆的版本完成率提升到了82%。这种差距不是模型能力造成的而是信息是否被“跨轮传递”造成的。要做到跨轮传递Memory Provider的写入链路必须从原始对话中抽取决定性信息而不是机械地存整个对话。这也是我建议使用类似Hindsight事后提取设计的原因。5. 踩坑实录与调优建议5.1 写入风暴每次对话都调LLM提取记忆成本炸了我第一版实现图省事直接在每轮对话结束后调用一次LLM做记忆提取结果一天下来Token消耗比主模型还多。后来我改成两个策略一是只有检测到“新实体”“用户明确偏好”“任务状态变更”时才触发提取其余时间只把消息暂存到缓冲区二是把提取任务丢进异步队列用便宜的小模型或专用模型来做而不是每次都让对话用的旗舰模型干这活。这两步直接把记忆相关成本砍掉了70%。5.2 召回串味检索到无关记忆导致回答前后矛盾这个问题非常高发。用户问A但你召回了一条跟A沾边但属于另一个主题的记忆模型就会被带偏。排查时我建议先打印召回结果看看分数排名前几的记忆到底是什么。常见原因有三个向量相似度阈值设得太低例如0.7以下就放行没有在检索时带用户ID过滤器导致跨用户召回没有对记忆做“主题标签”分类召回时无法精确过滤。我的解决方案是提高阈值到0.78所有检索都强制带session_id或user_id限制并给每条记忆加一个topic字段检索时用实体匹配先缩小候选集。5.3 遗忘策略记忆会过期不能只增不减很多人在做记忆系统时只盯着写入忘了设计遗忘。我问你一个问题如果用户三年前的地址还存在记忆库里每次对话都把它捞出来是不是一种污染所以我在Memory Provider里加了两个机制一是TTL普通情景记忆默认30天过期语义记忆除非被用户主动确认否则1年过期二是重要度衰减每次被召回的频率会提升记忆重要度长期不被召回的自动降权。这基本就是模拟人脑遗忘曲线效果还不错。5.4 集成前的自查清单给别人做完方案评审之后我习惯给一份自查清单。这里写几个最关键的检查点是否支持按用户隔离记忆是否所有记忆都有时间戳写入链路是否异步是否有去重机制是否支持用户手动删除记忆召回时是否能解释“为什么召回这条”最后一条尤其重要如果召回结果无法解释那么出问题时你根本没法调试。哪怕现成方案没有完整的可解释性也要自己在日志里记录每条记忆的score和来源。最后分享一个我自己的小经验这几个方案我最终只在生产环境里用了两个轻量场景直接用自己写的文件版MemoryProvider复杂场景选了一个带管理API的方案作为核心存储。踩过几次坑之后我越来越觉得Memory Provider不是越复杂越好而是先想清楚你的Agent会在什么场景下需要哪类记忆再决定是上一套完整平台还是自己封装一个简单模块。如果只是做Demo文件系统加简单向量检索完全够用生产环境再上带管理语义的组件也来得及。最好的一点是只要把读写接口抽象好后面换后端是完全不慌的。希望这篇文章能把你的记忆设计之旅拉直一点少走我走过的弯路。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

AI大模型日报:智能体训练新方法、本地部署与实战避坑 2026/9/28 15:53:36

AI大模型日报:智能体训练新方法、本地部署与实战避坑

1. 一日热点速览深夜盯完最后一轮模型评测数据,照例把这几天的AI圈动态做了个归档。说实话,这段时间的更新密度已经明显从“每周有惊喜”变成“每天不重样”,AI大模型、AI Agent、AI编程、AI应用开发这几个关键词几乎把所有技术讨论都卷在了一…

阅读更多 →
Innovus DRC修复实战:从Metal Short到天线效应及时序收敛 2026/9/28 15:53:36

Innovus DRC修复实战:从Metal Short到天线效应及时序收敛

做数字后端的人,应该都有过这种经历:floorplan、placement、CTS、routing一路跑下来,以为可以稍微喘口气,结果打开Innovus的DRC summary一看,几万条violation挂在眼前,其中“最扎眼”的往往就是Metal Short…

阅读更多 →
从GTX 1060到RTX 4090:NVIDIA显卡驱动版本选择与安装排查指南 2026/9/28 15:53:36

从GTX 1060到RTX 4090:NVIDIA显卡驱动版本选择与安装排查指南

NVIDIA显卡驱动,讲真是一个比很多硬件本身还耐人琢磨的东西。如果你只看官网,好像就是下载一个几百兆的安装包,双击、重启、完事。但等你手里同时有GTX 1060这种服役多年的老将,又种草RTX 4090这样的新卡时,会发现“NV…

阅读更多 →
基于ViT的CIFAR-10图像分类:训练与验证Python源码详解 2026/9/28 15:53:36

基于ViT的CIFAR-10图像分类:训练与验证Python源码详解

简介:基于Vit实现CIFAR10分类数据集的训练与验证Python源码包,是一份可直接运行的深度学习实践项目,面向计算机、人工智能、自动化等相关专业的学生、教师与从业者,适合期末课程设计、课程大作业或毕业设计等应用场景。项目以Visi…

阅读更多 →
硅胶球定制厂家有哪些 鼎诚橡塑源头生产厂家实力推荐 2026/9/28 15:53:36

硅胶球定制厂家有哪些 鼎诚橡塑源头生产厂家实力推荐

关于硅胶球的基础认知 硅胶球的核心属性与基础特征硅胶球是以硅胶为主要原材料加工制成的橡胶制品,属于弹性橡胶制品的一个细分品类,本身具备良好的回弹性、耐温性与化学稳定性。和普通橡胶球相比,硅胶球的材质稳定性更强,在长期震…

阅读更多 →
TP9932换XS9922C实战:车载视频解码芯片替代的引脚与配置全解析 2026/9/28 15:53:30

TP9932换XS9922C实战:车载视频解码芯片替代的引脚与配置全解析

做车载摄像头的同行应该对TP9932这颗芯片不陌生,尤其是做360环视、ADAS、DMS后装方案的工程师,前几年大量方案都是围绕它做的。最近我这边接到一个项目,客户明确要求把原方案里的TP9932替换成芯昇的XS9922C,说是成本、供货和交期方…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉