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

news2024/11/18 6:43:41

系列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 relevance
        for 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 getpass

from 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: str
    docs: 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 result


if __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.coloradmin.cn/o/1896859.html

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

相关文章

在Ubuntu上安装VNC服务器教程

Ubuntu上安装VNC服务器方法:按照root安装TeactVnc,随后运行vncserver输入密码,安装并打开RickVNC客户端,输入服务器的IP,最后连接输入密码即可。 VNC或虚拟网络计算,可让您连接到远程Linux / Unix服务器的…

如何在 Odoo 16 中继承和更新现有邮件模板

在本文中,让我们看看如何在 Odoo 16 中继承和编辑现有邮件模板。我们必须这样做才能对现有模板的内容进行任何调整或更新。让我们考虑一个在会计模块中更新邮件模板的示例。 单击“account.move”模型中的“发送并打印”按钮后,将打开上述向导。在这里,我们将进行更改。从向…

【遇坑笔记】Node.js 开发环境与配置 Visual Studio Code

【遇坑笔记】Node.js 开发环境与配置 Visual Studio Code 前言node.js开发环境配置解决pnpm 不是内部或外部命令的问题(pnpm安装教程)解决 pnpm : 无法加载文件 C:\Program Files\nodejs\pnpm.ps1,因为在此系统上禁止运行脚本。 vscode 插件开…

植物大战僵尸杂交版V2.1+修改器+融合版

植物大战僵尸杂交版v2.1 新增新植物,全新模式与玩法! 内含窗口放大工具与修改器 主播同款游戏,下载使用即可! 链接: https://pan.baidu.com/s/1k1BkDDgAtVILAEpHBNsZNw?pwdn81t 提取码: n81t

基于Java中的SSM框架实现野生动物公益保护系统项目【项目源码+论文说明】计算机毕业设计

基于Java中的SSM框架实现野生动物公益保护系统演示 摘要 本系统按照网站系统设计的基本流程,遵循系统开发生命周期法和结构化方法,基于Java语言设计并实现了野生动物公益保护系统。该系统基于浏览器/服务器模式,采用JSP技术,后台…

nginx的匹配及重定向

一、nginx的匹配: nginx中location的优先级和匹配方式: 1.精确匹配:location / 对字符串进行完全匹配,必须完全符合 2.正则匹配:location ^~ ^~ 前缀匹配,以什么为开头 ~区分大小写的匹配 ~* 不区分…

内衣迷你洗衣机什么牌子好?四款亲测表现出色内衣洗衣机安利

相信不少小伙伴都跟我一样。一方面,认为内裤、袜子与大件的上衣、裤子放一块清洗,会感觉很不卫生,而且穿在身上也不安心。但是另一方面,本身又很懒惰,也不想自己用手洗,不但经常会遗漏一些污渍,…

探索智能合约在医疗健康领域的革新应用

随着区块链技术的发展,智能合约作为其重要应用之一,在医疗健康领域展示了巨大的潜力和革新性。智能合约是一种基于区块链的自动化执行协议,它可以在无需中介的情况下执行和验证合同。在医疗健康领域,智能合约不仅简化了数据管理和…

CFS三层内网渗透——外网打点(一)

目录 外网打点 先爆破一下看看有没有啥可进攻路径 尝试那个可疑的路径发现是thinkphp这个框架,同时也知道了版本,那就nday打吧 写入php ​编辑写入php成功,简简单单nday拿下​编辑 蚁剑rce尝试链接 打点成功 外网打点 先爆破一下看看有…

护眼热点:台灯护眼是真的吗?一起来看台灯的功能作用有哪些

如今近视问题日益严峻,尤为引人瞩目的是,高度近视学生群体占比已逼近10%的警戒线,且这一比例伴随着学龄的增长而悄然攀升——从幼儿园6岁孩童中那令人忧虑的1.5%,到高中阶段惊人的17.6%,每一组数据都敲响了保护儿童视力…

Java面试八股之MySQL的pconenct和connect有什么区别

MySQL的pconenct和connect有什么区别 在PHP中,mysql_pconnect() 和 mysql_connect() 是用来建立与MySQL数据库服务器连接的两个函数,它们的主要区别在于连接的持久性。 mysql_connect(): 这个函数每次调用都会尝试创建一个新的数据库连接。 当PHP脚本…

超实用的VS Code插件推荐

VS Code代码编辑器中提供了丰富的插件,满足不同开发者的需求。这里为大家推荐一些强大的VS Code插件,帮助你打造一个个性化的开发环境,让你的编码体验更加舒适和高效。 打开扩展模块,输入安装包名称,回车进行搜索&…

想做亚马逊测评技术需要解决哪些问题,有哪些收益?

现在真正有亚马逊测评技术的人赚的盆满钵满,有些人看到别人赚取就自己盲目去做,买完了账号和设备就感觉自己懂了,却不知里面的水深着,花了钱却没有掌握真正的技术,号莫名其妙就封完了,而每一次大风控注定要…

震惊!张宇25版高数18讲发布,656页惹争议!

这个张宇老师在微博已经解释过了! 我觉得张宇老师本意是好的,在考研数学教学创新这方面,他真的有自己的思考。 他为什么要这么做? 其实作为一个考研高数老师,他完全可以像其他老师一样,什么都不做&#x…

内衣洗衣机和手洗哪个干净?4大值得信赖的高分佳品推荐

近年来,家庭洗衣机的标准容量有了很大的提高,从5公斤、6公斤发展到9公斤和10公斤。大容量的洗衣机可以在家里清洗大尺寸的衣服和床单被子。不过,因为洗衣机里的所洗的衣服都是比较混杂的,所以很多时候,由于内衣袜子和婴…

vue表单增加合计

vue表单增加合计,有两种方式: 第一种前端获取所有数据: 将 show-summary 设置为true就会在表格尾部展示合计行。 默认情况下,对于合计行,第一列不进行数据求合操作,而是显示「合计」二字(可通…

Springboot整合Jsch-Sftp

背景 开发一个基于jsch的sftp工具类&#xff0c;方便在以后的项目中使用。写代码的过程记录下来&#xff0c;作为备忘录。。。 Maven依赖 springboot依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-par…

python中的ProgressMeter类【自定义】

python中的ProgressMeter类【自定义】 显示进度条 # 1.定义类ProgressMeter class ProgressMeter(object):def __init__(self, num_batches, *meters):# 初始化头&#xff0c;如&#xff1a;[ 100/2500]&#xff08;占符号位&#xff09;self.batch_fmtstr self._get_batch_…

JVM原理(三):JVM对象回收判定机制与回收算法

如何判断一个对象是否存活(即是否还分配在堆中)&#xff0c;那看他是否还在用。 1. 引用计数算法 这是一种判断方式&#xff0c;相应的方法就是&#xff1a;如果一个对象被引用&#xff0c;那将被引用的对象中的一个计数器加一&#xff0c;引用失效就减一。在任何时刻引用计数…

数千万“四高”中老年患者,如何推动国产营养保健品创新

“三高”指高血压、高血糖&#xff08;糖尿病&#xff09;、高血脂&#xff0c;是中老年群体的常见病。 然而&#xff0c;除了前述三者&#xff0c;高尿酸血症在我国的患病率正逐年提高&#xff0c;已成为仅次于糖尿病的第二大代谢性疾病。痛风是高尿酸血症典型症状之一。 加上…