检索增强生成RAG系列7--RAG提升之高级阶段

系列5中讲到会讲解3个方面RAG的提升,它们可能与RAG的准确率有关系,但是更多的它们是有其它用途。本期来讲解第三部分:高级阶段。之所以说是高级阶段,可能是不好归一,而且实现起来相对于前面来说可能更为复杂。

目录

  • 1 重排(Re-ranking)
    • 1.1 RRF算法
    • 1.2 Cohere Rerank模型
    • 1.3 BGE-reranker模型
  • 2 self-RAG
  • 3 CRAG
  • 4 总结

1 重排(Re-ranking)

在系列4中讲到问题优化的方法RAG-Fusion,里面提到了它与Multi-Query最后不同就是使用RRF对结果进行重排。其实重排是一种提高RAG问题准确率很好的方法,但是之所以没有放入RAG优化,而放入RAG提升,主要考虑2方面,其一是它其实算是一套流程中一个中间操作,在问题优化方法中也有提到过,不好在RAG优化单独拎出来;其二是它也并非只是简单使用RRF算法重排那么简单。这里就是使用一个大篇幅来讲一下重排。(注意:重排技术与问题优化等提高RAG准确度并不绑定,很多技术都是可以合着一起使用,效果会更好

1.1 RRF算法

在系列4中讲到问题优化的方法RAG-Fusion中已经给出这个算法的代码,但是没有细说这个算法原理。这里来个大家举例说明一下。
RRF全称是Reciprocal Rank Fusion,也称为倒数排名融合。其实这个算法在日常生活中经常见到,比如足球、篮球等运动在评选MVP或者年度最佳球员时,经常会使用投票,这个投票一般会是一个排序,就是你排出你认为是MVP的三个人,注意:这里列出3个人是要排序,谁第一,谁第二,谁第三。然后再利用公式:1 / ( k + rank)。来计算每个人最终分数,然后通过最终分数排名。其中rank代表该球员在每张票的排名,k是一个常数。我们下面举个例子:

假如有3个人对本年度金球奖进行投票
A教练的投票结果:1.卡卡 2.C罗 3.梅西
B教练的投票结果:1.卡卡 2.梅西 3.C罗
C教练的投票结果:1.C罗 2.卡卡 3.梅西
假如k=0,那么:
卡卡的得分就是:1/1+1/1+1/2=2.5
C罗的得分就是:1/2+1/3+1/1=1.83
梅西的得分就是:1/3+1/2+1/3=1.17
因此最终排名就是:卡卡第一名、C罗第二名、梅西第三名。

代码实现如下:

# 定义RRF算法函数,代码来自:https://github.com/langchain-ai/langchain/blob/master/cookbook/rag_fusion.ipynb
def reciprocal_rank_fusion(results: list[list], k=60):fused_scores = {}for docs in results:# Assumes the docs are returned in sorted order of relevancefor rank, doc in enumerate(docs):doc_str = dumps(doc)if doc_str not in fused_scores:fused_scores[doc_str] = 0# previous_score = fused_scores[doc_str]fused_scores[doc_str] += 1 / (rank + k)reranked_results = [(loads(doc), score)for doc, score in sorted(fused_scores.items(), key=lambda x: x[1], reverse=True)]return reranked_results

1.2 Cohere Rerank模型

Cohere Rerank是一个商业闭源的Rerank模型。它根据与指定查询问题的语义相关性对多个文本输入进行排序,专门用于帮助关键词或向量搜索返回的结果做重新排序与提升质量。它是一个在线模型,也就是你无法在本地部署,使用步骤:

  • 在其官方网站注册一个API KEY
  • 使用其客户端或者使用langchain第三方组件进行访问

下面就以langchain框架实现一个demo
前置条件

  • 申请一个Cohere的API KEY
  • 下载m3e-base的embedding模型
  • 准备一些文档作为查询使用
import os
import getpassfrom langchain_community.llms import Cohere
from langchain.chains import RetrievalQA
from langchain_cohere import CohereRerank
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_community.vectorstores.chroma import Chroma
from langchain_community.document_loaders import DirectoryLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.retrievers.contextual_compression import ContextualCompressionRetriever# 前置工作1:设置COHERE的APIKEY
os.environ["COHERE_API_KEY"] = getpass.getpass("Cohere API Key:")# 前置工作2:文档存储,如果已经存储了文档,则不需要该步骤
encode_kwargs = {"normalize_embeddings": False}
model_kwargs = {"device": "cuda:0"}
embeddings = HuggingFaceEmbeddings(model_name='/root/autodl-tmp/model/AI-ModelScope/m3e-base',  # 换成自己的embedding模型路径model_kwargs=model_kwargs,encode_kwargs=encode_kwargs
)
if os.path.exists('VectorStore'):db = Chroma(persist_directory='VectorStore', embedding_function=embeddings)
loader = DirectoryLoader("/root/autodl-tmp/doc")  # 换成自己的文档路径
documents = loader.load()
text_spliter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
documents = text_spliter.split_documents(documents)
database = Chroma.from_documents(documents, embeddings, persist_directory="VectorStore")
database.persist()# 第一步:初始化Cohere模型
llm = Cohere(temperature=0)
compressor = CohereRerank()# 第二步:使用ContextualCompressionRetriever包装检索器
compression_retriever = ContextualCompressionRetriever(base_compressor=compressor, base_retriever=database.as_retriever(search_kwargs={"k": 20})
)# 第三步:使用RetrievalQA调用chain
chain = RetrievalQA.from_chain_type(llm=Cohere(temperature=0), retriever=compression_retriever
)
query = "ChatGLM是什么?"
chain({"query": query})

1.3 BGE-reranker模型

cohere毕竟是闭源的,无法本地部署,因此国内推出了开源项目BGE-reranker模型。BGE-reranker模型是北京智源人工智能研究院(BAAI)推出的一种重排序模型,主要用于优化信息检索系统的性能,底层是基于BAAI General Embedding模型扩展混合检索能力。目前该已经开源,推出bge-reranker-base、bge-reranker-large等版本,在hugging face或者魔塔均可下载。
下面借助FlagEmbedding(一款用于微调/评估文本嵌入模型的工具)和FastAPI可以将BGE-reranker模型封装为API格式,提供和Cohere模型一样的效果。
前置条件

  • 下载BAAI/bge-reranker-base模型
  • 安装FlagEmbedding和FastAPI工具
import uvicorn
from fastapi import FastAPI
from pydantic import BaseModel
from operator import itemgetter
from FlagEmbedding import FlagReranker# 定义FastAPI
app = FastAPI()
# 定义BGE-reranker模型
reranker = FlagReranker('你的BGE-reranker模型路径')  # 修改为你模型文件路径# 定义入参
class Query(BaseModel):question: strdocs: list[str]top_k: int = 1# 提供访问入口
@ app.post('/bge_rerank')
def bge_rerank(query: Query):scores = reranker.compute_score([[query.question, passage] for passage in query.docs])if isinstance(scores, list):similarity_dict = {passage: scores[i] for i, passage in enumerate(query.docs)}else:similarity_dict = {passage: scores for i, passage in enumerate(query.docs)}sorted_similarity_dict = sorted(similarity_dict.items(), key=itemgetter(1), reverse=True)result = {}for j in range(query.top_k):result[sorted_similarity_dict[j][0]] = sorted_similarity_dict[j][1]return resultif __name__ == '__main__':uvicorn.run(app, host='0.0.0.0', port=8000)

通过以上你就可以使用API 方式访问bge-reranker:

curl --location ‘http://localhost:50072/bge_base_rerank’
–header ‘Content-Type: application/json’
–data ‘{
“question”: “ChatGLM”,
“docs”: [“GLM3”, “Baichuan2”],
“top_k”: 2
}’

2 self-RAG

self-RAG是一种增强的RAG范式,其论文地址:https://arxiv.org/pdf/2310.11511。有兴趣的同学可以拜读,但是论文中更多的是底层和算法,如果研究应用的同学看起来会容易云里雾里。这里暂时摒弃数学公式,简单易懂给大家讲讲self-RAG的原理。
首先之所以提出self-RAG当然是RAG存在某些缺陷。RAG本身是借助外部知识,利用大模型推理得出答案,但是会存在几个问题

  • 搜索知识过多,通过相似度检索很容易过多搜索出知识,哪怕进行top k的处理也还是很多且有可能不是真正相关,并且很多模型并不能支持过长的token数
  • 大模型生成的结果,本身无法确保与搜出来的知识保持一致,哪怕你通过增加prompt,也难保本身搜出来的知识就存在错误

那么self-RAG如何解决这些问题?我们可以从下图看看self-RAG的工作流程

在这里插入图片描述

从上图,我们可以看到,self-RAG增加或者改进3方面的内容:

  • 判断是否需要检索:可以解决搜索知识过多问题,因为有些问题其实不需要进行检索
  • 搜索结果分别生成:这个可以解决大模型token不足的问题(相对于传统RAG是一起扔给大模型进行生成)
  • 评估生成结果:这个可以解决生成结果与知识内容的一致性

如何做到以上3个点,self-RAG通过微调训练大模型,让大模型在推理过程中实现自我反省。为了让大模型具备自我反省,那么self-RAG在微调过程中,加入了有标志的“反省Token”,当大模型生成这些标志性的“反省Token”时,那么就要进行不同token的自我反省操作。如模型输出如下例子:

[Relevant] ChatGLM3 是北京智谱华章科技有限公司和清华大学 KEG 实验室联合发布的对话预训练模型。关于北京智谱华章科技有限公司[Retrieval]

我们能看到有2个特殊的token,分别是[Relevant]和[Retrieval]。当有这2个特别含义的token时,模型会根据这些token做出对应的反省操作,比如[Relevant]代表内容与问题相关,[Retrieval]代表这里需要进行搜索。至于如何评判是否需要检索以及评判生成的分数,Self-RAG共设计了四种类型的评判指标:

特殊token作用取值
Retrieve是否需要知识检索,表示LLM后续的内容生成是否需要做额外知识检索。[No Retrieval]:无需检索,LLM直接生成;[Retrieval]:需要检索;[Continue to Use Evidence]:无需检索,使用之前内容
IsRel知识相关性,表示检索出来的知识是否提供了解决问题所需的信息。[Relevant]:检索出来的知识与需要解决的问题足够相关;[Irrelevant]:检索出来的知识与需要解决的问题无关
IsSup响应支持度,表示生成的响应内容是否得到检索知识的足够支持。[Fully supported]:输出内容陈述被检索的知识完全支持;[Partially supported]:输出内容陈述只有部分被检索的知识所支持;[No support / Contradictory]:输出内容不被检索的知识所支持(即编造)。
IsUse响应有效性。表示生成的响应内容对于回答/解决输入问题是否有用[Utility : x]:按有效的程度x分成1-5分,即最高为[Utility:5]

当然,这样的模型是需要特殊的训练,在Self-RAG的开源项目中提供了一个基于llama微调的模型selfrag_llama2_7b,希望将self-RAG应用于自身项目的同学,可以去看看这方面的内容。这就是self-RAG的流程原理,至于底层算法原理,有兴趣朋友也可以进行论文深入研读。

3 CRAG

在第二小节的self-RAG提出一种解决RAG痛点的流程框架,但是实际操作起来却是有些难度,特别是微调带有特殊token的模型,一说起微调就会是一个头疼的问题,不仅仅数据准备费时费力,并且微调后的模型稳定性也不一定能达到预期效果。那么有没有更为容易实现的简便方式呢,答案就是CRAG。
相比于传统的RAG,CRAG增加了一个用于矫正检索到的文档和用户问题之间知识相关性的可插拔模块。
在这里插入图片描述
从上图我们可以看到,CRAG就是增加了一个评估大模型,对结果进行评估。评估结果如下:

  • Correct:表示文档与用户问题有一定相关性的,但是doc其中仍会存在噪音或者过大问题,因此对文档进行refine精简。这里会对文档进行叫做knowledge strips的操作,然后从中过滤出有用的 strip重新整合,最后得到矫正后的文档。
  • Incorrect:表示文档对用户问题并没有相关性,需要引入新的知识源。这里引入 web searcher 从网上检索相关信息,并从中选出有用的内容,最后得到矫正后的文档。
  • Ambiguous:表示评估大模型无法判断文档是否与用户问题有关,就会同时做 Correct 和 Incorrect 时的动作。

相对于self-RAG来说,CRAG强调它是一种可插拔的设计模式,其中只是增加评估大模型,这个模型可以是微调模型,也可以是当今最好的大模型,比如ChatGPT。这使得在实际应用中,可能更为容易,当然,还有一点就是refine精简,这也是CRAG论文的重要价值点之一。

4 总结

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

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

相关文章

PyCharm中如何将某个文件设置为默认运行文件

之前在使用JetBrain公司的另一款软件IDEA的时候,如果在选中static main函数后按键altenter可以默认以后运行Main类的main函数。最近在使用PyCharm学习Python,既然同为一家公司的产品而且二者的风格如此之像,所以我怀疑PyCharm中肯定也有类似的…

fastadmin 如何给页面添加水印

偶然发现fastadmin框架有个水印插件&#xff0c;看起来漂亮&#xff0c;就想也实现这样的功能&#xff0c;看到需要费用。但是现成的插件需要费用&#xff0c;自己动手丰衣足食。说干就干。 1. 找到watermark.js &#xff0c;放到assets/js/ 下面 2.具体页面引入 <script…

【总线】AXI4第八课时:介绍AXI的 “原子访问“ :独占访问(Exclusive Access)和锁定访问(Locked Access)

大家好,欢迎来到今天的总线学习时间!如果你对电子设计、特别是FPGA和SoC设计感兴趣&#xff0c;那你绝对不能错过我们今天的主角——AXI4总线。作为ARM公司AMBA总线家族中的佼佼者&#xff0c;AXI4以其高性能和高度可扩展性&#xff0c;成为了现代电子系统中不可或缺的通信桥梁…

ssm高校宿舍用电管理系统-计算机毕业设计源码97859

摘要 随着高校规模的扩大和学生数量的增加&#xff0c;高校宿舍的用电需求也日益庞大。为了提高用电效率、节约能源、确保用电安全和方便管理&#xff0c;开发一个高校宿舍用电管理系统具有重要意义。本系统将采用Java作为后端开发语言&#xff0c;具备跨平台特性&#xff0c;能…

【高级篇】第10章 Elasticsearch 集群管理与扩展

在本章中,我们将深入探讨Elasticsearch集群的管理与扩展策略,旨在帮助读者构建一个既能应对大规模数据处理需求,又能保持高可用性和弹性的系统架构。我们将从集群架构设计入手,解析不同节点的角色与配置,然后转向节点发现与配置同步机制,最后讨论水平扩展与容错策略,确保…

windows中使用nssm设置nginx开机自启动

1、下载nssm工具 https://nssm.cc/release/nssm-2.24.zip 2、解压并根据自己电脑的位数定位到64或32 3、执行nssm.exe install 4、执行命令启动服务并设置开机自启动 #启动服务 net start nginxService #开机自启动 sc config nginx-service startauto

2024年洗地机哪个牌子好?内行人最建议这4个:清洁力口碑公认都不错

在当代生活中&#xff0c;洗地机可以称得上是一款必备“神器”&#xff0c;劳累的清洁、繁忙的时间、漫天纷飞的宠物毛发&#xff0c;都是家庭清洁面前的一座座大山。而洗地机的出现&#xff0c;完美解决了这些问题&#xff0c;既节约出了很多时间&#xff0c;又达到了很好的清…

Pspice添加新的元器件

1.下载好的Pspice的模型文件。 2.将模型文件的&#xff0c;识别类型修改为 lib 选择Pspice的模型路径 会立马跳出&#xff0c;下面的这个窗口。 核实元器件图形&#xff0c;没问题。 添加Pspic仿真模型文件 验证&#xff0c;是否添加模型文件成功 使用模型文件

完全理解C语言函数

文章目录 1.函数是什么2.C语言中的函数分类2.1 库函数2.1.1 如何使用库函数 2.2自定义函数 3.函数的参数3.1 实际参数&#xff08;实参&#xff09;3.2 形式参数&#xff08;形参&#xff09; 4.函数调用4.1传值调用4.2 传址调用4.3 练习 5.函数的嵌套调用和链式访问5.1 嵌套调…

java连接AD(Microsoft Active Directory)模拟用户登录认证

文章目录 一、背景二、页面效果三、代码LdapLoginRequest请求实体类Response返回结果MsgADTest测试类补充说明代码 四、认证结果认证成功认证失败 本人其他相关文章链接 一、背景 亲测可用,之前搜索了很多博客&#xff0c;啥样的都有&#xff0c;就是不介绍报错以及配置用处&a…

【探索Linux】P.37(传输层 —— TCP协议通信机制 | 确认应答(ACK)机制 | 超时重传机制)

阅读导航 引言一、确认应答(ACK)机制1. 成功接收2. 过程中存在丢包3. 引入序列号&#xff08;1&#xff09;序列号的定义&#xff08;2&#xff09;序列号的作用&#xff08;3&#xff09;序列号的工作原理&#xff08;4&#xff09;序列号和确认应答号 二、超时重传机制1. 超时…

基于Java的壁纸网站设计与实现

&#x1f497;博主介绍&#x1f497;&#xff1a;✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示&#xff1a;文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…

nftables(1)基本原理

简介 nftables 是 Linux 内核中用于数据包分类的现代框架&#xff0c;用来替代旧的 iptables&#xff08;包括 ip6tables, arptables, ebtables 等&#xff0c;统称为 xtables&#xff09;架构。nftables 提供了更强大、更灵活以及更易于管理的规则集配置方式&#xff0c;使得…

【java计算机毕设】办公用品管理系统MySQL ssm JSP maven项目设计代码源码+文档 前后端一体

1项目功能 【java计算机毕设】办公用品管理系统MySQL ssm JSP maven项目设计代码源码文档 前后端一体 2项目介绍 系统功能&#xff1a; 办公用品管理系统包括管理员、用户俩种角色。 管理员功能包括个人中心模块用于修改个人信息和密码、用户管理、用品分类管理、用品信息管理…

springcloud+vue项目,controller层接口返回json数据,前端可以接收到数据,但浏览器“F12-->网络-->响应“显示为空的问题处理

1.显示为空的场景 SharetekR(access_tokeneyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJQQzoxODA1ODA4ODc1MjUwMTIyNzUyIiwicm5TdHIiOiJrZEoxV05CV3NBSUdYb05TbktSU3kzOGNuSnk3c3FRTSIsInVzZXJJZCI6MTgwNTgwODg3NTI1MDEyMjc1MiwidXNlck5h…

grpc-go客户端接口添加

【1】 proto相关文件同服务端&#xff0c;如已经生成&#xff0c;可以直接使用服务端的文件&#xff08;包&#xff09; 【2】新建一个目录“WHG_CLIENT”&#xff0c;目录下新建一个main.go文件 package mainimport ("context""log""grpc-go-maste…

STM32F1+HAL库+FreeTOTS学习5——内核中断管理及中断控制函数

STM32F1HAL库FreeTOTS学习5——中断管理和临界段代码保护 中断简介中断优先级寄存器拓展FreeRTOS中PendSV和Systick中断优先级配置三个中断屏蔽寄存器FreeRTOS中断管理函数代码验证 上一期我们学习了FreeRTOS中任务挂起与恢复&#xff0c;在中断服务程序中恢复任务过程中&#…

[Redis]哨兵机制

哨兵机制概念 在传统主从复制机制中&#xff0c;会存在一些问题&#xff1a; 1. 主节点发生故障时&#xff0c;进行主备切换的过程是复杂的&#xff0c;需要人工参与&#xff0c;导致故障恢复时间无法保障。 2. 主节点可以将读压力分散出去&#xff0c;但写压力/存储压力是无法…

印章谁在管、谁用了、用在哪?契约锁让您打开手机一看便知

“印章都交给谁在管”、“哪些人能用”、“都有哪些业务在用”…这些既是管理者最关心的印章问题也是影响印章安全的关键要素。但是公司旗下分子公司那么多&#xff0c;各类公章、法人章、财务章、合同章一大堆&#xff0c;想“问”明白很难。 契约锁电子签及印控平台推出“印章…

14-11 2024 年的 13 个 AI 趋势

2024 年的 13 个 AI 趋势 人工智能对环境的影响和平人工智能人工智能支持的问题解决和决策针对人工智能公司的诉讼2024 年美国总统大选与人工智能威胁人工智能、网络犯罪和社会工程威胁人工智能治疗孤独与对人工智能的情感依赖人工智能影响者中国争夺人工智能霸主地位人工智能…