文章目录
- RAG解释
- 混合检索
- 重排序Rerank
- 为什么需要Rerank
- HNSW带来的随机性问题
- 当前大模型处理长输入的水平依然不够
- 大模型如何处理长输入?
- 重要信息位置为什么会影响大模型的效果
- LangChain的解决方案-检索后重新排序文档
- 召回模式
- N选1召回模式
- 多路召回模式
- 摘要
在RAG中,我们通常在数以万计甚至数以十亿计的海量文本文件里进行语义搜索。为了保证大规模文档情况下的快速检索,我们通常采取 向量检索,就是把文本转换为向量,然后放置在向量空间中,使用 余弦相似性等度量来比较它们与query向量的接近程度。
RAG解释
向量检索为核心的 RAG 架构已成为解决大模型获取最新外部知识,同时解决其生成幻觉问题时的主流技术框架,并且已在相当多的应用场景中落地实践。
开发者可以利用该技术低成本地构建一个 AI 智能客服、企业智能知识库、AI 搜索引擎等,通过自然语言输入与各类知识组织形式进行对话。以一个有代表性的 RAG 应用为例:
当用户提问时 “美国总统是谁?” 时,系统并不是将问题直接交给大模型来回答,而是先将用户问题在知识库中(如下图中的维基百科)进行向量搜索,通过语义相似度匹配的方式查询到相关的内容(拜登是美国现任第46届总统…),然后再将用户问题和搜索到的相关知识提供给大模型,使得大模型获得足够完备的知识来回答问题,以此获得更可靠的问答结果。
RAG 系统所做的事情:帮助大模型临时性地获得他所不具备的外部知识,允许它在回答问题之前先找答案。
混合检索
RAG 检索环节中的主流方法是向量检索,即语义相关度匹配的方式。技术原理是通过将外部知识库的文档先拆分为语义完整的段落或句子,并将其转换(Embedding)为计算机能够理解的一串数字表达(多维向量),同时对用户问题进行同样的转换操作。
计算机能够发现用户问题与句子之间细微的语义相关性,比如 “猫追逐老鼠” 和 “小猫捕猎老鼠” 的语义相关度会高于 “猫追逐老鼠” 和 “我喜欢吃火腿” 之间的相关度。在将相关度最高的文本内容查找到后,RAG 系统会将其作为用户问题的上下文一起提供给大模型,帮助大模型回答问题。
除了能够实现复杂语义的文本查找,向量检索还有其他的优势:
- 相近语义理解(如老鼠/捕鼠器/奶酪,谷歌/必应/搜索引擎)
- 多语言理解(跨语言理解,如输入中文匹配英文)
- 多模态理解(支持文本、图像、音视频等的相似匹配)
- 容错性(处理拼写错误、模糊的描述)
虽然向量检索在以上情景中具有明显优势,但有某些情况效果不佳。比如:
- 搜索一个人或物体的名字(例如,马斯克,iPhone 15)
- 搜索缩写词或短语(例如,RAG,RLHF)
- 搜索 ID(例如,
gpt-3.5-turbo
,titan-xlarge-v1.01
)
而上面这些的缺点恰恰都是传统关键词搜索的优势所在,传统关键词搜索擅长:
- 精确匹配(如产品名称、姓名、产品编号)
- 少量字符的匹配(通过少量字符进行向量检索时效果非常不好,但很多用户恰恰习惯只输入几个关键词)
- 倾向低频词汇的匹配(低频词汇往往承载了语言中的重要意义,比如“你想跟我去喝咖啡吗?”这句话中的分词,“喝”“咖啡”会比“你”“想”“吗”在句子中承载更重要的含义)
对于大多数文本搜索的情景,首要的是确保潜在最相关结果能够出现在候选结果中。向量检索和关键词检索在检索领域各有其优势。混合搜索正是结合了这两种搜索技术的优点,同时弥补了两方的缺点。
在混合检索中,你需要在数据库中提前建立向量索引和关键词索引,在用户问题输入时,分别通过两种检索器在文档中检索出最相关的文本。
不同的检索系统各自擅长寻找文本(段落、语句、词汇)之间不同的细微联系,这包括了精确关系、语义关系、主题关系、结构关系、实体关系、时间关系、事件关系等。可以说没有任何一种检索模式能够适用全部的情景。混合检索通过多个检索系统的组合,实现了多个检索技术之间的互补。
向量检索,通过生成查询嵌入并查询与其向量表示最相似的文本分段。
全文检索,索引文档中的所有词汇,从而允许用户查询任意词汇,并返回包含这些词汇的文本片段。
混合检索,同时执行全文检索和向量检索,并应用重排序步骤,从两类查询结果中选择匹配用户问题的最佳结果,需配置 Rerank 模型 API。
重排序Rerank
混合检索能够结合不同检索技术的优势获得更好的召回结果,但在不同检索模式下的查询结果需要进行合并和归一化(将数据转换为统一的标准范围或分布,以便更好地进行比较、分析和处理),然后再一起提供给大模型。这时候我们需要引入一个评分系统:重排序模型
重排序模型通过将候选文档列表与用户问题语义匹配度进行重新排序,从而改进语义排序的结果。
在大多数情况下,在重排序之前会有一次前置检索,这是由于计算查询与数百万个文档之间的相关性得分将会非常低效。所以,重排序一般都放在搜索流程的最后阶段,非常适合用于合并和排序来自不同检索系统的结果。
重排序并不是搜索技术的替代品,而是一种用于增强现有检索系统的辅助工具。它最大的优势是不仅提供了一种简单且低复杂度的方法来改善搜索结果,允许用户将语义相关性纳入现有的搜索系统中,而且无需进行重大的基础设施修改。
为什么需要Rerank
看了elasticsearch的相似度算法,es用的是KNN算法(开始以为是暴力搜索),但仔细看了一下,在es8的相似度检索中,用的其实是基于HNSW(分层的最小世界导航算法),HNSW是有能力在几毫秒内从数百万个数据点中找到最近邻的。
HNSW带来的随机性问题
我们想象这么一个场景:你昨天刚在其他地方看到过一本新书,你想在图书馆找到类似的书。K-近邻(KNN)算法的逻辑是浏览书架上的每一本书,并将它们从最相似到最不相似的顺序排列,以确定最相似的书(最有可能是你昨天看过的那本)。这也就是我们常说的暴力搜索,你有耐心做这么麻烦的工作吗?相反,如果我们对图书馆中的图书进行预排序和索引,要找到与你昨天看过的新书相似的书,你所需要做的就是去正确的楼层,正确的区域,正确的通道找到相似的书。
此外,你通常不需要对前10本相似的书进行精确排名,比如100%、99%或95%的匹配度,而是通通先拿回来。这就是近似近邻(ANN的思想。你应该注意到了,这里已经出现了一些随机性——不做匹配分数的排名。但是这些准确度上的损失是为了让检索效率更快,为了显著降低计算成本,它牺牲了找到绝对最近邻的保证,这算是在计算效率和准确性之间取得平衡。
ANN算法目前主要有三种:
-
基于图的算法创建数据的图表示,最主要的就是分层可导航小世界图算法(HNSW)。
-
基于哈希的算法:流行的算法包括:位置敏感哈希(LSH)、多索引哈希(MIH);
-
基于树的算法:流行的是kd树、球树和随机投影树(RP树)。对于低维空间(≤10),基于树的算法是非常有效的。
HNSW借鉴了跳表(Skip List)的思路。跳表是一种数据结构,用于维护一组已排序的元素,并允许进行高效的搜索、插入和删除操作。如果对Skip List感兴趣的话,可以参考之前写的一篇:实现跳表高效增删改查
当前大模型处理长输入的水平依然不够
在大语言模型(Large Language Model,LLM)中,”上下文长度”是指大语言模型在生成预测时考虑的输入文本的长度。上下文长度对于语言模型的性能有着重要的影响。一般来说,更长的上下文长度可以让模型看到更多的信息,从而做出更准确的预测。
然而,处理更长的上下文也需要更多的计算资源,这可能会限制模型的实用性。而且,在实际应用中,大多数模型在处理长输入的时候都发生了性能显著下降的情况。
大模型如何处理长输入?
大语言模型通常使用Transformer实现,但对于长序列的处理效果较差(例如,自注意力的复杂度与输入序列长度呈二次关系)。因此,大语言模型通常在相对较小的上下文窗口中进行训练。
最近硬件的改进使得语言模型具有更大的上下文窗口,但如何在执行下游任务时使用这些扩展上下文的方式仍不清楚。
为此,作者设计了2个实验来研究大模型如何使用上下文信息。这两种任务都需要模型识别输入上下文中的相关信息。
- 多文档问题回答(Multi-Document Question Answering,MDQA):在这个任务中,模型需要从多个文档中找到问题的答案。这个任务被设计成需要模型理解和记住长上下文中的信息。
- 键值检索(Key-Value Retrieval,KVR):在这个任务中,模型需要从一系列键值对中找到与给定问题相关的值。这个任务被设计成需要模型理解和记住长上下文中的信息。
在这两个任务中,作者们都设计了一系列实验,以测试模型在处理长上下文时的性能。他们测试了不同的模型,包括BERT、RoBERTa、GPT-3等,并且也测试了不同长度的上下文,以了解上下文长度对模型性能的影响。
最终的结果采用Sebastian Raschka老师的一幅图展示:
在大语言模型的输入上下文中改变相关信息的位置(即回答输入问题的段落的位置)会导致一个U形性能曲线——模型更擅长使用出现在输入上下文的开头或结尾的相关信息,而当模型需要访问和使用位于输入上下文中部的信息时,性能显著下降。例如,当将相关信息放置在输入上下文的中间时,GPT-3.5-Turbo在多文档问答任务上的开放式表现低于在没有任何文档的情况下的预测性能!也就是说,如果输入数据的重要信息没有出现在开始或者结尾位置,大模型可能会出现找不到答案的情况!
重要信息位置为什么会影响大模型的效果
Lightning AI的首席AI教育家, UW-Madison大学前统计学教授Sebastian Raschka也讨论了这个问题,给了他的一个观点。
Sebastian Raschka认为,基于transformer的大语言模型架构本身应该不会出现这种偏差。反而是基于RNN的模型可能会因为序列过长出现这种问题(因为RNN是按照序列处理的,早先处理的内容可能会被遗忘。而transformer是按照位置编码,一次性输入,没有先后概念)。因此,他怀疑可能是大多数人类写的文章内容习惯把重要的信息放在文章的开头和结尾,影响了大模型的训练结果。
这也是猜测,也有人认为,设计另一个类似论文的实验,但是测试代码类的问题可能就会看出是不是这样。因为,代码的执行是有逻辑的,不会出现把重要的信息放在文本的开头和结尾这种逻辑。
LangChain的解决方案-检索后重新排序文档
为了解决这个问题,LangChain提出了一种创新的方法,即在检索后重新排序文档。这种方法的关键思想是将最相似的文档放在顶部,然后将接下来的几个文档放在底部,将最不相似的文档放在中间。这样,最不相似的文档将位于LLMs通常容易迷失的位置。最重要的是,LangChain最新的LongContextReorder自动执行这个操作,使其非常便捷。
召回模式
N选1召回模式
根据用户意图和数据集描述,由 Agent 自主判断选择最匹配的单个数据集来查询相关文本,适合数据集区分度大且数据集数量偏少的应用。N选1召回模式依赖模型的推理能力,模型需要根据用户意图,选择最符合的一个数据集召回。在推理选择数据集时,数据集将作为 Agent 的工具类通过意图推理来进行选择,工具描述即数据集描述。
在用户上传数据集时,系统将自动为数据集创建一个摘要式的描述。为了在该模式下获得最佳的召回效果,你可以在“数据集->设置->数据集描述”中查看到系统默认创建的摘要描述,并检查该内容是否可以清晰的概括数据集的内容。
以下是 N 选 1 召回模式的技术流程图:
因此,在查询数据集过多,或者数据集描述差异较小时,该模式的保证召回的效果会受到影响。该模式更适用于数据集数量较少的应用。
多路召回模式
根据用户意图同时匹配所有数据集,从多路数据集查询相关文本片段,经过重排序步骤,从多路查询结果中选择匹配用户问题的最佳结果,需配置 Rerank 模型 API。在多路召回模式下,检索器会在所有与应用关联的数据集中去检索与用户问题相关的文本内容,并将多路召回的相关文档结果合并,并通过 Rerank 模型对检索召回的文档进行语义重排序。
以下是多路召回模式的技术流程图:
由于多路召回模式不依赖于模型的推理能力或数据集描述,该模式在多数据集检索时能够获得质量更高的召回效果,除此之外加入 Rerank 步骤也能有效改进文档召回效果。因此,当创建的知识库问答应用关联了多个数据集时,我们更推荐将召回模式配置为多路召回。
摘要
https://docs.dify.ai/v/zh-hans/learn-more/extended-reading/retrieval-augment/retrieval
https://luxiangdong.com/2023/11/06/rerank/#
https://www.datalearner.com/blog/1051688829605194