微信扫码
与创始人交个朋友
我要投稿
概述
检索增强生成(RAG)是一种通过结合外部知识来增强语言模型生成的技术。通常的做法是从大量文件语料库中检索相关信息,并利用这些信息为prompt。
客户通常拥有大量的私有文件。
提取具体信息无异于大海捞针。
检索效率不高。
模型容易忘记上下文窗口内容。
RAG 实施方法如下:
为每个文档段落创建索引。
快速识别相关段落。
将选定的段落输入到大型语言模型 (LLM) 中,例如 GPT4。
优点:
防止信息过载。
通过仅提供相关段落来提高结果质量。
借助 RAG,LLM 能够通过提供对外部知识源(如数据库)的访问来利用不一定属于其权重的知识和信息。
它利用检索器来查找相关上下文来调节 LLM,通过这种方式,RAG 能够使用相关文档来增强 LLM 的知识库。
此处的检索器可以是以下任何一种,具体取决于是否需要语义检索:
向量数据库:通常,使用 BERT 等模型嵌入查询,以生成密集向量嵌入。或者,TF-IDF 等传统方法可用于稀疏嵌入。然后根据术语频率或语义相似性进行搜索。
图形数据库:从文本中提取的实体关系中构建知识库。此方法很精确,但可能需要精确的查询匹配,这在某些应用程序中可能会受到限制。
常规 SQL 数据库:提供结构化数据存储和检索,但可能缺乏向量数据库的语义灵活性。
下面是使用图数据库与向量数据库进行 RAG 之间的区别。
与向量数据库相比,图形数据库更适合用于检索增强生成(RAG)。虽然向量数据库使用 LLM 编码的向量对数据进行分区和索引,允许语义相似的向量检索,但它们可能会获取不相关的数据。另一方面,图形数据库从文本中提取的实体关系中构建知识库,使检索简洁明了。但是,它需要精确的查询匹配,这可能会受到限制。一种可能的解决方案是结合两种数据库的优势:在图数据库中用向量表示法对解析的实体关系进行索引,以实现更灵活的信息检索。这种混合模式是否存在还有待观察。检索后,您可能需要通过添加排序层和(或)精细排序层来进一步过滤筛选信息,这样您就可以过滤掉不符合您的业务规则、未针对用户、当前上下文或响应限制进行个性化设置筛选信息。
让我们简明扼要地总结一下 RAG 的过程,然后深入探讨其利弊:
创建向量数据库:RAG 首先会将内部数据集转换为向量,并将其存储到向量数据库中。
用户输入:用户以自然语言提出查询,寻求答案或完成查询。
信息检索:检索机制扫描向量数据库,找出与用户查询(也是嵌入式查询)语义相似的片段。然后将这些片段交给 LLM,以丰富其生成响应的上下文。
组合数据:将从数据库中选择的数据段与用户的初始查询结合起来,创建一个扩展prompt。
生成文本:然后将扩展prompt提供给 LLM,LLM 会制作最终的上下文感知响应。
下图显示了高级RAG的工作。
LLM 的 RAG 和 Fine Tuning 之间的区别:
检索系统 (RAG) 使 LLM 系统能够访问事实、访问控制、及时的信息。微调不能做到这一点,所以他们不是竞争的关系。
Fine Tuning 也就是微调调整 LLM 的风格、语气和词汇,使你的语言与所需的领域和风格相匹配
总而言之,首先关注 RAG。成功的 LLM 应用程序必须将专有数据连接到 LLM 工作流。一旦您有了第一个完整的应用程序,您就可以添加微调以改进系统的样式和词汇。如果 RAG 与数据的连接构建不正确,微调也无法得到想要的效果。
向量数据库的选择:
下图直观地概述了 RAG 的三个不同步骤:数据提取、检索和合成/响应生成。
在下面的部分中,我们将介绍这些关键步骤。
数据提取(Ingestion)
分块(Chunking)
分块是将要检索的提示和/或文档划分为更小的、可管理的段或块的过程。这些块可以通过固定大小来定义,例如特定数量的字符、句子或段落。
在RAG中,每个块都被编码到嵌入向量中以供检索。更小、更精确的块会导致用户查询与内容之间的更精细匹配,从而提高检索信息的准确性和相关性。
较大的块可能包含不相关的信息,从而引入噪声并可能降低检索准确性。通过控制块大小,RAG 可以在全面性和精确性之间保持平衡。
因此,下一个自然而然的问题是,如何为您的用例选择正确的块大小?RAG 中块大小的选择至关重要。它需要足够小,以确保相关性并减少噪音,但又要足够大,以保持上下文的完整性。让我们看一下下面引用的Pinecone的几个方法:
固定大小的分块:只需确定我们块中的token数量以及它们之间是否应该重叠。块之间的重叠保证了块之间的语义上下文损失最小。此选项在计算上成本低且易于实现。
text = "..." # your textfrom langchain.text_splitter import CharacterTextSplittertext_splitter = CharacterTextSplitter(separator = "\n\n",chunk_size = 256,chunk_overlap= 20)docs = text_splitter.create_documents([text])
上下文感知分块:内容感知分块利用文本的内在结构来创建更有意义、与上下文更相关的分块。以下是实现这一目标的几种方法:
句子拆分:此方法与针对嵌入句子级内容而优化的模型相一致。可以使用不同的工具和技术进行句子拆分:
简单拆分:使用标点符号和换行拆分句子的基本方法。例:
text = "..."# Your text docs = text.split(".")
spaCy:spaCy 是用于 NLP 任务的高级 Python 库,提供高效的句子分割。例:
text = "..."# Your textfrom langchain.text_splitter import SpacyTextSplittertext_splitter = SpacyTextSplitter()docs = text_splitter.split_text(text)
递归分块:递归分块是一种迭代方法,它使用各种分隔符分层拆分文本。它通过递归应用不同的条件来适应创建相似大小或结构的块。使用LangChain的示例:
text = "..."# Your text from langchain.text_splitter import RecursiveCharacterTextSplitter text_splitter = RecursiveCharacterTextSplitter( chunk_size = 256, chunk_overlap = 20 ) docs = text_splitter.create_documents([text])
NLTK(自然语言工具包):用于语言处理的综合 Python 库。NLTK 包括一个句子分词器,可以有效地将文本拆分为句子。例:
text = "..."# Your textfrom langchain.text_splitter import NLTKTextSplittertext_splitter = NLTKTextSplitter()docs = text_splitter.split_text(text)
根据经验,如果没有上下文语境的文本块对人类有意义,那么对语言模型也有意义。因此,为语料库中的文档找到最佳块大小对于确保搜索结果的准确性和相关性至关重要。
嵌入(Embeddings)
一旦你的prompt被适当地分块,下一步就是嵌入它。在 RAG 中嵌入prompt和文档涉及将用户的查询(prompt)和知识库中的文档转换为可以有效比较相关性的格式。此过程对于 RAG 从其知识库中检索最相关信息以响应用户查询的能力至关重要。下面是它一般的工作原理:
可以通过HuggingFace 的大规模文本嵌入基准 (MTEB) 排行榜获取最适合的嵌入模型。有一个问题,即是否可以使用密集嵌入或稀疏嵌入,下面分析每种嵌入类型的特点:
稀疏嵌入:稀疏嵌入(如 TF-IDF)非常适合将提示与文档进行词法匹配。最适合关键字相关性要求较高的应用。它的计算强度较低,但可能无法捕获文本中更深层次的语义含义。
语义嵌入:语义嵌入,如 BERT 或 SentenceBERT,很自然地适合 RAG 用例。
BERT:适用于捕获文档和查询中的上下文细微差别。与稀疏嵌入相比,需要更多的计算资源,但提供语义更丰富的嵌入。
SentenceBERT:非常适合句子级别的上下文和含义很重要的场景。它平衡了 BERT 对深层次上下文的理解能力和对简洁、有意义的句子表达的需求。这通常是 RAG 的首选路线。
检索 (Retrieval)
让我们看一下两种不同类型的检索:标准检索、句子窗口检索和自动合并检索。这些方法各有优缺点,它们的适用性取决于 RAG 任务的要求,包括数据集的性质、查询的复杂性,以及在响应中特异性和上下文理解之间所需的平衡。
标准检索、句子窗口检索
如下图所示,标准pipeline使用相同的文本块进行索引/嵌入以及输出合成。
优势:
简单高效:这种方法简单高效,嵌入和合成都使用相同的文本块,简化了检索过程。
数据处理的一致性:它能保持检索和合并阶段所用数据的一致性。
缺点:
有限的上下文理解:LLM 可能需要更大的综合窗口来产生更好的返回,而这种方法可能无法提供足够的综合窗口。
可能存在非最优回复:由于上下文有限,LLM可能没有足够的信息来生成最相关、最准确的回复。
句子窗口检索/从小到大分块
句子窗口法将文档分解为更小的单元,如句子或小句子组。
对于检索任务(即存储在向量数据库中的较小块),它将嵌入解耦,但对于合成任务,它将检索到的块周围的上下文添加回去,如下图所示。
在检索过程中,我们通过相似性搜索检索与查询最相关的句子,并用完整的上下文替换句子(使用上下文周围的静态句子窗口,通过检索最初检索句子周围的句子来实现),如下图所示。
优势:
提高检索的针对性:通过将文档分解成更小的单元,可以更精确地检索与查询直接相关的片段。
丰富的语境合成:它围绕检索到的语块重新引入语境进行综合,为 LLM 提供了更广泛的理解,以制定应对措施。
平衡法:这种方法在重点检索和丰富语境之间取得了平衡,有可能提高答复质量。
缺点:
复杂性增加:管理检索和合成的不同流程会增加pipeline的复杂性。
潜在的背景空白:如果补充的周边信息不够全面,就有可能遗漏更广泛的背景。
检索器集成和重新排序
想法:如果我们能同时尝试多种块大小,并让重新排序器对结果进行修剪,会怎么样?
这样做有两个目的:
假设重新排序器的性能达到合理水平,通过汇集多个数据块的结果,可以获得更好(尽管成本更高)的检索结果。
对不同的检索策略(相对于重新排序器)进行基准测试的方法。
流程如下:
以多种不同的方式对同一文档进行分块,例如分块大小为 128、256、512 和 1024。
在检索过程中,我们从每个检索器中获取相关的数据块,从而将它们组合在一起进行检索。
使用重新排序器对结果进行排序/修剪。
下图描述了这一过程。
根据 LlamaIndex 的评估结果,集成方法的忠实度指标略有上升,表明检索到的结果稍微更相关。但成对比较会导致对两种方法的偏好相同,因此对于集成是否更好仍然存在疑问。
请注意,除块大小外,集合策略还可应用于 RAG pipeline的其他方面,如向量搜索与关键词搜索、混合搜索等
重新排名
词法重排:这包括根据查询和检索文档之间的词法相似性重新排序。常见的方法有 BM25 或带有 TF-IDF 向量的余弦相似性。
语义重新排序:这类重新排序使用语义理解来判断文档的相关性。它通常涉及神经模型,如 BERT 或其他基于转换器的模型,以理解上下文和意义,而不仅仅是单词重叠。
学习排名(LTR)方法:这种方法是根据从查询和文档中提取的特征,专门为文档排序任务(点排序、对排序和列表排序)训练一个模型。这可能包括词法、语义和其他特征的混合。
混合方法:这些方法结合了词法和语义法,可能还有用户反馈或特定领域特征等其他信号,以改进重新排序。
神经 LTR 方法在这一阶段最常用,因为候选集仅限于几十个样本。用于重新排序的一些常用神经模型包括
使用 BERT 进行多级文件排序(monoBERT 和 duo BERT)
RAG 中的重新排序是指根据检索到的文档或信息片段与给定查询或任务的相关性对其进行评估和排序的过程。
RAG 中使用了不同类型的重新排序技术:
生成回复
RAG pipeline的最后一步是生成反馈给用户的回复。在这一步中,模型将检索到的信息与其预先训练的知识进行综合,以生成连贯且与上下文相关的回复。这一过程包括整合从各种来源收集到的见解,确保准确性和相关性,并制作出不仅信息丰富,而且与用户的原始查询相一致的回复,同时保持自然的对话语气。
需要注意的是,在为 LLM 生成有根据的响应创建扩展prompt(包含检索到的 top-k 块)的同时,在输入序列的开头或结尾处战略性地放置重要信息可以提高 RAG 系统的有效性,从而使系统更加高效。
本文详细介绍了RAG(检索增强生成)的基本概念、工作流程和关键领域,包括数据提取、嵌入、检索和响应生成/合成。文章还探讨了各种检索和重新排序技术,以及如何有效地生成用户反馈。此外,文章还分析了语言模型如何使用长语境。
此外,文章也强调了在处理长文本时,模型的性能可能会受到影响,尤其是当相关信息位于文本的中部时。因此,文章建议在输入序列的开头或结尾处战略性地放置重要信息,以提高RAG系统的有效性。同时,通过改进检索和提示创建步骤,如使用排序阶段,可以将性能提高20%。这些见解对于理解和优化RAG的应用具有重要价值。
53AI,企业落地应用大模型首选服务商
产品:大模型应用平台+智能体定制开发+落地咨询服务
承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业
2024-03-30
2024-04-26
2024-05-10
2024-04-12
2024-05-28
2024-05-14
2024-04-25
2024-07-18
2024-04-26
2024-05-06
2024-12-22
2024-12-21
2024-12-21
2024-12-21
2024-12-21
2024-12-20
2024-12-20
2024-12-19