RAG 召回提升相关方案分享

44 篇文章 9 订阅
7 篇文章 0 订阅

最近大半年时间都在做RAG的工作,分享一点个人探索的方向。和提升的方案。文章中会分享是如何做的,以及对应的效果。

核心问题

如何提升RAG的效果?

如何提升召回的准确率。

写在前边:已验证的方案

方案

优化方向

效果

备注

3.1 优化分词器

英文去除停顿词,单复数标准化

解决了badcase

3.2 分词器

使用IK分词器

BM召回率提升了1%

3.3 向量检索召回

替换embedding模型

向量召回率提升了15%左右

3.4 丰富数据

定义有层级的数据结构

可以很有效的解决一些和标题相关的问题的case。

3.5.1 意图识别

判别是否走知识库检索

解决非检索问题

3.5.2 为问题生成假设性答案(HyDE)

假设性问答,解决场景问题

可以很好的解决 长尾的query整体召回率提升了3%

3.5.3 query 蒸馏

去除query中的不相关的关键词

可以很好的提升召回排名

3.5.4 query问题拆解 CoT思维链

解决复杂问题的问答

复杂难问题拆解后回答效果好

3.7 排序策略rerank

提高相关文档的排名

效果明显好。

3.8 ELSER稀疏向量模型

使用稀疏向量模型(es官方提供的),提升召回

在英文场景下,稀疏向量的召回率相比较BM25,提升明显!提升到了100%提升了14%

topK召回率有很大提升,top1提升了31%,top5提升了28.5%,top10提升了22%

收费纯英文环境。不支持中文。

3.9 同义词库

加入通用的同义词库

BM25召回效果,下降50%

问题分析1、长尾query,同义词库效果不好。需要对query进行更多处理,再配合上同义词会有好的效果。2、针对领域的专业词库,效果会更好一些。

3.10 评分排序优化

item weight

BM25召回率提提升了 1.23%

top1召回率提升了 7.6%,top5提升了 5%,top10提升了3.3%,top20提升了2%

1.基础的召回

使用es的标准分词器

相关性召回,mb25 + 向量(embedding模型使用m3e OR BGE-m3

2.测试数据集构建

这里是第一版,有点粗糙。最近在做RAG的benchmark工作,后续把构建测试数据的经验分享出来。如果可以的话,把测试数据集也贡献出来。

2.1 借助模型来构建QA和原文定位的测试数据

在有了测试数据以后,就可以验证召回的效果和RAG最终的效果了。

2.2 测试索引结构定义

2.2.1 召回率测试集

测试索引retrieval_test_20240118

只放问题和内容

唯一键(_id): doc_id + content_id

doc_id: 文章id

content :文本块内容

content_id:文本块id

question:问题

answer: 回答

basis:依据的句子

qid: 问题id(生成规则数字递增)

d_id: 文档id

2.2.2 召回完整度测试集

用来测试句子,测试召回的内容的完整度

需要把测试集中的问题和答案都存起来。

唯一键(_id): doc_id + q_id

doc_id: 文章id

content :文本块内容

content_id:文本块id

question:问题

answer: 回答

basis:依据的句子

qid: 问题id(生成规则数字递增)

d_id: 文档id

2.3 英文测试数据集

2.3 测试数据集合写入

这里写入es。

2.4 测试数据集标注

模型生成的问题还是会有问题。有的问题很乏。

eg:

2.4.1 人工标注规则

先把生成的qa入库。然后做一遍检索召回测试。重点关注向量和BM都没有召回的问题。这种问题是可能有问题的。再关注有召回,但是排名靠后的case。然后人工标注一次。

无法使用的问题,会标记为橙色,可用标识为0。弱相关的数据标识为绿色,可用标识为0。 相关但是无法被召回或者召回后排名靠后的标记为黄色,可用标识为1。后续提升重点关注可用标识为1的case,验证提升方案,对这些case的提升效果。

  1. 优化过程

最终目标是提升召回率和提升召回的rank质量。

可以考虑以解决badcase为出发点。总结badcase的共性,寻找通用的解决方法。

其中 向量无法召回,BM25召回的badcase,作为向量的提升方向。

其中 向量召回,但是BM25无召回的badcase,作为BM25的提升方向。

如何划分和定义搜索的最小单元。词?字?句子?短句?

TODO 待解决问题

  1. 召回策略制定:问题究竟要在什么粒度的数据中做检索。句子?还是段落?还是摘要?还是整篇文章?

此问题,目前只有在片段中做检索。

  1. 层级数据结构:..


 

3.1 优化分词器 —— 停顿词和单复数

解决中文和英文的问题,选择使用标准分词器。

需要添加额外的策略:英文去除停顿词,单复数标准化。

此策略,可以很好的解决单复数的问题。

3.1.1 badcase

问题

How should I respond to public demonstrations and protests?

期望召回

Article 27 Hong Kong residents shall have freedom of speech, of the press and  of publication; freedom of association, of assembly, of procession and of  demonstration; and the right and freedom to form and join trade unions,  and to strike.

3.1.2 效果

处理前无召回

经过处理后 top3即可召回

3.2 分词器测试

测试中英文数据分开存储,然后使用各自不同的分词器的效果。

3.2.2 测试IK分词器

案例一:切换IK中文分词器,只影响BM25的召回率,可以看到整体的召回率降低了3%

案例二:使用另外一个测试集对比,BM召回率提升了1%

在以上的测试中,案例一的QA对是基于全文的,而案例二的QA是基于片段的。且案例二的测试用例比案例一更多。

结论:可以考虑,使用中文分词器做替换。

3.3 向量检索召回—— 测试可替代m3e的模型

embedding模型的效果可能比较相近了。不过确实有一些排名更好的文本embedding模型。可以验证一下召回效果。以解决更多badcase为目标导向。

测试了xiaobu,bge,gte模型,将模型导入到es中。其中xiaobu无法成功导入,bge,gte导入后无法成功应用。

算法同事测试了不同的embedding模型的效果

基于段落的召回效果测试

基于全篇内容的召回测试

英文段落内容的召回测试

3.4 丰富数据

TODO :将以下需要丰富的内容,定义到mapping中。整理最新的mapping结构。

3.4.1 生成句子向量,单独一路召回。

句子向量,需要测试一下效果。可能之前测过,觉得不好。 可以拿一些badcase试试看,看看能不能解决badcase。将命中的句子对应的段落召回

3.4.2 为标题单独生成向量

为标题单独生成向量。召回的时候作为单独一路召回。如果相似度到达一个阈值以后。则考虑将标题下的内容给模型。测试效果。

3.4.3 为内容生成命题

为内容生成命题(使用模型生活,生成原子问题)。 这里和生成假设性问题思路类似。作为一路召回,测试对召回率的影响。

3.4.5 为句子,提取重要的关键词

在数据写入阶段,根据词性,以及词在句子中的重要性,去提取重要的关键词。目前来看可能不是太重要。

3.5 丰富Query 与 rewrite Query

3.5.1 意图识别

先弄清楚,请求是要做什么的。是简单召回请求,还是分析类型请求(需要做问题拆解),还是问答类的请求。

对于知识库来说,最应该清楚一件事情,是否应该走知识库检索?

实际上,想要判断是否能够从知识库中检索,是一件很难的事情。无法穷举知识库的特征,所以就无法做分类。但是换个角度,让模型判断query是否是模型应该回答的,是较为容易得事情。所以这里可以先判断模型是否能够回答。如果能够回答,则不走知识库搜索。

3.5.2 为问题生成假设性答案(HyDE)

为问题生成假设性答案,然后转向量。作为召回的一路,去测试召回提升率。或者去测试badcase,看看能不能解决。HyDE的核心思想是接收用户提问后,先让LLM在没有外部知识的情况下生成一个假设性的回复。然后,将这个假设性回复和原始查询一起用于向量检索。假设回复可能包含虚假信息,但蕴含着LLM认为相关的信息和文档模式,有助于在知识库中寻找类似的文档。

HyDE在解决法律的案例场景问答问题,有着出色的效果。 精准解决了90%的问题。

并且经过测试,在已有的测试数据集上,HyDE召回了提升了3%。

3.5.2.1 prompt

这里我限制了模型生成的内容的长度为256个token以内。

write a passage that answer zhe given query .  Please note that the answer is controlled within 256 tokens.  query:"What is the offence of using a copy of a fake document?"

3.5.2.2 拼接规则

新的query = 原始query + LLM 生成的答案

3.5.2.3 效果

对比了chatGPT 和yayi

测试数据说明。选用HK 人工整理的高质量测试数据集和高质量QA验证对。全部测试QA数据集是198个。

top5的召回率为92%。其中共有15个未成功召回的badcase。通过使用HpDE + Bm25 + GPT的方式,在top10以内召回的数量增加了5个,召回率为95%整体提升3%。yayi和chatGPT的query改写能力,基本持平。

3.5.3 query 蒸馏

在数据查询阶段,根据词性,以及词在query中的重要性,去提取重要的关键词。排除非必须的关键词。然后用提炼后的词去做bm25的召回。以通过排除干扰词来提高相关性。

eg.

Q: 今年春节以来,博爱县采取了哪些措施来促进消费市场的回暖?

如果能提取出来:博爱县 采取 措施 促进 消费市场 回暖

+ 同义词

你是一位专业的 prompt engineer,用户将给你提供一个问题。 你需要对问题进行重写。

要求,先理解问题。根据词性等信息,提取出来重要的内容,去掉一些不重要的内容。

对一些有必要的词扩展关键词。

例如:"今年春节以来,博爱县采取了哪些措施来促进消费市场的回暖?"

经过理解后,可以知道博爱县是主题词,提取出来,博爱县 采取 措施 促进 消费市场 回暖。并添加一些关键词的同义词。

eg:文章中提到了哪些特色产业领域?

实际上有意义的,只有特色领域。应该有一个步骤,将这些问题的干扰项去掉。(文章中提到了哪些特色产业领域)

3.5.4 query问题拆解 CoT思维链

query问题拆解。将复杂问题进行拆解成N个子问题。使用LLM生成多个搜索查询,特别适用于一个问题可能需要依赖多个子问题的情况。

3.5.5 上下文会话信息改写query

使用滑动窗口,例如基于前10轮对话,来改写当前的query。

3.6 丰富召回策略

更多的召回与Q相关的content

BM25能召回的:关键词匹配命中的

向量检索:内容有一定的相关度。

需要挖掘的:有些内容需要阅读全文才能获取知识。这里能不能抽取一些政策和关键词出来。这里需要知道什么时候应该把全文召回。

eg:兴隆村在推动乡村振兴方面采取了哪些措施,以及这些措施带来了哪些具体的产业变化?

3.7 排序策略与相关性蒸馏 rerank

将更相关的数据排序在前。对召回的全部内容进行蒸馏,将不相关的杂质去除。

3.8 ELSER稀疏向量模型——英文场景 与 BM25对比测试

在英文场景下,稀疏向量的召回率相比较BM25,提升明显!提升到了100%提升了14%

topK召回率有很大提升,top1提升了31%,top5提升了28.5%,top10提升了22%

注意!这里在做测试的时候,有发现中文数据一定不能掺杂到英文数据中来,否则会严重影响召回率

3.9 同义词库

中文同义词库的对比测试

其中3是未添加同义词库前,6为添加同义词库后。

明显看到。在添加了同义词库后,BM25整体的召回效果降低了很多!降低了将近50%

结论:这里暂时不考虑使用同义词库。同义词库作为未来的探索方向,是不是词库不好?

3.10 评分排序优化-1

对于有一些问题case,是可以考虑抽取实体的。通过实体匹配来加分,提高排序的效果。

eg:文章中提到了哪些促进区域协调发展的措施

通过词性分析,提取一些重要的词来做加分的查询操作。使用should语法

整理了一定的规则。

NT : 时间名词,连续的NT词必须是一个整体;
VV: 去除单字;保留2个字及以上;
NN:前后独立的NN去除;单字的NN需和前后NN组成整体词;
OD:中文序数词,如“第一、第二、十九”,需与前后组成整体词;
M:数量词;需与前后组成整体词;

在通过加分的优化下:

BM25召回率提提升了 1.23% 。原来有63个没有被召回。修改后只有34个没有召回。实际上效果已经提升了将近50%

top1召回率提升了 7.6%,top5提升了 5%,top10提升了3.3%,top20提升了2%

在34个没有召回的case里边。其中有24条,是有问题的问题(问题太泛了)。

剩余10条没有召回case里,看到加分策略的副作用。这里举一个例子:如何理解“十个行动”?

显然这里会拿着"理解" + "行动"去加分,结果会变差。

3.11 评分排序优化-2

在数据写入的阶段抽取实体在检索的过程中,对query也抽取实体,然后利用实体去加分。

还可以考虑使用模型来规划query(TODO 调试prompt)

  1. 测试方案

4.1 测试项

4.1.1 优化分词器 —— 停顿词和单复数

4.2 整体性测试

召回率,top值

5. yayi提升记录

针对HK问题,最初的测试结果

人工进行PDF文档切分后

重新训练模型后

错误原因分析:
24-02-03版评测中20条错误答案归因:
正确回答 2条
未召回 9条 (最终确认,未召回,是指未出现在Top5中,需要优化rerank过程。)
主体内容正确,模型延伸出现幻觉 2条
主体内容正确,判断出错 3 条
内容正确,但对问题回复太过笼统,未回答出核心  2条
引用内容正确,数理逻辑判断错误  1条
被截断 1条

  1. 文档拆分问题

文档排重

原始文档中的数据,要做一个排重。相同的文档,理应只存储一份,否则在多文档检索中,会严重的影响召回率!

文档分类

应该按照什么样的策略,来对文档数据进行分类?

首先同类型的数据一定是要放在同一类中。例如论文、书籍、法律法规、财务报表、等等。不同类型的文档又有不同的知识密度。在检索的时候,分开检索,可以有效减少之间的相互影响。

如何解析转义文档?

如何原值原味的保留文档的原始结构? 通常文档的结构都有特定的含义,例如不同级别的标题。

文档转行 markdown格式。是否能转?是否能切分?(langchain)

分块大小的问题,每个块要分多大,以什么规则分?

大块数据和小块数据各自有各自的优势。处理长篇文章或书籍时,较大的分块有助于保留更多的上下文和主题连贯性;而对于社交媒体帖子,较小的分块可能更适合捕捉每个帖子的精确语义。如果用户的查询通常是简短和具体的,较小的分块可能更为合适。

不同的嵌入模型有其最佳输入大小。比如Openai的text-embedding-ada-002的模型在256 或 512大小的块上效果更好。实际场景中,我们可能还是需要不断实验调整,在一些测试中,128大小的分块往往是最佳选择,在无从下手时,可以从这个大小作为起点进行测试。

所以根据文档,应该有不同的切分规则。有句子构成的句向量有必要,由段落构成的块儿向量也有必要。通常句子向量中蕴含的信息较少,在回答一个问题的时候,通常具有信息确实的可能性。一般情况下,句子向量应该是作为标记点,使用窗口的方式,把对应的段落,或者是上下文召回。

7. 关于query改写的理解

query改写其实理解起来很简单,就是把原始的query经历一系列的操作,然后变成另外一个query,从而达到提升召回率和准确率的效果。

query改写的过程中,这一系列的操作,其实是围绕两个方面展开的。第一是在原始query中添加一些有用的内容(可以理解为query扩展),把本该召回却没有召回的内容给召回,提高topK的召回率。第二是在原始query中去掉一些杂质内容(可以理解为蒸馏),主要操作是对召回的数据,进行一个反馈。

围绕这两个方面,特别是在LLM越来越火热的情况下,学术界有了越来越多的研究。

针对扩展这个方向,要看具体的相关度匹配方法。例如以BM25为代表的稀疏检索。query扩展是会引入更多的词,扩大了召回的可能性,但是前提是引入正向的词,假如引入的是噪音数据,那么反而会降低召回的效果。

在PRF中,主要的思想是想用query在候选集中做一次召回。然后从召回的结果集中挖掘有意义的扩展信息,重写query。在多篇文章中,提到了召回的数量一般设置为10,通常会截取召回的数据,有的是128个token,有的是256个token。

  • 20
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值