资讯动态

AI Agent记忆机制详解:从上下文管理到向量检索的工程实践

发布时间:2026/9/10 20:31:21 来源:尧图企业网站定制
1. 为什么Agent需要“记住你”这件事赶在写这篇之前我刚把手头一个客服对话Agent的上下文方案重做了一遍。之前那个版本有个很典型的问题用户昨天刚问过“你们家有没有支持POE供电的8口交换机”今天换个方式问“那个能走网线的交换机会员价多少”Agent就完全懵了不仅答非所问还把用户当新访客又重新推销了一遍基础款。问题不复杂就是Agent没有记忆。在之前的文章里我们聊过Agent的基本运行逻辑和工具调用但说实话如果Agent上线后连用户是谁、聊过什么、做过什么决策都记不住那它的体验跟一个每次都重新自我介绍的客服没什么区别。记忆功能是AI Agent从“能用”走向“好用”的关键分水岭它决定了多轮对话的连贯性、个性化推荐的准确度以及复杂任务比如跨多天的方案跟进能否跑得通。这篇博文适合谁看如果你已经在用LangChain、Cohere、OpenAI、LlamaIndex这类框架搭过Agent但一直觉得对话“智商在线但不贴心”如果你正在做一个需要沉淀用户画像、历史决策、偏好信息的AI产品又或者你只是对“怎么让AI记住我”这件事感到好奇这篇文章都能给你一条清晰的落地方案。我先摆一段实操里最典型的场景方便你对齐这篇文章要解决的问题用户第一轮“帮我推荐一款适合200平米办公室的无线AP。”Agent推荐了型号、数量、部署建议。用户隔天再来“上次那套方案你帮我算一下带46个终端会卡吗”如果Agent没有记忆第二个问题它根本不知道“上次那套方案”指什么。有记忆的Agent会从存储里召回上次对话的实体信息——产品型号、办公室面积、终端数量然后基于这些内容直接计算。这才是“记住你”的真实含义。2. 记忆机制设计的核心思路与选型考量2.1 先搞清楚“记忆”在Agent里到底是什么在涉足具体实现之前得先重新审视“记忆”这个词。做Agent的记忆跟人类记忆有一点点相似但又不完全相同。从工程角度拆解Agent的记忆至少可以分成四层第一层会话级工作记忆。就是当前这一轮对话窗口里的所有内容包括用户输入、模型输出、工具调用的中间结果。它通常存在上下文字段里随请求一起发给大模型。它的特点是读取快、寿命短只要会话结束或窗口超长就会被截断或丢弃。大多数人刚开始做Agent的时候用的就是这一层记忆——严格来说这只能叫“上下文”谈不上“记忆”。第二层会话间短期记忆。用户在短时间内比如几小时内多次访问Agent能记住他上次问过什么、做到哪一步。通常通过把历史消息摘要或关键实体写入数据库在下一轮对话开始时主动加载。这层记忆解决的是“用户换了会话但Agent不能失忆”的问题。第三层长期用户画像记忆。这层对应的是“记住你”的升级版——记住用户的身份、偏好、历史决策、禁忌甚至用户的情绪倾向和沟通习惯。比如“这个用户是运维工程师负责300人公司的网络预算敏感喜欢华为设备”这些信息不依赖某一次对话而是跨时间的稳定沉淀。第四层全局世界知识记忆。Agent对整个业务领域、产品参数、行业知识的结构化存储。它不完全针对某个用户但决定了Agent的回答是否专业。做记忆系统时最容易犯的错误是试图用一套存储解决所有层级的记忆。我早期就是这样——把所有历史对话都塞进向量数据库每次请求都做相似度检索然后拼到上下文里发给模型。结果对话一长相关和不相关的内容全被召回模型被大量低相关的“记忆”干扰回答质量反而下降。2.2 记忆方案选型哪种存储适合哪类需求用最简单的话来区分短期记忆可以用KV缓存或关系库临时表长期记忆的核心是向量数据库用户画像建议用图数据库或文档型数据库。但这不是绝对的我按实际场景把常见选型列了个表记忆类型存储选型核心理由会话工作记忆内存 / Redis读写延迟低TTL自动过期适合高频访问会话间短期记忆Redis 摘要存储快速加载最近N轮要点不用全量灌上下文长期事实/偏好向量数据库如Milvus、Qdrant、pgvector支持语义检索自然语言直接召回实体关系/用户画像图数据库如Neo4j或PostgreSQL JSONB适合描述“用户—偏好—历史决策”的多跳关系业务知识/产品参数文档库 向量索引结构化知识与非结构化描述结合如果你是个人开发者或者小团队刚开始做记忆功能我建议别一上来就上Milvus集群。先用PostgreSQLpgvector一张表存会话摘要一张表存用户画像再给关键实体建向量索引完全够支撑几十万用户的记忆场景。等并发量真的大上来了再迁移到独立向量数据库也来得及。很多人问为什么不用Redis一把梭Redis确实快但它不是为语义检索设计的。当你需要“找出和‘上次聊过的预算方案相关的历史记录’”时用Redis的模糊匹配几乎是不可行的而向量检索只需要一句话的自然语言表达就能搞定。2.3 为什么“记忆”不只是存储还有遗忘和抽取做记忆系统时还有一个常被忽略的关键点存储只是记忆的一半另一半是写入策略和遗忘策略。如果什么东西都往长期记忆里塞Agent会变得越来越“啰嗦”——因为检索结果里充斥着无关紧要的细节模型被迫在噪音中找信号。我自己的经验是记忆写入层一定要做“提取-结构化-压缩”三步处理而不是把原始对话直接存进向量库。具体来说提取从每轮对话中抽出关键实体用户名字、公司、产品型号、预算、时间点结构化把这些实体整理成固定的Schema比如[用户ID, 实体类型, 实体值, 关联对话ID, 时间戳]压缩对完整对话做摘要只保存摘要级别的文本进长期库这样后续检索时召回的是“这个人对预算敏感、上次选型倾向华为”而不是一整段三十分钟的聊天记录。模型拿到的是提炼过的记忆而不是原始日志。3. 记忆系统核心实操从接入到落库全流程3.1 第一步给Agent加一个记忆模块的数据结构既然要动代码先把底层的存储结构设计好。我这里用一个兼容LangChain和LlamaIndex的实践方案做讲解但是我们可以直接用OpenAI的Assistants API模拟一个轻量级的记忆接口。对于没有用框架的读者也可以照着这个思路自己写。第一步先定义记忆的数据模型。建议用类似下面的数据结构from pydantic import BaseModel from typing import Optional, List from datetime import datetime class MemoryItem(BaseModel): user_id: str memory_type: str # short_term | long_term | profile content: str entities: List[str] [] importance: float # 0.0 ~ 1.0 created_at: datetime last_accessed_at: Optional[datetime] None access_count: int 0这里面的importance字段是我从很多次踩坑后加上的。它体现了记忆的权重——重要的信息比如“用户是负责采购的决策人”权重高不重要的信息比如“用户夸过一句界面好看”权重低。检索时可以用它做排序过滤重要性高的记忆优先被送入上下文。初始写入时可以让大模型自己给信息的重要性打分也可以基于规则比如是否包含金额、是否包含决策词。3.2 第二步对话记忆的写入与更新当用户和Agent进行多轮对话时我们不可能在每轮对话后都把全部内容写入长期记忆那样会产生海量冗余数据。更合理的策略是设置一个写入触发点当前轮次对话包含决策性内容下单、选型、同意某个方案用户明确提到重要信息“我是做运维的”“预算不能超过五万”每个会话结束时做一次整体摘要下面是一个简化的写入逻辑配合LangChain使用from langchain.memory import ConversationSummaryBufferMemory from langchain_openai import ChatOpenAI # 设置一个带摘要的缓冲记忆 llm ChatOpenAI(modelgpt-4o-mini, temperature0) memory ConversationSummaryBufferMemory( llmllm, max_token_limit2000, # 超过这个 token 数自动触发摘要 return_messagesTrue, memory_keychat_history ) # 模拟一次带工具调用的对话 from langchain.schema import HumanMessage, AIMessage memory.chat_memory.add_message(HumanMessage(content我想给办公室做一个无线覆盖大概200平米预算1万以内)) memory.chat_memory.add_message(AIMessage(content好的200平米建议使用2个吸顶式AP预算内可以覆盖需要我提供具体型号吗)) memory.chat_memory.add_message(HumanMessage(content可以我倾向于华为的设备)) # 让LLM从上面的对话中抽取长期记忆 extract_prompt 从以下对话中抽取需要长期记住的信息要求输出JSON格式包含实体、属性、重要性评分 # 实际工程中会封装一个函数做抽取这段代码的关键点在于max_token_limit2000。当对话累积的token超过这个阈值时LangChain会自动用LLM生成一个压缩摘要替换掉最老的原始消息。这样短期记忆不会无限膨胀但又不会丢失核心信息。至于长期记忆的写入通常是在这个摘要生成后再让模型从摘要里抽取实体和偏好写进向量库或画像库。3.3 第三步记忆的检索与上下文集装有了存储下一步就是如何把记忆送进模型的上下文。这一步有几条核心原则不是所有记忆都要加载只加载与当前问题相关的部分按时间衰减过滤太久远且访问次数极少的信息可以忽略按重要性截断宁可少给不要给不相关的干扰信息我用pgvector做一个简单的相似度检索示例-- 假设走过的表结构已经带上了 embedding 列 SELECT content, importance, created_at, embedding $query_embedding AS distance FROM memory_entries WHERE user_id $user_id AND memory_type long_term ORDER BY CASE WHEN importance 0.8 THEN 0 ELSE 1 END, embedding $query_embedding LIMIT 5;这个SQL有意思的地方在于排序逻辑先按重要性分组再按语义距离排序。这样即使某个不重要的历史信息和当前问题语义上很接近也不会挤掉重要性更高的记忆。实测下来这个策略能明显提升生成结果的相关性尤其是面对长尾问题时。召回后再把这些记忆拼装成系统提示词里的一个段落比如以下是关于用户的历史记忆按重要性排序 1. 用户是XX公司的网络运维工程师负责约200人办公室的网络设备选型重要度0.95 2. 用户对华为设备有明显偏好重要度0.88 3. 用户预算敏感上次提到预算上限为1万元重要度0.80模型看到这些信息后再处理“上次那套方案帮我算一下带46个终端会不会卡”这样的问题时表现会完全不同——它知道“上次那套方案”是华为的AP知道要结合预算评估而不是从零开始提问。3.4 第四步用户画像的构建与更新前面那几层记忆是所有Agent产品的基础但“记住你”要做到极致还需要一个更细致的用户画像层。我的实现方式是这样的预设一套用户画像Schema包含静态属性姓名、角色、公司、动态偏好设备倾向、预算区间、沟通风格、历史决策记录买过什么、拒绝过什么、为什么拒绝。每一轮对话结束后我会让模型做一个增量更新而不是全量重建画像。看一个具体的实现示例class UserProfile(BaseModel): user_id: str static_attributes: dict {} # 静态属性 preference_tags: dict {} # 偏好标签及其权重 decision_history: list [] # 历史决策记录 negative_preferences: list [] # 明确拒绝过的东西 def update_user_profile(user_id: str, conversation_text: str): prompt f 你是用户画像分析师。根据以下对话更新用户的画像信息。 只提取对话中有明确依据的信息不要推测。不要编造。 输出JSON格式字段如下 - static_attributes: {company: ..., role: ..., name: ...} - preference_tags: {华为: 0.9, 预算敏感: 0.8} - decision_history: [{...}] - negative_preferences: [...] 对话内容 {conversation_text} # 调用LLM解析... # 然后将返回的JSON与数据库中的已有画像进行合并这里有一个特别容易被忽视的细节增量更新时不要直接覆盖旧值。比如用户第一次说“预算1万以内”第二次说“预算可以放宽到两万”这时画像里的预算信息应该更新为最新值但要保留历史轨迹这样才能理解用户的决策变化过程。我用的是“版本化画像”的思路——每个字段保存最近N次取值并附带时间戳这样Agent既能看出用户的稳定偏好也能感知偏好变化。4. 实操经验调试记忆Agent最容易踩的五个坑4.1 记忆污染召回了一堆不该召回的内容这是我在项目里踩过最深的坑。向量检索是按语义相似度找内容的它不管“这条信息是不是适合这轮对话”。比如用户问“你们的AP支持802.11ax吗”结果向量检索召回了历史里“用户上次问过802.11ac和802.11ax的区别”这一记录看起来相关但那条记忆里的产品信息和当前问题指向不同型号模型被干扰之后反而给了错误答案。我的解法是检索前先做一次意图粗分类。如果当前用户问题是“产品参数”就只检索长期知识库和当前型号相关的记忆不检索用户画像如果问题是“推荐方案”才结合用户偏好和历史决策。这个意图闸门让召回质量提升了非常多。4.2 上下文膨胀记忆越多模型越“失焦”大模型的注意力窗口虽然越来越长但太长的上下文会导致“lost in the middle”问题——模型对上下文中间部分的信息记忆特别差。如果把一堆记忆塞在中间模型实际上“看到了”但没有“用到”。解决这个问题我是用了一个“记忆分级加载”的策略系统提示词附近的记忆权重最高放最重要、最相关的长期画像对话历史放在中段压缩成摘要当前用户的输入永远放在最末尾。实测下来同样的记忆内容调整位置之后回答准确率能提升约15%。4.3 实时性和异步写入的矛盾做记忆系统时会发现如果等LLM生成完回答再写记忆整个请求链路会长很多。而且LLM抽取需要时间用户等不起。后来我改成了异步写入先返回Agent的回答给用户同时在后台任务里异步抽取记忆并落库。这样在用户感知上响应更快而且如果抽取失败也不会影响主流程。但要注意一个问题异步写入要加锁和去重避免同一个信息被重复写入多次。我在Redis里做了一个简单指纹去重用对话ID加实体哈希作为key写入前先检查。4.4 记忆过期与遗忘策略没有定义如果只做写入不做过期长期记忆库会越来越脏。比如用户半年前说过“预算2万以内”半年后可能已经完全不符合实际。如果Agent还拿这个旧画像决策那反而是负资产。我建议像操作系统管理缓存一样管理记忆低重要性、长时间未访问的记忆逐步降级确认过时或有冲突的信息优先删除定期做一轮“记忆回顾”让LLM对一堆旧记忆做清洗和合并。4.5 多用户隔离没做好这是涉及隐私和安全的高危问题。如果你的Agent是给多个用户服务的记忆检索时一定要在所有查询中都加上user_id的条件过滤。我见过有团队初期没加这个过滤结果用户A的问询历史被用户B的对话检索到了这在生产环境是严重事故。任何记忆检索的SQL或向量查询都应该把用户隔离作为默认的第一条件。5. 面向2026年AI Agent记忆功能还能怎么做深5.1 记忆从“被动存储”走向“主动理解”现在的记忆系统基本都是被动的——用户说什么我们存什么再在合适的时机取回。但更进一步的记忆应该具备“主动推断”的能力。比如用户没有明确说“我是管理采购的”但从他多次询问价格、要对比表格、顾虑审批周期这些信息Agent应该主动推断出他可能是采购决策人或影响者并把这条推断加入画像。当然这里要有边界推断结果不能直接当事实用而是作为一个“待验证标签”随着更多证据积累再提高置信度。5.2 多模态记忆会成为新的差异化点现在的记忆大多存的是文本。但用户跟Agent交互时的表情、语气、停留时长甚至浏览记录都可以成为记忆的一部分。比如用户在看到某一款产品介绍时停留了特别久这可能是一个强偏好信号用户连续两次追问某功能说明这是他在意的点。这类隐式信号虽然没有被用户说出口但对个性化推荐非常有用。5.3 记忆的“可解释化”与用户可控未来的Agent记忆应该做到让用户知道“你记住了什么”。比如很多产品会在设置页展示“Agent对我的了解”用户可以选择删除某条记忆、关闭某类记忆。这不只是合规需求也是信任建立的关键。我甚至建议在对话里做到一种轻量级的“记忆透明化”当Agent的回答明显是基于某条历史记忆时可以标注一下“这是根据您上次提到的XX信息”。5.4 跨Agent的记忆共享与迁移现在的记忆系统大多绑定在单一Agent上。未来可能会出现一种场景用户有一个通用偏好库不同的垂直Agent客服Agent、运维Agent、选型Agent都遵循同一个标准接口来读写这个偏好库。这样用户在任何一个Agent那里沉淀的信息都能被另一个Agent继承真正做到“一次了解处处贴心”。当然这里数据安全和隐私授权的挑战很大需要从架构层面设计好权限模型。最后说一点个人体会。做Agent记忆功能技术选型从来不是最难的最难的是想清楚“哪些记忆值得存、哪些该忘、怎么在不打扰用户的前提下让用户感觉被记住”。我在实际操作中试过三次大的方案调整最终效果最好的反而是“轻存储、重抽取、精召回”这条路线——不需要把每一句话都存下来但要让存下来的每条记忆都足够精准。如果你刚开始做这个功能我建议先跑通一个最小闭环一次会话的记忆写入、一次跨会话的召回、一次基于记忆生成的个性化回答。把这个闭环跑通了再去想多模态、去中心化这些更远的事情也不迟。

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

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

免费获取报价