关于AI检索增强生成的几点记录
AI检索增强生成我没按教科书顺序做。
如果检索到的内容本身就错了,那RAG也没用。
问题是怎么暴露出来的
最开始我们做的是一个纯ChatGPT对话系统。用户提问,直接把问题丢给OpenAI的API,然后返回答案。
表面上看起来没啥问题,回答也挺流畅,像模像样。但后来发现几个现象:
- 时间敏感性错误:用户问到某个产品功能的发布时间,AI会给出一个完全错误的日期,而且答得特别确定
- 业务逻辑错误:明明我们的产品不支持某个功能,AI却说"支持",还详细描述了操作步骤
- 版本混乱:用户问的是v2.0的功能,AI却用v1.0的逻辑在解释
最严重的一次是有个销售同事拿AI的回答去给客户演示,结果客户当场就指出了错误。那个同事后来跟我说,他现在用这个系统之前都要先自己在内部文档确认一遍,不然不敢直接相信。
这不就是我们花了很多精力搭建的系统,最后却让用户失去了信任吗?
RAG是个啥,用人话解释一下
RAG(Retrieval-Augmented Generation)说白了就是给AI外挂一个"参考书"。它的核心思想是:在生成答案之前,先去知识库里检索相关内容,然后把检索结果作为上下文一起喂给模型。
这样一来,AI就不是完全靠"想象"来回答问题了,而是有"参考资料"可以依仗。
用一个简单的流程来说明:
这个流程的关键在于检索的准确性和检索结果的质量。如果检索到的内容本身就错了,那RAG也没用。
我们是怎么实现的
技术选型
在技术选型上,我们主要考虑了几个因素:
- 向量数据库:最终选择了Chroma,原因很简单——部署方便,不需要单独维护一套复杂的分布式系统
- 嵌入模型:先用的是OpenAI的
text-embedding-3-small,后来因为某些原因切换到开源的bge-large-zh-v1.5 - 检索策略:最开始用简单的相似度检索,后来加入了重排序(rerank)来提升准确性
- LLM:继续使用GPT-4,但我们加了prompt engineering来让它更依赖检索结果
文档处理
文档处理这块踩了不少坑。我们的知识库里有各种格式:Word文档、PDF、网页内容、Markdown笔记、Excel表格。
最开始我们写了一个简单的转换脚本,把所有内容都转成纯文本,然后按固定长度切分成chunk。但很快就发现这样问题很大:
- 上下文丢失:一段关于某个功能介绍的内容被切成了两半,检索时只能拿到一半,导致理解偏差
- 格式信息丢失:Excel表格转成文本后,列关系变得不清晰
- 更新困难:当文档更新时,如何智能地只更新受影响的部分,而不是全部重新处理
后来我们采用了更智能的切分策略:
- 优先按照文档的自然结构(标题、段落、列表)来切分
- 保留一些元信息(章节标题、作者、时间)
- 对表格和代码块特殊处理,尽量保持完整性
- 给每个chunk加上文档ID和位置信息,方便溯源
检索优化
检索准确性的提升是整个RAG效果好坏的关键。我们做了几轮优化:
- 混合检索:结合了向量检索和关键词检索,用BM25作为关键词检索的方法
- 查询改写:对用户的问题进行改写和扩展,比如把"怎么配置数据库"改成"数据库配置步骤"和"设置数据库方法"
- 重排序:先用向量检索快速筛选出top-50,再用一个专门的重排序模型精排到top-10
这里有个坑,我们一开始没太重视:检索结果的多样性。如果检索到的10个chunk都来自同一份文档,那么答案就会有严重的偏向性。后来我们加入了去重和多样性控制,确保检索结果能覆盖不同来源的信息。
踩坑记录
坑1:检索结果过多
刚开始我们每次检索返回10个chunk,认为信息越多越好。但实际发现:
- Token消耗急剧上升,成本翻倍
- LLM容易"捡了芝麻丢了西瓜",关注了次要信息而忽略了重点
- 上下文窗口有限,有时候关键的chunk被挤掉了
后来我们把检索结果数量动态调整:根据问题的复杂度和检索结果的相似度分数,决定返回多少个chunk。简单问题可能只返回3-5个,复杂问题最多返回10个。
坑2:检索到的内容本身就有问题
这可能是RAG最大的陷阱。我们遇到过几次这种情况:
- 文档里写的是过时的信息,但检索到了
- 不同文档对同一个问题有冲突的描述
- 文档是草稿或者标注了"待确认",但被当成了正式内容
解决方案是加强了数据治理:
- 给文档加上了版本信息和有效性标记
- 建立了文档审核流程,确保进入知识库的内容是经过确认的
- 在prompt里明确告诉AI,如果检索到的内容有明显冲突,要指出问题而不是盲目选择
坑3:AI还是会"自作聪明"
即使给了检索结果,AI有时候还是会"自作聪明"地添加一些自己的"补充"。这导致了新的幻觉问题。
我们在prompt里做了几轮优化:
- 明确要求AI只基于检索结果回答,不要添加额外信息
- 要求AI在不确定时直接说"检索到的信息不足以回答这个问题"
- 让AI在答案中标注信息的来源,增加可追溯性
但这也不是完美的。有时候检索结果确实不够,AI如果直接说"不知道",用户体验会受影响。这里有个平衡需要把握。
实际效果
经过这些折腾,现在的效果确实比之前好多了:
- 事实准确率提升了:根据我们的统计,关于产品功能和操作步骤的回答,准确率从之前的65%提升到了92%
- 用户信任度恢复了:之前要"二次确认"的同事,现在更愿意直接使用AI的回答
- 可以溯源了:每个答案都能追溯到具体是哪份文档、哪一段内容
但也还有一些边界:
- 推理类问题还是不行:如果用户问的是"我们为什么这么设计架构"这种需要深度理解的问题,RAG的效果一般,因为它还是检索+生成,不是真正的理解
- 实时性信息处理困难:如果知识库更新不及时,还是会回答过时信息
- 复杂问题需要多轮对话:有时候用户的问题需要多轮对话才能澄清,RAG在多轮场景下的检索策略还需要优化
还要继续折腾的
这次实践让我们对RAG有了更深的理解。它不是一个"银弹",不能解决所有问题,但在"事实性问答"这个场景下,确实比纯LLM可靠得多。
接下来打算继续优化几个方向:
- 多模态检索:我们有很多流程图、架构图,目前只能靠OCR提取文字,效果一般。直接用图像检索可能更好
- 个性化检索:不同用户的角色、背景不同,检索结果应该有所区别
- 主动更新机制:当知识库内容更新时,如何智能地触发相关chunk的重新处理
技术这东西就是这样,解决了一个问题,又会冒出三个新问题。但正是这种不断的"发现-解决-再发现"的过程,让我们对AI落地有了更清醒的认识。
RAG不是终点,而是从"有意思"走向"有用处"的一站。
参考文献
- Lewis et al. (2020). “Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks”
- LangChain RAG documentation: https://python.langchain.com/docs/use_cases/question_answering/
- ChromaDB documentation: https://docs.trychroma.com/
版权声明: 本文首发于 指尖魔法屋-关于AI检索增强生成的几点记录(https://blog.thinkmoon.cn/post/361-ai-rag-hallucination-fact-practice/) 转载或引用必须申明原指尖魔法屋来源及源地址!
评论
使用 GitHub 账号登录后即可留言,支持 Markdown。