每日 Agent 核心知识 · 第 03 期记忆系统深度拆解

每日 Agent 核心知识 · 第 03 期记忆系统深度拆解 个人主页代码不加冰欢迎来访作者简介java后端学习者❄️个人专栏LeetCode刷题日记 苍穹外卖日记SSM框架深入JavaWeb✨命运的结局尽可永在不屈的挑战却不可须臾或缺大家好接着昨天的ReAct框架今天我们继续更新我们的每日agent知识分享让我们一起看看吧。LLM 本身无状态每次调用都是一张白纸。Agent 的「记忆」全靠工程手段拼出来的幻觉。本文拆解记忆系统的四层架构、检索机制和生产级踩坑点。目录01无状态的真相context window 才是唯一真实02记忆四层架构全景03短期记忆上下文窗口的工程管理04长期记忆向量检索的完整链路05记忆的写入策略什么该存什么不该存06生产级踩坑记忆系统的五个陷阱07面试高频问题01 无状态的真相第一期提过 LLM 是无状态的这里要讲透彻所谓Agent 记得我们之前聊过什么本质上是每次调用 API 时把历史对话重新塞进 prompt而不是模型内部有什么记忆机制在运行。python # 这才是记忆的真相每次都是全新调用只是 context 变长了 # 第1轮 messages [{role:user,content:我叫小明}] response_1 llm.call(messages) # 你好小明 # 第2轮 —— 注意把第1轮的内容原样又传了一遍 messages [ {role:user,content:我叫小明}, {role:assistant,content:你好小明}, {role:user,content:我叫什么名字} ] response_2 llm.call(messages) # 你叫小明 # 模型没有记住任何东西它只是在阅读你重新发给它的全部历史这个事实推导出 Agent 工程的核心命题记忆系统的全部工作就是决定在每次调用时往 context window 里塞什么内容。所谓短期记忆长期记忆向量记忆最终都要落地成这次调用prompt 里包含哪些文本。这是理解整个记忆系统的钥匙不存在真正的读取记忆操作只存在把存储的东西转换成文本塞进下一次的 context。所有设计问题都归结为存什么、怎么存、什么时机取、取多少。02 记忆四层架构全景工程上把记忆拆成四层每层解决不同时间尺度的问题层级名称时间尺度L1工作记忆Working Memory毫秒级 · 单次调用内L2短期记忆Short-term Memory会话级L3长期记忆Long-term Memory跨会话L4程序记忆Procedural Memory跨任务L1 工作记忆Working Memory就是当前这一次 LLM 调用所看到的全部 context——包括 System Prompt、对话历史、工具返回结果。这是唯一真正被模型看到的记忆其余三层都是为了在合适的时机把内容注入到这一层。容量受限于 context window如 200K tokens且 attention 在超长 context 下会出现中间遗忘现象lost in the middle。03 短期记忆上下文窗口的工程管理即使是「短期记忆」也不能无脑把所有历史全塞进 context——会话进行得越久历史越长最终一定会超过 context window 上限或者即使没超限过长的 context 也会拖慢推理、增加成本、降低准确率。三种主流策略策略一滑动窗口截断只保留最近 N 轮对话更早的直接丢弃。实现最简单但会彻底丢失早期信息——用户10轮前说的关键约束Agent 完全不记得。策略二摘要压缩用另一次 LLM 调用把超出窗口的历史压缩成一段摘要替代原始对话插入 context。保留信息密度更高但摘要本身可能丢失细节且多一次 LLM 调用增加延迟和成本。策略三分层缓冲生产级最常用把对话历史分成「热区」和「冷区」最近 K 轮原文保留热区保证细节完整更早的滚动压缩成摘要并持续更新冷区控制 token 消耗。LangChain 的ConversationSummaryBufferMemory就是这个思路的实现。python # 分层缓冲伪代码 class HybridMemory: def __init__(self, hot_window6, max_tokens4000): self.hot_messages [] # 最近 N 轮原文保留 self.cold_summary # 更早历史的滚动摘要 self.hot_window hot_window def add_message(self, msg): self.hot_messages.append(msg) if len(self.hot_messages) self.hot_window * 2: # 热区溢出把最老的一轮压缩进摘要 overflow self.hot_messages[:2] self.hot_messages self.hot_messages[2:] self.cold_summary llm_summarize(self.cold_summary, overflow) def build_context(self): return [ {role: system, content: f早期对话摘要{self.cold_summary}}, *self.hot_messages # 最近对话原文逐条展开 ]深度视角lost in the middle 现象2023 年斯坦福的研究发现LLM 对 context中间部分的信息利用率显著低于开头和结尾——即使没有超出窗口限制塞在中间的关键信息也可能被忽视。这意味着只控制 token 数量不够还需要考虑信息在 context 中的位置把最重要的信息放在 context 的开头或结尾靠近当前问题的位置而不是简单地按时间顺序堆叠。04 长期记忆向量检索的完整链路长期记忆是 Agent 工程里水最深的部分因为它涉及向量数据库、Embedding、相似度计算、重排序等一整条技术链。我们逐步拆开。4.1 写入链路从文本到向量python # Step 1: 把信息切分成合适大小的片段chunking chunks text_splitter.split( raw_text, chunk_size500, # token 数太大检索粒度粗太小丢失上下文 chunk_overlap50 # 片段间重叠避免关键信息被切断在边界 ) # Step 2: 每个 chunk 转成向量Embedding for chunk in chunks: vector embedding_model.encode(chunk.text) # 输出如 [0.021, -0.034, ...] 1536维 vector_db.insert( idchunk.id, vectorvector, metadata{text: chunk.text, source: chunk.source, timestamp: now()} ) # 关键Embedding 模型把语义相近的文本映射到向量空间里相近的位置 # 我喜欢吃辣和无辣不欢的向量距离会比我喜欢吃辣和今天天气不错近得多4.2 检索链路从问题到相关片段python # Step 1: 把用户问题也转成向量 query_vector embedding_model.encode(user_query) # Step 2: 在向量空间里做近似最近邻搜索ANN candidates vector_db.search( query_vector, top_k20, # 先粗召回多一些 metriccosine # 余弦相似度衡量向量方向的接近程度 ) # Step 3: 重排序Rerank—— 用更精确但更慢的模型二次打分 reranked rerank_model.score(user_query, candidates) top_results reranked[:5] # 精排后只取最相关的几条 # Step 4: 拼接进 context context_injection \n.join([r.text for r in top_results]) messages.append({ role: system, content: f相关历史信息\n{context_injection} })⚠️很多人跳过了 Step 3 重排序直接把粗召回的 top_k 结果塞进 context。问题在于向量相似度余弦距离衡量的是语义相关性不等于对回答这个问题的有用程度。Rerank 模型如 Cohere Rerank、BGE-reranker专门训练来判断这段文本能不能回答这个问题准确率远高于纯向量距离。生产系统强烈建议加这一步。4.3 为什么用余弦相似度而不是欧氏距离面试常考的细节Embedding 向量的「方向」编码语义「长度」(norm) 更多反映文本长度等无关因素。余弦相似度只比较方向向量夹角天然忽略长度差异欧氏距离会被向量长度干扰导致长文本和短文本即使语义相近距离也可能偏大这就是为什么几乎所有语义检索场景默认用余弦相似度或者先做归一化后用点积数学上等价。05 记忆的写入策略什么该存什么不该存长期记忆最容易踩的坑不是检索技术而是「写入判断」——不是所有对话内容都值得存进长期记忆。盲目把每句话都向量化存储会导致检索噪声暴增反而拉低准确率。应该写入长期记忆用户的稳定偏好我对海鲜过敏关键决策和承诺我们约定周五交付跨会话仍然有效的事实我的项目用 Python 3.11用户主动要求记住的内容不应该写入长期记忆闲聊寒暄你好谢谢已经过时/被覆盖的信息我昨天的心情不好单次会话内的临时上下文工具调用的中间结果高度敏感但无需跨会话的信息工程实践memory extraction工程上常见的判断方式是用一个轻量 LLM 调用或规则对每条消息做「是否值得记忆」的分类python def should_remember(message: str) - dict: # 用小模型做分类成本远低于每次都调用主力模型 prompt f判断这句话是否包含值得长期记住的信息用户偏好/事实/承诺。 如果是提取出简洁的记忆条目如果不是返回 null。 消息{message} 输出 JSON: {{should_remember: bool, memory: str | null}} result small_llm.call(prompt) return json.loads(result) # 示例 should_remember(我对花生过敏点餐要注意) # → {should_remember: true, memory: 用户对花生过敏} should_remember(今天天气真好) # → {should_remember: false, memory: null}工程关键点MemGPT现为 Letta和 ChatGPT 的 Memory 功能都采用类似机制不是把对话流水线式地全部存储而是主动「提炼」出结构化的记忆条目再写入。这个提炼过程本身消耗一次通常是小模型调用是记忆系统成本的隐藏部分工程预算时容易遗漏。06 生产级踩坑记忆系统的五个陷阱指标参考值典型召回率60-80%Rerank 提升15-25%chunk 重叠建议10-20%陷阱 1chunk 切分破坏语义完整性固定长度切分比如每500字符切一刀可能把一句关键陈述从中间切断导致两个 chunk 都丢失了完整语义。改进方案按语义边界切分段落、句子并保留 overlap10-20% 重叠让边界信息在相邻 chunk 间有冗余备份。陷阱 2记忆冲突未做处理用户上个月说我在北京工作这个月说我搬到上海了。如果系统两条都存、检索时都召回LLM 会拿到矛盾信息可能给出错误回答。改进方案生产系统需要做「记忆更新」而不只是「记忆追加」——检测到语义冲突的新信息时标记旧记忆为过期而非物理删除保留审计能力。陷阱 3检索注入了无关甚至有害内容向量检索基于相似度不基于安全性。如果长期记忆里存了用户曾经的误操作记录或敏感数据检索时可能被无差别召回并注入 context造成隐私泄露或误导性回答。改进方案在向量数据库层面加 metadata 过滤如按用户 ID、敏感级别、时间范围过滤作为检索前置条件而不仅靠向量相似度排序。陷阱 4Embedding 模型与查询语言不匹配某些 Embedding 模型对多语言支持不均衡中文查询英文存储的内容或反之召回率会显著下降。改进方案生产环境要么选用强多语言 Embedding 模型如 BGE-M3、OpenAI text-embedding-3要么在写入时统一翻译为单一语言需要在数据规模评估时提前验证跨语言检索效果。陷阱 5记忆无限增长导致检索质量退化向量数据库不会自动清理过时或低价值的记忆长期运行后数据量膨胀检索噪声增加相关结果被大量无关历史稀释。改进方案设计记忆的生命周期策略——定期归档低访问频率的旧记忆、对相似记忆做去重合并、设置 TTL过期时间针对明确具有时效性的信息。07 面试高频问题Q为什么不能直接把所有历史塞进超大 context window比如 Gemini 的 1M token三个原因成本——即使模型支持超长窗口token 数直接决定 API 调用费用每次都传几十万 token 不现实延迟——context 越长首 token 生成时间TTFT越久用户体验下降准确率——lost in the middle现象表明超长 context 不等于更好的信息利用率过多无关信息反而稀释了模型对关键信息的注意力检索式记忆的价值在于「精准注入」而不是「全量塞入」。QRAG 和长期记忆是一回事吗RAG检索增强生成是一种通用技术范式指检索外部知识 注入 context 生成回答。长期记忆是 RAG 的一种应用场景——检索的对象是过去和用户的交互历史而不是外部文档库。两者用的是同一套底层技术Embedding 向量检索区别只在于知识来源RAG通常面向静态文档长期记忆面向动态生成的交互记录Q向量数据库选型要考虑哪些因素几个核心维度维度考量点召回延迟毫秒级 vs 秒级影响用户体验metadata 过滤按用户、时间、权限过滤是生产刚需索引算法HNSW速度快但内存占用高vs IVF适合超大规模但召回率略低混合检索向量 关键词 BM25 结合提升精确匹配场景的召回率运维成本托管服务Pinecone/Weaviate Cloudvs 自建Milvus/QdrantQ怎么评估记忆系统的好坏核心指标是检索的「召回率」Recall相关信息有没有被找到和「精确率」Precision找到的信息有没有用。生产实践中常用方法构造一批用户问题 标准答案应引用的记忆条目测试集计算 top-k 召回中命中标准答案的比例。另外要单独评估「记忆写入质量」——记下来的内容是否准确提炼了关键信息避免提炼过程本身引入幻觉。本文是「每日 Agent 核心知识」系列第 03 期持续更新中欢迎关注。