资讯动态

AI Agent记忆系统实战:从短期到长期,让智能体真正记住用户

发布时间:2026/9/9 4:57:39 来源:尧图企业网站定制
1. 先搞清楚Agent为什么需要一个脑子来记东西做AI Agent的同学应该都遇到过这种尴尬场景你上周刚跟客户聊完需求细节这周再打开对话窗口Agent一脸茫然地问你请问您的项目背景是什么。那一刻你才意识到自己养的不是智能助手而是一条只有七秒记忆的鱼。我在写走进AI Agent这个系列的第一篇、第二篇时反复强调过一个观点Agent的核心能力可以拆成感知、规划、行动三大块。但今天我要补上第四块也是最容易被忽略的一块——记忆。没有记忆的Agent学不会新东西记不住用户偏好更谈不上个性化服务。你让它帮你订机票它每次都问你一遍护照号你让它管理项目它每轮对话都要重新理解一遍业务背景。这哪是智能体这是失忆患者。所以让Agent记住你这个命题本质上是解决两个问题一是让Agent在单一会话内部保持状态短期记忆二是让跨会话、跨天的信息能够被持久化并重新调用长期记忆。前者靠上下文窗口和维护对话状态就能解决后者才是真正的技术分水岭。聊到记忆先得把概念分层。我习惯把Agent的记忆拆成三层短期记忆当前对话上下文可以用上下文窗口直接承载也可以单独维护一个对话状态对象。它的特点是容量小、实时性高、易丢失。长期记忆跨会话的用户画像、历史决策、偏好习惯存储在外部媒介数据库、文件、向量库需要时再检索回来。工作记忆Agent在执行一个复杂任务时临时保存的中间结果与任务状态比如当前正在处理哪个子任务已经完成了哪几步。这三层不是割裂的而是互相协作。短期记忆负责让对话接得上工作记忆负责让任务跟得完长期记忆负责让Agent懂你。真正要做到让Agent记住你难点几乎全在长期记忆的设计上。2. 记忆系统的关键技术选型与原理拆解2.1 先给记忆翻译成机器能懂的语言Embedding嵌入模型长期记忆要解决的第一件事是让Agent记住的信息可以被模糊找回。你不能指望用户某天翻旧账的时候说的话和当初记录时一字不差。比如用户曾经说过我特别怕冷冬天开会希望空调开高一点下次你可能只提一句会议室有点凉Agent就得能联想到上面的偏好。裸文本做不到这种联想必须把文本转成语义向量。这个转换过程就是Embedding。简单说嵌入模型会把一段文字映射成一组几百上千维的浮点数数组语义相近的文本在向量空间里的距离也近。你不需要自己训练这个模型——市面上现成的Embedding模型很多比如OpenAI的text-embedding系列、智谱的embedding-2、还有各种开源的BGE、M3E系列都可以直接用。实操中要注意一个点嵌入模型的选择直接影响记忆召回的质量而且不分语义粒度。如果你只是让Agent记住用户叫什么、家住哪这种结构化字段完全没必要走向量但如果你要记的是用户上一轮吐槽了项目进度这种自由文本必须靠向量才能做语义级召回。我自己的习惯是结构化偏好用JSON字段存非结构化内容才转向量。混着来成本高且效果未必好。2.2 记忆放哪向量数据库与存储选型有了向量就得决定把向量存在哪。现在大家最常接触到的方案是向量数据库比如Chroma、FAISS、Milvus、Qdrant、Pinecone。但这里必须说句大实话如果你做的Agent只是个人项目或者小规模内测压根没必要先上重型向量数据库。起步阶段用SQLite加一个向量索引、甚至直接用一个本地FAISS索引文件完全够用。等到数据量真的上了几十上百万条、需要高并发查询了再迁移到Milvus或者Qdrant也不迟。我踩过这个坑。当时一上来就部署了集群版向量库结果Agent没写多复杂运维先把自己劝退了。后来换成本地文件索引开发效率直线提升。技术选型永远要服从阶段目标。当然存储选型还牵涉到记忆的元数据管理。一条记忆不止是向量原文本还需要带时间戳、来源会话ID、记忆类型标签偏好/事实/事件、权重值。这样后续做记忆的过期、去重、更新才有依据。只用裸向量存记忆就是个只能存不能管的仓库。2.3 检索不是玄学召回、重排与混合检索存储解决的是放进去检索解决的是找出来。大多数Agent记忆系统的核心链路是用户问题 - 转为查询向量 - 在向量库里做相似度检索 - 挑出Top K条记忆 - 塞进Prompt上下文。听起来简单但要做好不容易。相似度检索的常用指标是余弦相似度或点积相似度。每条记忆算出来一个分数取分最高的几条。问题在于单纯靠向量相似度很容易捡回一堆字面相关但实际没用的垃圾记忆。比如用户问下午要不要开会系统可能召回一条用户上周说讨厌开会虽然语义有点关联但跟下午要不要开会这个具体查询差远了。我的做法是混合检索加一层重排。混合检索就是同时用关键词BM25检索和向量检索再把两路结果合并。重排环节可以简单点用LLM对候选记忆打分或者用交叉编码器模型做精排。前者灵活但费token后者成本低但需要额外部署模型。个人项目建议先用LLM打分准确率提升明显。2.4 技术栈选择不同语言生态的Agent记忆实现热词里提到Java AI AgentSpring Boot AI Agent客户端说明不少人关心传统Java技术栈怎么做Agent。这个我单独说一下。Python生态做Agent确实是最顺手的LangChain、LlamaIndex这些框架对记忆的支持已经很成熟拿过来就能跑。但如果你所在团队是Java为主也没必要强行切语言。Spring Boot 3.x配合Spring AI框架同样能实现对话记忆和向量检索向量库可以用Milvus或者PgvectorEmbedding调用也可以走HTTP接口方式接入。我自己实际用过Spring Boot Pgvector的组合效果并不差只是社区资料少一点一些细节要自己翻文档。比如会话记忆的持久化Spring AI里可以自定义一个Memory实现类把对话历史塞进PostgreSQL表里加上user_id和session_id字段就能实现跨会话的短期记忆读取。长期记忆部分再接上向量检索。真要给个建议的话如果Agent业务逻辑复杂、迭代快选Python如果重点是跟现有Java业务系统整合选Spring Boot不用盲目跟风重构技术栈。3. 实操从零搭建一个带记忆的Agent3.1 整体架构设计与记忆写入链路理论说了半天接下来直接上实操。我以Python生态为例搭一个最简但五脏俱全的带长期记忆的Agent。整体架构分五块对话入口接收用户消息记忆检索器根据当前问题召回历史记忆对话管理器组装Prompt系统人设 检索到的记忆 最近对话历史LLM调用层调用大模型生成回复记忆写入器从对话中抽取值得记住的信息转向量、入库import chromadb from sentence_transformers import SentenceTransformer # 初始化向量库这里用Chroma做演示 client chromadb.PersistentClient(path./agent_mem_db) collection client.get_or_create_collection( namelong_term_memory, metadata{hnsw:space: cosine} ) # 初始化嵌入模型 embedder SentenceTransformer(BAAI/bge-small-zh-v1.5) def write_memory(user_id, content, memory_typeevent): # 生成向量 vec embedder.encode(content).tolist() # 给记忆一个唯一ID这里用时间戳hash简化 import hashlib, time mem_id hashlib.md5((user_id content str(time.time())).encode()).hexdigest() collection.add( ids[mem_id], embeddings[vec], documents[content], metadatas[{ user_id: user_id, memory_type: memory_type, created_at: time.time(), access_count: 0 }] )这段代码做完你的记忆仓库就建好了。写入时可以按记忆类型打标签比如偏好、事实、事件方便后续过滤。3.2 记忆写入的触发策略到底什么值得记住记忆系统最大的坑之一就是把什么都往数据库里塞。用户的每一句话都记要不了几天向量库里全是噪音好的嗯嗯稍等一下。检索时屁用没有还平白增加存储和延迟。所以写入什么比怎么存更重要。我现在的策略分三层过滤信息价值过滤只记忆包含明确信息量的句子。判断方法可以是LLM输出结构化标签也可以简单用规则——句子长度小于N个字、不含任何实体、语气词为主的直接丢弃。时效性过滤临时性信息我今天下午开会记为短期事件过期就删长期偏好我不喜欢周三开会写入长期记忆。冲突处理新记忆跟旧记忆矛盾时不直接覆盖旧记录而是把两条都加上时间戳检索时以时间近的为准。比如用户以前说我喜欢靠窗的位置后来又说靠窗晒得慌两条记录共存靠时间去过滤。这一步如果用LLM来做抽取Prompt可以写复杂一点让模型输出JSON格式的抽取结果{ memory_items: [ { content: 用户不喜欢周三下午开会, type: preference, importance: 0.8 }, { content: 用户在上周提过项目A的截止日期是月底, type: event, importance: 0.5 } ] }写定时把importance低于某个阈值的丢弃可以顺便控制记忆库质量。3.3 记忆检索与注入让Agent在回答时想起你记忆写入之后关键是在合适的时机把它想起来。检索流程我固定为三步第一步基于当前用户输入生成检索Query。可以直接用用户原话也可以先做一轮意图改写。比如用户说今天会议还开吗如果只拿原话去检索大概率召回的是各种跟会议沾边的记录不如改写为查询用户今日会议安排。第二步做混合检索。向量召回Top50关键词召回Top30合并之后重排出Top5。第三步把检索结果按照相关性排序注入Prompt。这里的注入位置有讲究——我建议放在系统人设之后、对话历史之前并且要给每条记忆标注时间让LLM知道这条记忆是什么时候发生的。def retrieve_memory(user_query, user_id, top_k5): # 1. 生成查询向量 query_vec embedder.encode(user_query).tolist() # 2. 先按user_id过滤再向量检索 results collection.query( query_embeddings[query_vec], where{user_id: user_id}, n_resultstop_k * 3 ) # 3. 简单重排这里示意只做去重和按时间排序 memories [] for doc, meta in zip(results[documents][0], results[metadatas][0]): memories.append(f[{timestamp_to_str(meta[created_at])}] {doc}) return memories[:top_k] def build_prompt(system_prompt, user_query, user_id, chat_history): mems retrieve_memory(user_query, user_id) memory_block \n.join([f- {m} for m in mems]) return f系统设定 {system_prompt} 你掌握的用户长期记忆如下注意在合适时引用但不要生硬提及 {memory_block} 当前对话历史 {chat_history} 用户最新消息{user_query} 3.4 让Agent主动更新已有记忆而不是只追加能写能查大多数简易Agent记忆系统就到此为止了。但用多了你会发现记忆库里积累了一堆过时但仍相似的记录。用户三个月前说我在北京工作下次聊天改口我搬到上海了。旧的北京和新的上海两条记录同时存在检索出来模型就懵了。所以一个成熟的记忆系统必须支持更新和合并。我目前用的方法是在对话结束时做一轮离线整理把本次会话产生的所有候选记忆先跟已有的Top5相似记忆做一次相似度匹配如果相似度超过阈值判定为同一主题就执行合并或者替换如果低于阈值才作为新记忆插入。def upsert_memory(user_id, new_content): vec embedder.encode(new_content).tolist() # 先查一下库里有没有高度相似的 dup collection.query( query_embeddings[vec], where{user_id: user_id}, n_results1 ) if dup[documents][0]: old_doc dup[documents][0][0] similarity compute_cosine_similarity(vec, dup[embeddings][0][0]) if similarity 0.92: # 更新这条记忆的内容这里简化了实际还要保留历史版本 old_id dup[ids][0][0] collection.update( ids[old_id], documents[new_content], embeddings[vec], metadatas[{**dup[metadatas][0][0], updated_at: time.time()}] ) return updated # 没找到就新增 write_memory(user_id, new_content) return created这个0.92的阈值是我调出来的经验值不同嵌入模型、不同文本类型会有偏差建议你自己跑一批标注数据卡一下。4. 记忆系统的工程化落地与避坑实录4.1 记忆污染不该记的被记住了怎么办记忆污染是Agent记忆系统里最隐蔽也最致命的坑。典型场景用户说了一句气话你们这个产品真是垃圾Agent把它当成长期偏好记录下来后续每次对话都以为用户对产品有成见回答都变得小心翼翼。本来只是玩笑结果变成长期记忆里的事实。解决这块我总结了三条情绪化表达不入库在抽取记忆前加一层情绪识别负向情绪强烈的句子默认只记当次对话上下文不写入长期记忆。建立记忆纠错机制用户明确说我上次说的不对或者你记错了时触发对该主题记忆的删除或降权。这一条在Prompt里码清楚模型基本能做到。定期抽查可解释每条记忆都要能溯源到原始对话。我建过一个简单的管理后台列出Agent记住了用户什么用户能手动删除某条记录。这既是纠错手段也是用户信任的来源。4.2 记忆的生命周期管理过期、归档与遗忘遗忘能力在记忆系统里的重要性比很多人以为的更高。有些信息天生有时效性我在找房子这种状态三个月后大概率失效。如果不过期Agent会把过时信息当最新情报用。我给每条记忆设置了三个维度重要度0到1、最后访问时间、创建时间。后台跑一个定时任务重要度低 超过30天未访问 - 归档到冷存储不再参与日常检索任何记忆超过180天未访问 - 降权处理用户主动要求删除 - 物理删除遗忘机制的价值还在于控制记忆规模。向量库的检索速度在数据量小的时候不敏感但到了百万级每次检索的延迟和成本都会上来。有策略地遗忘比一味扩容更健康。4.3 检索不准向量召回失灵时怎么排查做记忆检索最常遇到的问题就是召回了看似相关实则没用的记忆。我总结了一套排查思路分享给遇到同样问题的朋友。按顺序查三层问题第一层是嵌入模型是否合适。中文场景下用英文语料训练的Embedding模型语义召回效果会明显偏差。换成BGE或M3E等中文优化过的模型往往能解决大部分问题。第二层是检索策略是否太单一。纯向量检索适合语义相近的场景但某类查询其实更适合关键词。比如用户问上次说的那个项目预算如果记忆里恰好有预算这个词但语义向量关系弱向量检索可能漏掉。把BM25加上用混合检索的调和平均分数取Top结果召回率会好看很多。第三层是Query本身是否需要改写。用户口语化表达太多比如那个就是那个啥直接用原话检索大概率召回一堆废话。在检索前让LLM把用户问题改写成一个查询式语句比如用户询问上次提到的项目预算金额效果会明显改善。4.4 记忆的成本与性能别让记忆系统拖垮你的Agent记忆系统的成本主要包括两部分存储成本和检索成本甚至还有LLM重排的成本。很多项目做大了之后发现整个Agent的响应延迟一大半花在记忆检索上。控制成本的实操建议召回调低再精排向量检索阶段多召回一些候选比如Top50但精排时用轻量级模型或规则优先过滤只有最终Top5才塞进Prompt。给记忆分区热点用户记忆放热存储低频记忆放冷存储不要让日常查询扫全量数据。对记忆做缓存同一个用户在同一天多次查询相似内容时直接复用上一次的记忆检索结果配合Redis或者内存缓存能省掉一半以上的向量检索调用。我跑过一组对比测试加了记忆分区和缓存之后记忆检索环节的P95延迟从620毫秒降到了180毫秒。对于对话型Agent来说这个体感差异非常大值得花时间去调。4.5 场景落地Obsidian Agent构建个人知识库扒热搜词的时候看到obsidian ai agent 知识库这个词条我自己搭过这套方案正好展开说说。Obsidian本地Markdown库天然是Agent记忆的好载体——因为记忆本来就是文本Markdown文件存储、Git管理版本、本地检索架构清晰。我搭了一个个人记忆增强工作流每天Agent处理完对话后将抽取出的重要信息按类型写入Obsidian库中的不同目录比如用户偏好、项目事件、灵感笔记Obsidian的双链特性可以辅助记忆关联Agent在写入新记忆时自动插入关联链接检索时用Agent读取Markdown目录索引再配合向量检索定位具体段落这套方案的优点有两个一是记忆文件是纯文本可读可控可修改随时可以用Obsidian手动查看和编辑Agent的记忆解决了黑盒问题二是可以借助Obsidian的插件生态把Agent记忆和用户的日常笔记打通形成真正的第二大脑。当然它的局限也很明显不适合高并发、多租户的线上场景只适合个人或小团队内部使用。如果你的产品要给多人提供服务还是老实用数据库加向量库那一套。4.6 隐私与数据安全记住用户要守住边界让Agent记住用户本质上是在采集和存储用户的数据。这里牵扯到隐私问题我建议做Agent项目的朋友都认真对待别等到出事再补窟窿而且这也是用户的信任根基。坦白说我认为AI从业者不能只顾着追效果避重就轻。我给自己的记忆系统定了几条硬规矩敏感信息默认不写入长期记忆。密码、身份证号、银行卡号、精确家庭住址这类信息Agent识别出来之后直接丢弃或者只做一次性使用不落入持久化存储。记忆数据加密存储尤其向量库里的元数据和原始文本至少要做字段级加密。提供记忆管理权给用户。用户应该能查看Agent记住了自己什么、能删掉某条记忆最好能一键清空。数据隔离不同用户之间的记忆必须通过user_id严格隔离检索时强制过滤不能出现跨用户数据泄露。这些规矩在技术实现上并不复杂成本也低但能避免大量后患。如果你要把Agent做成商业化产品记忆合规的设计更是绕不开的关卡。比如你保存用户喜欢什么咖啡没问题但如果保存的是身份敏感信息就得谨慎再谨慎。5. 常见问题速查表与排错实战把记忆系统从0搭到可用的过程中我踩过不少坑。这里整理成速查表方便大家对号入座。常见问题表现排查方向解决方案记忆检索结果不相关Agent回答时引用了错误的记忆检查Embedding模型是否适配语言检查混合策略是否生效换成中文优化模型加BM25关键词召回重排前先过滤user_id记忆库增长过快存储成本升高检索变慢检查写入策略是否滥记引入重要性过滤、情绪过滤低质信息直接不入库用户信息变更后Agent仍然用旧记忆用户说搬到了上海Agent还按北京的上下文回答检查更新逻辑和冲突处理策略实现upsert时间戳冲突时以新记忆为优先定期离线合并相似记忆Prompt被记忆塞满上下文超长token消耗飙升检查Top K设置和记忆长度限制Top K为3到5条每条记忆摘要化时间敏感的旧记忆剪掉同一用户的记忆互相干扰不同项目的偏好混在一起回答检查记忆tags是否缺失增加场景、主题标签检索时携带tag过滤条件Agent突然失忆重启后长时间记忆消失检查持久化是否落盘本地向量库路径是否正确确认使用PersistentClient定期备份向量存储文件并发写导致记忆重复同一会话多次写入同一条记忆检查写入去重逻辑在写入前做相似度检查用全局记忆ID保证幂等性用户敏感的对话被长期保存使用者反馈隐私风险检查敏感信息识别与生命周期管理敏感字段脱敏、加密设置记忆过期策略提供用户手动删除入口补充一个很多新手容易忽略的点LLM本身的上下文窗口再大也不能替代记忆系统。哪怕你用的是128K上下文窗口的模型把用户3个月的对话全塞进去也不现实——token成本高、有用信息被稀释、模型注意力被拉散。记忆系统真正要做的不是全存全取而是算准该记什么、找准该取什么。另外有条件的话建议给记忆检索加一层简单的A/B测试。同一个用户问题分别走无检索记忆和有检索记忆两条链路比较回答的相关性和用户满意度。我做过一次对比测试加了长期记忆之后用户评价里的它懂我类反馈提升了大约40%这个提升幅度相当可观。6. 记忆之上Agent从工具到伙伴的进化关键谈完记忆的技术实现我想往深里聊一层。记忆对Agent的意义不仅仅是能记住用户说过的话。它把Agent从一个无状态的工具变成了一个有连续自我认知的系统。这个转变的深度超出很多人的想象当Agent能记住上次我们讨论到哪了你上次说过你倾向哪种方案它就不再被当作搜索引擎的替代品而是一个真正可以协作的伙伴。我观察到一个有意思的现象很多Agent应用在没加记忆之前用户的活跃时长很短用完即走一旦加上长期记忆用户开始有意愿回来继续对话因为它居然记得我。记忆是建立粘性的重要抓手。顺着这个思路看热词里提到的ai agent 2026发展趋势。我个人判断未来两年Agent市场的分化很大程度上取决于记忆能力的深浅。短期靠模型能力长期拼的是记忆架构的成熟度——谁能把跨会话、跨场景、多用户的记忆系统做好谁就能在当前同质化的Agent赛道上拉开明显差距。另一个值得关注的方向是多Agent共享记忆。一个Agent记住的经验能不能迁移给另一个Agent用比如客服Agent学会了某个问题的处理方式把它沉淀成标准流程的记忆再传递给销售Agent参考。这个领域目前还比较早期但它会是Agent从单体智能走向群体智能的必经之路。还有一点记忆系统正在反向塑造大模型的交互范式。过去我们总是把记忆塞进Prompt让模型被动读取现在慢慢开始出现模型主动向记忆系统发起读取请求的设计模式让Agent在对的时间查询对的记忆比一次性把记忆全量注入效果更好。当然记忆系统的构建没有银弹。我给不同阶段项目的建议是原型验证阶段别想太复杂先用ChatGPT的记忆功能或者LangChain的大窗口上下文验证带记忆的交互体验是不是用户真正需要的MVP阶段接入一个向量数据库Chroma足够实现短期记忆拼接 长期记忆检索的最简链路规模化阶段再考虑混合检索、重排、记忆分区、多级缓存、自动遗忘这类工程化能力如果你正准备给自己的Agent加记忆模块我的建议是先跑通最简链路不要一上来就上重型架构。一个能稳定跑通的记忆1.0比一个画饼的记忆2.0有价值得多。最后分享一个我个人的小习惯每过一段时间我会去翻一翻我自己Agent的记忆库看看它记住了什么、忘了什么、记错了什么。这既是排查系统问题的有效手段也是在不断提醒自己——Agent记忆能力的边界本质上也是我们对用户理解的边界。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价