使用LOTR合并检索提高RAG性能

news2024/12/22 18:56:55

RAG结合了两个关键元素:检索和生成。它首先使用语义搜索等高级技术来浏览大量数据,包括文本、图像、音频和视频。RAG的本质在于它能够检索相关信息,然后作为下一阶段的基础。生成组件利用大型语言模型的能力,解释这些数据块,制作连贯的、类似人类的响应。与传统的生成模型相比,这个过程确保RAG系统可以提供更细致和准确的输出。

“Lost in the Middle”

在RAG中“LIM”问题相当具有挑战性。斯坦福大学和加州大学伯克利分校等大学的研究强调了这一问题,这与人们经常记住购物清单上的第一个和最后一个项目,但忘记中间的项目类似。语言模型人一样很擅长识别他们正在分析的文本的开头或结尾的信息,但他们往往会忽略中心的关键细节。

为了解决这个问题,我们一般都是用下面的方法:

1、避免使用单一知识库,对不同类型的文档只使用一个知识库可能会混淆检索模型。他们可能很难根据主题或上下文找到正确的信息。

2、使用多个矢量存储,为不同类型的文档创建单独的数据存储区域(称为矢量存储)。这有助于更有效地组织信息。

3、使用一个称为Merge retriver的工具合并来自这些不同VectorStores的数据。这有助于汇集来自不同来源的相关信息。

4、使用长上下文重新排序(LOTR)重新排序,这确保了模型对文本中间的数据给予同等的关注,而不仅仅是在开头或结尾。

通过使用上面这些技术,可以确保数据的所有部分(包括中间部分)都得到了适当的检索并用于生成响应。这些步骤有助于改进RAG系统的性能,使它们更有效地处理和解释大量不同的信息源。

LOTR(合并检索器)

本文主要介绍LOTR

LOTR: Lord of the retrivers,也称为mergerretriver,它将检索器列表作为输入,并将它们的get_relevance _documents()方法的结果合并到单个列表中。合并的结果将是与查询相关的文档列表,这些文档是被不同的检索器排序过的。

MergerRetriever类可以通过几种方式用于提高文档检索的准确性:它结合多个检索器的结果,这有助于减少结果偏差的风险。并且可以对不同检索器的结果进行排序,这有助于确保首先返回最相关的文档。

我们将以医疗/医疗保健相关的RAG为例构建回答一些保健被问题的聊天机器人。

代码

安装使用的包:

 pip -q install langchain lancedb  pypdf sentence-transformers openai tiktoken

在python中导入所需的包

 from langchain.embeddings import HuggingFaceEmbeddings, OpenAIEmbeddings,HuggingFaceBgeEmbeddings
 from langchain.document_transformers import (
     EmbeddingsClusteringFilter,
     EmbeddingsRedundantFilter,
 )
 from langchain.text_splitter import RecursiveCharacterTextSplitter
 from langchain.retrievers import ContextualCompressionRetriever
 from langchain.retrievers.document_compressors import DocumentCompressorPipeline
 from langchain.retrievers.merger_retriever import MergerRetriever
 from langchain.schema import Document
 from langchain.embeddings.openai import OpenAIEmbeddings
 from langchain.document_loaders import PyPDFLoader
 from langchain.embeddings import SentenceTransformerEmbeddings
 from langchain.vectorstores import LanceDB
 import lancedb

这里我们使用openai的模型所以需要设置apikey

 import os
 os.environ["OPENAI_API_KEY"] = "sk-xxxx"

对于嵌入模型,我们有3种选择

1、Huggingface BGE嵌入,这是在MTEB排行榜上排名前面的模型。

2、NeuML/pubmedbert-base-embeddings 这个模型专注于医疗相关数据。

3、Openai embedding mode 最后可以使用Openai嵌入模型来移除相同的嵌入,这个作为后续改进,本文暂不不讨论

 #embedding models
 
 medical_health_embedding = SentenceTransformerEmbeddings(
     model_name="NeuML/pubmedbert-base-embeddings")
 
 hf_bge_embeddings = HuggingFaceBgeEmbeddings(model_name="BAAI/bge-large-en",
                                              model_kwargs={"device":"cpu"},
                                              encode_kwargs = {'normalize_embeddings': False})
 filter_embeddings = OpenAIEmbeddings()

加载文档文件

 loader = PyPDFLoader("/content/AyurvedicHomeRemedies.pdf")
 # pages = loader.load_and_split()
 
 
 text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000,chunk_overlap=200)
 text = text_splitter.split_documents(loader)

将两个不同的嵌入模型实例化,并生成两个不同的索引

 # embedding 1 model - NeuML/pubmedbert-base-embeddings
 db = lancedb.connect('/tmp/lancedb')
 table = db.create_table("health embedding", data=[
     {"vector": medical_health_embedding.embed_query("Hello World"), "text": "Hello World", "id": "1"}
 ], mode="overwrite")
 
 # Initialize LanceDB retriever
 db_all = LanceDB.from_documents(text, medical_health_embedding, connection=table)
 
 
 ## embeding 2 model - 
 db_multi = lancedb.connect('/tmp/lancedb')
 table = db_multi.create_table("bge embedding", data=[
     {"vector": hf_bge_embeddings.embed_query("Hello World"), "text": "Hello World", "id": "1"}
 ], mode="overwrite")
 # Initialize LanceDB retriever
 db_multiqa = LanceDB.from_documents(text, hf_bge_embeddings, connection=table)

保存两个retriever的输出,供后续代码调用

 retriever_med = db_all.as_retriever(search_type="similarity",
                                   search_kwargs={"k": 5, "include_metadata": True}
                                   )
 retriever_bge = db_multiqa.as_retriever(search_type="similarity",
                                         search_kwargs={"k": 5, "include_metadata": True})

MergerRetriever(通常称为LOTR)通过以顺序的、循环的方式组合来自各种检索源的结果。它首先收集由每个检索器标识的相关文档,然后将这些文档合并到一个单一的内聚列表中。该列表显示与特定查询相关的文档并根据不同检索器确定的相关性对其进行排序。

为了提高合并列表的效率并避免重复,EmbeddingsRedundantFilter可以与附加的嵌入模型一起使用。这有助于从组合检索器中过滤掉任何重叠或重复的结果。还可以将文档分组到主题簇或相关内容的“中心”,从这些簇中选择与每个簇的中心主题最接近的文档进行最终结果。EmbeddingsClusteringFilter优化了这个聚类和选择过程,确保了结果集更有组织、更集中。

 lotr = MergerRetriever(retrievers=[retriever_med, retriever_bge])
 
 for chunks in lotr.get_relevant_documents("What is use of tulsi ?"):
     print(chunks.page_content)

合并的检索器中删除冗余结果。

 filter = EmbeddingsRedundantFilter(embeddings=filter_embeddings)

无论模型的体系结构是什么,当包含10个以上的检索文档时,都会有很大的性能下降。也就是说,当模型必须在长上下文中访问相关信息时,它们倾向于忽略所提供的文档。

 from re import search
 from langchain.document_transformers import LongContextReorder
 
 reordering = LongContextReorder()  
 
 pipeline = DocumentCompressorPipeline(transformers=[filter, reordering])
 compression_retriever_reordered = ContextualCompressionRetriever(
     base_compressor=pipeline, base_retriever=lotr,search_kwargs={"k": 5, "include_metadata": True}
 )
 
 docs = compression_retriever_reordered.get_relevant_documents("What is use of tulsi ?")
 print(len(docs))
 
 print(docs[0].page_content)

以上文档已经处理完毕了,我们开始加载LLM模型

 from langchain.chains import RetrievalQA
 from langchain.llms import OpenAI
 from langchain.chains import RetrievalQA
 from langchain.chat_models import ChatOpenAI
 
 llm = ChatOpenAI(openai_api_key="sk-openaiapikey")
 #check our blog for using different llms  https://github.com/lancedb/vectordb-recipes/blob/main/tutorials/chatbot_using_Llama2_&_lanceDB
 
 qa = RetrievalQA.from_chain_type(
       llm=llm,
       chain_type="stuff",
       retriever = compression_retriever_reordered,
       return_source_documents = True
 )

测试结果如下:

 query ="What is use of tulsi?"
 results = qa(query)
 print(results['result'])
 
 print(results["source_documents"])
 
 ## results
 For high fever and cough, you can try the following home remedies:
 
 1. Take 1-2 grams of Pippali (Piper longum) powder with honey twice daily.
 2. Drink a warm decoction prepared from 20 ml of water and 1 gram of Laung (clove) 3-4 times daily. This can help with both dry and productive cough.
 3. Take 2 grams of Elaichi (cardamom) powder with honey 2-3 times a day.
 4. Drink plenty of warm fluids like herbal teas, soups, and warm water to stay hydrated and soothe the throat.
 5. Gargle with warm salt water to alleviate throat discomfort.
 6. Rest and get plenty of sleep to support your immune system.
 
 Remember, these remedies are for mild conditions. If your symptoms persist or worsen, it is important to consult a doctor for proper diagnosis and treatment.

通过这种方法可以使RAG获得更好的性能

总结

为了解决LIM问题并提高检索性能,对RAG系统进行增强是非常重要的。通过设置不同的VectorStores并将它们与Merge retriver结合,以及使用LongContextReorder重新排列结果,可以减少LIM问题并使检索过程更高效。此外,在合并检索器中合并特定领域的嵌入也有着关键作用。这些步骤对于确保我们不会在检索文件的过程中遗漏重要细节至关重要。

Lost in the Middle: How Language Models Use Long Contexts 论文

https://arxiv.org/abs//2307.03172

langchain的merger_retriever实现代码:

https://github.com/langchain-ai/langchain/blob/master/libs/langchain/langchain/retrievers/merger_retriever.py

本文完整代码:

https://avoid.overfit.cn/post/d252399e19e5409abf9990591523c11f

作者:Akash A Desai

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

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

相关文章

操作系统大题

目录 作业一: 前驱图 作业二:信号量 作业三:同步算法 1‘’生产者消费者问题 解1: 解2:利用AND信号量解决生产者-消费者问题 解3. 利用管程解决生产者-消费者问题 2‘’ 哲学家进餐问题(The Dinning…

Conda:Python环境管理的瑞士军刀

在数据科学和机器学习的世界中,管理各种库和依赖关系的重要性不容忽视。Conda 就是为此而生的强大工具。本文将深入探讨 Conda 的简介、功能以及使用示例,帮助你更好地理解和使用这个工具。 Conda 简介 Conda 是一个开源的包管理系统和环境管理系统&am…

MPLS动态协议LDP配置示例

一、预习: MPLS是一种根据报文中携带的标签来转发数据的技术,两台LSR必须在它们之间转的数据 的标签使用上“达成共识”。LSR之间可以运行LDP来告知其他LSR本设备上的标签绑定信息,从而实现标签报文的正确转发。 LSR:Label Switch…

跨进程通信 macOS XPC 创建实例

一:简介 XPC 是 macOS 里苹果官方比较推荐和安全的的进程间通信机制。 集成流程简单,但是比较绕。 主要需要集成 XPC Server 这个模块,这个模块最终会被 apple 的根进程 launchd 管理和以独立进程的方法唤起和关闭, 我们主app 进…

网络运行状况监控工具

网络运行状况是网络在其操作和环境约束范围内按预期运行的能力,但是,随着云和人工智能等技术的出现,网络变得越来越复杂,维护其 IT 基础设施是一项越来越繁琐的任务。为了确保网络可靠性,组织需要了解每个端点的运行状…

【c/c++】指针例图基础详解

文章目录 指针变量内存指针详解例1例2练习&答案解析 指针变量内存 int main(){// 各类型变量占字节数printf("char: %d\n",sizeof(char)); // 1printf("short: %d\n",sizeof(short)); // 2printf("int: %d\n",sizeof(int)); // 4pri…

详解C语言单链表接口函数

准备工作 创建一个头文件(SList.h),两个源文件(SList.c和test.c) SList.h:用于包含库函数的头文件,链表节点结构体声明,接口函数的声明等【另外两个源文件要包含SList.h这个头文件,才能使用其…

【项目管理】CMMI-项目总体计划模版

目录 1、总体目录结构 2、重点章节概要示例 2.1 第四章 项目管理 2.2 第六章 实施与交付计划 2.3 第七章 运维计划 1、总体目录结构 2、重点章节概要示例 2.1 第四章 项目管理 2.2 第六章 实施与交付计划 2.3 第七章运维计划

【2023年终总结】纵是一路仆仆风尘,也莫忘了仰头

文章目录 1. 写在前面2. 关于生活3. 关于工作4. 关于以后 【作者主页】:吴秋霖 【作者介绍】:Python领域优质创作者、阿里云博客专家、华为云享专家。长期致力于Python与爬虫领域研究与开发工作! 【作者推荐】:对JS逆向感兴趣的朋…

vue3+ts+vite自定义组件上传npm流程

1. 创建项目 npm create vite 这里踩坑点: 运行vite生成的vue项目时报错“SyntaxError: Unexpected token ?? at “ 是因为node版本过低 电脑为windows11系统,我当时使用的版本node版本是14.21.3,如下图,后边安装了nvm版本…

Redisson依赖冲突记录

前言&#xff1a;项目使用的springboot项目为2.7.X 依赖冲突一&#xff1a;springboot 与 redisson版本冲突 项目中依赖了 Lock4j&#xff0c;此为苞米豆开源的分布式锁组件 <dependency><groupId>com.baomidou</groupId><artifactId>lock4j-redisso…

《面向复杂仿真元建模的序贯近邻探索实验设计方法》论文复现

# peaks函数热力图 from matplotlib import pyplot as plot import numpy as np import math from mpl_toolkits.mplot3d import Axes3D#python绘图显示中文 plot.rcParams[font.sans-serif][SimHei] plot.rcParams[axes.unicode_minus] False#创建画布 fig plot.figure(figs…

GPT系列概述

OPENAI做的东西 Openai老窝在爱荷华州&#xff0c;微软投资的数据中心 万物皆可GPT下咱们要失业了&#xff1f; 但是世界不仅仅是GPT GPT其实也只是冰山一角&#xff0c;2022年每4天就有一个大型模型问世 GPT历史时刻 GPT-1 带回到2018年的NLP 所有下游任务都需要微调&#x…

sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set问题解决方案

sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set问题解决方案 当我们使用sudo su切换权限时提示错误&#xff1a; sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set该错误出现原因&#xff1a;是因为/usr/bin/sudo的权限被…

计算机网络复习5

传输层——端到端 文章目录 传输层——端到端功能传输层的寻址与端口UDPTCPTCP连接管理TCP可靠传输TCP流量控制TCP拥塞控制网络拥塞的处理 功能 从通信和信息处理的角度看&#xff0c;传输层向它上面的应用层提供通信服务&#xff0c;它属于面向通信部分的最高层&#xff0c;同…

再升级|川石教育鸿蒙应用开发4.0教程发布

全新鸿蒙蓄势待发 HarmonyOS是一款面向未来的全场景分布式智慧操作系统。 对于消费者而言&#xff0c;HarmonyOS用一个统一的软件系统从根本上解决消费者面对大量智能终端体验割裂的问题&#xff0c;为消费者带来统一、便利、安全的智慧化全场景体验。 对于开发者而言&#xf…

现在AI那么发达,还有必要系统地学习Excel吗?

随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;许多传统的工作和技能正在逐渐被自动化和取代。在这个背景下&#xff0c;一些人开始质疑学习Excel等传统技能的必要性。然而&#xff0c;我认为学习Excel仍然是非常有必要的&#xff0c;原因如下。 首先&…

.NET DevOps 接入指南 | 1. GitLab 安装

引言 容器、DevOps和微服务被称为驱动云原生快速发展的三架马车。而DevOps是其中非常重要的一环&#xff0c;DevOps 是由Developers&#xff08;Dev&#xff09;和Operations&#xff08;Ops&#xff09;两个单词简称组成&#xff0c;中文直译就是“开发运维一体化”。 DevOps…

python大于等于小于等于,python大于等于怎么写

大家好&#xff0c;小编为大家解答python中大于等于且小于等于的问题。很多人还不知道python大于号小于号如何运用&#xff0c;现在让我们一起来看看吧&#xff01; 大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python中大于并小于一个数代码&#xff0c;python 大…

STL——stack容器

1.stack基本概念 概念&#xff1a;stack是一种先进后出&#xff08;First In Last Out,FILO&#xff09;的数据结构&#xff0c;它只有一个出口。 栈中只有顶端的元素才可以被外界使用&#xff0c;因此栈不允许有遍历行为。 栈中进入数据称为——入栈&#xff08;push&#x…