做了两年多 RAG 项目,踩过的坑比写的代码还多。说几个真正管用的优化点,都是血泪教训换来的。
第一个认知:RAG 效果差,90% 的锅不在大模型
很多人一上来就想换更贵的模型,其实问题往往出在"喂给模型的资料本身就是垃圾"。
垃圾进,垃圾出——这句话在 RAG 里体现得淋漓尽致。
真正值得花时间的几个方向
1. 文档预处理(最容易被忽略,但收益最大)
你把一份 PDF 直接丢进去切块,会发生什么?
页眉页脚、目录、水印、广告、导航条……全都被当成"知识"存进去了。用户问个正经问题,召回的全是这些垃圾。
我现在的做法:入库前先过一遍清洗脚本,把这些噪声干掉。别小看这一步,有时候光做好清洗,效果就能提升 30%。
2. 切块策略(别再无脑按 500 字切了)
按固定长度切块是最偷懒的做法,也是效果最差的。
举个例子:一个操作步骤分 5 步,你正好从第 3 步中间切开了,模型拿到的上下文根本不完整,它怎么可能答对?
更好的做法:
- 按语义边界切(标题、段落、列表项)
- 代码文档按函数/类切
- FAQ 把问题和答案绑在一起,别拆开
3. 混合检索(别只押宝向量)
纯向量检索有个致命问题:对精确匹配的东西很弱。
比如用户问"ERR_10086 是什么错误",向量检索可能给你召回一堆"错误处理"相关的内容,但就是找不到 ERR_10086 这个具体错误码。
解法很简单:关键词检索 + 向量检索并行跑,结果合并。一个擅长精确匹配,一个擅长语义理解,互补。
4. 召回后加一层重排序(性价比极高)
第一轮召回的时候可以放宽一点,比如先捞 50 条。然后用一个轻量的排序模型(比如 bge-reranker)再筛一遍,只把最相关的 5-10 条喂给大模型。
这一步成本很低,但能显著过滤掉那些"看起来相关但其实不相关"的噪声。
5. 上下文扩展(命中的那一小段往往不够)
检索命中了一个 300 字的块,但这 300 字可能只是在讲结论,前面的前提条件、后面的注意事项全丢了。
做法:命中后把相邻的块也带上,或者把同一个标题下的内容都拼进去。用小块搜索(更精准),用大块生成(更完整)。
6. 提示词里加一条硬约束
"必须基于提供的资料回答,如果资料中找不到相关信息,请直接说'资料中未找到相关内容',不要自行推测。"
就这一句话,能干掉一大半的"幻觉"问题。
一个快速见效的优化顺序
如果你时间有限,按这个顺序来:
- 先做好文档清洗(立竿见影)
- 上混合检索(关键词 + 向量)
- 加重排序(过滤噪声)
- 调整切块策略(按语义切)
- 提示词加硬约束(减少幻觉)
每做完一步就测一批真实问题,别一口气全改完再测——不然出问题你都不知道是哪一步搞的。
以上是我自己实践下来觉得最有用的几个点。如果你说说具体场景(客服、知识库、代码问答?),可以给更针对性的建议。