Reranking for Better Search
TL;DR · AI 摘要
Reranking for Better Search - Qdrant Improve Semantic Search with Reranking using Qdrant In Retrieval-Augmented Generati...
核心要点
- 主题聚焦:Reranking for Better Search
- 来源:Qdrant,建议结合原文判断细节。
- AI 分析暂不可用,本条为保底评分与摘要。
通过重排序提升搜索效果 - Qdrant
使用 Qdrant 重排序提升语义搜索效果
在检索增强生成(Retrieval-Augmented Generation,RAG)系统中,不相关或缺失的信息可能会影响模型生成准确、有意义输出的能力。确保为语言模型提供最相关、上下文丰富的文档的最佳方式之一是使用重排序。这是一种革命性的方法。
在本指南中,我们将探讨如何在 Qdrant 中使用重排序来提升搜索结果的相关性。我们将通过一个简单的用例,演示如何利用 Cohere Rerank 模型。如需了解更高级的结合 ColBERT 重排序与混合搜索的方法,请参阅 [结合重排序的混合搜索](#)。
准备好了吗?让我们开始吧。
重排序原理
本节分为几个关键部分,帮助您轻松理解重排序的背景、机制和重要性。
背景
在搜索系统中,精确率(precision)和召回率(recall)是成功的关键指标。但它们具体意味着什么?精确率告诉我们检索结果中有多少是真正相关的,而召回率衡量我们捕捉到所有相关结果的全面性。简单来说:
稀疏向量搜索通常能提供较高的精确率,因为它们擅长找到精确匹配。但问题是,当相关文档中不包含这些精确关键词时,召回率可能会下降。另一方面,密集向量搜索在召回率方面表现优异,因为它们能捕捉查询的更广泛语义含义。然而,这可能导致精确率降低,出现仅松散相关的结果。
这就是重排序发挥作用的地方。它首先通过广泛抓取文档(提供高召回率),然后根据相关性评分重新排序候选结果,从而在不丢失广泛理解的前提下提升精确率。通常,重排序后我们只保留前 K 个候选结果,以聚焦于最相关的结果。
工作原理
想象一下:你走进一个巨大的图书馆,请求一本关于“气候变化”的书。图书管理员拿出十几本书给你——有些是科学论文,有些是个人随笔,甚至有一本小说。虽然它们都相关,但你首先拿到的却是小说。这显然不是你期望的结果,对吗?
现在,想象一位更聪明、更直观的图书管理员,真正了解你的需求。这位图书管理员能准确判断哪些书籍最具影响力、最新颖,并且完全符合你的需求。重排序正是为搜索结果所做的类似事情——它不会随意抓取相关文档,而是智能地重新排序,让最相关的结果排在列表最前面。这就像拥有一个在你开口之前就完全了解你需求的图书管理员!
重排序模型优先选择更优结果的示意图。
要成为这样聪明、直观的图书管理员,算法需要学习如何理解你的查询和检索到的文档。它必须有效评估它们之间的关系,从而精准地为你提供所需内容。
重排序模型的工作方式取决于其类型,这将在后面讨论,但总体而言,它们会为每对文档-查询计算一个相关性分数。与提前将每段文本压缩为单一向量的嵌入模型不同,大多数重排序器在计算该分数时会同时查看查询和文档。结果?精确性。但存在权衡——重排序可能很慢。处理数百万文档可能需要数小时,这就是为什么重排序器专注于优化结果,而不是遍历整个文档集合。
重排序器有不同种类,每种都有其独特优势。让我们逐一分析:
- 交叉编码模型:这些模型通过使用分类系统来评估数据对(如句子或文档)来提升重排序效果。它们输出一个相关性分数,显示文档与查询的匹配程度。但问题在于,交叉编码器需要同时接收查询和文档,因此无法单独处理独立文档或查询。
- 多向量重排序器(如 ColBERT):这些模型采用更高效的方式。它们分别对查询和文档进行编码,之后才进行比较,从而降低计算负担。这意味着文档表示可以预先计算,加快检索速度。
- 大型语言模型(LLMs)作为重排序器:LLM 接收查询和候选文档,并被指示对每个文档进行评分、成对比较文档,或按相关性顺序返回整个列表。像 TypeSafe 的 Jev 这样训练用于用概率而非生成文本回答此类问题的模型,也可作为高效的重排序器使用。
每种重排序器都有其独特的方式,确保您快速获得最相关、最精准的搜索结果。
重要性
在上一节中,我们探讨了重排序的背景和机制,现在让我们谈谈使用重排序带来的三大优势:
- 提升搜索准确性:重排序的核心在于让搜索结果更清晰、更相关。在初步排序后,重排序器会基于更深入的分析重新排列结果,确保最关键的信息优先呈现。
- 减少信息过载:如果您感觉淹没在海量搜索结果中,重排序器可以解救您。它们过滤并优化信息洪流,让您精准获取所需内容,避免压力感。这使搜索体验更聚焦、更有序。
- 平衡速度与相关性:第一阶段检索和第二阶段重排序在速度与准确性之间达到完美平衡。虽然第二阶段可能因计算能力而略微增加延迟,但这种权衡是值得的。最终,您将获得高度相关的结果,而这才是最重要的。
现在您了解了重排序为何如此重要,让我们深入探讨其实际应用。
使用重排序实现向量搜索
在本节中,您将看到如何使用 Cohere 实现带重排序的向量搜索。但在此之前,让我们先进行概述。
概述
典型的搜索系统分为两个主要阶段:数据摄入和检索。将数据摄入视为数据准备并加载到系统中的过程,而检索则是魔法发生的地方——您的查询从中提取最相关的文档。
以下是翻译后的 Markdown 内容:
查看下方的架构图,了解这些阶段是如何协同工作的。
搜索系统的两个关键阶段:数据摄入(Ingestion)和检索过程(Retrieval Process)
#### 数据摄入阶段(Ingestion Stage)
- 文档(Documents):一切由此开始。系统接收需要进行搜索预处理的原始数据或文档,这是你的初始输入。
- 嵌入向量(Embeddings):接下来,这些文档会被转换为稀疏或密集的嵌入向量,本质上是向量表示形式。这些向量能够捕捉文本的深层语义,使系统能够基于语义含义执行智能、高效的搜索和比较。
- 向量数据库(Vector Database):当文档被转换为嵌入向量后,它们会被存储到向量数据库中——这相当于实现快速、精确相似性搜索的核心引擎。在这里,我们将看到 Qdrant 向量搜索引擎的能力。
#### 检索阶段(Retrieval Stage)
- 用户查询(User’s Query):现在我们进入检索阶段。用户提交查询,需要将该查询与存储的文档进行匹配。
- 嵌入向量(Embeddings):与文档处理方式相同,用户的查询也会被转换为稀疏或密集的嵌入向量。这使系统能够将查询的语义与存储文档的语义进行比较。
- 向量搜索(Vector Search):系统通过将查询的嵌入向量与向量数据库中的向量进行比较,找到最相关的文档并返回最佳匹配结果。
- 重排序(Rerank):当初步结果返回后,重排序过程会启动以确保最佳结果排在最前面。我们将使用 Cohere 的 rerank-v4.0-pro 模型。该模型支持多语言,可处理高达 32,000 个 token,为其提供了丰富的上下文处理能力。
实现(Implementation)
现在是时候深入实际实现部分了。
#### 环境搭建(Setup)
要跟随本教程,你需要以下关键工具:
- Qdrant 的 Python 客户端
- Cohere
使用 Python 包管理器一次性安装所有依赖:
pip install qdrant-client cohere现在,我们一次性导入所有必要组件:
from
qdrant_client
import
QdrantClient
from
qdrant_client.models
import
Distance
,
VectorParams
,
PointStruct
import
cohereQdrant 是一个功能强大的向量相似性搜索引擎,它为你提供一个开箱即用的服务,通过简单易用的 API 实现数据的存储、搜索和管理。你可以通过本地或云端部署与 Qdrant 交互;这里我们选择云端部署。
#### Qdrant 云端部署步骤(Steps to Set Up Qdrant Cloud)
- 注册账号(Sign Up):前往 Qdrant 官网,使用邮箱、Google 或 GitHub 凭证注册云账号。
- 创建第一个集群(Create Your First Cluster):登录后,进入概览页面,按照“创建第一个集群”部分的引导步骤操作。
- 获取 API 密钥(Get Your API Key):创建集群后,系统将生成一个 API 密钥。该密钥将允许你通过 Python 客户端与集群进行交互。
- 查看集群(Check Your Cluster):你的新集群将显示在“集群”部分。从此处,你就可以开始与数据进行交互了。
添加你的 API 密钥。这将使你的 Python 客户端能够连接到 Qdrant 和 Cohere。
client
=
QdrantClient
(
url
=
"<ADD-URL>"
,
api_key
=
"<API-KEY>"
,
)
print
(
client
.
get_collections
())接下来,我们为重排序设置 Cohere。登录你的 Cohere 账户,生成 API 密钥,并按如下方式添加:
co
=
cohere
.
Client
(
"<API-KEY>"
)数据摄入包含三个关键部分:创建集合、将文档转换为嵌入向量,以及插入数据。让我们逐步解析:
#### 创建集合
集合本质上是可搜索的命名点(带数据的向量)分组。集合中的所有向量需要具有相同维度,并使用统一的距离度量方式进行比较。创建方式如下:
client
.
create_collection
(
collection_name
=
"basic-search-rerank"
,
vectors_config
=
VectorParams
(
size
=
1024
,
distance
=
Distance
.
DOT
),
)此处将向量维度设置为1024以匹配我们的密集嵌入向量,并采用点积作为距离度量方式——这在向量归一化后能完美捕捉向量相似性。
#### 文档到嵌入向量
让我们准备一些示例数据。以下是一个查询和几个演示文档。最后两个文档使用了机器学习以外的"特征缩放"概念,用于展示重排序能捕捉到的场景:
query
=
"What is the purpose of feature scaling in machine learning?"示例文档:
文档
=
[
"在机器学习中,特征缩放是标准化自变量或特征范围的过程。其目标是确保所有特征对模型的贡献相同,特别是在支持向量机(SVM)或k近邻算法等依赖距离计算的算法中。"
,
"特征缩放常用于数据预处理,以确保特征处于相同量级。这对基于梯度下降的算法尤为重要,因为量级较大的特征可能会不成比例地影响损失函数。"
,
"在数据科学中,特征提取是将原始数据转换为可用于预测模型的工程特征集的过程。特征缩放与之相关,但侧重于调整这些特征的数值范围。"
,
"无监督学习算法(如聚类方法)可能受益于特征缩放,因为它能确保数值范围较大的特征不会主导学习过程。"
,
"数据科学中常见的数据预处理技术是特征选择。与特征缩放不同,特征选择旨在减少模型使用的输入变量数量以避免过拟合。"
,
"主成分分析(PCA)是数据科学中用于降低变量数量的降维技术。当数据经过标准化后效果最佳,因为PCA依赖方差,而不同量级的特征可能导致方差偏差。"
,
"最小-最大缩放是一种常见特征缩放技术,通常将特征转换到固定范围[0,1]。当数据分布不符合正态分布时,该方法特别有用。"
,
"标准化(Z-score归一化)是另一种技术,将特征转换为均值为0、标准差为1的分布。该方法对符合正态分布的数据效果显著。"
,
"在使用依赖距离的算法(如k均值聚类)时,特征缩放至关重要,因为未缩放的特征可能导致误导性结果。"
,
"缩放可以通过防止不同特征量级影响损失函数曲率来提高梯度下降算法的收敛速度。"
,
"在深度学习中,特征缩放有助于稳定学习过程,在训练期间实现更好的性能和更快的收敛。"
,
"鲁棒缩放是另一种方法,使用中位数和四分位距来缩放特征,对异常值的敏感度较低。"
,
"在处理时间序列数据时,特征缩放有助于标准化输入数据,提升模型在不同时间段的表现。"
,
"归一化常用于图像处理,将像素值缩放到增强计算机视觉任务模型性能的范围。"
,
"当特征具有不同计量单位(如厘米的身高和千克的体重)时,特征缩放尤为重要。"
,
"在推荐系统中,对用户评分等特征进行缩放可以提升模型发现相似用户或物品的能力。"
,
"降维技术(如t-SNE和UMAP)通常需要特征缩放,以有效将高维数据可视化到低维空间。"
,
"异常检测技术也可以从特征缩放中受益,因为未缩放的特征可能因极端值而产生偏差。"
,"数据预处理步骤(包括特征缩放)会显著影响机器学习模型的性能,因此是建模流程中的关键环节。" , "在集成方法(如随机森林)中,特征缩放并非严格必要,但仍然可以提升特征重要性比较的可解释性。" , "特征缩放需要在训练集和测试集上保持一致的应用,以避免数据泄露并确保模型评估的可靠性。" , "在自然语言处理(NLP)中,当处理来自文本数据的数值特征(如词频或词项频率)时,特征缩放可能具有实际价值。" , "对数变换是一种可用于处理偏态数据的技术,能够稳定方差并使数据更适用于缩放处理。" , "机器学习中的数据增强技术也可能包含缩放操作,以确保训练数据集的一致性,特别是在计算机视觉任务中。" , "在图像编辑软件中,特征缩放的目的是在不扭曲照片中选定特征(如人脸或标志)的前提下调整其尺寸。" , "对于初创公司而言,特征缩放的目的是让产品功能能够服务于数百万用户,而非仅限于几百名用户。"
我们将使用 Cohere 的 embed-english-v3.0 模型为这些文档生成嵌入向量,该模型生成 1024 维向量:
model
=
"embed-english-v3.0"
doc_embeddings
=
co
.
embed
(
texts
=
documents
,
model
=
model
,
input_type
=
"search_document"
,
embedding_types
=
[
'float'
])它使用 embed-english-v3.0 模型,将输入类型设置为 "search_document",并要求以浮点格式返回嵌入向量。这些嵌入向量将存储在 doc_embeddings 中,随时可以使用。
#### 插入数据
我们需要将这些密集嵌入向量转换为 Qdrant 可以处理的格式,这就是 Points 的作用。Points 是 Qdrant 的基本构建块——它们是由向量(嵌入向量)和可选有效载荷(如文档文本)组成的记录。
这是我们将这些嵌入向量转换为 Points 的方法:
points
=
[]
for
idx
,
(
embedding
,
doc
)
in
enumerate
(
zip
(
doc_embeddings
.
embeddings
.
float_
,
documents
)):
point
=
PointStruct
(
id
=
idx
,
vector
=
embedding
,
payload
=
{
"document"
:
doc
}
)
points
.
append
(
point
)这里发生了什么?我们正在从嵌入向量构建 Points 列表:
- 首先,我们从一个空列表开始。
- 然后,使用 enumerate() 同时遍历 doc_embeddings 和 documents,途中获取索引(idx)。
- 对于每对(一个嵌入向量及其对应的文档),我们创建一个 PointStruct。每个点获得:一个 id(来自 idx)。一个向量(嵌入向量)。一个有效载荷(实际文档文本)。
- 每个 Point 都被添加到我们的列表中。
完成之后,是时候使用 upsert() 函数将这些 Points 插入到你的 Qdrant 集合中了:
operation_info
=
client
.
upsert
(
collection_name
=
"basic-search-rerank"
,
points
=
points
)现在你的嵌入向量已经在 Qdrant 中准备就绪,可以为搜索提供支持。
#### 检索
这里的前几步与我们之前进行的摄入过程类似——就像之前一样,我们需要将查询转换为嵌入向量:
query_embeddings
=
co
.
embed
(
texts
=
[
query
],
model
=
model
,
input_type
=
"search_query"
,
embedding_types
=
[
'float'
])之后,我们将使用向量搜索检索结果,并对结果进行重排序。
#### 向量搜索
此代码片段使用查询嵌入向量从你的 Qdrant 集合中获取最相关的前 10 个点:
search_result
=
client
.
query_points
(
collection_name
=
"basic-search-rerank"
,
query
=
query_embeddings
.
embeddings
.
float_
[
0
],
limit
=
10
)
.
points它是这样工作的:我们使用 query_points 方法在 "basic-search-rerank" 集合中进行搜索。它将查询嵌入向量(query_embeddings 中的第一个嵌入向量)与所有文档嵌入向量进行比较,提取出最接近的 10 个匹配项。匹配的点将存储在 search_result 中。
这是向量搜索结果的预览:
| ID | 文档 | 分数 | |----|------|------| | 0 | 在机器学习中,特征缩放是归一化特征范围的过程… | 0.81 | | 1 | 特征缩放通常用于数据预处理,以确保特征处于… | 0.76 | | 10 | 在深度学习中,特征缩放有助于稳定学习过程,允许… | 0.75 | | 24 | 在图像编辑软件中,特征缩放的目的是调整所选特征的大小… | 0.70 | | 3 | 无监督学习算法(如聚类方法)可能从特征… | 0.68 | | 25 | 对于初创公司而言,特征缩放的目的是使产品功能适用于… | 0.67 | | 19 | | |
在集成方法中,如随机森林,特征缩放并非严格必要,但…
2
在数据科学中,特征提取是将原始数据转换为一组…
0.65
12
在处理时间序列数据时,特征缩放有助于标准化输入…
18
数据预处理步骤(包括特征缩放)可能会显著影响模型…
0.64
现在,基于这些坚实的结果基础,是时候通过重排序进一步优化它们了。
#### 重排序
这段代码会从搜索结果中提取文档,并根据你的查询对它们进行重新排序,确保最相关的结果排在最前面。
首先,我们从搜索结果中提取文档。然后使用Cohere的重排序模型对结果进行优化:
document_list
=
[
point
.
payload
[
'document'
]
for
point
in
search_result
]
rerank_results
=
co
.
rerank
(
model
=
"rerank-v4.0-pro"
,
query
=
query
,
documents
=
document_list
,
top_n
=
5
,
)这里发生了什么?第一行代码通过从每个搜索结果点中提取“document”字段来构建文档列表。然后,我们将这个列表与原始查询一起传递给Cohere的重排序方法。使用rerank-v4.0-pro模型,它会重新排列文档并返回与查询相关性最高的前5个结果。
每个结果的索引对应document_list中文档的位置,因此你可以用它来查找原始点并打印其ID、得分和文本:
for
result
in
rerank_results
.
results
:
point
=
search_result
[
result
.
index
]
print
(
point
.
id
,
round
(
result
.
relevance_score
,
2
),
point
.
payload
[
"document"
])这是重排序后的结果表格,包含新的顺序及其相关性得分:
相关性得分
在机器学习中,特征缩放是将独立变量或特征的范围进行标准化的过程。该…
0.96
特征缩放常用于数据预处理,以确保特征处于同一量级。这有助于…
0.92
在深度学习中,特征缩放有助于稳定学习过程,从而实现更好的性能和更快的…
0.86
无监督学习算法(如聚类方法)可能受益于特征缩放,因为它确保了…
0.85
在处理时间序列数据时,特征缩放有助于标准化输入数据,提升模型…
0.77
向量搜索将一个使用“特征缩放”但指图像编辑(24)的文档排在第四位。重排序器同时读取查询和文档,识别到它与机器学习无关,因此被排除在前五之外。
结论
重排序是增强RAG系统搜索结果相关性和精确性的有效方法。但这也伴随着权衡:每个查询都需要向重排序器发出额外请求,这会增加延迟,并且使用托管模型(如Cohere重排序)会产生基于使用量的成本。
本指南展示了重排序如何提升精确度,提供更清晰且富有上下文的结果。现在你已经掌握了构建能带来有意义且具有影响力用户体验的搜索系统所需的知识!