LLM之RAG实战(二十五)| 使用LlamaIndex和BM25重排序实践

       本文,我们将研究高级RAG方法的中的重排序优化方法以及其与普通RAG相比的关键差异。

一、什么是RAG?

       检索增强生成(RAG)是一种复杂的自然语言处理方法,它包括两个不同的步骤:信息检索生成语言建模。这种方法旨在为语言模型提供访问外部数据源,来提高其在生成响应时的准确性和相关性,从而增强语言模型的能力。

1.1 检索组件:

目的:检索组件的主要功能是响应查询或提示,从大型数据库或语料库中提取相关文档或信息片段。

过程:当收到查询时,检索系统会搜索其数据库(如维基百科文章、书籍或其他文本数据的集合),以找到与查询相关的内容。

输出:此阶段的输出是一组与输入查询相关的文档或文本段落。

1.2 生成语言模型:

与检索到的数据集成:将检索到的文档输入到生成语言模型中,该模型使用这些文档中的信息来通知其响应生成。

响应生成:语言模型处理原始查询和检索到的文档中的信息,以生成不仅与上下文相关而且由外部数据提供信息的响应。

      这种方法(RAG)允许语言模型产生比仅依靠其预先训练的知识更准确、更详细、更适合上下文的反应。

二、什么是高级RAG?

       高级检索增强生成(Advanced RAG)通过结合复杂的检索前和检索后过程来增强传统的RAG。Advanced RAG中检索后过程的一个关键方面是“ReRank”,它涉及对检索到的文档进行重新排序,来优先考虑最相关的信息。ReRank通过采用各种算法或框架来实现的,比如基于文档多样性与查询的相关性之类的标准来调整排序。重新排序的目的是向大型语言模型提供最相关的信息,从而提高生成的响应的质量和相关性。

三、RAG和高级RAG之间的主要区别是什么?

四、高级RAG重排序代码实施:

       有了对Advanced RAG概念的理解,现在让我们将使用LlamaIndex作为实施的框架,BM25作为我们的排序函数。BM25算法是信息检索系统中广泛使用的排序函数,特别是在文档检索中。它是概率信息检索家族的一部分,是对经典TF-IDF(术语频率逆文档频率)方法的改进。因此,我们将使用它作为我们的重新排序函数。

       在这篇文章中,我们将研究两种不同的实现高级RAG的方法,一种是使用OpenAI LLM,另一种是在完全局部LLM(Mistral)

       首先在项目文件夹的根目录中创建一个项目文件夹和包括如下内容的.env文件。

OPENAI_API_KEY="<YOUR_OPENAI_API_KEY>"LLM_URI="http://localhost:11434"

        导入相关库

import nest_asyncioimport osimport sysimport loggingfrom dotenv import load_dotenv, find_dotenvfrom llama_index import (    SimpleDirectoryReader,    ServiceContext,    StorageContext,    VectorStoreIndex,)from llama_index.query_engine import RetrieverQueryEnginefrom llama_index.retrievers import BM25Retrieverfrom llama_index.llms import OpenAI, Ollamafrom llama_index.embeddings import OllamaEmbeddingfrom llama_index.postprocessor import SentenceTransformerRerankfrom llama_index import QueryBundle

        配置asynciologger

logging.basicConfig(stream=sys.stdout, level=logging.INFO)logging.getLogger().handlers = []logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))nest_asyncio.apply()

        让我们设计一个名为AdvancedRAG的类,该类具有以下3个函数:

class AdvancedRAG:    def __init__(self):        _ = load_dotenv(find_dotenv())        # load documents        self.documents = SimpleDirectoryReader("./data/", required_exts=['.pdf']).load_data()        # global variables used later in code after initialization        self.retriever = None        self.reranker = None        self.query_engine = None        self.bootstrap()    def bootstrap(self):        # initialize LLMs        llm = OpenAI(model="gpt-4",                    api_key=os.getenv("OPENAI_API_KEY"),                    temperature=0,                    system_prompt="You are an expert on the Inflamatory Bowel Diseases and your job is to answer questions. Assume that all questions are related to the Inflammatory Bowel Diseases (IBD). Keep your answers technical and based on facts – do not hallucinate features.")        # initialize service context (set chunk size)        service_context = ServiceContext.from_defaults(chunk_size=1024, llm=llm)        nodes = service_context.node_parser.get_nodes_from_documents(self.documents)        # initialize storage context (by default it's in-memory)        storage_context = StorageContext.from_defaults()        storage_context.docstore.add_documents(nodes)        index = VectorStoreIndex(            nodes=nodes,            storage_context=storage_context,            service_context=service_context,        )        # We can pass in the index, doctore, or list of nodes to create the retriever        self.retriever = BM25Retriever.from_defaults(similarity_top_k=2, index=index)        # reranker setup & initialization        self.reranker = SentenceTransformerRerank(top_n=1, model="BAAI/bge-reranker-base")        self.query_engine = RetrieverQueryEngine.from_args(            retriever=self.retriever,            node_postprocessors=[self.reranker],            service_context=service_context,        )    def query(self, query):        # will retrieve context from specific companies        nodes = self.retriever.retrieve(query)        reranked_nodes = self.reranker.postprocess_nodes(            nodes,            query_bundle=QueryBundle(query_str=query)        )        print("Initial retrieval: ", len(nodes), " nodes")        print("Re-ranked retrieval: ", len(reranked_nodes), " nodes")        for node in nodes:            print(node)        for node in reranked_nodes:            print(node)        response = self.query_engine.query(str_or_query_bundle=query)        return response

Initialization方法(__init__):

环境设置:使用load_dotenv(find_dotenv())加载环境变量。这可能用于配置设置,如API密钥或URL。

文档加载:使用SimpleDirectoryReader从指定目录加载文档。这些文档可能被用作检索任务的语料库。

全局变量:为检索器重排序器query_engine设置占位符,它们可能是检索和排序过程中的关键组件。

Bootstrap方法调用:调用Bootstrap方法来初始化各种组件。

Bootstrap方法:

初始化大型语言模型(llm):使用Ollama或OpenAI GPT-4设置语言模型实例(llm)。

初始化嵌入模型:使用OllamaEmbedding设置嵌入模型(embed_mode),该模型用于创建文本的矢量表示。

服务上下文:使用块大小和模型(llm和embed_mode)配置服务上下文。

节点解析和存储:将文档解析为节点,并将其存储在内存数据库中,以便快速访问。

索引创建:使用VectorStoreIndex创建索引,以高效检索文档。

Retriever初始化:初始化BM25Retriever,这是一个基于BM25算法的检索模型。

重新排序初始化:使用SentenceTransformerRerank设置重新排序,重新排序检索到的结果的相关性。

查询引擎初始化:初始化一个查询引擎,该引擎将检索器重排序器组合在一起以处理查询。

Query方式:

检索:检索与给定查询相关的节点(文档)。

重排序:对检索到的节点应用重新排序。

响应生成:使用查询引擎根据查询生成响应。

if __name__ == "__main__":    adv_rag = AdvancedRAG()    resp = adv_rag.query("What is the impact of IBD in women ?")    print(resp)

         当您使用OpenAI GPT-4配置运行上述代码时,以下应该是输出。

       使用本地LLM和本地嵌入模型(Mistral)修改代码,在上面的代码中,只需注释现有的OpenAI GPT-4 LLM并使用下面的代码。

# initialize LLMsllm = Ollama(base_url=os.getenv("LLM_URI"), model="mistral")

        初始化Mistral嵌入,如下所示

# initialize mistral embed modelembed_model = OllamaEmbedding(base_url=os.getenv("LLM_URI"), model_name="mistral")

        现在,通过传递embed_mode来修改现有的服务上下文,如下所示:

# initialize service context (set chunk size)service_context = ServiceContext.from_defaults(chunk_size=1024, llm=llm, embed_model=embed_model)

      现在,如果将代码指向下面的本地LLM和本地嵌入来编写代码,那么输出如下:

      您可以清楚地看到,GPT-4和Mistral等2种方法生成的响应发生了一些显著变化,但具有置信度|重新排序分数的检索节点保持不变。

六、结论

       总之,高级检索增强生成(Advanced Retrieval Augmented Generation,简称RAG)是信息检索和自然语言处理领域的一次重大飞跃。通过将BM25等最先进的排名算法与先进的重新排序技术和GPT-4或Mistral等尖端语言模型相集成,advanced RAG为处理复杂的查询任务提供了一个强大而灵活的解决方案。正如我们在讨论中举例说明的那样,这种实际实现不仅展示了Advanced RAG的理论潜力,还展示了其在现实世界中的适用性。无论是在提高搜索引擎的准确性、提高聊天机器人中响应的相关性,还是在推进知识系统的前沿领域,高级RAG证明了人工智能驱动的语言理解和信息处理的不断发展和成熟。Advanced RAG中检索准确性和上下文生成的融合为各种应用中更智能、更灵敏、更知识渊博的系统铺平了道路,预示着人工智能能力的新时代。

参考文献:

[1] https://blog.stackademic.com/advanced-retrieval-augmented-generation-how-reranking-can-change-the-game-d06e12b77074

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【开源】JAVA+Vue.js实现车险自助理赔系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 角色管理模块2.3 车辆档案模块2.4 车辆理赔模块2.5 理赔照片模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 角色表3.2.2 车辆表3.2.3 理赔表3.2.4 理赔照片表 四、系统展示五、核心代码5.1 查询车…

【PyQt】10 QLineEdit

文章目录 前言一、回显模式&#xff08;EchoMode&#xff09;1.1 四种回显模式1.2 代码展示运行结果 二、校验器2.1 代码2.2 运行结果 三、通过掩码限制输入3.1 代码3.2 运行结果 总结 前言 1、QLineEdit 可以输入单行文字 2、回显模式 3、校验器 4、掩码输入 一、回显模式&am…

图片懒加载:从低像素预览到高清加载

老生常谈的问题&#xff0c;图片太多太大的网站&#xff0c;往往由于图片加载过慢而导致页面白屏时间过长。本次年前最后一更&#xff0c;来讲一个加载方法来处理这种情况。 在使用 Next.js 时&#xff0c;发现其支持模糊图片占位符加载的方式&#xff0c;本文就手动实现一个 图…

最近vscode链接Autodl出现的问题

最近vscode链接Autodl出现的问题 一、问题的概述 在使用vscode连接autodl远程服务器的时候&#xff0c;在vscode的右下角出现了&#xff0c;以下的问题提示&#xff1a; 远程主机可能不符合glibc和libstdc VS Code服务器的先决条件 二、问题的原因 vscode版本过高的问题&…

远程git仓库已有仓库,若想本地代码覆盖远程代码,操作如下

1.首先 2.其次 3.然后 4.最后 git push -f origin "master" -f&#xff1a;强制推送&#xff0c;若远程是空项目&#xff0c;可以换成-u

基于Java (spring-boot)的宿舍管理系统

一、项目介绍 基于Java (spring-boot)的宿舍管理系统功能&#xff1a;登录界面、宿舍管理、学生管理、班级管理、宿舍楼管理、维修记录、晚归记录、请假记录、用户管理、角色管理、菜单管理、日志管理、我收到的、退宿审核&#xff0c;等等等 二、作品包含 三、项目技术 后端语…

MATLAB环境下生成对抗网络系列(11种)

为了构建有效的图像深度学习模型&#xff0c;数据增强是一个非常行之有效的方法。图像的数据增强是一套使用有限数据来提高训练数据集质量和规模的数据空间解决方案。广义的图像数据增强算法包括&#xff1a;几何变换、颜色空间增强、核滤波器、混合图像、随机擦除、特征空间增…

人生就是一场大考

感觉人生就是一场大考&#xff0c;最重要的高考&#xff0c;而这个考试要到49岁左右才有得分。如&#xff0c;当初事业的选择&#xff0c;爱情伴侣的选择&#xff0c;出去在外发展的选择……这都决定了你以后人生高考的走向。现在的你过得怎么样&#xff0c;也是你在人生这场高…

Java实现河南软件客服系统 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统管理人员2.2 业务操作人员 三、系统展示四、核心代码4.1 查询客户4.2 新增客户跟进情况4.3 查询客户历史4.4 新增服务派单4.5 新增客户服务费 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的河…

机器学习系列5-特征组合、简化正则化

1.特征组合 1.1特征组合&#xff1a;编码非线性规律 我们做出如下假设&#xff1a;蓝点代表生病的树。橙色的点代表健康的树。 您可以绘制一条直线将生病的树与健康的树清晰地分开吗&#xff1f;不可以。这是一个非线性问题。您绘制的任何线条都无法很好地预测树的健康状况…

1【算法】——最大子数组问题(maximum subarray)

一.问题描述 假如我们有一个数组&#xff0c;数组中的元素有正数和负数&#xff0c;如何在数组中找到一段连续的子数组&#xff0c;使得子数组各个元素之和最大。 二.问题分析 分治法求解&#xff1a; 初始状态&#xff1a; low0&#xff1b;highA.length-1&#xff1b;mid&am…

GO 的 Web 开发系列(五)—— 使用 Swagger 生成一份好看的接口文档

经过前面的文章&#xff0c;已经完成了 Web 系统基础功能的搭建&#xff0c;也实现了 API 接口、HTML 模板渲染等功能。接下来要做的就是使用 Swagger 工具&#xff0c;为这些 Api 接口生成一份好看的接口文档。 一、写注释 注释是 Swagger 的灵魂&#xff0c;Swagger 是通过…

leaflet 显示自己geoserver发布的中国地图

安装vscode 安装 通义灵码 问题&#xff1a; 用leaflet显示一个wms地图 修改下代码&#xff0c;结果如下&#xff1a; 例子代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport&q…

【HarmonyOS 4.0 应用开发实战】ArkTS 快速入门之常用属性

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

《统计学简易速速上手小册》第5章:回归分析(2024 最新版)

文章目录 5.1 线性回归基础5.1.1 基础知识5.1.2 主要案例&#xff1a;员工薪资预测5.1.3 拓展案例 1&#xff1a;广告支出与销售额关系5.1.4 拓展案例 2&#xff1a;房价与多个因素的关系 5.2 多元回归分析5.2.1 基础知识5.2.2 主要案例&#xff1a;企业收益与多因素关系分析5.…

【小沐学GIS】基于WebGL绘制三维数字地球Earth(OpenGL)

&#x1f37a;三维数字地球系列相关文章如下&#x1f37a;&#xff1a;1【小沐学GIS】基于C绘制三维数字地球Earth&#xff08;OpenGL、glfw、glut&#xff09;第一期2【小沐学GIS】基于C绘制三维数字地球Earth&#xff08;OpenGL、glfw、glut&#xff09;第二期3【小沐学GIS】…

最短路径算法

1. Dijkstra算法 在正数权重的有向图中求解某个源点到其余各个顶点的最短路径一般可以采用迪杰斯特拉算法&#xff08;Dijkstra算法&#xff09;。 1.1 适用场景 单源最短路径权重都为正 1.2 伪代码 1.3 示例 问题描述&#xff1a; 计算节点0到节点4的最短路径&#xff0c…

arduino uno R3驱动直流减速电机(蓝牙控制)

此篇博客用于记录使用arduino驱动直流减速电机的过程&#xff0c;仅实现简单的功能&#xff1a;PID调速、蓝牙控制 1、直流减速电机简介2、DRV8833电机驱动模块简介3、HC-05蓝牙模块简介电机转动测试4、PID控制5、蓝牙控制电机 1、直流减速电机简介 我在淘宝购买的电机&#x…

C语言整型数据类型..

1.整型数据类型 在C语言中 根据数据范围从小到大依次为char、short、int、long、long long 但是对于整型来说 为什么有这么多类型呢 我们得先说字节的本质&#xff1a; 计算机是通过晶体管的开关状态来记录数据 晶体管通常8个为一组 称为一个字节 而晶体管由两种状态 分别是开…

交叉熵损失函数(Cross-Entropy Loss)的基本概念与程序代码

交叉熵损失函数&#xff08;Cross-Entropy Loss&#xff09;是机器学习和深度学习中常用的损失函数之一&#xff0c;用于分类问题。其基本概念如下&#xff1a; 1. 基本解释&#xff1a; 交叉熵损失函数衡量了模型预测的概率分布与真实概率分布之间的差异。在分类问题中&…