这道题问的其实是[[Agent]]记忆和[[RAG]]知识库到底有什么不一样,为什么不能简单把对话历史扔进[[向量数据库]]就完事。要我说,核心差异有三点:记忆是动态演进的,每轮交互都在变;它有时序敏感性,既要最近发生的事情也要历史相关的事情;还有[[多模态]]关联,比如用户说了句话,调了个工具,返回了个结果,这些得串起来。向量数据库的[[稠密检索]]刚好擅长找语义相关但表述不同的内容,而且增量写入很自然,所以成了标配。
具体到设计,先说[[Embedding]]模型。通用场景我直接用开源模型,比如BGE或者M3E,成本低,基线可用。但如果是垂直领域,比如高德地图这种,我会用历史对话数据做领域微调,用对比学习强化地点、路线、偏好这些语义。说白了,Agent记忆的Embedding不能只看字面,得捕捉意图。比如用户说‘明天去机场,要早到’,模型得理解‘明天’是时间意图,‘机场’是地点,‘早到’是偏好,而不是单纯把这句话编码成一个向量。还有一种情况是多任务目标,比如同时优化检索相关性和对话连贯性,那我会做联合训练。
再一个,[[Chunk]]粒度怎么切。这里有个边界划分:粗粒度保留整轮对话,适合检索一次完整交互;细粒度切到句子或意图单元,适合提取关键事实。但真正落地我倾向混合策略,存储时细粒度切分,检索时动态扩展上下文。还是高德那个例子,用户说‘明天去机场,要早到’,我会拆成三个意图单元,分别存。检索时如果命中其中一个,再把同轮的其他单元拉回来,这样既精准又不丢上下文。
索引和检索策略这块,索引结构我选[[HNSW]],平衡速度和召回。按用户ID分区是必须的,防止跨用户污染。时间戳作为辅助索引,方便做范围过滤。检索策略我设计成三层。第一层,相似度召回,向量检索Top-K,比如50个候选。第二层,时序衰减加权,得分等于相似度乘以exp(-λ乘以时间差),λ控制遗忘速度,用户会话内λ设小一点,跨会话设大一点。第三层,重要性[[重排序]],用一个轻量模型打分,考虑三个信号:是否包含用户明确确认的信息,比如用户说‘对的’‘没错’;是否在后续对话被引用;是否跨会话反复提到,这往往是长期偏好。这里有个坑,重排序模型不能太重,否则延迟受不了,我一般用[[Cross-Encoder]]精排前10个候选,或者训练一个小BERT做二分类。
其实还有一个挑战是记忆的删除和修改。向量数据库的图索引结构,原地删除非常危险,召回质量会崩。我会用软删除加异步重建,查询时用双缓冲影子索引,构建完用固定query回放对比Recall@K,通过才原子切换。
最后说落地风险。前提是Embedding模型得能捕捉意图,否则检索结果就是垃圾。常见失败场景是用户说‘还是上次那个’,模型没把‘上次’和具体记忆关联起来,导致召回失败。上线我会特别关注记忆是否可用,就是检索结果在Prompt里能不能真正帮上忙;是否可控,支持显式删除修改,符合合规要求;是否可解释,检索时返回时间戳,方便Debug。所以我会把记忆机制看成动态演进的状态机,不是静态索引,更倾向用混合策略加层级检索,而不是单一方案。