RAG 召回提升相关方案分享

最近大半年时间都在做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。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/871293.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

iPad锁屏密码忘记怎么办?有什么方法可以解锁?

当我们在日常使用iPad时,偶尔可能会遇到忘记锁屏密码的尴尬情况。这时,不必过于担心,因为有多种方法可以帮助您解锁iPad。接下来,小编将为您详细介绍这些解决方案。 一、使用iCloud的“查找我的iPhone”功能 如果你曾经启用了“查…

07-7.5.3 处理冲突的方法

👋 Hi, I’m Beast Cheng 👀 I’m interested in photography, hiking, landscape… 🌱 I’m currently learning python, javascript, kotlin… 📫 How to reach me --> 458290771qq.com 喜欢《数据结构》部分笔记的小伙伴可以…

Biz-Logger操作日志框架

文章目录 前言一、设计 / 对比 / 实现1.1 注解1.1.1 EnableBizLogger1.1.2 BizLogger1.1.3 BizLoggerComponent1.1.4 BizLoggerFunction 1.2 自定义函数1.2.1 IBizLoggerFunctionRegistrar1.2.2 AbstractBizLoggerFunctionResolver 1.3 日志上下文1.3.1 BizLoggerContext 1.4 S…

SSM学习6:Spring事务

简介 事务作用:在数据层保障一系列的数据库操作同成功同失败Spring事务作用:在数据层或业务层保障一系列的数据库操作同成功同失败 public interface PlatformTransactionManager{void commit(TransactionStatus status) throws TransactionStatus ;vo…

Elasticsearch 角色和权限管理

在大数据和云计算日益普及的今天,Elasticsearch 作为一款强大的开源搜索引擎和数据分析引擎,被广泛应用于日志分析、全文搜索、实时监控等领域。随着业务规模的扩大和数据敏感性的增加,对 Elasticsearch 的访问控制和权限管理也变得越来越重要…

【人工智能】Transformers Pipeline概述

欢迎来到我的博客,很高兴能够在这里和您见面!欢迎订阅相关专栏: 欢迎关注微信公众号:野老杂谈 V: LAF20151116 进行更多交流学习 ⭐️ 全网最全IT互联网公司面试宝典:收集整理全网各大IT互联网公司技术、项目、HR面试真…

【网络文明】关注网络安全

在这个数字化时代,互联网已成为我们生活中不可或缺的一部分,它极大地便利了我们的学习、工作、娱乐乃至日常生活。然而,随着网络空间的日益扩大,网络安全问题也日益凸显,成为了一个不可忽视的全球性挑战。认识到网络安…

Python数据分析案例52——基于SSA-LSTM的风速预测(麻雀优化)

案例背景 又要开始更新时间序列水论文的系列的方法了,前面基于各种不同神经网络层,还有注意力机制做了一些缝合模型。 其实论文里面用的多的可能是优化算法和模态分解,这两个我还没出专门的例子,这几天正好出一个优化算法的例子来…

uboot学习:(四)顶层makefile分析

目录 版本号 MAKEFLAGS变量 命令输出 静默输出 设置编译结果输出目录 代码检查(一般不需要使用,了解就行) 模块编译(一般不用uboot编译模块,了解就行) 获取主机架构和系统 设置目标架构、交叉编译…

隔离驱动-视频课笔记

目录 1、需要隔离的原因 1.2、四种常用的隔离方案 2、脉冲变压器隔离 2.1、脉冲变压器的工作原理 2.2、泄放电阻对开关电路的影响 2.3、本课小结 3、光耦隔离驱动 3.1、光耦隔离驱动原理 3.2、光耦隔离驱动的电源进行分析 3.3、本课小结 4、自举升压驱动 4.1…

JS【详解】对象(含对象的存储原理,对象的常用操作,判断对象是否为空对象,对象的深拷贝,对象的创建、遍历、合并、拷贝等)

简介 任何事物都可以看作一个对象,用属性描述它的特征,用方法描述它的行为,如下方代码所示: let obj {name: "朝阳",sayHi: function () {console.log("你好!");}, }; typeOf obj // object变量…

大数据开发中的元数据:从基础到高级应用的全面指南

在大数据开发中,元数据(Metadata)是指描述数据的数据。元数据可以提供有关数据结构、数据类型、数据约束和数据关系的重要信息。合理利用元数据可以显著提高数据建模和管理的效率。本文将详细介绍如何根据元数据建表,并提供一些代…

2024年公司电脑屏幕监控软件推荐|6款好用的屏幕监控软件盘点!

在当今的商业环境中,确保员工的工作效率和数据安全是每个企业管理者的重要任务。屏幕监控软件通过实时监控和记录员工的电脑活动,帮助企业有效地管理和优化工作流程。 1.固信软件 固信软件https://www.gooxion.com/ 主要特点: 实时屏幕监控…

ConditionalOnSingleCandidate注解使用介绍、应用场景以及示例代码

概述 ConditionalOnSingleCandidate 是Spring Framework中的一个条件注解,它用于根据特定类型的 bean 是否有且仅有一个候选者来决定是否创建一个 bean 或者配置一个类。 应用场景 依赖特定类型的唯一bean: 当需要依赖一个特定类型的 bean,并且这种类型…

养殖业饲料加工新选择,粉碎机械提升效率

在当今畜牧业快速发展的时代,饲料加工设备成为提升养殖效益的重要一环。其中,饲料加工粉碎机凭借其G效、便捷的特点,成为了养殖场的得力助手。 饲料加工粉碎机作为养殖业的重要设备之一,其主要功能是将各种原料如玉米、豆粕、麦…

简单的网页压力测试

要进行简单的网页压力测试,可以使用Python的requests库来发起请求,并结合time模块来控制请求频率。以下是一个基本的实现,它会每分钟发送指定次数的请求到目标网址。 import requests import time# 目标网址 url ***# 每分钟请求的次数 req…

【GameFramework扩展应用】6-3、GameFramework框架增加日志保存功能

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址QQ群:398291828大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 【GameFramework框架】系列教程目录: https://blog.csdn.net/q764424567/article/details/1…

Sentinel限流算法:滑动时间窗算法、漏桶算法、令牌桶算法。拦截器定义资源实现原理

文章目录 滑动时间窗算法基本知识源码算法分析 漏桶算法令牌桶算法拦截器处理web请求 滑动时间窗算法 基本知识 限流算法最简单的实现就是使用一个计数器法。比如对于A接口来说,我要求一分钟之内访问量不能超过100,那么我们就可以这样来实现&#xff1…

(一)高并发压力测试调优篇——MYSQL数据库的调优

前言 在实际项目开发中,很多业务场景下都需要考虑接口的性能要求,追求高并发、高吞吐量。那么对于此类问题如何入手呢?关注作者,不迷路。本节内容主要介绍在数据库db方面的优化,以mysql数据库为例。 关于db的优化&am…

7、matlab实现SGM/BM/SAD立体匹配算法计算视差图

1、matlab实现SGM/BM/SAD立体匹配算法计算视差图简介 SGM(Semi-Global Matching)、BM(Block Matching)和SAD(Sum of Absolute Differences)都是用于计算立体匹配(Stereo Matching)的…