检索步骤
- 开启精排(可以做成项目配置,根据配置是否开启)
精排的关键是我们topk的参数得传大点,检索的更多语义相关性chunk 在大模型检索好的结果中的多语义相关性打分,打分最高的优先取出几条来
- 密集向量检索
将query进行embedding后通过milvus的查询enbedding后的chunk。进行语义相似度cos比对
- 稀疏向量检索
- 词频(TF):这个词在文档里出现越多,分数越高
- 逆文档频率(IDF):这个词在整个知识库里越稀有,分数越高("的""是"这种常见词权重很低)
- 重排序 RRF(Reciprocal Rank Fusion)
- RRF得分 = 1/(k + 密集向量排名) + 1/(k + 稀疏向量排名)
- k=60 是平滑参数(代码指定的参数)
- 总结:是将密集向量的排名 + 稀疏向量的排名 = RRF的分,两者排名都靠前,得分最高。
- 按时间衰减排序(若知识库文档更新频繁,知识内容易过期的场景)
- 新资料优先的规则,根据chunk的update_at时间排序新的chunk优先
- 开启MMR排序(可以做成根据项目配置的功能)
- 每条都和 query 足够相关(相关性项保证)
- 彼此之间内容尽量不重复,采用贪心算法,query语义话相关的前提下,越是和当前已采纳的chunk内容不一致,越容易被采纳
-
功能: MMR 在 RRF 之后再做一轮,补上这个"去冗余"的能力。(先保证每条都相关,再保证整体不重复)
-
总结: 既要和 query 相关,又要和已选的 chunk 不一样,两个条件同时满足得分才高。
其他的优化项目
- 提高Chunk 切分质量,比如
- 语义边界优先切分
- 第一步:按段落预切分
- 先按 \n\n 把文本切成若干段落块,每个段落块保证语义完整。
- 第二步:合并小段落
- 相邻的小段落(< chunkSize)合并,直到接近 chunkSize 再输出为一个 chunk,避免 chunk 太短。
- 第三步:拆分大段落
- 遇到超过 chunkSize 的大段落,在句子边界(。!?)处切,而不是硬截断。
- 第四步:重叠保留上下文
- 重叠部分取上一个 chunk 的最后一句完整句子,而不是固定 150 个字符。
- 第五步:表格单独处理
- PDF 解析出的表格通常有特征(多个 | 或对齐的空格列),可以识别出来,把整张表格作为一个 chunk,不参与滑动窗口切分。
- 标题注入,把章节标题前缀到每个 chunk 里。这样每个 chunk 即使脱离上下文,也知道自己在讲的哪个部分,embedding 更准确
- 语义边界优先切分
- Embedding 模型质量
- 知识库本身的质量(文档本身内容混乱、格式不规范,再好的检索也没用)
总结
这只是普通的RAG检索方案和流程,RAG进阶还有很多如
-
Adaptive RAG
-
Self-RAG
-
CRAG
-
Agentic RAG