从业者都知道一句话:看似智能的对话,背后往往藏着一堆“假装记得”的妥协。我做过不少智能体项目,最常被问的问题不是“模型效果怎么样”,而是“它怎么老是记不住我之前说过的话”。比如用户上午说要周五去成都出差,下午问“帮我订那家火锅店”,智能体一脸茫然。原因很简单——模型本身没有记忆机制,每一轮对话都是重新开始,而知识库又只解决“懂不懂”,解决不了“记不记得你”的问题。
这篇文章我想完整拆一遍智能体记忆体系的设计思路,从知识库到长期记忆的分工、写入流程、更新策略,再到检索和落地时的常见坑。内容全部来自我做实际项目时验证过的方案和踩过的坑,适合正在做智能体应用、AI客服、知识助手或Agent记忆机制相关工作的朋友。文章不会堆概念,以可直接落地的实操经验为主。
1. 记忆体系的分工:先搞清楚三类记忆各管哪一段
1.1 为什么知识库解决不了“记住用户”的问题
很多团队的第一反应是“把用户资料也存进向量库,跟知识库一起检索不就行了”。这个思路能跑通demo,但一到真实场景就会出问题。知识库的本质是面向全体用户的静态文档集,它回答的是“成都哪些火锅店评分高”“周五有没有直飞成都的航班”这类事实性问题。它的内容来自产品手册、业务文档、FAQ,是预置好的,跟具体某个用户没有关系。
长期记忆不一样。它回答的是“这个用户上周说了什么”“他偏好靠窗还是靠走廊”“他之前出差去过几次成都”。这类信息的钥匙是用户ID,不是关键词。你把用户的历史记录塞进知识库,等于让所有人共享同一份记忆,检索时必然串扰——A用户的偏好可能被B用户触发,这在真实业务里是不可接受的。
所以我把记忆体系拆成三条并行的通道,各管一段,互不替代:
- 知识库:静态的、可检索的领域知识,面向全体用户,人工维护为主。
- 短期记忆:当前会话内的上下文,比如“用户上一步操作是什么”“当前意图是什么”,对话结束即失效。
- 长期记忆:跨会话的用户画像级信息,包括偏好、习惯、历史决策、身份属性,动态写入并长期保留。
用一句话记忆这三者的边界:知识库解决“懂不懂”,短期记忆解决“接不接得上”,长期记忆解决“记不记得你”。
1.2 它们在工作流程上有什么本质区别
我见过最直观的对照表是这张,平时给别人讲记忆体系时也直接拿这张表用:
| 记忆类型 | 典型存储 | 检索方式 | 生命周期 | 更新频率 |
|---|---|---|---|---|
| 知识库 | 向量库、文档索引 | 语义检索+关键词混合 | 随业务文档迭代 | 低,人工为主 |
| 短期记忆 | 对话上下文窗口 | 按顺序拼接、截断 | 单次会话 | 每轮都在变 |
| 长期记忆 | KV库、向量库、结构化DB | 按用户ID精准过滤+语义召回 | 跨会话长期保留 | 中,关键节点触发 |
三条通道的存储介质甚至都可以不同。长期记忆我通常拆成两部分:结构化字段存原子事实,比如“不吃辣”“偏好靠窗”,用KV或关系库;语义描述存场景化摘要,比如“用户提到过去成都出差经常住在春熙路附近”,用向量库。知识库可以单独放一套文档索引。把存储分清楚,后续的写入和更新才会好做。
1.3 设计记忆分层的第一个判断标准
落到具体方案设计时,我习惯先拿一张纸列出所有可能被智能体用到的信息,然后逐个打标签:这个信息是“所有用户共同的”,还是“某个用户私有的”?是“这个会话有效”,还是“跨会话都必须记得”?是“人工维护的静态数据”,还是“从对话里自动提取的动态数据”?这一轮打标签做完了,整个系统的边界就清晰了,后面选型、建表、定检索策略都会顺畅很多。
注意:记忆分层不是越复杂越好。业务简单时,两层就够了——知识库加短期上下文。长期记忆只有在真的需要“记住用户”的场景才值得做,比如AI客服、个性化推荐、行程规划、健康管理。别为了做记忆而做记忆。
2. 历史会话筛选与压缩:长期记忆的“材料预处理”才是真正的分水岭
2.1 原始对话记录不能直接进长期记忆
这是很多人踩的第一个大坑。把每一轮对话原封不动存进长期记忆库,短期内数据量少看不出问题,跑几个月之后整个库就变成了一堆噪声。一次10分钟的正常客服对话,可能有一大半是“嗯”“好的”“谢谢”“我再看看”,真正值得记住的也许只有一句话:“用户偏好安静的餐厅”。直接存原始文本,不仅浪费存储,还会在检索时召回大量无意义片段,严重干扰模型判断。
我把长期记忆的写入分成三个阶段:筛选、压缩、结构化。筛选用规则或LLM判断信息价值,压缩把长文本折叠成短描述,结构化把短描述转成JSON字段或固定格式。三个阶段都做完了,才算得到一条合格的长期记忆条目。
2.2 三步筛选法:从对话里找出值得记住的东西
第一步是领域相关度过滤。不同业务值得记住的信息类型不同。旅行场景核心是偏好、行程决策、身份属性;电商客服核心是订单状态、售后诉求、商品偏好;企业办公助手核心是会议时间、项目里程碑、协作关系。我会准备一张“值得记忆的信息类型清单”,过滤时直接对号入座,不在此列的内容一律丢弃。
第二步是信息新鲜度判断。同一信息在对话中反复出现时,只保留最新一次的表达。比如用户先说“我比较喜欢安静”,两轮后又补充“安静但不要太贵”,长期记忆里应该合并成“喜欢安静且价格适中的餐厅”,而不是存两条互相覆盖的旧描述。
第三步是结构化提取。我通常用一个专门的LLM调用来做,传入对话片段,输出严格的JSON:
你是长期记忆提取器。请从以下对话中提取值得长期记忆的用户信息,输出JSON。只保留对后续服务有持久价值的信息。 对话片段: {对话文本} 输出格式要求: 1. 用户偏好:明确的偏好描述,如饮食偏好、沟通风格、服务要求 2. 用户属性:身份、时间约束、场景信息 3. 历史事件:已完成或计划中的关键动作 4. 如果某类信息没有出现在对话中,则输出空数组实操时我会再加一个最低价值阈值:如果某一段对话提取出来的条目少于一条,整段直接丢弃,不写库。这一步能有效控制长期记忆库的膨胀速度。
2.3 压缩的两种策略:摘要式还是抽稀式
压缩和筛选是两件事。筛选决定“哪些内容可以进库”,压缩决定“进库的内容以什么形态存在”。我常用的两种方案可以组合用。
策略一是轮次摘要,适合长会话的中间部分。按固定窗口(比如每10轮)生成一段摘要,把窗口内的细节折叠成一句话,保留关键实体和决策结果。优点是token消耗可控,缺点是会丢细节——如果用户在第8轮提了一个特殊要求但在第15轮才确认,摘要可能把中间过程压没了。所以我会避开关键信息密集区,会话开头和结尾尽量保留原文。
策略二是关键信息抽稀,适合信息密度高的业务。只保留对话中出现的“实体变更记录”和“用户明确表态”,比如“改成周一”“我不喜欢辣的”“就定这家吧”。这类内容可操作性强,几乎都是决策类信息,压缩损失极小。下单、预订、投诉处理这类场景我基本用抽稀模式。
注意:压缩必须在写入前完成,不能在检索后再临时压缩。检索后压缩会丢失被召回的上下文,导致生成质量不稳定。这个顺序我踩过一次,后来统一在写入管道里解决。
3. 长期记忆的写入机制:何时写、怎么合并、怎么控制质量
3.1 写入时机的折中方案
长期记忆写入时机有两个极端,我都试过。会话结束时一次性写入,准确率高,因为能拿到完整上下文,但中途断线就会整段丢失。实时逐轮写入,抗中断能力强,但开销大,而且容易产生中间状态覆盖最终状态的问题——用户先说“我要去成都”,后来又“算了不去了”,逐轮写入可能已经把“要去成都”存进去了。
我最终采用的关键节点触发写入是这两个极端的中间态。设定四个明确的写入节点:用户明确表达偏好时、完成一次决策时、更正了之前的信息时、会话进入收尾阶段时。这四个节点触发即时提取和写库,其他轮次只放在短期上下文里。实测下来,写入频率大幅降低,关键信息又不丢,成本也可控。
3.2 写入流程里必须有去重与合并
长期记忆最怕重复和矛盾。重复让检索结果冗余,矛盾让模型无所适从。我的写入管道里有一个独立的合并模块,逻辑是这样的:
- 主键设计:每个记忆条目用“用户ID+实体类型+实体名”做主键。比如“用户123擅长前端”,主键就是 user123_skill_前端。
- 写入前查询:新条目写入前,先按主键查一次旧条目。没有旧条目就正常写入,有旧条目就进入合并判断。
- 合并策略:按下述三种情况选择处理方式。偏好变更类场景用时间优先,保留时间戳最新的值;语义不冲突的场景做语义合并,把新旧融合成更完整的表述;新旧确实冲突且无法判断优先级时,保留旧条目的同时新增带时间戳的新版本,让模型调用时自行判断。
- 冲突检测:用LLM做一次矛盾判断。判断“用户不吃辣”和“用户点了麻辣火锅”是否矛盾,这类任务需要语义理解,字符串匹配做不到。
3.3 写入质量控制的几个细节
写入质量直接决定检索质量,这三个细节我长期坚持。
第一,信息粒度要小。一条记忆只表达一个事实,不要写成长段落。小粒度条目检索命中率高,合并去重也容易。我习惯把长期记忆拆成“原子事实”,每个事实控制在50字以内,或者直接以JSON结构存在。
第二,来源要可追溯。每条记忆都带时间戳和来源会话ID。没有时间戳的记忆,面对“上周说喜欢A,这周说喜欢B”的场景,你根本没有判断依据。来源会话ID更是排查问题时的关键线索,哪条记忆写错了,顺着会话ID回去看原始上下文就行。
第三,冷启动时做记忆预置。如果业务有历史数据沉淀,用离线任务批量提取存量对话,生成初始记忆库。你的长期记忆是从零慢慢积累的,有存量数据就值得做一次预置,能显著提升新用户冷启动时的个性化体验。
4. 长期记忆的更新策略:不更新比不记忆更危险
4.1 三种必须触发更新的场景
用户是会变的。长期记忆如果只写不更新,跑一段时间就会积累大量过时信息,比没有记忆还糟糕。因为过时信息会主动误导模型判断。我总结出三种必须触发更新的场景。
偏好变更,用户明确说“我现在不吃辣了”“以后不用靠窗位置了”。这是最优先级最高的主动更新,必须立即覆盖旧值,不能犹豫。
行为纠正,用户对智能体推荐说“不要这个”“这次换一个”。这说明之前对用户的理解有偏差,要根据纠正内容反向更新相关条目。比如之前记忆“用户偏好商务酒店”,用户纠正“上次的酒店太商务了,这次换民宿”,那这条记忆就要改成“用户偏好有设计感的民宿”。
时间衰减,某些记忆有时效性,比如“用户周三出差”“用户近期在看相机”。到期后如果不清理,就会变成长期噪声。这类记忆我一般用一个过期时间字段管理,到点自动转成expired状态。
4.2 更新的工程实现:版本升级而不是物理删除
更新流程跟写入类似,但多了一步“旧值处理”。我不会直接物理删除旧条目,而是给每个记忆条目加状态字段:active代表当前生效,superseded代表已被覆盖但保留历史,expired代表已过期失效。
这个设计有三个好处。检索时只查active状态,避免新旧冲突;出现争议时能回溯历史版本,搞清楚某条记忆是怎么来的;做用户画像分析时,历史记忆轨迹本身就是很有价值的数据。
实际操作上,我用LLM生成“更新指令”而不是直接改写数据库。比如LLM输出一条JSON,表示“将主键 user123_pref_spicy 的值从'能吃辣'更新为'不吃辣',操作类型overwrite,原因‘用户主动更正’”。下游程序解析这个指令后执行数据库操作。这样做能把模型生成内容和实际数据库状态解耦,任何一条更新都有据可查。
4.3 更新粒度:增量为主,全量重建为辅
很多人更新长期记忆时习惯每次会话结束,就把这个用户的所有记忆用LLM重写一遍。小规模时没问题,记忆量大了就很浪费,全量重写一次动辄几千token,还容易在重写中遗漏细节。
我的习惯是增量更新为主,全量重建为辅。平时会话产生的更新,几乎都可以通过“定位目标条目→覆盖值”完成,成本低且精准。只有两种情况做全量重建:一是用户历史记忆长期未整理,条目碎片化严重;二是业务规则或记忆schema变更,比如新增了记忆维度,需要重新提炼历史数据。全量重建时,先导出该用户所有历史记忆与关键会话摘要,交给LLM重新生成结构化记忆库,规则校验后再替换。
重要提醒:任何全量重写都必须先备份旧数据。一次生成结果出错,没有备份,用户的长期记忆就彻底乱了,这种基于语义的错误用规则很难自动修复。
5. 知识库与长期记忆的协同:检索策略与上下文构建
5.1 先做场景路由,再决定查哪类记忆
同时拥有知识库和长期记忆两套数据源后,接下来要解决的是判断“当前这轮该查哪个”。我加了一个轻量级路由判断,放在检索之前。
依据是用户问题里的关键词、指代关系和业务上下文。百科型问题,比如“成都太古里有什么好逛的”,走知识库。个性化内容,比如“我上周收藏的那家店叫什么”,走长期记忆。建立了依赖的,比如“结合我之前说的预算,推荐一家川菜馆”,需要两路并发,把结果拼接后再处理。
路由本身可以让LLM输出一个分类结果,三种意图:knowledge_base、long_term_memory、both。both时并行走两条链路,最后合并。这个路由判定的准确率对整体体验影响很大,值得花心思调优。
5.2 长期记忆检索的两条铁律
长期记忆检索和知识库检索最大的区别在于,检索范围必须先按用户隔离。这不仅是数据安全的要求,也是检索质量的前提。不做隔离,向量相似度会从其他用户那里捞出相似记忆,导致串台。
完成用户隔离后,我用两个手段保证检索质量。
手段一是融合检索。向量相似度负责语义召回,结构化过滤负责精排。比如先用“餐厅+安静”做语义召回,再用“用户ID+城市+菜系”做结构化过滤。长期记忆里大量是结构化偏好字段,纯靠向量检索浪费了这些高精度信息。融合检索能发挥两类数据的优势。
手段二是时间衰减加权。给越新的记忆越高的检索权重。在向量距离分数的基础上,按时间衰减系数加权,比如最近7天权重1.0,每过一个日志衰减一部分。这样相同偏好描述里,最新一次表达的权重显著高于几个月前的旧描述。实践中我用一个衰减系数结合具体业务去调,让新旧记忆的排序更合理。
5.3 上下文构建:克制地喂给模型
检索到了记忆,还要决定怎么拼进上下文。我踩过一次典型的坑:把检索回来的所有记忆不分主次全拼进去,模型被大量无关信息干扰,回答质量反而下降。上下文构建的原则是克制。
优先放高确定性的结构化信息,比如用户身份、明确的偏好变更、最近一次决策记录。这些信息模型可以直接信任并应用。长尾记忆折叠成摘要,不重要的历史过时偏好就一句话概括,并注明“用户过去半年内曾提到,后期未再提及,仅供参考”。长期记忆相关token控制在上下文窗口的四分之一以内。记忆不是越多越好,超出窗口承载后边际收益会迅速下降。
从检索到拼接的每一步,都要按用户ID严格隔离。这技术上是底线要求,合规上也是必须做到的。
6. 工程实践中的常见问题与排查实录
6.1 记忆检索不到,或检索结果不相关
这是最常见的问题,我排查时按这个顺序走。
先看写入侧。查一下用户对话有没有被正确提取并写入,很多“检索不到”其实根本是“写入就没成功”。检查写入日志,看关键节点有没有触发提取流程。
写入没问题就看检索条件。用日志确认路由判断是否正确,是否把个性化问题误路由到了知识库。再看过滤条件是否过于严格——比如加了菜系过滤但用户根本没提菜系,结果集被过滤成空。向量检索的相似度阈值也值得复查,阈值设太高会滤掉所有相关记忆。我的处理习惯是先放宽召回,再用精排过滤。
链路都通了还是检索不到,大概率是语义表示覆盖不足。对记忆条目做改写扩写是个有效兜底方案,把口语化的记忆文本扩展成不同表述,提高被检中概率。比如“爱吃辣”扩写成“偏好辣味”“喜欢川湘菜”“无辣不欢”。
6.2 记忆更新后出现矛盾信息
更新机制没做好冲突合并,就会出现新旧记忆并存。我最保守的处理方式是“叠加版本”——任何时候都不轻易物理删除旧记忆,尤其是偏好类信息。发现矛盾时,先看时间戳,用条目里的时间戳判断最新版本,把superseded状态的旧条目过滤掉。如果新条目本身有歧义,比如“用户不吃辣”和“用户点了麻辣火锅”并存,再做一轮基于上下文的消歧,判断是偏好更改、特殊情况还是提取错误。
6.3 长期记忆的隐私与安全问题
这点必须单独说。长期记忆保存的是用户个人数据,泄露或被错误使用的后果和知识库完全不同。
我落地时的最低要求是:读写分离,检索服务逻辑上没有更新入口,更新任务走独立管道。所有记忆条目访问必须绑定用户ID权限校验,服务端做二次校验。同时提供用户透明机制,比如“记忆管理”页面,让用户能查看、导出、删除自己的记忆数据。删除要做成深度清理,连同历史版本和日志引用一并清除,防止残留在备份或缓存里。
做记忆系统的安全意识需要很强。每多存一条用户数据,就多一分责任。记忆是为了更好地服务用户,不是为了让用户被看得更透。
6.4 成本与性能控制
长期记忆的成熟度是用成本换来的。写入阶段每次要调LLM做提取,检索阶段要查向量库,上下文拼接要占token。几个控制成本的方法供参考。
批处理写入,把同一用户一个时间段内的多条待写入记忆合并成一次LLM调用,能明显减少重复开销。热点记忆做缓存,高频访问的记忆条目放本地缓存减少重复检索,但用户主动更新后必须立即失效缓存。分级存储,高频记忆放热存储,低频历史记忆放冷存,必要时才加载。动态窗口控制,根据时间衰减动态调整参与检索的条目数量,不每次全量召回。
控制成本的底层逻辑是:大部分用户80%被检索到的记忆集中在20%的条目上,热点冷点分层能大幅降低开销。这个规律在很多业务里都成立。
7. 长期记忆系统的整体架构与演进方向
7.1 一套经过验证的分层架构
把前面所有模块合成一个整体,我目前验证过最稳的架构长这样:
- 会话层:维护短期记忆与当前意图,负责多轮对话。
- 接入层:做路由判断和上下文构建。
- 记忆写入管道:从原始对话中筛选、压缩、提取、合并,写入长期记忆库。
- 记忆更新服务:处理主动更新、冲突合并、过期清理、全量重建。
- 记忆检索服务:按用户隔离、语义召回、结构化精排、时间加权。
- 存储层:结构化存储(KV或关系库,存原子事实和偏好字段)、向量库(存语义化摘要)、日志库(存写入与更新审计记录)。
整个架构的核心原则是读写分离、分层解耦、按用户隔离。写入管道和检索服务之间不共享在线状态,用任务队列异步衔接。这样写入过程不阻塞在线查询,系统也具备更好的水平扩展能力。
7.2 接下来可以怎么做
有几个经过验证的演进方向,按优先级排序供参考。自动记忆整理,定期对长期记忆做碎片整理和冗余合并,防止体系长期运行后碎片过多。分层记忆抽象,从原子事实向上归纳出用户画像级副本,服务不同粒度的任务需求。多智能体记忆共享,在用户授权前提下,让不同业务域的智能体共享一部分偏好,减少重复询问。可解释记忆,回答生成时附带记忆引用来源,用户问“你怎么知道我不吃辣”时能给出明确出处。
这些方向不需要一步推完。我的建议是从记忆的可靠写入和稳定检索做起,基础打牢后再逐步演进。记忆体系做得越深,智能体的上限越高,但它依赖的是扎扎实实的工程沉淀。
最后的体会
这套记忆体系我前后迭代了好几版,最大教训可以浓缩成一句:长期记忆的难点不在存储,而在写入和更新的纪律。你能否从噪声对话里精准筛选值得记住的信息,能否在偏好变更时干净地覆盖旧值,能否在检索时严格守住用户边界——这些决策的质量,直接决定智能体的表现上限。
从知识库到长期记忆,本质上是让智能体从“知道世界”进化到“了解用户”。前者考验检索能力,后者考验系统设计能力。如果你正在做类似的系统,我的建议是先选一个小范围场景跑通全链路,再逐步放开数据规模。遇到底层模型效果波动时不必慌张,重点检查记忆写入和检索链路是否稳定——很多输出质量问题,归根结底是记忆质量问题。
我每天都在和这套体系打交道,越来越确信一个判断:记忆能力就是智能体的分水岭。没有记忆的智能体,永远只能回答眼前的问题;有记忆的智能体,才可能真的做到“越用越懂你”。这条路上坑不少,但方向是对的,值得扎扎实实做下去。