Agent 的长短期记忆系统怎么做的?记忆是怎么存的?粒度是多少?怎么用的
1️⃣ 考察意图
面试官想看你是否真正理解 Agent 记忆系统的工程实现,而非停留在“短期=上下文,长期=向量库”的泛泛之谈。考察类型是系统设计 + 工程取舍,刁钻点在于:记忆粒度如何选择(句子/段落/摘要)、存储如何兼顾检索效率与语义保真、使用时机如何平衡 prompt 长度与延迟。答好了能展示你对 RAG、向量检索、缓存策略的实战理解,以及面对多轮对话时记忆管理的系统思维。
2️⃣ 标准答
Agent 的记忆系统通常分短期记忆和长期记忆两层,核心是解决“上下文窗口有限”与“知识持久化”的矛盾。
短期记忆(Short-Term Memory)
- 存储方式:直接拼接在 LLM 的 prompt 中,本质是滑动窗口。例如,保留最近 4K tokens 的对话历史,超出则丢弃最早轮次。
- 粒度:以对话轮次为单位,每轮包含用户输入和 Agent 回复。实践中,轮次内可压缩为摘要(如用 LLM 将 3 轮对话压缩成 1 句),减少 token 消耗。
- 使用方式:在每次推理前,将窗口内的历史作为 system prompt 的一部分传入。坑:窗口大小需权衡——太小丢失上下文,太大导致 LLM 注意力分散(如 GPT-4 在 8K 窗口后性能下降)。解法:动态窗口,根据任务复杂度调整(简单任务 2K,复杂任务 6K)。
长期记忆(Long-Term Memory)
- 存储方式:主流用向量数据库(如 Chroma、Pinecone)存储 embedding,辅以结构化存储(如 SQLite)存元数据。例如,每个记忆片段存为
{id, embedding, text, timestamp, source}。 - 粒度:关键取舍点。常见三种:
- 句子级(~50 tokens):检索精度高,但存储量大,易产生碎片化记忆。
- 段落级(~500 tokens):平衡检索与语义完整性,适合对话历史。
- 摘要级(~200 tokens):用 LLM 生成每段摘要,压缩信息但丢失细节。推荐:段落级 + 摘要级混合——段落存原始内容,摘要用于快速检索,命中后再拉取段落。
- 使用方式:通过检索增强(RAG) 实现。流程:
- 用户输入 → embedding 模型(如 text-embedding-3-small)生成 query embedding。
- 向量库召回 top-k(k=3-5),结合时间衰减(如 BM25 加权,近期记忆权重高)。
- 召回片段经重排序(如 Cohere rerank)后,拼接进 prompt 的“记忆”部分。
- 工程坑:记忆冲突。例如,用户昨天说“喜欢咖啡”,今天说“戒咖啡”,旧记忆干扰新决策。解法:记忆合并——用 LLM 定期扫描冲突记忆,生成新摘要(如“用户曾喜欢咖啡,但已戒掉”),并标记旧记忆为“过期”。
混合策略
- 短期记忆负责实时上下文,长期记忆提供背景知识。实践中,Agent 先检查短期窗口是否命中(如用户重复问题),未命中才触发长期检索,减少延迟。
- 记忆压缩:每 10 轮对话后,用 LLM 将短期记忆压缩为长期记忆片段,存入向量库。例如,将“用户问天气、订餐厅、查路线”压缩为“用户计划周末出行,偏好户外活动”。
3️⃣ 答题模板(30 秒电梯版)
“这个问题我从存储、粒度、使用三个层面回答。存储上,短期记忆用 prompt 滑动窗口,长期记忆用向量数据库加结构化元数据;粒度上,短期以轮次为单位,长期推荐段落级加摘要级混合;使用上,短期直接拼接,长期通过 RAG 检索加重排序,并引入时间衰减和记忆合并解决冲突。总结一句:记忆系统本质是平衡上下文长度、检索精度和存储成本。”
4️⃣ 高频追问 & 应对
追问 1:如果用户对话长达 100 轮,你怎么保证长期记忆检索不遗漏关键信息?
应对策略:引入分层检索。第一层用时间窗口(如最近 20 轮)做粗筛,第二层用语义相似度(cosine > 0.7)做精筛。同时,对长期记忆做聚类(如 K-means,k=10),每类存一个代表向量,检索时先匹配类,再在类内搜索。这样复杂度从 O(n) 降到 O(log n)。坑:聚类可能丢失边缘信息,所以保留每个类的 top-3 片段作为“热点记忆”。
追问 2:记忆存储的 embedding 模型怎么选?为什么不用同一个模型做检索和生成?
应对策略:检索用专用 embedding 模型(如 BGE-M3),生成用 LLM。原因:embedding 模型优化的是语义相似度(如对比学习),LLM 优化的是文本生成,两者目标不同。混合使用会降低检索精度。工程上,embedding 模型选 768 维(平衡精度和存储),batch 大小 32,用 FAISS 做索引(IVF 加速)。坑:模型版本更新后,新旧 embedding 空间不一致,需定期重索引。
追问 3:短期记忆窗口满了,丢弃历史时怎么避免丢失关键信息?
应对策略:不直接丢弃,而是压缩。用 LLM 生成历史摘要(如“用户前 10 轮讨论了项目 A 的需求,已确认 deadline 为下周五”),存入长期记忆。同时,对窗口内内容做重要性评分(如基于用户情绪词频或任务完成度),保留高重要性轮次。例如,用户说“这个方案不行”比“好的”更重要,权重高 3 倍。坑:压缩可能引入幻觉,所以保留原始轮次的 embedding 作为校验。
5️⃣ 避坑 · 常见错误答法
- ❌ 说“长期记忆用 Redis 存 JSON,直接查” → ✅ 正确切入:Redis 适合缓存,但语义检索必须用向量库,否则无法处理模糊查询(如“上次说的那个项目”)。应强调 embedding + 近似最近邻搜索(ANN)。
- ❌ 说“记忆粒度统一用句子,因为最细” → ✅ 正确切入:句子级存储量大、检索噪声高,实际工程中段落级更常用,且需结合摘要级做快速索引。粒度选择取决于任务:问答用段落,对话用轮次摘要。
- ❌ 说“短期记忆就是 prompt 长度,不用管” → ✅ 正确切入:短期记忆有性能拐点(如 GPT-4 在 4K 后准确率下降),需动态调整窗口,并引入压缩策略。忽略这点会导致 Agent 在长对话中“失忆”。
6️⃣ 简历呼应
- 如果你有 RAG 项目:从“长期记忆检索优化”切入,讲你如何用 BM25 + embedding 混合检索提升召回率,并对比不同 chunk 大小(256 vs 512 tokens)对任务成功率的影响。
- 如果你只做过传统 NLP:用“对话状态跟踪(DST)”类比,说记忆系统类似 DST 的槽位管理,但 Agent 需要更灵活的语义检索而非固定槽位。强调你理解从规则到向量检索的演进。
- 如果你是校招无项目:聚焦“记忆压缩”论文复现,如“MemGPT”的虚拟上下文管理,用开源代码(如 LangChain 的 Memory 模块)做 demo,展示你对滑动窗口和摘要生成的理解。
- MemGPT: Towards LLMs as Operating Systems(论文,提出虚拟上下文管理)
- LangChain Memory 模块文档(实践,对比 Buffer/Summary/VectorStore 记忆)
- BGE-M3: Multi-Lingual Multi-Granularity Embedding(论文,检索模型选择)
- FAISS: A Library for Efficient Similarity Search(工具,向量索引优化)
- “RAG vs. Long-Context LLMs” 博客(取舍分析,对比检索与长窗口的优劣)