大模型 Advanced-RAG(高级检索增强生成):从理论到 LlamaIndex 实战!

最近关于检索增强生成进行了调查,总结了三种最近发展的范式:

  1. Naive RAG(简单RAG)
  2. Advanced RAG(高级RAG)
  3. Modular RAG(模块化RAG)

本文首先讨论这些技术,接着分享如何使用 Python 中的 Llamaindex 实现一个简单的 RAG ,然后将其改进为一个包含以下高级 RAG 技术的高级 RAG 的全流程:

  1. 检索前优化:句子窗口检索
  2. 检索优化:混合搜索
  3. 检索后优化:重新排序

更多技术可以加入我们的讨论群

技术交流

前沿技术资讯、算法交流、求职内推、算法竞赛、面试交流(校招、社招、实习)等、与 10000+来自港科大、北大、清华、中科院、CMU、腾讯、百度等名校名企开发者互动交流~

我们建了大模型技术交流群, 想要进交流群、获取完整源码&资料、提升技术的同学,可以直接加微信号:mlc2060。加的时候备注一下:研究方向 +学校/公司+CSDN,即可。然后就可以拉你进群了。

方式①、微信搜索公众号:机器学习社区,后台回复:技术交流
方式②、添加微信号:mlc2060,备注:技术交流

通俗易懂讲解大模型系列

  • 做大模型也有1年多了,聊聊这段时间的感悟!

  • 用通俗易懂的方式讲解:大模型算法工程师最全面试题汇总

  • 用通俗易懂的方式讲解:不要再苦苦寻觅了!AI 大模型面试指南(含答案)的最全总结来了!

  • 用通俗易懂的方式讲解:我的大模型岗位面试总结:共24家,9个offer

  • 用通俗易懂的方式讲解:大模型 RAG 在 LangChain 中的应用实战

  • 用通俗易懂的方式讲解:一文讲清大模型 RAG 技术全流程

  • 用通俗易懂的方式讲解:如何提升大模型 Agent 的能力?

  • 用通俗易懂的方式讲解:ChatGPT 开放的多模态的DALL-E 3功能,好玩到停不下来!

  • 用通俗易懂的方式讲解:基于扩散模型(Diffusion),文生图 AnyText 的效果太棒了

  • 用通俗易懂的方式讲解:在 CPU 服务器上部署 ChatGLM3-6B 模型

  • 用通俗易懂的方式讲解:使用 LangChain 和大模型生成海报文案

  • 用通俗易懂的方式讲解:ChatGLM3-6B 部署指南

  • 用通俗易懂的方式讲解:使用 LangChain 封装自定义的 LLM,太棒了

  • 用通俗易懂的方式讲解:基于 Langchain 和 ChatChat 部署本地知识库问答系统

  • 用通俗易懂的方式讲解:在 Ubuntu 22 上安装 CUDA、Nvidia 显卡驱动、PyTorch等大模型基础环境

  • 用通俗易懂的方式讲解:Llama2 部署讲解及试用方式

  • 用通俗易懂的方式讲解:基于 LangChain 和 ChatGLM2 打造自有知识库问答系统

  • 用通俗易懂的方式讲解:一份保姆级的 Stable Diffusion 部署教程,开启你的炼丹之路

  • 用通俗易懂的方式讲解:对 embedding 模型进行微调,我的大模型召回效果提升了太多了

  • 用通俗易懂的方式讲解:LlamaIndex 官方发布高清大图,纵览高级 RAG技术

  • 用通俗易懂的方式讲解:为什么大模型 Advanced RAG 方法对于AI的未来至关重要?

  • 用通俗易懂的方式讲解:使用 LlamaIndex 和 Eleasticsearch 进行大模型 RAG 检索增强生成

  • 用通俗易懂的方式讲解:基于 Langchain 框架,利用 MongoDB 矢量搜索实现大模型 RAG 高级检索方法

  • 用通俗易懂的方式讲解:使用Llama-2、PgVector和LlamaIndex,构建大模型 RAG 全流程

高级 RAG

随着 RAG 领域的最新进展,高级RAG已经成为一种新范式,针对简单 RAG 范式的一些局限性进行了有针对性的增强。

正如最近一项调查[1]所总结的,高级RAG技术可以分为三类:检索前优化、检索优化和检索后优化。

检索前优化

检索前优化集中在数据索引优化和查询优化上。数据索引优化技术旨在以有助于提高检索效率的方式存储数据,例如 [1]:

  1. 滑动窗口使用片段之间的重叠,是最简单的技术之一。
  2. 提高数据粒度应用数据清洗技术,例如删除无关信息、确认事实准确性、更新过时信息等。
  3. 添加元数据,如日期、目的或章节,用于过滤目的。
  4. 优化索引结构涉及不同的策略来索引数据,例如调整片段大小或使用多索引策略。本文将实现的一项技术是句子窗口检索,它将单个句子嵌入到检索中,并在推断时用更大的文本窗口替换它们。

此外,检索前技术不仅限于数据索引,还可以涉及推理时的技术,如查询路由、查询重写和查询扩展。

检索优化

检索阶段的目标是确定最相关的上下文。通常,检索基于向量搜索,它计算查询与索引数据之间的语义相似性。因此,大多数检索优化技术都围绕嵌入模型展开 [1]:

  1. 微调嵌入模型,将嵌入模型定制为特定领域的上下文,特别是对于术语不断演化或罕见的领域。例如,BAAI/bge-small-en是一个高性能的嵌入模型,可以进行微调(请参阅微调指南)。
  2. 动态嵌入根据单词的上下文进行调整,而静态嵌入则为每个单词使用单一向量。例如,OpenAI的embeddings-ada-02是一个复杂的动态嵌入模型,可以捕获上下文理解。[1]

除了向量搜索之外,还有其他检索技术,例如混合搜索,通常是指将向量搜索与基于关键字的搜索相结合的概念。如果您的检索需要精确的关键字匹配,则此检索技术非常有益。

检索后优化

对检索到的上下文进行额外处理可以帮助解决一些问题,例如超出上下文窗口限制或引入噪声,从而阻碍对关键信息的关注。在RAG调查中总结的检索后优化技术包括:

  1. 提示压缩:通过删除无关内容并突出重要上下文,减少整体提示长度。
  2. 重新排序:使用机器学习模型重新计算检索到的上下文的相关性得分。

先决条件

本节讨论了在本文中跟随所需的软件包和API密钥。

所需软件包

本文将使用 Python 在 LlamaIndex 中实现一个简单的和一个高级的RAG管道。

pip install llama-index

在本文中,我们将使用LlamaIndex v0.10。如果您正在从较旧的LlamaIndex版本升级,您需要运行以下命令以正确安装和运行LlamaIndex:

pip uninstall llama-index
pip install llama-index --upgrade --no-cache-dir --force-reinstall

LlamaIndex 提供了将向量嵌入存储在JSON文件中进行持久存储的选项,这对于快速原型设计是很好的。但是,由于高级RAG技术旨在用于生产环境的应用,我们将使用向量数据库进行持久存储。

除了存储向量嵌入之外,我们还需要元数据存储和混合搜索功能。因此,我们将使用支持这些功能的开源向量数据库 Weaviate(v3.26.2)。

pip install weaviate-client llama-index-vector-stores-weaviate

API密钥

我们将使用 Weaviate 嵌入式,您可以在不注册API密钥的情况下免费使用。但是,本教程使用了来自OpenAI的嵌入模型和LLM,您将需要一个OpenAI API密钥。要获得API密钥,您需要一个OpenAI帐户,然后在API密钥下“创建新的密钥”。

接下来,在根目录中创建一个名为 .env 的本地文件,并在其中定义您的API密钥:

OPENAI_API_KEY="<YOUR_OPENAI_API_KEY>"

然后,您可以使用以下代码加载您的API密钥:

# !pip install python-dotenv
import os
from dotenv import load_dotenv,find_dotenvload_dotenv(find_dotenv())

使用 LlamaIndex 实现简单RAG

本节讨论了如何使用 LlamaIndex 实现简单的RAG管道。您可以在这个 Jupyter Notebook 中找到整个简单RAG管道。

步骤 1:定义嵌入模型和LLM

首先,您可以在全局设置对象中定义一个嵌入模型和LLM。这样做意味着您不必再次在代码中明确指定模型。

嵌入模型:用于为文档块和查询生成向量嵌入。
LLM:用于根据用户查询和相关上下文生成答案。

from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.llms.openai import OpenAI
from llama_index.core.settings import SettingsSettings.llm = OpenAI(model="gpt-3.5-turbo", temperature=0.1)
Settings.embed_model = OpenAIEmbedding()

步骤 2:加载数据

接下来,您将在根目录中创建一个名为 data 的本地目录,并从LlamaIndex GitHub存储库(MIT许可证)中下载一些示例数据。

!mkdir -p 'data'
!wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/examples/data/paul_graham/paul_graham_essay.txt' -O 'data/paul_graham_essay.txt'

然后,您可以加载数据以进行进一步处理:

from llama_index.core import SimpleDirectoryReader# Load data
documents = SimpleDirectoryReader(input_files=["./data/paul_graham_essay.txt"]
).load_data()

步骤 3:将文档分块成节点

由于整个文档太大,无法适应LLM的上下文窗口,因此您需要将其分割成更小的文本块,称为节点。您可以使用 SimpleNodeParser 将加载的文档解析为节点,并定义块大小为 1024。

from llama_index.core.node_parser import SimpleNodeParsernode_parser = SimpleNodeParser.from_defaults(chunk_size=1024)# Extract nodes from documents
nodes = node_parser.get_nodes_from_documents(documents)

步骤 4:构建索引

接下来,您将构建一个索引,该索引将所有外部知识存储在Weaviate中,这是一个开源的向量数据库。

首先,您需要连接到Weaviate实例。在本例中,我们使用的是Weaviate Embedded,它允许您在Notebooks中免费进行实验,而无需API密钥。对于生产就绪的解决方案,建议您自己部署Weaviate,例如通过Docker或利用托管服务。

import weaviate# Connect to your Weaviate instance
client = weaviate.Client(embedded_options=weaviate.embedded.EmbeddedOptions(), 
)

接下来,您将从Weaviate客户端构建一个 VectorStoreIndex 来存储和交互您的数据。

from llama_index.core import VectorStoreIndex, StorageContext
from llama_index.vector_stores.weaviate import WeaviateVectorStoreindex_name = "MyExternalContext"# Construct vector store
vector_store = WeaviateVectorStore(weaviate_client = client, index_name = index_name
)# Set up the storage for the embeddings
storage_context = StorageContext.from_defaults(vector_store=vector_store)# Setup the index
index = VectorStoreIndex(nodes,storage_context = storage_context,
)

步骤 5:设置查询引擎

最后,您将将索引设置为查询引擎。

# The QueryEngine class is equipped with the generator
# and facilitates the retrieval and generation steps
query_engine = index.as_query_engine()

步骤 6:在您的数据上运行一个简单的 RAG 查询

现在,您可以在您的数据上运行一个简单的RAG查询,如下所示:

# Run your naive RAG query
response = query_engine.query("What happened at Interleaf?"
)

使用 LlamaIndex 实现高级RAG

本教程将涵盖以下一系列高级 RAG 技术的选择:

  • 检索前优化:句子窗口检索
  • 检索优化:混合搜索
  • 检索后优化:重新排序

索引优化示例:句子窗口检索

对于句子窗口检索技术,您需要进行两个调整:首先,您必须调整如何存储和后处理您的数据。我们将使用 SentenceWindowNodeParser,而不是 SimpleNodeParser。

from llama_index.core.node_parser import SentenceWindowNodeParsernode_parser = SentenceWindowNodeParser.from_defaults(window_size=3,window_metadata_key="window",original_text_metadata_key="original_text",
)

SentenceWindowNodeParser 做了两件事情:

  • 它将文档分成单个句子,这些句子将被嵌入。
  • 对于每个句子,它创建一个上下文窗口。如果您指定 window_size = 3,则生成的窗口将为三个句子长,从嵌入句子的前一个句子开始,并跨越后一个句子。窗口将存储为元数据。

在检索过程中,返回与查询最接近的句子。检索后,您需要通过定义 MetadataReplacementPostProcessor 并在节点后处理器列表中使用它来用元数据替换句子。

from llama_index.core.postprocessor import MetadataReplacementPostProcessor# The target key defaults to `window` to match the node_parser's default
postproc = MetadataReplacementPostProcessor(target_metadata_key="window"
)
...
query_engine = index.as_query_engine( node_postprocessors = [postproc],
)

检索优化示例:混合搜索

在LlamaIndex中实现混合搜索与两个参数更改相同,如果底层向量数据库支持混合搜索查询的话。alpha 参数指定向量搜索和基于关键字的搜索之间的加权,其中 alpha = 0

表示基于关键字的搜索,alpha = 1 表示纯向量搜索。

query_engine = index.as_query_engine(...,vector_store_query_mode="hybrid", alpha=0.5,...
)

检索后优化示例:重新排序

将 reranker 添加到您的高级RAG管道中只需要三个简单的步骤:

首先,定义一个重新排序模型。在这里,我们使用来自Hugging Face的 BAAI/bge-reranker-base。
在查询引擎中,将重新排序模型添加到节点后处理器列表中。
在查询引擎中增加 similarity_top_k 以检索更多的上下文段落,在重新排序后可以将其减少到 top_n。

# !pip install torch sentence-transformers
from llama_index.core.postprocessor import SentenceTransformerRerank# Define reranker model
rerank = SentenceTransformerRerank(top_n = 2, model = "BAAI/bge-reranker-base"
)
...
# Add reranker to query engine
query_engine = index.as_query_engine(similarity_top_k = 6,...,node_postprocessors = [rerank],...,
)

高级RAG范式中还有许多不同的技术。如果您对进一步的实现感兴趣,可以加入我们讨论群。

参考

[1] Gao, Y., Xiong, Y., Gao, X., Jia, K., Pan, J., Bi, Y., … & Wang, H. (2023). Retrieval-augmented generation for large language models: A survey. arXiv preprint arXiv:2312.10997.
[2] https://towardsdatascience.com/advanced-retrieval-augmented-generation-from-theory-to-llamaindex-implementation-4de1464a9930

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

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

相关文章

数字电路 第二章—第二节(半导体二极管、三极管和MOS管的开关特性)

一、理想开关的开关特性 1、静态特性 &#xff08;1&#xff09;断开时&#xff0c;无论在多大范围内变化&#xff0c;其等效电阻&#xff0c;通过其中的电流。 &#xff08;2&#xff09;闭合时&#xff0c;无论流过其中的电流在多大范围内变化&#xff0c;其等效电阻&…

Spark大数据分析与实战笔记(第三章 Spark RDD 弹性分布式数据集-05)

文章目录 每日一句正能量第3章 Spark RDD弹性分布式数据集章节概要3.7 Spark的任务调度3.7.1 DAG的概念3.7.2 RDD在Spark中的运行流程 总结 每日一句正能量 成功的速度一定要超过父母老去的速度&#xff0c;努力吧。做事不必与俗同&#xff0c;亦不与俗异&#xff1b;做事不必令…

Mysql运维篇(六) 部署MHA--一主二从部署

MAH架构图 一、上传MySQL软件 1、同步MySQL软件 [rootmysql01 ~]# ls -lrt total 626112 -rw-r--r--. 1 root root 641127384 Jan 30 15:13 mysql-5.7.20-linux-glibc2.12-x86_64.tar.gz -rw-------. 1 root root 1697 Feb 3 12:09 anaconda-ks.cfg -rw-r--r--. 1 root…

[SpringDataMongodb开发游戏服务器实战]

背景&#xff1a; xdb其实足够完美了&#xff0c;现在回想一下&#xff0c;觉得有点复杂&#xff0c;我们不应该绑定语言&#xff0c;最好有自己的架构思路。 七号堡垒作为成功的商业项目&#xff0c;告诉我&#xff1a;其实数据是多读少写的&#xff0c;有修改的时候直接改库也…

推荐一个 Obsidian 的 ChatGPT 插件

源码地址&#xff1a;https://github.com/nhaouari/obsidian-textgenerator-plugin Text Generator 是目前我使用过的最好的 Obsidian 中的 ChatGPT 功能插件。它旨在智能生成内容&#xff0c;以便轻松记笔记。它不仅可以在 Obsidian 中直接使用 ChatGPT&#xff0c;还提供了优…

Python staticmethod函数

Python是一种功能强大且灵活的编程语言&#xff0c;具有许多特性和功能&#xff0c;其中之一就是staticmethod函数。staticmethod函数是Python中用于定义静态方法的一种特殊装饰器。在本文中&#xff0c;将深入探讨staticmethod函数的用法、优势以及与其他方法类型的比较。 什…

【力扣 - 将有序数组转化为二叉搜索树】

题目描述 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 高度平衡 二叉搜索树。 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。 题解 前言 二叉搜索树的中序遍历是升序序列&a…

黑马JavaWeb开发跟学(一)Web前端开发HTML、CSS基础

黑马JavaWeb开发一.Web前端开发HTML、CSS基础 引子、Web开发介绍传统路线本课程全新路线本课程适用人群课程收获一、什么是web开发二、网站的工作流程三、网站的开发模式四、网站的开发技术 前端开发基础一、前端开发二、HTML & CSS2.1 HTML快速入门2.1.1 操作第一步第二步…

Arduino中安装ESP32网络抽风无法下载 暴力解决办法 python

不知道什么仙人设计的arduino连接网络部分&#xff0c;死活下不下来。&#xff08;真的沙口&#xff0c;第一次看到这么抽风的下载口&#xff09; 操作 给爷惹火了我踏马解析json选zip直接全部下下来 把这个大家的开发板管理地址下下来跟后面python放在同一目录下&#xff0c…

FDTD算法总结

计算电磁学(Computational Electromagnetics, CEM)是通过数值计算来研究电磁场的交叉学科。 数值求解电磁学问题的方法可以分成频域(Frequency Doamin, FD)、时域(Time Domain, TD)等两类。 频域法基于时谐微分&#xff0c;通过对多个采样值的傅里叶逆变换得到所需的脉冲响应…

构建高效教学平台系统:关键要素与最佳实践

随着在线教育的迅速发展&#xff0c;教学平台系统成为了教育行业不可或缺的一部分。本文将总结构建高效教学平台系统的关键要素&#xff0c;并介绍最佳实践&#xff0c;以帮助教育机构和企业打造具有竞争力的教学平台系统。 引言&#xff1a; 随着信息技术的不断进步和普及&…

神经网络系列---分类度量

文章目录 分类度量混淆矩阵&#xff08;Confusion Matrix&#xff09;&#xff1a;二分类问题二分类代码多分类问题多分类宏平均法:多分类代码多分类微平均法&#xff1a; 准确率&#xff08;Accuracy&#xff09;&#xff1a;精确率&#xff08;Precision&#xff09;&#xf…

K8s安全一

Kubernetes是一个开源的&#xff0c;用于编排云平台中多个主机上的容器化的应用&#xff0c;目标是让部署容器化的应用能简单并且高效的使用, 提供了应用部署&#xff0c;规划&#xff0c;更新&#xff0c;维护的一种机制。其核心的特点就是能够自主的管理容器来保证云平台中的…

值得推荐收藏的5款顶级免费数据恢复软件!

今天分享5个超级简单又适合电脑小白的恢复删除的文件的恢复方法&#xff01; 在我们的日常生活中&#xff0c;偶尔会因为误删除或者清空回收站等原因导致数据丢失。对于电脑小白来说&#xff0c;这或许是一个非常棘手的问题。但是&#xff0c;不用太担心&#xff0c;今天我为大…

【C++那些事儿】C++入门 | 命名空间 | 缺省参数 | 引用 | 内联函数 | auto关键字 | 范围for循环 | nullptr

&#x1f4f7; 江池俊&#xff1a; 个人主页 &#x1f525;个人专栏&#xff1a; ✅数据结构冒险记 ✅C那些事儿 &#x1f305; 有航道的人&#xff0c;再渺小也不会迷途。 文章目录 前言1. C关键字(C98)2. 命名空间2.1 命名空间定义2.2 命名空间使用 3. C输入&输出4. 缺…

模型上下文长度达到10000000,又一批创业者完蛋了?

没有疑问&#xff0c;Gemini 1.5 Pro的隆重推出被Sora抢了风头。 社交平台X上OpenAI介绍Sora的第一条动态&#xff0c;现在已经被浏览了超过9000万次&#xff0c;而关于Gemini 1.5 Pro热度最高的一条&#xff0c;来自谷歌首席科学家Jeff Dean&#xff0c;区区123万人。 或许J…

【设计模式】策略模式及函数式编程的替代

本文介绍策略模式以及使用函数式编程替代简单的策略模式。 策略模式 在策略模式&#xff08;Strategy Pattern&#xff09;中一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。 在策略模式定义了一系列算法或策略&#xff0c;并将每个算法封装在独立…

Jenkins解决Host key verification failed (2)

Jenkins解决Host key verification failed 分析原因情况 一、用OpenSSH的人都知ssh会把你每个你访问过计算机的公钥(public key)都记录在~/.ssh/known_hosts。当下次访问相同计算机时&#xff0c;OpenSSH会核对公钥。如果公钥不同&#xff0c;OpenSSH会发出警告&#xff0c;避免…

基于SpringBoot的航班进出港管理系统

文章目录 项目介绍主要功能截图&#xff1a;部分代码展示设计总结项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 &…

【Java程序设计】【C00319】基于Springboot的志愿服务管理系统(有论文)

基于Springboot的志愿服务管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的志愿服务管理系统设计与实现&#xff0c;本系统有管理员以及用户二种角色权限 管理员&#xff1a;首页、个人中心、管理员管理、…