LLM之RAG实战(四十一)| 使用LLamaIndex和Gemini构建高级搜索引擎

       Retriever 是 RAG(Retrieval Augmented Generation)管道中最重要的部分。在本文中,我们将使用 LlamaIndex 实现一个结合关键字和向量搜索检索器的自定义检索器,并且使用 Gemini大模型来进行多个文档聊天。

通过本文,我们将了解到如下内容:

  • 深入了解 RAG 管道中 Retriever 和 Generator 组件在上下文生成响应中的作用;
  • 学习集成关键字矢量搜索技术以开发自定义检索器,从而提高 RAG 应用程序中搜索的准确性;
  • 熟练掌握使用 LlamaIndex 进行数据摄取,提供给LLMs上下文信息;
  • 了解自定义检索器在通过混合搜索机制减轻LLM响应中的幻觉方面的重要性;
  • 探索高级检索器实现,例如rerank和 HyDE,以增强 RAG 中的文档相关性;
  • 了解如何在 LlamaIndex 中集成 Gemini LLM 和嵌入,以生成响应和存储数据,从而提高 RAG 功能;
  • 开发自定义检索器配置的决策技能,包括在 AND 和 OR 操作之间进行选择以优化搜索结果。

一、retriever的重要性

       要开发自定义retriever,确定最适合我们需求的retriever类型至关重要。这里,我们将实现一个集成关键字搜索和矢量搜索的混合搜索。

       矢量搜索根据相似性或语义搜索来识别用户查询的相关文档,而关键字搜索则根据术语出现的频率来查找文档。使用 LlamaIndex 可以通过两种方式实现这种集成。为混合搜索生成自定义检索器时,一个重要的决策是在使用 AND 或 OR 操作之间进行选择:

  • AND 操作:此方法检索包含所有指定术语的文档,使其更具限制性,但确保高度相关性。可以将其视为关键字搜索和矢量搜索之间的结果交集;
  • OR 操作:此方法检索包含任何指定术语的文档,从而增加结果的广度,但可能会降低相关性。可以将其视为关键字搜索和矢量搜索之间的结果联合。

二、构建自定义retriever

       现在让我们使用 LlamaIndex 构建自定义retriever,大致需要如下步骤:

2.1 安装所需的包

       在我们的例子中,使用 LlamaIndex 来构建自定义检索器,使用 Gemini 来构建嵌入模型和LLM推理,并使用 PyPDF 来构建数据连接器,因此,需要安装所需的库。

!pip install llama-index!pip install llama-index-multi-modal-llms-gemini!pip install llama-index-embeddings-gemini

2.2 设置Google API密钥

       利用 Google Gemini 作为大型语言模型来生成响应,并作为嵌入模型,使用 LlamaIndex 将数据转换和存储在vector数据库或内存中。

如果没有Google API Key,可以在这里(http://ai.google.dev/)申请。

from getpass import getpassGOOGLE_API_KEY = getpass("Enter your Google API:")

2.3 加载数据并创建文档节点

       在 LlamaIndex 中,数据加载是使用 SimpleDirectoryLoader 完成的。首先,需要创建一个文件夹并将任何格式的数据上传到此数据文件夹中。在我们的示例中,我们将把一个 PDF 文件上传到 data 文件夹中。加载文档后,将文档拆分为更小的段,将其解析为节点。节点是在 LlamaIndex 框架中定义的数据架构。

       最新版本的 LlamaIndex 更新了其代码结构,现在包括节点解析器、嵌入模型和LLM设置中的定义。

from llama_index.core import SimpleDirectoryReaderfrom llama_index.core import Settingsdocuments = SimpleDirectoryReader('data').load_data()nodes = Settings.node_parser.get_nodes_from_documents(documents)

2.4 设置嵌入模型和大型语言模型

        Gemini 有各种型号,包括 gemini-pro、gemini-1.0-pro、gemini-1.5、视觉模型等。这里,我们将使用默认模型并提供 Google API Key。对于 Gemini 中的嵌入模型,我们目前使用的是 embedding-001。

from llama_index.embeddings.gemini import GeminiEmbeddingfrom llama_index.llms.gemini import GeminiSettings.embed_model = GeminiEmbedding(    model_name="models/embedding-001", api_key=GOOGLE_API_KEY)Settings.llm = Gemini(api_key=GOOGLE_API_KEY)

2.5 定义Storage context,并存储数据

       一旦数据被解析为节点,LlamaIndex 就会提供一个存储上下文,它提供默认的文档存储,用于存储数据的向量嵌入。此存储上下文将数据保留在内存中,以便以后对其进行索引。

from llama_index.core import StorageContextstorage_context = StorageContext.from_defaults()storage_context.docstore.add_documents(nodes)

       为了构建自定义检索器以执行混合搜索,我们需要创建两个索引。第一个可以执行向量搜索的向量索引,第二个可以执行关键字搜索的关键字索引。为了创建索引,我们需要存储上下文和节点文档,以及嵌入模型和LLM的默认设置。

from llama_index.core import SimpleKeywordTableIndex, VectorStoreIndexvector_index = VectorStoreIndex(nodes, storage_context=storage_context)keyword_index = SimpleKeywordTableIndex(nodes, storage_context=storage_context)

2.6 构建自定义Retriever

       要使用 LlamaIndex 构建用于混合搜索的自定义检索器,我们首先需要定义架构,尤其是配置合适的节点。需要矢量索引检索器和关键字检索器来执行混合搜索,是通过指定模式(AND 或 OR)来实现这两种检索器的组合,集成这两种技术以最大限度地减少幻觉。

       一旦节点配置好后,我们就可以使用 vector 和 keyword 检索器查询每个节点 ID 的数据。然后,根据所选模式,最终确定自定义检索器。

from llama_index.core import QueryBundlefrom llama_index.core.schema import NodeWithScorefrom llama_index.core.retrievers import (    BaseRetriever,    VectorIndexRetriever,    KeywordTableSimpleRetriever,)from typing import Listclass CustomRetriever(BaseRetriever):    def __init__(        self,        vector_retriever: VectorIndexRetriever,        keyword_retriever: KeywordTableSimpleRetriever,        mode: str = "AND") -> None:               self._vector_retriever = vector_retriever        self._keyword_retriever = keyword_retriever        if mode not in ("AND", "OR"):            raise ValueError("Invalid mode.")        self._mode = mode        super().__init__()    def _retrieve(self, query_bundle: QueryBundle) -> List[NodeWithScore]:        vector_nodes = self._vector_retriever.retrieve(query_bundle)        keyword_nodes = self._keyword_retriever.retrieve(query_bundle)        vector_ids = {n.node.node_id for n in vector_nodes}        keyword_ids = {n.node.node_id for n in keyword_nodes}        combined_dict = {n.node.node_id: n for n in vector_nodes}        combined_dict.update({n.node.node_id: n for n in keyword_nodes})        if self._mode == "AND":            retrieve_ids = vector_ids.intersection(keyword_ids)        else:            retrieve_ids = vector_ids.union(keyword_ids)        retrieve_nodes = [combined_dict[r_id] for r_id in retrieve_ids]        return retrieve_nodes

2.7 定义retriever

       定义好自定义检索器类后,我们需要实例化检索器并合成查询引擎。响应合成器用于根据用户查询和给定的文本块集生成LLM响应。Response Synthesizer 的输出是一个 Response 对象,该对象将自定义检索器作为参数之一。

from llama_index.core import get_response_synthesizerfrom llama_index.core.query_engine import RetrieverQueryEnginevector_retriever = VectorIndexRetriever(index=vector_index, similarity_top_k=2)keyword_retriever = KeywordTableSimpleRetriever(index=keyword_index)# custom retriever => combine vector and keyword retrievercustom_retriever = CustomRetriever(vector_retriever, keyword_retriever)# define response synthesizerresponse_synthesizer = get_response_synthesizer()custom_query_engine = RetrieverQueryEngine(    retriever=custom_retriever,    response_synthesizer=response_synthesizer,)

2.8 运行自定义检索查询引擎

       最后,我们已经开发好了自定义的retriever,它可以显著减少幻觉。为了测试其有效性,我们使用一个包括上下文的提示和一个不包括上下文的提示来评估生成的响应。

query = "what does the data context contain?"print(custom_query_engine.query(query))print(custom_query_engine.query("what is science?")

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

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

相关文章

Face_recognition实现人脸识别

这里写自定义目录标题 欢迎使用Markdown编辑器一、安装人脸识别库face_recognition1.1 安装cmake1.2 安装dlib库1.3 安装face_recognition 二、3个常用的人脸识别案例2.1 识别并绘制人脸框2.2 提取并绘制人脸关键点2.3 人脸匹配及标注 欢迎使用Markdown编辑器 本文基于face_re…

Python 安装Numpy 出现异常信息

文章目录 前言一、包源二、安装完成异常 前言 安装Python Numpy包出现异常问题 Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location. 一、包源 使用默认的包源出现超时异常,改用清华包源 pip …

娱乐圈幕后揭秘孙俪天选打工人

【娱乐圈幕后揭秘:孙俪“天选打工人”背后的热议风暴】在聚光灯下光鲜亮丽的娱乐圈,每一位明星的日常备受瞩目。近日,实力派演员孙俪在社交媒体上分享了一段片场棚拍的趣事,本是无心之举,意外引爆了网络热议的导火索。…

这几类人,千万不要买纯电车

文 | AUTO芯球 作者 | 响铃 纯电车的冤大头真是太多了, 我之前劝过,有些人不适合买纯电车, 你们看,果然吧,麦卡锡最近的一份报告就披露了 去年啊,22%的人在买了电车后后悔了, 这些人说了&a…

面试常考题---128陷阱(详细)

1.问题引入 分别引入了int和Integer变量,并进行比较 int b 128; int b1 128;Integer d 127; Integer d1 127;Integer e 128; Integer e1 128;System.out.println(bb1); System.out.println(dd1); System.out.println(ee1); System.out.println(e.equals(e1)…

kafka系列之offset超强总结及消费后不提交offset情况的分析总结

概述 每当我们调用Kafka的poll()方法或者使用Spring的KafkaListener(其实底层也是poll()方法)注解消费Kafka消息时,它都会返回之前被写入Kafka的记录,即我们组中的消费者还没有读过的记录。 这意味着我们有一种方法可以跟踪该组消费者读取过的记录。 如前…

【力扣高频题】014.最长公共前缀

经常刷算法题的小伙伴对于 “最长”,“公共” 两个词一定不陌生。与此相关的算法题目实在是太多了 !!! 之前的 「动态规划」 专题系列文章中就曾讲解过两道相关的题目:最长公共子序列 和 最长回文子序列 。 关注公众…

跨境电商代购系统与电商平台API结合的化学反应

随着全球化的不断推进和互联网技术的飞速发展,跨境电商已成为国际贸易的重要组成部分。跨境电商代购系统作为连接国内外消费者与商品的桥梁,不仅为消费者提供了更多元化的购物选择,也为商家开辟了更广阔的市场空间。在这一过程中,…

如何将heic转jpg格式?四种图片格式转换方法【附教程】

如何把heic转jpg格式?heic是用于存储静态图像和图形的压缩格式,旨在以更小的文件大小保持高质量的图像。HEIC格式自iOS 11和macOS High Sierra(10.13)内测开始,被苹果设置为图片存储的默认格式,广泛应用于i…

【VUE基础】VUE3第四节—核心语法之computed、watch、watcheffect

computed 接受一个 getter 函数&#xff0c;返回一个只读的响应式 ref 对象。该 ref 通过 .value 暴露 getter 函数的返回值。它也可以接受一个带有 get 和 set 函数的对象来创建一个可写的 ref 对象。 创建一个只读的计算属性 ref&#xff1a; <template><div cl…

【一次成功】清华大学和智谱AI公司的ChatGLM-4-9B-Chat-1M大模型本地化部署教程

【一次成功】清华大学和智谱AI公司的ChatGLM-4-9B-Chat-1M大模型本地化部署教程 一、环境准备二、ChatGLM-4-9B-Chat-1M简介三、模型下载2.1 安装Git LFS2.2 初始化仓库2.3 同步Git文件2.4 拉取文件2.5 下载完毕 四、python和源码安装与下载4.1 安装python4.2 下载源码4.3 安装…

Monaco 中添加 CodeLens

CodeLens 会在指定代码行上添加一行可点击的文字&#xff0c;点击时可以触发定义的命令&#xff0c;效果如下&#xff1a; 通过调用 API 注册 LensProvider&#xff0c;点击时触发 Command&#xff0c;首先要注册命令&#xff0c;通过 editor.addCommand () 方法进行注册。三个…

韦东山嵌入式linux系列-LED驱动程序

之前学习STM32F103C8T6的时候&#xff0c;学习过对应GPIO的输出&#xff1a; 操作STM32的GPIO需要3个步骤&#xff1a; 使用RCC开启GPIO的时钟、使用GPIO_Init函数初始化GPIO、使用输入/输出函数控制GPIO口。 【STM32】GPIO输出-CSDN博客 这里再看看STM32MP157的GPIO引脚使用…

高通开发系列 - 使用QFIL工具单刷某个镜像文件

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 返回:专栏总目录 目录 背景过程记录背景 有时候设备中刷的是user版本,无法使用fastboot刷单个镜像,这个时候该怎么办呢? 要解决在user…

Websocket在Java中的实践——整合Rabbitmq和STOMP

大纲 Rabbitmq开启STOMP支持 服务端依赖参数参数映射类配置类逻辑处理类 测试测试页面Controller测试案例 在《Websocket在Java中的实践——STOMP通信的最小Demo》一文中&#xff0c;我们使用enableSimpleBroker启用一个内置的内存级消息代理。本文我们将使用Rabbitmq作为消息代…

计算机类期刊横纵向对比

备注&#xff1a;综合影响因子更具针对性&#xff0c;将科技类期刊和人文社科期刊的影响力考虑&#xff0c;更加聚焦于某一特定科学领域&#xff1b;复合影响因子是基于期刊、学位论文、以及会议论文等多个类型的文献作为计算基础。 两者都是通过前两年发表的可被引文献在统计年…

pandas数据分析(8)

描述性统计量和数据聚合 描述性统计量 描述性统计量通过量化数据来概括数据集。DataFrame和Series可以通过sum、mean、count等方法来获取各种描述性统计量。在默认情况下会按照axis0返回一个Series&#xff0c;也就是说会得到一个有关列的统计量&#xff1a; 如果要计算行的统…

鼠标宏怎么设置?6款鼠标自动点击器强推,游戏玩家专用!(2024全)

随着电子游戏和日常应用的不断发展&#xff0c;我们经常会遇到一些重复性的任务或操作。而在这种情况下&#xff0c;鼠标宏以其自动化的特点成为了许多玩家和使用者的利器之一。如果你正在寻找如何设置鼠标宏来简化操作并提高效率&#xff0c;那么你来对地方了。在本文中&#…

理解算法复杂度:空间复杂度详解

引言 在计算机科学中&#xff0c;算法复杂度是衡量算法效率的重要指标。时间复杂度和空间复杂度是算法复杂度的两个主要方面。在这篇博客中&#xff0c;我们将深入探讨空间复杂度&#xff0c;了解其定义、常见类型以及如何进行分析。空间复杂度是衡量算法在执行过程中所需内存…

利用canvas压缩图片

前情提要 页面打印导出pdf文件的时候&#xff0c;图片大小会影响pdf文件大小。 为了减小pdf文件大小&#xff0c;需要将图片压缩一下。在只有图片地址的情况下&#xff0c;将图片压缩后显示&#xff0c;一开始用的browser-image-compression插件&#xff0c;这是js压缩&#x…