关于AI检索增强生成的几点记录

AI检索增强生成我没按教科书顺序做。

如果检索到的内容本身就错了,那RAG也没用。

问题是怎么暴露出来的

最开始我们做的是一个纯ChatGPT对话系统。用户提问,直接把问题丢给OpenAI的API,然后返回答案。

表面上看起来没啥问题,回答也挺流畅,像模像样。但后来发现几个现象:

  1. 时间敏感性错误:用户问到某个产品功能的发布时间,AI会给出一个完全错误的日期,而且答得特别确定
  2. 业务逻辑错误:明明我们的产品不支持某个功能,AI却说"支持",还详细描述了操作步骤
  3. 版本混乱:用户问的是v2.0的功能,AI却用v1.0的逻辑在解释

最严重的一次是有个销售同事拿AI的回答去给客户演示,结果客户当场就指出了错误。那个同事后来跟我说,他现在用这个系统之前都要先自己在内部文档确认一遍,不然不敢直接相信。

这不就是我们花了很多精力搭建的系统,最后却让用户失去了信任吗?

RAG是个啥,用人话解释一下

RAG(Retrieval-Augmented Generation)说白了就是给AI外挂一个"参考书"。它的核心思想是:在生成答案之前,先去知识库里检索相关内容,然后把检索结果作为上下文一起喂给模型。

这样一来,AI就不是完全靠"想象"来回答问题了,而是有"参考资料"可以依仗。

用一个简单的流程来说明:

flowchart LR A[用户问题] --> B[向量化] B --> C[检索相关文档] C --> D[构建提示词] D --> E[LLM生成答案] C --> F[返回来源引用] E --> G[最终答案] F --> G

这个流程的关键在于检索的准确性和检索结果的质量。如果检索到的内容本身就错了,那RAG也没用。

我们是怎么实现的

技术选型

在技术选型上,我们主要考虑了几个因素:

  1. 向量数据库:最终选择了Chroma,原因很简单——部署方便,不需要单独维护一套复杂的分布式系统
  2. 嵌入模型:先用的是OpenAI的text-embedding-3-small,后来因为某些原因切换到开源的bge-large-zh-v1.5
  3. 检索策略:最开始用简单的相似度检索,后来加入了重排序(rerank)来提升准确性
  4. LLM:继续使用GPT-4,但我们加了prompt engineering来让它更依赖检索结果

文档处理

文档处理这块踩了不少坑。我们的知识库里有各种格式:Word文档、PDF、网页内容、Markdown笔记、Excel表格。

最开始我们写了一个简单的转换脚本,把所有内容都转成纯文本,然后按固定长度切分成chunk。但很快就发现这样问题很大:

  1. 上下文丢失:一段关于某个功能介绍的内容被切成了两半,检索时只能拿到一半,导致理解偏差
  2. 格式信息丢失:Excel表格转成文本后,列关系变得不清晰
  3. 更新困难:当文档更新时,如何智能地只更新受影响的部分,而不是全部重新处理

后来我们采用了更智能的切分策略:

  • 优先按照文档的自然结构(标题、段落、列表)来切分
  • 保留一些元信息(章节标题、作者、时间)
  • 对表格和代码块特殊处理,尽量保持完整性
  • 给每个chunk加上文档ID和位置信息,方便溯源

检索优化

检索准确性的提升是整个RAG效果好坏的关键。我们做了几轮优化:

  1. 混合检索:结合了向量检索和关键词检索,用BM25作为关键词检索的方法
  2. 查询改写:对用户的问题进行改写和扩展,比如把"怎么配置数据库"改成"数据库配置步骤"和"设置数据库方法"
  3. 重排序:先用向量检索快速筛选出top-50,再用一个专门的重排序模型精排到top-10

这里有个坑,我们一开始没太重视:检索结果的多样性。如果检索到的10个chunk都来自同一份文档,那么答案就会有严重的偏向性。后来我们加入了去重和多样性控制,确保检索结果能覆盖不同来源的信息。

踩坑记录

坑1:检索结果过多

刚开始我们每次检索返回10个chunk,认为信息越多越好。但实际发现:

  • Token消耗急剧上升,成本翻倍
  • LLM容易"捡了芝麻丢了西瓜",关注了次要信息而忽略了重点
  • 上下文窗口有限,有时候关键的chunk被挤掉了

后来我们把检索结果数量动态调整:根据问题的复杂度和检索结果的相似度分数,决定返回多少个chunk。简单问题可能只返回3-5个,复杂问题最多返回10个。

坑2:检索到的内容本身就有问题

这可能是RAG最大的陷阱。我们遇到过几次这种情况:

  • 文档里写的是过时的信息,但检索到了
  • 不同文档对同一个问题有冲突的描述
  • 文档是草稿或者标注了"待确认",但被当成了正式内容

解决方案是加强了数据治理:

  1. 给文档加上了版本信息和有效性标记
  2. 建立了文档审核流程,确保进入知识库的内容是经过确认的
  3. 在prompt里明确告诉AI,如果检索到的内容有明显冲突,要指出问题而不是盲目选择

坑3:AI还是会"自作聪明"

即使给了检索结果,AI有时候还是会"自作聪明"地添加一些自己的"补充"。这导致了新的幻觉问题。

我们在prompt里做了几轮优化:

  • 明确要求AI只基于检索结果回答,不要添加额外信息
  • 要求AI在不确定时直接说"检索到的信息不足以回答这个问题"
  • 让AI在答案中标注信息的来源,增加可追溯性

但这也不是完美的。有时候检索结果确实不够,AI如果直接说"不知道",用户体验会受影响。这里有个平衡需要把握。

实际效果

经过这些折腾,现在的效果确实比之前好多了:

  1. 事实准确率提升了:根据我们的统计,关于产品功能和操作步骤的回答,准确率从之前的65%提升到了92%
  2. 用户信任度恢复了:之前要"二次确认"的同事,现在更愿意直接使用AI的回答
  3. 可以溯源了:每个答案都能追溯到具体是哪份文档、哪一段内容

但也还有一些边界:

  1. 推理类问题还是不行:如果用户问的是"我们为什么这么设计架构"这种需要深度理解的问题,RAG的效果一般,因为它还是检索+生成,不是真正的理解
  2. 实时性信息处理困难:如果知识库更新不及时,还是会回答过时信息
  3. 复杂问题需要多轮对话:有时候用户的问题需要多轮对话才能澄清,RAG在多轮场景下的检索策略还需要优化

还要继续折腾的

这次实践让我们对RAG有了更深的理解。它不是一个"银弹",不能解决所有问题,但在"事实性问答"这个场景下,确实比纯LLM可靠得多。

接下来打算继续优化几个方向:

  1. 多模态检索:我们有很多流程图、架构图,目前只能靠OCR提取文字,效果一般。直接用图像检索可能更好
  2. 个性化检索:不同用户的角色、背景不同,检索结果应该有所区别
  3. 主动更新机制:当知识库内容更新时,如何智能地触发相关chunk的重新处理

技术这东西就是这样,解决了一个问题,又会冒出三个新问题。但正是这种不断的"发现-解决-再发现"的过程,让我们对AI落地有了更清醒的认识。

RAG不是终点,而是从"有意思"走向"有用处"的一站。

参考文献

版权声明: 本文首发于 指尖魔法屋-关于AI检索增强生成的几点记录https://blog.thinkmoon.cn/post/361-ai-rag-hallucination-fact-practice/) 转载或引用必须申明原指尖魔法屋来源及源地址!