RAG 不是银弹。文档喂进去了,但 LLM 还是胡说八道——不是 LLM 的问题,是你的检索没做对。
RAG 也会产生幻觉?
很多人以为加了 RAG 就不会有幻觉了。错。
RAG 的幻觉有自己的特点:
- LLM 原生幻觉:凭训练数据编答案
- RAG 幻觉:检索到了文档,但用错了——张冠李戴、断章取义、过时信息
RAG 幻觉的三个根因:
根因 1:检索不精准——「搜到了但不相关」
现象:用户问「轴承温度过高」,检索返回了「齿轮箱温度过高」的维修知识。
原因:Embedding 模型对某些领域术语的语义理解不够。AllMiniLmL6V2 是通用模型,不了解「轴承温度」和「齿轮箱温度」在工业场景中是不同的问题。
诊断方法:
// 手动验证检索结果
var results = embeddingStore.search(
EmbeddingSearchRequest.builder()
.queryEmbedding(queryEmbedding)
.maxResults(3)
.build()
);
for (var r : results.matches()) {
System.out.println("Score: " + r.score() + " | " + r.embedded().text());
}
如果 top-3 结果的相关性分数都低于 0.5,说明这块知识的 Embedding 质量有问题。
修复方案:
- 换用领域优化的 Embedding 模型(如 BGE-Large-Zh)
- 加入 BM25 稀疏检索做混合召回
- 提高
minScore阈值,宁可返回空也不给不相关结果
根因 2:分块不当——「切断了语义」
现象:检索到的文档片段只包含半个诊断结论,缺少关键信息。
# 原文档
"轴承温度超过70°C时,应立即检查润滑系统。常见原因包括:
1. 润滑脂不足 2. 润滑脂变质 3. 轴承间隙过小。"
# 如果分块切在第二行之前...
块A: "轴承温度超过70°C时,应立即检查润滑系统。常见原因包括:"
块B: "1. 润滑脂不足 2. 润滑脂变质 3. 轴承间隙过小。"
# 检索时只能命中块A → LLM 只知道「要检查润滑系统」但不知道为什么
修复方案:
- 分块重叠:
DocumentSplitters.recursive(500, 50)—— 每块 500 字,块间重叠 50 字 - 按语义边界分块:用
\n##(Markdown 标题)作为自然断点,而非纯字符数切割 - 实验分块大小:200 / 500 / 1000 / 2000 字符对比测试命中率
根因 3:Query 和文档用词不匹配——「你问 A,文档写的是 B」
现象:用户口语化的问题检索不到专业术语写的文档。
用户问: "CNC 机器震动得厉害是怎么回事?" → Embedding → [向量 A]
文档写: "电机振动超标(>4.5mm/s)的诊断流程" → Embedding → [向量 B]
向量 A ≠ 向量 B。虽然人知道「震动得厉害」=「振动超标」,但 Embedding 模型不一定知道。
修复方案:
1. 改写 Query(Query Rewriting)
让 LLM 在检索前先改写用户的问题:
原始: "CNC 机器震动得厉害是怎么回事?"
改写: "CNC 设备振动超标的原因和诊断方法"
改写后的问题用词更接近文档中的术语,检索命中率显著提升。
2. 生成假设答案(HyDE)
让 LLM 先「假设性地回答」这个问题,然后用假设答案去做检索:
用户问 → LLM 生成假设答案(不需要准确) → 用假设答案向量检索 → 找到真实文档
HyDE 的核心思想:答案和文档的用词风格更接近,用假设答案检索比用原始问题检索效果更好。
3. 多 Query 检索
生成多个不同角度的 Query,合并检索结果:
"CNC 机器震动得厉害是怎么回事?"
→ Query 1: "CNC 振动超标故障诊断"
→ Query 2: "机械设备振动异常原因排查"
→ Query 3: "机床震动故障维修方法"
快速诊断你的 RAG
| 症状 | 大概率根因 | 修复 |
|---|---|---|
| 检索结果不相关 | Embedding 模型不适合你的领域 | 换 BGE-Large-Zh 或领域微调 |
| 检索到但不完整 | 分块切断了语义 | 加大分块 + 加重叠 |
| 搜不到但文档存在 | 用户用词和文档术语不匹配 | Query Rewriting / HyDE |
| Top-3 得分都很低 | 知识库缺少该领域内容 | 补充文档 |
| LLM 输出和检索结果不一致 | LLM 没优先看检索结果 | SystemMessage 强化「请基于提供的资料回答」 |
一句话总结
RAG 的幻觉不在 LLM,在检索。三大根因——检索不精准、分块不当、用词不匹配——全是检索管线的问题。做好 RAG 的第一步,不是训练更好的 Embedding 模型,而是做分块实验验证你的检索质量。
本文由 LaoLiang 原创,首发于掘金/知乎/微信公众号。转载请联系作者。