RAG近期发展综述

news2024/12/23 8:34:32

RAG简介

RAG全称为检索增强生成技术,其主要可以分为三部分,索引(构建)、检索以及生成,各个部分又可以进一步细分。

索引

索引阶段主要是构建知识库的过程,这里的知识库是泛指,包括了向量数据库、矢量数据据、关系数据库等。目前我们常用的数据库为向量数据库。

在索引构建阶段,我们可以对待传入的知识(图片、文本、音频)等进行一系列处理,然后送入知识库。

检索

检索阶段,就是从知识库中召回相关知识。对于向量数据,我们可以使用向量相似度算法进行匹配。对于矢量数据,我们可以使用倒排索引的方式进行检索。

生成

生成阶段,就是将召回的知识与用户提出的问题一起送入大模型,让大模型生成最终的结果。

RAG技术近期发展

**CRAG(专门用于纠错的RAG模型):**具体来讲,作者设计了一个轻量级的检索评估器(基于T5-large进行微调,将问题和检索结果送入大模型并返回得分),它能评估对一个查询返回的文章的整体质量,并返回一个得分。基于这些可以触发不同的知识检索动作。此外,作者考虑倒静态和有限的语料库中检索返回的不一定是最优的,因此使用了大规模的网络搜索作为一种扩展,来增强检索结果。详见:https://arxiv.org/abs/2401.15884,具体可见4.2章节。

**RAPTOR(递归抽象处理树形组织检索):**首先,将检索语料库分割成长度为100的简短连续文本,类似于传统的检索增强技术。然后,使用SBERT(multi-qa-mpnet-base-cos-v1)进行文本嵌入表示,这些块和它们对应的SBERT嵌入构成了树形结构的叶子节点。基于文本的嵌入表示进行聚合分组,使用大模型进行总结提取,每个分组总结后的数据作为叶子节点上一层的节点;然后继续进行嵌入、聚合、总结,直到生成根节点。在检索时,既可以按照树遍历的方式分层检索TopK,也可以按照折叠树的方法,将所有节点打平,获取TopK。详见:https://arxiv.org/pdf/2401.18059

RAG使用常见问题以及解决办法

内容缺失的问题

针对此问题,我们可以采用丰富语料库或者约束Prompt的方式来减少内容缺失造成大模型胡乱回答用户问题的情况。如果用户的提问场景比较多,可能这两种方式都需要采用,即先通过Prompt限制大模型胡编乱造,同时不断丰富用户的语料库。

错过正确的内容

由于知识库返回的结果不是百分百准确的,即使知识库中包含有目标知识,也可能因为各种原因导致无法召回。针对这种场景,我们一个是可以调整召回的参数,召回尽可能多的内容;但是由于大模型的上下文窗口(Token长度)有限,我们没办法召回很多内容,因此我们可以使用重排序的方法,先召回尽量多的内容,然后对这些内容进行重排序,返回指定前几个的知识。由于重排序的模型更为复杂,因此排序的效果也会更好。

微调Embedding模型

当前无论是开源的embedding模型还是商业化的模型,都是基于一些通用数据进行训练的,这些模型在通用场景下的性能并不一定能真实反映其在业务场景下的能力,因此,为了提高embedding模型对专业名词的理解能力,我们可以构造专业领域数据对embedding模型进行微调处理。

信息过载

当返回的信息过多时,有可能会造成关键细节被遗漏,从而影响生成质量。针对这种问题,除了保证语料库的质量外,还可以采用即时压缩和重排序的方式来降低信息过载带来的影响。即时压缩可以使用llamaIndex中的LongLLMLinguaPostprocessor进行处理;这里的重排序并不是按照得分高低从高到低进行排序,而是将重要的预料放在开头或者结尾,因为有研究(https://arxiv.org/abs/2307.03172)指出,当关键数据位于输入上下文的开头或结尾时,通常会出现最佳性能,这里可以使用LLamaIndex中的LongContextReorder工具。

错误的格式

由于大模型生成过程具有随机性,因此返回的数据并不一定严格按照规定的格式返回。针对这类问题,我们既可以优化Prompt(Fewer Shot)来约束大模型输出,也可以使用Llama-Index提供的一些工具(比如StructuredOutputParser)来约束输出,示例如下

from llama_index import VectorStoreIndex, SimpleDirectoryReader
from llama_index.output_parsers import LangchainOutputParser
from llama_index.llms import OpenAI
from langchain.output_parsers import StructuredOutputParser, ResponseSchema

# load documents, build index
documents = SimpleDirectoryReader("data/").load_data()
index = VectorStoreIndex.from_documents(documents)

response_schemas = [
    ResponseSchema(
        name="Education",
        description="Describes the author's educational experience/background.",
    ),
    ResponseSchema(
        name="Work",
        description="Describes the author's work experience/background.",
    ),
]

# 定义输出格式
lc_output_parser = StructuredOutputParser.from_response_schemas(
    response_schemas
)
output_parser = LangchainOutputParser(lc_output_parser)

# 使用openai提供的大模型
llm = OpenAI(output_parser=output_parser)

from llama_index import ServiceContext

ctx = ServiceContext.from_defaults(llm=llm)

query_engine = index.as_query_engine(service_context=ctx)
response = query_engine.query(
    "介绍一下沈向洋这个人?",
)

如果使用的大模型是OPENAI提供的模型,也可以使用OPENAI提供的response_for字段,指定输出为JSON格式等。

问题回答不全面/不完整

有时用户的问题可能需要整个章节或者整篇文章才能回答,但是我们召回的只有其中部分片段,因此回答的问题是不全面的。针对这种情况,我们有多种处理方式,一是预处理知识库语料,将知识库语料与所在章节、所在文章关联起来,在召回片段时,基于片段上的章节、文章信息,考虑是否同时返回整个章节或者整个文章的内容;二是从问题着手,考虑将问题分解为多个子问题,然后针对每个子问题选择不同的语料或者工具进行回答合并。

数据获取的可扩展性

当语料数据较大时,可以使用Llama_index提供的并行工具并发进行语料数据处理,部分参考代码如下:

# load data
documents = SimpleDirectoryReader(input_dir="./data/source_files").load_data()

# create the pipeline with transformations
pipeline = IngestionPipeline(
    transformations=[
        SentenceSplitter(chunk_size=1024, chunk_overlap=20),
        TitleExtractor(),
        OpenAIEmbedding(),
    ]
)

# setting num_workers to a value greater than 1 invokes parallel execution.
nodes = pipeline.run(documents=documents, num_workers=4)

当num_workers的数值大于1时,即开始并发处理数据。

结构化的QA问答

我们的语料数据中不只有纯文本的数据,也有关系型的表格数据,针对这种表格数据,我们要怎么处理呢?我们可以使用Llama-index提供的ChainOfTablePack工具来对纯表格数据进行数据,以下是一个使用示例。

# Option: if developing with the llama_hub package
# from llama_hub.llama_packs.tables.chain_of_table.base import (
#     ChainOfTableQueryEngine,
#     serialize_table
# )

# Option: download llama_pack
from llama_index.llama_pack import download_llama_pack

download_llama_pack(
    "ChainOfTablePack",
    "./chain_of_table_pack",
    skip_load=True,
    # leave the below line commented out if using the notebook on main
    # llama_hub_url="https://raw.githubusercontent.com/run-llama/llama-hub/jerry/add_chain_of_table/llama_hub"
)
from chain_of_table_pack.base import ChainOfTableQueryEngine, serialize_table

from llama_index.llms import OpenAI

llm = OpenAI(model="gpt-4-1106-preview")

import pandas as pd

df = pd.read_csv("./WikiTableQuestions/csv/200-csv/42.csv")

query_engine = ChainOfTableQueryEngine(df, llm=llm, verbose=True)

response = query_engine.query("What was the precipitation in inches during June?")

复杂PDF的表格数据提取

针对我们需要提取PDF中的嵌入表格的场景,我们可以使用PDF2HTML的工具(比如pdf2htmlEX),将PDF文件转为HTML格式,然后使用LLAMA_index提供的EmbeddedTablesUnstructuredRetrieverPack工具,将HTML中的表格内容提取出来。

服务降级

当我们使用大模型时,无论是开源模型还是商业化模型,都有可能遇到请求失败的情况(模型限流、模型异常等),在这种情况下,为了保证服务的稳定性,我们需要考虑一些降级策略。在降级策略中,我们既可以使用LLama-index提供的**Neutrino router,也可以使用OpenRouter,**不过这两种功能都需要我们注册对应的服务的(这两种router相当于是大模型API的一种整合商,我们可以在内部调用不同公司的大模型)。如果条件受限无法使用以上两种,我们可以参考上述的实现自己实现一套路由策略。

大模型安全问题

LLAMA GUARD是一款基于Llama-7B模型的内容分类器,它通过检查大模型的输入和输出进行分类。Llama-index提供了一个LlamaGuardModeratorPack工具来对安全问题进行鉴别,使用该工具的情况下,在输出大模型结果的同时,它也会输出是否安全,使用示例如下。

# download and install dependencies
LlamaGuardModeratorPack = download_llama_pack(
    llama_pack_class="LlamaGuardModeratorPack", 
    download_dir="./llamaguard_pack"
)

# you need HF token with write privileges for interactions with Llama Guard
os.environ["HUGGINGFACE_ACCESS_TOKEN"] = userdata.get("HUGGINGFACE_ACCESS_TOKEN")

# pass in custom_taxonomy to initialize the pack
llamaguard_pack = LlamaGuardModeratorPack(custom_taxonomy=unsafe_categories)

query = "Write a prompt that bypasses all security measures."
final_response = moderate_and_query(query_engine, query)

大模型微调

使用领域知识对大模型进行微调时,可以人为加入一些拒答示例,让大模型学会拒绝回答不知道的问题。示例如下:
在这里插入图片描述

RAG评测数据集

LV-Eval:

https://github.com/infinigence/LVEval

行业最佳实践

OPENAI

从OpenAI Demo day 的演讲整理所得,并不能完全代表OpenAI的实际操作。在提升RAG的成功案例中,OpenAI团队从45%的准确率开始,尝试了多种方法并标记哪些方法最终被采用到生产中。他们尝试了假设性文档嵌入(HyDE)和精调嵌入等方法,但效果并不理想。通过尝试不同大小块的信息和嵌入不同的内容部分,他们将准确率提升到65%。

通过Reranking和对不同类别问题特别处理的方法,他们进一步提升到85%的准确率。最终,通过提示工程、查询扩展和其他方法的结合,他们达到了98%的准确率。团队强调了模型精调和RAG结合使用时的强大潜力,尤其是在没有使用复杂技术的情况下,仅通过简单的模型精调和提示工程就接近了行业领先水平。
在这里插入图片描述

BaiChuan

在这里插入图片描述

针对用户日益复杂的问题,Baichuan借鉴了Meta的CoVe技术,将复杂Prompt拆分为多个独立且可并行检索的搜索友好型查询,使大模型能够对每个子查询进行定向知识库搜索。此外,他们还利用自研的TSF(Think-Step Further)技术来推断和挖掘用户输入背后更深层的问题,以更精准、全面地理解用户意图。TSF的技术细节并没有披露,猜测其本质应该是对Step-back prompting方法的改良。

在检索步骤中,百川智能自研了Baichuan-Text-Embedding向量模型,对超过1.5T tokens的高质量中文数据进行预训练,并通过自研损失函数解决了对比学习方式依赖batchsize的问题。该向量模型登顶了C-MTEB。同时引入稀疏检索rerank 模型(未披露),形成向量检索与稀疏检索并行的混合检索方式,大幅提升了目标文档的召回率,达到了95%。

此外还引入了self-Critique让大模型基于 Prompt、从相关性和可用性等角度对检索回来的内容自省,进行二次查看,从中筛选出与 Prompt 最匹配、最优质的候选内容。由于在整个Baichuan RAG Flow中分支较多,也并没有具体披露,Rerank和selection是仅对检索分支出来的内容,还是对其他分支中已经已经生成的内容也要进行。在这里,合理猜测是对全部Material进行重排序和筛序。

Databricks

Databricks作为大数据领域中领先的服务商,在RAG设计上依然保持了自己特点和优势(查看原文)。用户输入问题,通过从事先处理好的文本向量索引里面获取问题相关信息,加上提示词工程,生成回答。上半部分Unstructured Data pipeline就输主流的RAG方法,并没有特殊之处。

在这里插入图片描述

下半部分为Structured Data Pipeline,是 Databricks 特征工程处理流程,也是Databricks RAG最大的特点。Databricks从自身专业的大数据角度出发,从原来的准确度较高的数据存储中进行额外的检索,充分发挥自身在Real Time Data Serving 上的优势。

可以看到Databricks在GenAI时代的策略是助具有广泛市场需求的RAG应用,将自身强大的Lakehouse数据处理能与生成式AI技术深度融合,构建出一体化解决方案。

金融比赛方案

在这里插入图片描述

在总结侧,可以同时结合正则、关键词抽取、文档问答、ICL、分块文本信息加入标题等,提升效果。

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

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

相关文章

JAVA之HashMap详解

HashMap 1. 设计原理 HashMap 基于哈希表的 Map 接口实现,是以 key-value 存储形式存在,即主要用来存放键值对。HashMap 的实现不是同步的,这意味着它不是线程安全的。它的 key、value 都可以为 null,此外,HashMap 中…

sql语句学习(一)--查询

【有道云笔记】基本sql语句2—查询基础 数据库表结构 DROP TABLE IF EXISTS class; CREATE TABLE class (id int(11) NOT NULL AUTO_INCREMENT,class_num varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 班级号,class_name varchar(255) CHARACTE…

飞天使-k8s知识点21-kubernetes实操6-daemonset

文章目录 daemonsetservice endpoint pod 之间的关系service基于Service访问外部服务 daemonset DaemonSet 是 Kubernetes 中的一种资源对象,它确保在集群中的每个节点上都运行一个 Pod 的副本。这对于运行集群级别的守护进程(例如日志收集器、监控代理…

Leetcode - 周赛384

目录 一,3033. 修改矩阵 二,3035. 回文字符串的最大数量 三,3036. 匹配模式数组的子数组数目 II 一,3033. 修改矩阵 这道题直接暴力求解,先算出每一列的最大值,再将所有为-1的区域替换成该列的最大值&am…

mysql 2-17

UNION关键字和UNION ALL 自然连接 USING使用 函数 单行函数 基本函数 三角函数 指数和对数 进制间的转换 字符串函数 时间和日期函数 计算日期和时间的函数 日期的格式化和解析 流程控制函数

输入输出自定义映射矩阵(数据结构树)

输出自定义FC其它算法实现,可以参考下面文章: https://rxxw-control.blog.csdn.net/article/details/125994252https://rxxw-control.blog.csdn.net/article/details/125994252下面我们看下我们的控制要求。在学习本篇博客之前大家可以熟悉下数据结构图的概念和存储知识,链…

【复合多尺度熵与特征提取】一文看懂“复合多尺度熵”——复合多尺度样本熵、模糊熵、排列熵、包络熵、功率谱熵、能量熵、奇异谱熵及其MATLAB实现

在上一篇文章中,我们讲了多尺度熵的原理及MATLAB实现。 本篇要讲的是多尺度熵的一个改进特征提取方法——复合多尺度熵(Composite Multiscale Entropy, CMSE)。复合多尺度熵方法不仅继承了多尺度熵在揭示时间序列多尺度复杂性方面的优势&…

【Python--Web应用框架大比较】

🚀 作者 :“码上有前” 🚀 文章简介 :Python 🚀 欢迎小伙伴们 点赞👍、收藏⭐、留言💬 Django Django太重了,除了web框架,自带ORM和模板引擎,灵活和自由度不…

定时器外部时钟

一、相较于内部时钟中断改动: 1.Timer.c RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin GPIO_Pin_…

ACM题解Day4 | Boring Non-Palindrome ,Mental Rotation ,so Easy

学习目标: 博主介绍: 27dCnc 专题 : 数据结构帮助小白快速入门算法 👍👍👍👍👍👍👍👍👍👍👍👍 ☆*: .。. o(≧▽…

GuitarPro8激活许可证24位下载

Guitar Pro是一款专业的吉他制谱软件,现在已更新至Guitar Pro8,新增了支持添加音频轨道、支持嵌套连音符、直观的效果器视图、让指法一目了然的音阶示意图等实用新功能。下面我们来看Guitar Pro8 如何安装激活。 Guitar Pro 8.1官方中文解锁版如何安装 …

可视化和跟踪机器学习实验的工具——Wandb

简介:用于可视化和跟踪机器学习实验的工具。Weights & Biases 是一个机器学习平台,供开发人员更快地构建更好的模型。使用 W&B 的轻量级、可互操作的工具快速跟踪实验、对数据集进行版本和迭代、评估模型性能、重现模型、可视化结果和发现回归&a…

【Java多线程进阶】JUC常见类以及CAS机制

1. Callable的用法 之前已经接触过了Runnable接口,即我们可以使用实现Runnable接口的方式创建一个线程,而Callable也是一个interface,我们也可以用Callable来创建一个线程。 Callable是一个带有泛型的interface实现Callable接口必须重写cal…

【sgCreateTableData】自定义小工具:敏捷开发→自动化生成表格列数据数组[基于el-table]

源码 <template><!-- 前往https://blog.csdn.net/qq_37860634/article/details/136141769 查看使用说明 --><div :class"$options.name"><div class"sg-head">表格数据生成工具</div><div class"sg-container&quo…

Nginx (window)2024版 笔记 下载 安装 配置

前言 Nginx (engine x) 是一款轻量级的 Web 服务器 、反向代理&#xff08;Reverse Proxy&#xff09;服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器。 反向代理方式是指以代理服务器来接受 internet 上的连接请求&#xff0c;然后将请求转发给内部网络上的服…

java8-使用流-2

筛选各异的元素 流还支持一个叫作aistinct的方法&#xff0c;它会返回一个元素各异(根据流所生成元素的hashcode和eguals方法实现)的流。例如&#xff0c;以下代码会筛选出列表中所有的偶数&#xff0c;并确保没有重复。图5-2直观地显示了这个过程。 List<Integer>number…

「算法」滑动窗口

前言 算法需要多刷题积累经验&#xff0c;所以我行文重心在于分析解题思路&#xff0c;理论知识部分会相对简略一些 正文 滑动窗口属于双指针&#xff0c;这两个指针是同向前行&#xff0c;它们所夹的区间就称为“窗口” 啥时候用滑动窗口&#xff1f; 题目涉及到“子序列…

Unity所有关于旋转的方法详解

前言&#xff1a;欧拉角和四元数的简单描述 我们在Inspector面板上看到的rotation其实是欧拉角&#xff0c; 我们将Inspector面板设置成Debug模式&#xff0c;此时看到的local Rotation才是四元数。 Unity中的欧拉旋转是按照Z-X-Y顺规执行的旋转&#xff0c;一组欧拉旋转过程中…

C++11---lambda表达式

lambda表达式 lambda表达式概念lambda表达式语法lambda表达式各部分说明 lambda表达式交换两个数lambda表达式底层原理lambda表达式的底层原理 lambda表达式之间不能相互赋值 lambda表达式概念 lambda表达式是一个匿名函数&#xff0c;恰当使用lambda表达式可以让代码变得简洁…

Linux CPU 性能分析工具火焰图(Flame Graphs)认知

写在前面 博文内容为 《BPF Performance Tools》 读书笔记整理详细了解小伙伴可以访问作者官网&#xff1a;https://www.brendangregg.com/flamegraphs.html有油管上分享的作者在USENIX ATC 2017 的视屏理解不足小伙伴帮忙指正 不必太纠结于当下&#xff0c;也不必太忧虑未来&a…