用通俗易懂的方式讲解:太棒了!构建大模型 Advanced RAG(检索增强生成)的速查表和实战技巧最全总结来了!

新的一年开始了,也许您正打算通过构建自己的第一个RAG系统进入RAG领域。或者,您可能已经构建了基本的RAG系统,现在希望将它们改进为更高级的系统,以更好地处理用户的查询和数据结构。

无论哪种情况,了解从何处或如何开始可能本身就是一个挑战!如果是这样,希望这篇博客文章能为您指明下一步的正确方向,更重要的是,在构建高级RAG系统时为您提供一个思维模型,以便在做决策时有所依据。

上面分享的 RAG 备忘单受到了最近一篇RAG调查论文的启发(Retrieval-Augmented Generation for Large Language Models: A Survey” Gao, Yunfan, et al. 2023)。

文章目录

    • 通俗易懂讲解大模型系列
    • 技术交流&资料
    • 基础 RAG
    • RAG成功的要求
    • 高级RAG
    • 高级生成技术必须能够充分利用检索到的文档
    • 解决检索和生成成功要求的高级技术
    • RAG的测量方面
    • 结论

通俗易懂讲解大模型系列

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

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

  • 用通俗易懂的方式讲解:我的大模型岗位面试总结:共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 全流程

技术交流&资料

技术要学会分享、交流,不建议闭门造车。一个人可以走的很快、一堆人可以走的更远。

成立了大模型技术交流群,本文完整代码、相关资料、技术交流&答疑,均可加我们的交流群获取,群友已超过2000人,添加时最好的备注方式为:来源+兴趣方向,方便找到志同道合的朋友。

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

在这里插入图片描述

基础 RAG

如今,主流的RAG定义涉及从外部知识数据库中检索文档,并将这些文档与用户的查询一起传递给LLM进行响应生成。换句话说,RAG包含检索组件、外部知识数据库和生成组件。

LlamaIndex 基础RAG配方:

from llama_index import SimpleDirectoryReader, VectorStoreIndex# 加载数据
documents = SimpleDirectoryReader(input_dir="...").load_data()# 构建VectorStoreIndex,负责对文档进行分块
# 并为将来的检索编码块以进行嵌入
index = VectorStoreIndex.from_documents(documents=documents)# QueryEngine类配备了生成器
# 并促进了检索和生成步骤
query_engine = index.as_query_engine()# 使用默认的RAG
response = query_engine.query("用户的查询")

RAG成功的要求

为了使RAG系统被认为是成功的(以提供有用且相关的答案给用户问题为标准),实际上只有两个高层次的要求:

  1. 检索必须能够找到与用户查询最相关的文档。
  2. 生成必须能够充分利用检索到的文档,以足够回答用户的查询。

高级RAG

有了成功的要求定义,我们可以说构建高级RAG实际上是关于应用更复杂的技术和策略(对检索或生成组件)以确保最终满足这些要求。

此外,我们可以将复杂的技术分类为解决两个高层次成功要求之一的技术(或多或少独立于另一个),或者是同时解决这两个要求的技术。

检索的高级技术必须能够找到与用户查询最相关的文档
以下简要描述了几种更复杂的技术,以帮助实现第一个成功要求。

  1. 块大小优化:由于LLMs受上下文长度限制,因此在构建外部知识数据库时需要对文档进行分块。块的大小过大或过小可能会导致生成组件出现问题,从而导致不准确的响应。

LlamaIndex 块大小优化配方:

from llama_index import ServiceContext
from llama_index.param_tuner.base import ParamTuner, RunResult
from llama_index.evaluation import SemanticSimilarityEvaluator, BatchEvalRunner# 执行超参数调整,就像在传统ML中通过网格搜索一样
# 1. 定义一个排名不同参数组合的目标函数
# 2. 构建ParamTuner对象
# 3. 使用ParamTuner.tune()执行超参数调整# 1. 定义目标函数
def objective_function(params_dict):chunk_size = params_dict["chunk_size"]docs = params_dict["docs"]top_k = params_dict["top_k"]eval_qs = params_dict["eval_qs"]ref_response_strs = params_dict["ref_response_strs"]# 构建RAG流水线index = _build_index(chunk_size, docs)  # 此处未显示辅助函数query_engine = index.as_query_engine(similarity_top_k=top_k)# 对提供的问题`eval_qs`执行RAG流水线的推断pred_response_objs = get_responses(eval_qs, query_engine, show_progress=True)# 通过将其与参考响应`ref_response_strs`进行比较来执行预测的评估evaluator = SemanticSimilarityEvaluator(...)eval_batch_runner = BatchEvalRunner({"semantic_similarity": evaluator}, workers=2, show_progress=True)eval_results = eval_batch_runner.evaluate_responses(eval_qs, responses=pred_response_objs, reference=ref_response_strs)# 获取语义相似性指标mean_score = np.array([r.score for r in eval_results["semantic_similarity"]]).mean()return RunResult(score=mean_score, params=params_dict)# 2. 构建ParamTuner对象
param_dict = {"chunk_size": [256, 512, 1024]}  # 要搜索的参数/值
fixed_param_dict = {  # 固定的超参数"top_k": 2,"docs": docs,"eval_qs": eval_qs[:10],"ref_response_strs": ref_response_strs[:10],
}
param_tuner = ParamTuner(param_fn=objective_function,param_dict=param_dict,fixed_param_dict=fixed_param_dict,show_progress=True,
)# 3. 执行超参数搜索
results = param_tuner.tune()
best_result = results.best_run_result
best_chunk_size = results.best_run_result.params["chunk_size"]
  1. 结构化外部知识:在复杂的场景中,可能需要以比基本的矢量索引更为结构化的方式构建外部知识,以便在处理明智分离的外部知识源时允许递归检索或路由检索。

LlamaIndex递归检索配方:

from llama_index import SimpleDirectoryReader, VectorStoreIndex
from llama_index.node_parser import SentenceSplitter
from llama_index.schema import IndexNode### 配方
### 构建一个递归检索器,使用小块进行检索
### 但将相关的较大块传递到生成阶段# 加载数据
documents = SimpleDirectoryReader(input_file="some_data_path/llama2.pdf"
).load_data()# 通过NodeParser构建父块
node_parser = SentenceSplitter(chunk_size=1024)
base_nodes = node_parser.get_nodes_from_documents(documents)# 定义较小的子块
sub_chunk_sizes = [256, 512]
sub_node_parsers = [SentenceSplitter(chunk_size=c, chunk_overlap=20) for c in sub_chunk_sizes
]
all_nodes = []
for base_node in base_nodes:for n in sub_node_parsers:sub_nodes = n.get_nodes_from_documents([base_node])sub_inodes = [IndexNode.from_text_node(sn, base_node.node_id) for sn in sub_nodes]all_nodes.extend(sub_inodes)# 还要添加原始节点到节点original_node = IndexNode.from_text_node(base_node, base_node.node_id)all_nodes.append(original_node)# 使用所有节点定义一个VectorStoreIndex
vector_index_chunk = VectorStoreIndex(all_nodes, service_context=service_context
)
vector_retriever_chunk = vector_index_chunk.as_retriever(similarity_top_k=2)# 构建RecursiveRetriever
all_nodes_dict = {n.node_id: n for n in all_nodes}
retriever_chunk = RecursiveRetriever("vector",retriever_dict={"vector": vector_retriever_chunk},node_dict=all_nodes_dict,verbose=True,
)# 使用recursive_retriever构建RetrieverQueryEngine
query_engine_chunk = RetrieverQueryEngine.from_args(retriever_chunk, service_context=service_context
)# 使用高级RAG执行推理(即查询引擎)
response = query_engine_chunk.query("你能告诉我有关安全微调的关键概念吗?"
)

其他有用的链接

我们有几个指南演示了在复杂情况下应用其他高级技术以确保准确检索。以下是其中一些的链接:

  • 使用知识图构建外部知识
  • 使用Auto Retrievers执行混合检索
  • 构建Fusion Retrievers
  • 微调用于检索的嵌入模型
  • 转换查询嵌入(HyDE)

高级生成技术必须能够充分利用检索到的文档

与前一节类似,我们提供了这一类别下的一些复杂技术的示例,这可以被描述为确保检索到的文档与生成器的LLM很好地对齐。

  1. 信息压缩:LLMs不仅受到上下文长度的限制,而且如果检索到的文档带有太多噪声(即无关信息),则可能会导致响应降级。

LlamaIndex信息压缩配方:

from llama_index import SimpleDirectoryReader, VectorStoreIndex
from llama_index.query_engine import RetrieverQueryEngine
from llama_index.postprocessor import LongLLMLinguaPostprocessor### 配方
### 定义一个Postprocessor对象,这里是LongLLMLinguaPostprocessor
### 构建使用此Postprocessor处理检索到的文档的QueryEngine# 定义Postprocessor
node_postprocessor = LongLLMLinguaPostprocessor(instruction_str="在给定的上下文中,请回答最后的问题",target_token=300,rank_method="longllmlingua",additional_compress_kwargs={"condition_compare": True,"condition_in_question": "after","context_budget": "+100","reorder_context": "sort",  # 启用文档重新排序},
)# 定义VectorStoreIndex
documents = SimpleDirectoryReader(input_dir="...").load_data()
index = VectorStoreIndex.from_documents(documents)# 定义QueryEngine
retriever = index.as_retriever(similarity_top_k=2)
retriever_query_engine = RetrieverQueryEngine.from_args(retriever, node_postprocessors=[node_postprocessor]
)# 使用你的高级RAG
response = retriever_query_engine.query("用户的查询")
  1. 结果重新排名:LLMs受到所谓的“中间丢失”现象的影响,该现象规定LLMs专注于提示的极端部分。鉴于此,将检索到的文档重新排名并在传递给生成组件之前是有益的。

LlamaIndex重新排名以获得更好生成配方:

import os
from llama_index import SimpleDirectoryReader, VectorStoreIndex
from llama_index.postprocessor.cohere_rerank import CohereRerank
from llama_index.postprocessor import LongLLMLinguaPostprocessor### 配方
### 定义一个Postprocessor对象,这里是CohereRerank
### 构建使用此Postprocessor处理检索到的文档的QueryEngine# 构建CohereRerank检索后处理器
api_key = os.environ["COHERE_API_KEY"]
cohere_rerank = CohereRerank(api_key=api_key, top_n=2)# 构建QueryEngine(RAG),使用后处理器
documents = SimpleDirectoryReader("./data/paul_graham/").load_data()
index = VectorStoreIndex.from_documents(documents=documents)
query_engine = index.as_query_engine(similarity_top_k=10,node_postprocessors=[cohere_rerank],
)# 使用你的高级RAG
response = query_engine.query("在这篇文章中,Sam Altman做了什么?"
)

解决检索和生成成功要求的高级技术

在这个子节中,我们考虑使用检索和生成的协同作用来实现更好的检索以及对用户查询更准确生成响应的复杂方法。

  1. 生成器增强检索:这些技术利用LLM固有的推理能力,在执行检索之前优化用户查询,以更好地指示提供有用响应所需的内容。

LlamaIndex生成器增强检索配方:

from llama_index.llms import OpenAI
from llama_index.query_engine import FLAREInstructQueryEngine
from llama_index import (VectorStoreIndex,SimpleDirectoryReader,ServiceContext,
)
### 配方
### 构建一个FLAREInstructQueryEngine,其中生成器LLM通过提示
### 在检索中发挥更积极的作用,以引导它提取检索
### 关于如何回答用户查询的指示。# 构建FLAREInstructQueryEngine
documents = SimpleDirectoryReader("./data/paul_graham").load_data()
index = VectorStoreIndex.from_documents(documents)
index_query_engine = index.as_query_engine(similarity_top_k=2)
service_context = ServiceContext.from_defaults(llm=OpenAI(model="gpt-4"))
flare_query_engine = FLAREInstructQueryEngine(query_engine=index_query_engine,service_context=service_context,max_iterations=7,verbose=True,
)# 使用你的高级RAG
response = flare_query_engine.query("你能告诉我作者在创业界的轨迹吗?"
)
  1. 迭代检索生成RAG:对于一些复杂情况,可能需要多步推理才能为用户查询提供有用且相关的答案。

LlamaIndex迭代检索生成配方:

from llama_index.query_engine import RetryQueryEngine
from llama_index.evaluation import RelevancyEvaluator### 配方
### 构建RetryQueryEngine,执行检索生成周期
### 直到它达到合格的评估或达到最大次数
### 周期已达到# 构建RetryQueryEngine
documents = SimpleDirectoryReader("./data/paul_graham").load_data()
index = VectorStoreIndex.from_documents(documents)
base_query_engine = index.as_query_engine()
query_response_evaluator = RelevancyEvaluator()  # 评估器来批评# 检索生成周期
retry_query_engine = RetryQueryEngine(base_query_engine, query_response_evaluator
)# 使用你的高级RAG
retry_response = retry_query_engine.query("一个用户查询")

RAG的测量方面

评估RAG系统当然是至关重要的。在他们的调查论文中,Gao,Yunfan等人在附上的RAG备忘单的右上部分指出了7个测量方面。llama-index库包括多个评估抽象以及与RAGAs的集成,以帮助构建者通过这些测量方面的视角了解他们的RAG系统达到成功要求的水平。下面,我们列举了一些评估笔记本指南。

  • 答案相关性和上下文相关性
  • 忠实度
  • 检索评估
  • 使用BatchEvalRunner进行批量评估

结论

希望通过阅读本博客文章,您感到更有能力和信心应用一些这些复杂的技术来构建高级RAG系统!

参考文献
https://blog.llamaindex.ai/a-cheat-sheet-and-some-recipes-for-building-advanced-rag-803a9d94c41b

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

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

相关文章

JVM系列-4.类加载器

👏作者简介:大家好,我是爱吃芝士的土豆倪,24届校招生Java选手,很高兴认识大家📕系列专栏:Spring原理、JUC原理、Kafka原理、分布式技术原理、数据库技术、JVM原理🔥如果感觉博主的文…

LeetCode670.最大交换

我真的怀疑他是不是难度等级评错了,因为感觉没到中级,总之先看题吧 给定一个非负整数,你至多可以交换一次数字中的任意两位。返回你能得到的最大值。 示例 1 : 输入: 2736 输出: 7236 解释: 交换数字2和数字7。示例 2 : 输入: 9973 输出:…

常用的三维尺寸公差分析软件有哪些?各有什么特点?

公差分析软件主要用于产品设计和制造过程中,帮助工程师们评估和控制产品的尺寸和公差。以下是一些常用的公差分析软件: 1.DTAS3D是一种用于三维尺寸公差分析的软件系统。 DTAS软件可以帮助工程师和设计师对零件和装配体的尺寸公差进行分析,…

静态路由实验

一:实验内容 二:实验分析 (一):实验要求 1、R6为ISP,接口IP地址均为公有地址;该设备只能配置IP地址,之后不能再对其进行其他任何配置; 2、R1-R5为局域网&#xff0c…

过滤器监听器拦截器AOP

过滤器、监听器、拦截器、AOP的实现 一、过滤器 Filter ​ 在传统的Servlet容器中,可以使用过滤器和监听器,在Java框架中还可以使用拦截器。 ​ 过滤器,这里指的是Servlet过滤器,它是在Java Servlet中定义的,能够对…

EasyExcelFactory 导入导出功能的实战使用

EasyExcelFactory 导入导出功能的实战使用分享&#xff1a; 1、jar包引入 <!-- 阿里巴巴Excel处理--><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.0.6</version></dependen…

1、Seaborn可视化库

你的数据可视化编程初体验! Seaborn是一个基于matplotlib的图形可视化Python库,它提供了一种高级的API接口,使得制作统计图形更加容易。 Seaborn的目标是使可视化成为探索和理解数据的核心部分,它面向数据集的绘图功能对整个数据集进行操作,并在内部执行必要的语义映射和统…

Python - 【Socket】消息粘包处理demo(一)

一. 前言 在网络编程中&#xff0c;粘包是指TCP协议在传输过程中&#xff0c;多条数据被合并成一条数据发送或者一条数据被拆分成多个数据发送的现象。 二. 粘包问题的常规处理方法&#xff1a; 使用固定长度的包头 可以在发送数据前先发送一个固定长度的包头&#xff0c;包…

个人云服务器docker搭建部署前后端应用-myos

var code "87c5235c-b551-45bb-a5e4-9593cb104663" mysql、redis、nginx、java应用、前端应用部署 本文以单台云服务器为例&#xff1a; 1. 使用腾讯云服务器 阿里或其他云服务器皆可&#xff0c;类似 安装系统&#xff0c;现在服务器系统都集成安装了docker镜像&a…

[ACM学习]自上而下树形dp

问题引入 设置dp状态&#xff0c;相比于更容易出错的贪心更...不易出错。 状态设计 如果选择父结点&#xff0c;就会使孩子结点不能被选择&#xff0c;我们会多开一维的dp&#xff0c;用来标记该点是否被标记过。 以1点举例&#xff0c;f[1][0]为不选它的状态&#xff0c;那么…

FOR XML PATH 函数与同一分组下的字符串拼接

FOR XML PATH 简单介绍 FOR XML PATH 语句是将查询结果集以XML形式展现&#xff0c;通常情况下最常见的用法就是将多行的结果&#xff0c;拼接展示在同一行。 首先新建一张测试表并插入数据&#xff1a; CREATE TABLE #Test (Name varchar(70),Hobby varchar(70) );insert #T…

芯驰E3340软件编译以及更新步骤

打开已有工程File->Open Solution: 东南项目&#xff1a;e3340\boards\e3_324_ref_display\proj\jetour-t1n-fl3\sf\SES 编译&#xff1a;build->build sf 增加头文件和宏定义&#xff1a; 编译完成sf后&#xff0c;进行编译bootloader 东南项目&#xff1a;e3340\boa…

IaC基础设施即代码:Terraform 创建ACK集群 与部署应用

目录 一、实验 1.环境 2.Terraform 创建网络资源 3. 阿里云给RAM添加权限 4.Terraform 创建 ACK集群 5.在ACK集群中部署应用 6.销毁资源 二、问题 1.Terraform 验证失败 2.Terraform申请资源失败 一、实验 1.环境 &#xff08;1&#xff09;主机 表1-1 主机 主机系…

火山引擎ByteHouse:“专用向量数据库”与“数据库+向量扩展”,怎么选?

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 背景 随着LLM&#xff08;Large Language Model&#xff09;的不断发展&#xff0c;向量检索也逐渐成为关注的焦点。LLM通过处理大量的文本数据&#xff0c;获取丰…

第1章-计算机网络基础

目录 1. 计算机网络与计算机 2. 计算机网络的定义和基本功能 2.1. 定义&#xff1a;计算机网络是一组自治计算机互连的集合 2.2. 基本功能 2.3. 计算机网络的演进 2.4. 广域网(Wide Area Network&#xff0c;WAN) 2.5. 网络的拓扑结构 2.6. 数据交换方式 2.7. 衡量计算…

图灵日记之java奇妙历险记--异常包装类泛型

目录 异常概念与体系结构异常的分类异常的处理防御式编程异常的抛出异常的捕获异常声明throwstry-catch捕获并处理 自定义异常类 包装类基本数据类型及其对应包装类装箱和拆箱 泛型泛型使用类型推导 裸类型说明 泛型的编译机制泛型的上界语法 异常概念与体系结构 在java中,将程…

VisualODX——ODX数据自动转换工具 加快开发进度

在创建ODX数据库的过程中&#xff0c;我们需要录入大量的数据以及应对多种数据格式。这不仅费时费力&#xff0c;而且还需很高的人力成本&#xff0c;且其错误率也非常高&#xff0c;从而导致开发速度缓慢、效率低下。基于多年的汽车行业诊断经验&#xff0c;我们开发了VisualO…

org.apache.rocketmq.remoting.exception.RemotingTooMuchRequestException

异常信息&#xff1a; org.apache.rocketmq.remoting.exception.RemotingTooMuchRequestException: sendDefaultImpl call timeout 开发环境描述&#xff1a; rocketMq 版本是 4.9.0&#xff0c;部署在服务器主机上&#xff0c; Broker 部署为单节点&#xff08;单机&#xff…

jdk的安装和Tomcat的安装

jdk的安装 双击jdk&#xff0c;然后一路下一步 公共JRE可以关闭&#xff0c;没多大用&#xff0c;反而会占用内存 计算机–>属性–>高级系统设置–>环境变量 系统变量–新建 JAVA_HOMEjdk的存放路径 修改path 在path的最后面添加&#xff08;&#xff1b;%JAVA_H…

Python算法题集_移动零

本文为Python算法题集之一的代码示例 题目283&#xff1a;移动零 说明&#xff1a;给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序 注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作 本文给出四…