凌晨一点,客户群聊炸开了锅:“你们的客服机器人只有七秒的记忆吗?我刚才给了它订单号,下一轮它又问我‘请提供订单号’。我感觉自己在跟一条金鱼说话!”
我爬起床查看日志。检索增强生成(RAG)的对话记忆模块在服务重启后丢失了所有历史记录。当用户询问“我能退款那个我提到过的订单吗?”时,检索器无法从之前的对话轮次中提取出订单号,导致回答完全偏离。修复这个漏洞后,我意识到:如果每次对记忆逻辑的修改都依赖用户来为我“测试”,那这个系统注定要失败。我必须实现记忆的持久化,并通过自动化测试覆盖多轮对话场景。这篇文章是我事后复盘的血泪总结。
问题剖析:为什么多轮 RAG 记忆如此脆弱
在多轮检索增强生成(RAG)中,用户的问题往往依赖于上一轮的信息,例如:“查询订单 12345” → “能退款吗?”第二个问题不包含订单号,但大语言模型(LLM)需要知道“它”指的是订单 12345。传统的方法是将完整的对话历史塞入提示词中,但两个痛点显而易见:
-
记忆不可靠:
ConversationBufferMemory将历史存储在进程内存中,重启后一切归零。用户对话进行到一半,你部署了一个新版本,所有上下文都消失了。 -
固定窗口导致上下文丢失:
ConversationBufferWindowMemory仅保留最近 K 轮对话。如果用户在五轮前提到了订单号,而在第六轮问“能退那个订单的款吗?”,窗口之外的信息就会丢失,无法被检索到。
更糟糕的是,在多轮检索增强生成(RAG)中,历史记录和新问题都必须向量化以搜索知识库。如果历史仅以原始文本形式存储而没有语义索引,你就根本无法在数百条聊天记录中快速回忆起“那个订单号”。传统的 Redis 缓存解决了持久性问题,但它无法按语义含义召回相关的历史片段。这就是根本原因:我们需要一种记忆存储方案,既要持久化,又要支持向量语义检索,并能轻松集成到 LangChain 管道中。
方案设计:为什么选择 Chroma 而不是在 Redis 上自行构建向量功能
- Redis + 向量插件:你必须维护自己的倒排索引、过期策略和手动序列化——开发成本高昂。
- FAISS + 手动持久化:FAISS 没有内置的持久化功能;你每次都必须保存和加载索引文件,版本不匹配可能会带来令人头疼的问题。
- Qdrant / Weaviate:功能非常强大,但它们需要运行独立的服务,对于小团队来说,这种维护负担很难证明其合理性。
-
Chroma:一个嵌入式向量数据库。只需执行
pip install chromadb,你就能获得元数据过滤、持久化功能,以及作为向量存储和检索器的原生 LangChain 集成。它附带VectorStoreRetrieverMemory,这是一个现成的记忆包装器。开箱即用,你可以将历史对话存储在 Chroma 中,按语义相似度召回最相关的前 K 个历史项目,并按时间戳和用户 ID 等元数据进行过滤。
架构很简单:在每轮对话结束时,将用户的问题和人工智能的回答拼接成一个文档,计算其嵌入向量,并将其存储在带有时间戳和会话 ID 等元数据的 Chroma 集合中。当下一轮对话到来时,u
免责声明:本文内容来自互联网,该文观点不代表本站观点。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请到页面底部单击反馈,一经查实,本站将立刻删除。