从《红楼梦》的视角看大模型知识库 RAG 服务的 Rerank 调优

Rerank tuning of RAG service in large model knowledge base from the perspective of 'Dream of Red Mansions'

Posted by Bryan on May 22, 2024

背景介绍

在之前的文章 有道 QAnything 源码解读 中介绍了有道 RAG 的一个主要亮点在于对 Rerank 机制的重视。

从目前来看,Rerank 确实逐渐成为 RAG 的一个重要模块,在这篇文章中就希望能讲清楚为什么 RAG 服务需要 Rerank 机制,以及如何选择最合适的 Rerank 模型。最终以完整的《红楼梦》知识库进行实践。

至于为什么要用红楼梦,答案就是作为读了很多遍《红楼梦》的忠实粉丝,问题的答案是不是靠谱一眼就能判断,问题相关的片段也能快速定位,就像定位 bug 一样快。

Rerank 是什么

以有道 QAnything 的架构来看 Rerank 在 RAG 服务中所处的环节

qanything_arch

可以看到有道 QAnything 中的 Rerank 被称为为 2nd Retrieval, 主要作用是将向量检索的内容进行重新排序,将更精准的文章排序在前面。通过向大模型提供更精准的文档,从而提升 RAG 的效果。

在目前的 2 阶段检索(Embedding + Rerank)设计下,Embedding 模型只需要保证召回率,从海量的文档中获取到备选文档列表,不需要保证顺序的绝对准确。而 Rerank 模型负责对少量的备选文档列表的顺序进行精调,优中选优确定最终传递给大模型的文档。

打个简单的比方,目前的 Embedding 检索类似学校教育筛选中的实验班,从大量的学生中捞出有潜质的优秀学生进行培养。而 Rerank 则从实验班中对学生进一步精细排序,选出少数能上清北的重点培养。

为什么不能一步到位

Embedding 检索时会获得问题与文本之间的相似分,以往的 RAG 服务直接基于相似分进行排序,但是事实上向量检索的相似分是不够准确的。

原因是 Embedding 过程是将文档的所有可能含义压缩到一个向量中,方便使用向量进行检索。但是文本压缩为向量必然会损失信息,从而导致最终 Embedding 检索的相似分不够准确。参考 Pipecone 对应的图示如下所示:

embedding

可以看到 Embedding 过程包含两步:

  1. 运行单个 Transformer 计算以创建查询向量。
  2. 将查询向量与具有余弦相似性的文档向量进行比较,获取相似文档。

而 Rerank 阶段不会向量化,而是将查询与匹配的单个文档 1 对 1 的计算相似分,没有向量化带来的信息损失,必然会得到更好的效果,对应的过程如下所示:

rerank_diff

那直接执行 Rerank 是否可行呢?肯定也是不行的,Rerank 需要 1 对 1 计算相似分的,在海量的文档中一一比对查找文档,效率肯定是不能接受的。

除了这个原因以外,拆分 Rerank 阶段也提供了更加灵活的筛选文档的能力,比如之前介绍过的 Ragflow 就是在 Rerank 中使用 0.3 * 文本匹配得分 + 0.7 * 向量匹配得分 加权得出综合得分进行排序,Rerank 阶段可以提供类似这种灵活的选择手段。

支持超大上下文的模型是否可以避免 Rerank

我们之所以需要提供准确的文档,一般是因为大模型提供的窗口有限,无法塞入过多的文档。但是目前有模型提供了更大的上下文窗口,重排是否就可有可无了呢。

Pipecone 提供的曲线图可以看到 GPT 3.5 中存在如下所示现象:

more_issue

随着塞入大模型上下文的文档数增加,大模型从文档中召回信息的准确性会下降。

以我实际碰到的一个例子来看,两次检索与重排得到的都是同样顺序的文本内容,而且需要召回的信息都出现在排名第一的位置上。当我选择加入大模型上下文中的文档数量为 10 时,大模型最终的回答如下所示:

10th

但是减少加入上下文的数量为 5 时,大模型最终的答案如下所示:

5th

可以看到,加入大模型的文档过多,召回信息的准确性确实会下降。所以超大上下文窗口并不是解决所有问题的灵丹妙药。

Rerank 模型的选择

目前开源的 Rerank 模型选择不如 Embedding 模型那么多,主要是下面几个:

  • 智源提供的 BGE 系列
  • 有道提供的 BCE 模型
  • Cohere 提供的 CohereRerank 系列

由于主要考虑开源可使用的模型,因此先排除了 CohereRerank 系列模型,结合搜索的信息确定备选的模型如下所示:

  • bce-reranker-base_v1 有道 BCE 系列只提供了这一款 Rerank 模型,上个月 huggingface 下载量 8.7k
  • bge-reranker-large 这一款为 BGE 系列的经典 Rerank 模型,评价比较高,上个月 huggingface 下载量 33.2k
  • bge-reranker-v2-m3 这一款为智源目前推荐的多种场景的建议模型,上个月 huggingface 下载量 69.4k

参考的信息源主要是:

那个模型表现最好呢?

有道在 网站 上放出来的测评结果如下所示:

rag_eval_multiple_domains_summary

可以看到测评得到的结果是 bce-reranker-base_v1 是略胜一筹的,当然大家都知道各家官方上给出的都是对自己有利的测评结果,但是其中对友商的测评结果大概率还是可以相信的,可以看到 bge-reranker-v2-m3 小幅领先 bge-reranker-large

另外一个测评是来自于 智源网站 提供的

llama-index

可以看到表现最好是 bge-rerank-v2-minicpm-28, 但是看了下 hugggingface 上模型大小为 10G 左右,相对 2G 左右的 bge-reranker-large 资源开销大太多了。

综合下载量和测评结果,bge-reranker-v2-m3 看来是当前最佳选择,bge-reranker-large 和 bce-reranker-base_v1 可以作为备选。实际表现如何还需要进一步验证。

动手实践

具体的实现可以直接参考 langchain-chatchat 中的 Rerank 模块。

此模块主要实现的就是加载 Rerank 模型,然后计算文档块与问题的相似分,之后根据此相似分进行重排。

接下来的实践过程相对简单,将完整的《红楼梦》导入知识库,分片向量化,为了方便在本地的普通 CPU 笔记本上运行,我接入了百度提供的在线大模型 API 进行测试。而 Embedding 模型我使用的是 stella-base-zh-v3-1792d

在本次测试中,我主要验证了两种场景:

  1. 多 Rerank 模型的效果比较,主要关注同样的文档使用 Rerank 模型排序后的顺序差异,看哪个 Rerank 排序的结果最符合人的预期;
  2. 选择 Rerank 模型的优胜者和无 Rerank 情况进行比较,确认是否吊打无 Rerank 的情况;

多 Rerank 模型比较

实际基于 Kimi 生成了 15 个问题,具体的问题如下所示:

  1. 红楼梦中,贾宝玉和林黛玉第一次见面是在哪一年?
  2. 请列举《红楼梦》中贾府的四位主要女性角色。
  3. 《红楼梦》中,王熙凤为什么被称为“凤姐”?
  4. 贾宝玉的通灵宝玉有什么特殊之处?
  5. 林黛玉的诗作中,有一首描写春天的诗,请找出并描述其内容。
  6. 在《红楼梦》中,贾母为何偏爱贾宝玉?
  7. 描述《红楼梦》中薛宝钗的性格特点。
  8. 请找出《红楼梦》中关于“大观园”的描述,并说明其在故事中的意义。
  9. 《红楼梦》中,贾宝玉和林黛玉的关系是如何发展的?
  10. 请列出《红楼梦》中提到的几种不同的茶。
  11. 红楼梦中,林黛玉的死因是什么?
  12. 请列举《红楼梦》中贾府的几位仆人,并描述他们的角色。
  13. 《红楼梦》中,贾宝玉和薛宝钗的婚姻是如何安排的?
  14. 红楼梦中,贾元春的封号是什么?
  15. 请描述《红楼梦》中贾宝玉的人生观和价值观。

测试中除了 Rerank 模型外,其他部分都保持一致,最终测试下来,结论如下:

  1. bge-reranker-v2-m3 模型表现最好,bce-reranker-base_v1 和 bge-reranker-large 在不同问题中各有胜负。
  2. bge-reranker-large 的相似分很容易出现接近 1 的高分,与实际人的直觉不完全一致
  3. bce-reranker-base_v1 的相似分相对更均衡,经常在 0.4 ~ 0.7 之间,与常规的人的直觉更接近

当然这个测试偏向简单验证,有一定的主观判断,而且问题的数量不够多,如果进行模型选型还是需要根据自己的数据集和问题进行进一步测试。

部分的问题的结果展示如下,下面测试结果中的第一个百分比为 Rerank 模型给出的相似分,第二个百分比为原始 Embedding 模型给出的相似度评分,可以看到其中的判断差异:

问题 1. 红楼梦中,贾宝玉和林黛玉第一次见面是在哪一年?

bce-reranker-base_v1 q1_bce

bge-reranker-large q1_bge

bge-reranker-v2-m3 q1_bge_v2

问题中大模型最后都没有正确回答,因为没有检索到正确的内容,但是 bge-reranker-v2-m3 确实给出了相当低的相似分,表明没有正确的内容,而其他模型在这种情况下都没体现出这个特征。

问题 13. 《红楼梦》中,贾宝玉和薛宝钗的婚姻是如何安排的?

bce-reranker-base_v1 q13_bce

bge-reranker-large q13_bge

bge-reranker-v2-m3 q13_bge_v2

这个比较明显,bce-reranker-base_v1 和 bge-reranker-large 都没能将正确的片段排序在最前面,而 bge-reranker-v2-m3 排序最靠前的片段才是符合预期的。而大模型的回答也体现出这种差异,回答明确提到了婚姻是由贾母等长辈决定的。

而且可以看到 bge-reranker-large 中由于上下文排序不合适导致大模型的幻觉更加严重了,连林黛玉意外远嫁都幻想出来了。

有无 Rerank 机制的比较

同样创建了一批问题进行测试,Rerank 模型选择的是 bge-reranker-v2-m3,实际测试确实效果还是比较明显的,Rerank 后前面的回答相关性明显更强,比如:

无 Rerank 原始版本 q3

Rerank 版本 q3_rerank

可以看到 Rerank 后给出了更准确的信息,大模型的回答中也会包含更多细节,回答质量也会更高。

总结

从本次《红楼梦》的实践来看,Rerank 机制的效果还是比较明显的。通过额外的精细重排,给大模型提供了更精准的上下文,从而提升大模型知识库回答的质量。

从本次测试的情况来看,开源模型 bge-reranker-v2-m3 表现更胜一筹,当然实际的表现与数据集和问题都有很大关系,大家实际使用时可以基于自己的知识库与问题进行有针对性的测试。