检索与重排序

语义搜索中,我们展示了如何使用SentenceTransformer为查询、句子和段落计算嵌入,以及如何利用这些嵌入进行语义搜索。

对于复杂的搜索任务,例如问答检索,通过使用**检索与重排序(Retrieve & Re-Rank)**可以显著提升搜索效果。

检索与重排序流程

以下信息检索/问答检索流程表现非常出色。本文中提供了所有组件并进行了解释:

信息检索

给定一个搜索查询,我们首先使用一个检索系统,该系统检索出一个较大的列表,例如100个可能的相关结果。对于检索,我们可以使用词汇搜索,例如使用Elasticsearch这样的向量引擎,或者我们也可以使用双编码器进行密集检索。然而,检索系统可能会检索到与搜索查询不太相关的文档。因此,在第二阶段,我们使用基于交叉编码器(Cross-Encoder)重排序器,为给定搜索查询的所有候选文档评分。输出将是一个我们呈现给用户的排序列表。

检索:双编码器

对于候选集的检索,我们可以使用词汇搜索(例如Elasticsearch),或者我们也可以使用Sentence Transformers中实现的双编码器。

词汇搜索在文档集合中寻找查询词的字面匹配。它不会识别同义词、缩写词或拼写变体。相比之下,语义搜索(或密集检索)将搜索查询编码到向量空间,并检索在向量空间中接近的文档嵌入。

语义搜索

语义搜索克服了词汇搜索的不足,能够识别同义词和缩写词。请查看语义搜索文章,了解实现语义搜索的不同选项。

重排序器:交叉编码器

检索器必须对包含数百万条目的文档集合高效运行。然而,它可能返回不相关的候选文档。基于交叉编码器的重排序器可以显著提升最终结果的用户体验。查询和一个可能的文档同时传递给transformer网络,然后输出一个介于0和1之间的分数,指示该文档对于给定查询的相关性。

交叉编码器

交叉编码器的优势在于其更高的性能,因为它们在查询和文档之间执行注意力机制。对数千或数百万个(查询,文档)对进行评分会相当慢。因此,我们使用检索器创建一个例如100个可能的候选集,然后由交叉编码器进行重排序。

示例脚本

  • retrieve_rerank_simple_wikipedia.ipynb [ Colab版本 ]: 此脚本使用较小的简单英语维基百科作为文档集合,提供用户问题/搜索查询的答案。首先,我们将所有维基百科文章分割成段落,并使用双编码器对其进行编码。当输入新的查询/问题时,它由相同的双编码器编码,并检索与查询具有最高余弦相似度的段落(参见语义搜索)。接下来,检索到的候选文档由交叉编码器重排序器评分,并呈现给用户得分最高的5个段落。

  • in_document_search_crossencoder.py: 如果你只有一小部分段落,我们不进行检索阶段。例如,如果你想在单个文档内进行搜索。在这个例子中,我们取关于欧洲的维基百科文章并将其分割成段落。然后,搜索查询/问题和所有段落使用交叉编码器重排序器进行评分。返回与查询最相关的段落。

预训练的双编码器(检索)

双编码器独立地为你的段落和搜索查询生成嵌入。你可以这样使用它:

from sentence_transformers import SentenceTransformer

model = SentenceTransformer("multi-qa-mpnet-base-dot-v1")

docs = [
    "我的第一段话。里面包含了一些信息",
    "Python是一种编程语言。",
]
document_embeddings = model.encode(docs)

query = "Python是什么?"
query_embedding = model.encode(query)

有关如何比较嵌入的更多详细信息,请参阅语义搜索

我们提供了基于以下内容的预训练模型:

  • MS MARCO: 来自必应搜索引擎的50万条真实用户查询。参见MS MARCO模型

预训练的交叉编码器(重排序器)

有关预训练的交叉编码器模型,请参阅:MS MARCO交叉编码器