1. 搜索索引
(1)向量存储索引
- 最原始的实现是使用平面索引 — 查询向量和所有块向量之间的暴力计算距离。
- 根据索引选择、数据和搜索需求,还可以存储元数据,并使用元数据过滤器来按照日期或来源等条件进行信息检索。
- LlamaIndex 支持多种向量存储索引,同时也兼容其他简单的索引类型,如列表索引、树索引和关键词表索引。
(2)分层索引
- 在大型数据库的情况下,一个有效的方法是创建两个索引 —— 一个由摘要组成,另一个由文档块组成,然后分两步进行搜索,首先通过摘要过滤掉相关文档,然后只在这个相关组内搜索。
(3)假设性问题和 HyDE
- 让 LLM 为每个块生成一个问题,并将这些问题嵌入到向量中,在运行时对这个问题向量的索引执行查询搜索(将块向量替换为索引中的问题向量),然后在检索后路由到原始文本块并将它们作为 LLM 获取答案的上下文发送。这种方法提高了搜索质量,因为与实际块相比,查询和假设问题之间的语义相似性更高。
- HyDE 的反向逻辑方法——你要求 LLM 在给定查询的情况下生成一个假设的响应,然后将其向量与查询向量一起使用来提高搜索质量。
(4)内容增强
- 语句窗口检索器
在此方案中,文档中的每个句子都是单独嵌入的,这为上下文余弦距离搜索提供了极大的查询准确性。
为了在获取最相关的单个句子后更好地推理找到的上下文,我们将上下文窗口扩展为检索到的句子前后的 k 个句子,然后将这个扩展的上下文发送到 LLM。 - 自动合并检索器(或父文档检索器)
搜索更精细的信息片段,然后在在LLM 进行推理之前扩展上下文窗口。文档被拆分为较小的子块,这些子块和较大的父块有引用关系。
首先在检索过程中获取较小的块,然后如果前 k 个检索到的块中有超过 n 个块链接到同一个父节点(较大的块),我们将这个父节点替换成给 LLM 的上下文。
(5)融合检索或混合搜索
- 结合传统的基于关键字的搜索(稀疏检索算法,如 tf-idf 或搜索行业标准 BM25)和现代语义或向量搜索,并将其结果组合在一个检索结果中。
这里唯一的关键是如何组合不同相似度分数的检索结果。这个问题通常通过 Reciprocal Rank Fusion算法来解决,该算法能有效地对检索结果进行重新排序,以得到最终的输出结果。
- RAG-Fusion’s 工作步骤:
查询语句的相关性复制:通过LLM将用户的查询转换为相似但不同的查询。
并发的向量搜索:对原始查询及其新生成的同级查询执行并发的向量搜索。
智能重新排名:聚合和细化所有结果使用倒数排序融合(RRF)。
最后优中选优:将精心挑选的结果与新查询配对,引导LLM进行有针对性的查询语句输出,考虑所有查询和重新排序的结果列表。
2. 检索技术
(1)相似度检索:
包括欧氏距离、曼哈顿距离、切比雪夫距离、明氏距离和余弦相似度。
(2)关键词检索:
这是很传统的检索方式,但是有时候也很重要。实体抽取将元数据过滤,还有一种就是先把chunk做摘要,再通过关键词检索找到可能相关的chunk,增加检索效率。据说Claude.ai也是这么做的;
(3)SQL检索:
对于一些本地化的企业应用来说,SQL查询是必不可少的一步,比如销售数据,就需要先做SQL检索。
(4)图关系检索:
如果可以将很多实体变成node,把它们之间的关系变成relation,就可以利用知识之间的关系做更准确的回答。特别是针对一些多跳问题,利用图数据索引会让检索的相关度变得更高;
3. 重排序(Rerank)
引入重排序是对召回结果进行重新排序的过程,目的是为了提升问题和召回上下文的相关性,进而提高生产答案的质量。
使用重排序的原因:
(1)搜索的时候存在随机性,如果索引有数百万甚至千万的级别,那你只能牺牲一些精确度,换回时间。
(2)chunks在系统内数量很多,我们检索的维度不一定是最优的,一次检索的结果可能就会在相关度上面没有那么理想。
应对方案:
(1)增加top_k的大小,比如从原来的10个,增加到30个。然后再使用更精确的算法来做rerank,使用一一计算打分的方式,做好排序。比如30次的遍历相似度计算的时间,我们还是可以接受的。
(2)使用planB重排序,或者把组合相关度、匹配度等因素做一些重新调整,得到更符合我们业务场景的排序。
-
常见的Rerank模型如:BGE-Rerank、Cohere Rerank等。
-
在 LlamaIndex 中,有各种可用的后处理器,根据相似性分数、关键字、元数据过滤掉结果,或使用其他模型(如 LLM)、sentence-transformer 交叉编码器,Cohere 重新排名接口或者基于元数据重排它们。
因为在这一步之后,我们就会把结果送给LLM进行最终处理了,所以这一部分的结果很重要。这里面还会有一个内部的判断器来评审相关度,触发重排序。
4. 评测方法
为了衡量我们的检索系统的有效性,我们主要依赖于两个被广泛接受的指标:命中率和平均倒数排名(MRR)。
命中率: 计算在前k个检索文档中找到正确答案的查询比例。简单来说,它是关于我们的系统在前几次猜测中正确的频率。
平均倒数排名(MRR): 计算方式为进行多次召回,得到每次召回中包含答案的文本块在召回列表中的排名倒数,然后取平均。因此,如果第一个相关文档是顶部结果,则倒数排名为1;如果是第二个,倒数是1/2,以此类推。