Qdrant

How to Tune Hybrid Search in Qdrant

8.5内容质量

TL;DR · AI 摘要

混合搜索优化需先验证融合效果,RRF与DBSF在信号处理上存在本质差异,实验数据证明合理参数调整可提升搜索质量。

核心要点

  • 预调整阶段需用nDCG@10评估RRF(k=2)与单模检索的差距
  • RRF默认k=2但原论文参数为k=60,参数选择影响效果
  • DBSF通过分数尺度差异判断结果,适合存在显著分数差距的数据集

结构提纲

按章节快速跳转。

  1. 通过nDCG@10验证索引状态并建立基准线

  2. 比较dense/sparse检索与RRF(k=2)在5个数据集的nDCG@10表现

  3. 解释Qdrant默认k=2与原始论文k=60的参数差异

  4. 对比RRF基于位置的融合与DBSF基于分数尺度的融合机制

  5. 展示DBPedia-entity数据集中融合效果劣于dense检索的异常情况

  6. 建议基于数据特征选择RRF或DBSF并进行标签集验证

思维导图

用一张图看清主题之间的关系。

查看大纲文本(无障碍 / 无 JS 友好)
  • 混合搜索优化
    • 预调整检查
      • nDCG@10基准测试
    • 融合方法对比
      • RRF
        • k参数影响
      • DBSF
        • 分数尺度处理
    • 实验验证
      • 5个数据集对比分析

金句 / Highlights

值得收藏与分享的关键句。

#Qdrant#搜索优化#RRF#DBSF#混合搜索
打开原文

如何在 Qdrant 中调整混合搜索

返回搜索质量

Dylan Couzon

·

2026 年 8 月 22 日

在调整融合策略之前,请使用预调整检查来验证索引状态并建立带标签的基准线。

混合搜索会检索密集和稀疏候选列表,然后将它们融合成一个排名。密集预取查找语义相似的内容;稀疏预取查找匹配的关键词。融合会重新排序预取返回的候选项,因此同时缺失在两个列表中的文档不会出现在结果中。

确认融合优于任一预取

调整之前,请比较 k=2 且权重相等时的密集检索、稀疏检索和默认的倒数排名融合(RRF)。使用 nDCG@10 对三者进行评分,该指标会评估前 10 个结果,并对排名靠前的相关文档给予更高权重。

Qdrant 默认使用 k=2。原始 RRF 论文使用 60,这在 Qdrant 公式中对应 k=61。这种差距正是本文大部分内容所讨论的重点。

"优于最佳预取的提升" 是默认 RRF 的 nDCG@10 减去最佳单个预取的得分。"第二次预取成本" 是第二次预取在仅密集预取基础上增加的延迟中位数。

| 数据集 | 仅密集 | 仅稀疏 | RRF (k=2) | 优于最佳预取的提升 | 第二次预取成本 | |-------------|------|------|--------|----------|----------| | SciFact | 0.6239 | 0.6886 | 0.7175 | +0.0289 | +0.73 ms | | ArguAna | 0.4905 | 0.4224 | 0.5216 | +0.0311 | +1.47 ms | | WANDS | 0.6921 | 0.7098 | 0.7254 | +0.0156 | +0.60 ms | | CodeSearchNet | 0.6299 | 0.5126 | 0.6555 | +0.0256 | +0.68 ms | | DBPedia-entity | 0.4677 | 0.3857 | 0.4638 | -0.0039 | +0.64 ms |

在四个数据集中,融合都优于两个预取,且每个提升的 95% 置信区间都不包含零。DBPedia-entity 是例外:融合比密集检索低 0.0039,且其置信区间跨越零。

第二次预取还需要为每个数据点建立第二个索引和第二个向量。当它能提升你自己的标签相关性时,请保留该操作。

RRF 和 DBSF 使用不同的信号

倒数排名融合(RRF)仅使用候选项在每个预取中的位置。一个文档在排名第一时,无论它是否以较大或较小的优势击败第二名,得分都相同。基于分布的得分融合(DBSF)则为每个查询将两个列表放在同一尺度上,使用每个列表的平均得分和得分分布范围。将两个重新缩放的得分相加会将领先优势的幅度带入融合排名,而仅被一个预取检索到的文档则保留其单一的重新缩放得分。

RRF 读取每个文档的位置,因此 A 的密集领先优势会被压缩为一步,而 B 被两个预取都排在接近顶部则会获胜。DBSF 在共享轴上保留间距,因此 A 的领先优势在求和后仍然存在,A 会获胜。

RRF 忽略得分尺度,因此余弦相似度和 BM25 分数可以结合而不会相互主导。DBSF 假设得分差距的大小有意义,因此一个离群得分可能会影响结果。哪种方法更优取决于你的数据,因此请将两者都与你的标签进行测试。

在你的标签上对比 RRF 和 DBSF

使用你的带标签查询集,在相同预取上对比 RRF 和 DBSF。在 k=2 且权重相等时运行 RRF,然后运行 DBSF。

两个查询读取相同的两个候选列表,因此只需连接一次并构建一次预取。预取必须使用集合所建立的模型。

code
from
qdrant_client
import
QdrantClient
,
models
from
your_embedding_setup
import
dense_query
,
sparse_query
client
=
QdrantClient
(
url
=
"https://YOUR-CLUSTER.cloud.qdrant.io"
,
api_key
=
"<your-api-key>"
,
)
dense_prefetch
=
models
.
Prefetch
(
query
=
dense_query
,
using
=
"dense"
,
limit
=
200
)
sparse_prefetch
=
models
.
Prefetch
(
query
=
sparse_query
,
using
=
"bm25"
,
limit
=
200
)
prefetches
=
[
dense_prefetch
,
sparse_prefetch
]

RrfQuery 同时携带 RRF 设置参数 k 和权重对,此处显示为默认值。该功能需要 Qdrant v1.17 或更高版本以及兼容的 qdrant-client 发布版本。

code
rrf_response
=
client
.
query_points
(
collection_name
=
"products"
,
prefetch
=
prefetches
,
query
=
models
.
RrfQuery
(
rrf
=
models
.
Rrf
(
k
=
2
,
weights
=
[
1.0
,
1.0
])),
limit
=
10
,
)

DBSF 查询仅在融合步骤上有所不同。

code
dbsf_response
=
client
.
query_points
(
collection_name
=
"products"
,
prefetch
=
prefetches
,
query
=
models
.
FusionQuery
(
fusion
=
models
.
Fusion
.
DBSF
),
limit
=
10
,
)

在五个数据集中的三个上,DBSF 的得分高于默认 RRF,且差异的 95% 置信区间不包含零。SciFact 的 0.0148 提升和 ArguAna 的 0.0045 下降均跨越零点,因此这两个数据集的结果尚无定论。

DBSF

相对于默认 RRF

0.5171

-0.0045

0.6716

+0.0161

0.7323

+0.0148

0.4822

+0.0184

0.7637

+0.0383

DBSF 不需要任何参数:k 和权重对属于 RRF 设置,公共 API 仅在 RrfQuery 中接受这些参数。因此,如果 DBSF 在您的标签数据上表现更优,可跳过接下来的两个部分,直接进行保留集验证。

使用标签选择 k 值范围

Qdrant 对每个预取中位置为 pos 的文档评分公式为 1 / ((pos + 1) / weight + k - 1),然后在所有预取中求和。当权重相等时,公式简化为 1 / (pos + k),此时 k 值单独决定列表头部与尾部的排名差异程度。

在 Qdrant 默认的 k=2 设置下,排名第一的文档得分是第十名的 5.50 倍。当 k=61 时,这一倍数降至 1.15 倍,此时文档是否出现在预取结果中的重要性几乎与排名位置相当。

在 k=5 时,第一名得分是第十名的 2.80 倍;在 k=20 时,这一倍数为 1.45 倍。因此,大部分变化发生在 k<20 的区间。以 5 为步长进行扫描时,大部分运行都会超过曲线停止变化的临界点。

依次扫描 k=1、2、5、20 和 61,仅修改 models.Rrf 中的 k 值并保持权重相等。较小的 k 值更倾向于重视单个预取中排名较高的文档,较大的 k 值则更重视两个预取都检索到的文档。

表格展示了在五个 k 值下(默认 RRF 为 k=2)权重相等时的 nDCG@10 值,星号标记出每行最佳的 k 值。

查询

每查询相关文档数

k=1

k=2

k=5

k=20

k=61

1,401

1.0

0.5304*

0.5269

0.5207

1,000

0.6501

0.6580*

0.6511

0.6258

300

1.1

0.7117

0.7175*

0.7154

0.7122

0.7067

400

38.2

0.4625

0.4641

0.4682*

0.4606

480

358.9

0.7232

0.7336

0.7571

0.7614*

在 WANDS 数据集上,k=2 和 k=61 在 42% 的查询中选择了不同的最佳结果,同时 nDCG@10 提升了 0.0360。即使总体提升幅度较小,仍可能影响用户首先看到的内容。

这五个数据集表明了一个趋势:当每个查询平均有约 1 个相关文档时,最佳 k 值为 2 或 5;当相关文档数量达到数十或数百时,最佳 k 值为 20 或 61。请统计您标注查询集中的每个查询相关文档数量,然后优先尝试对应区间内的 k 值。

如果你正在将 RRF 配置从其他系统迁移过来,请记住 Qdrant 使用的是零基位置。要复现 Cormack 等人提出的 1/(rank + 60) 公式(使用一基排名),请使用 k=61。

最后调整权重

权重对为每个预取操作提供一个乘数,乘数顺序与查询中预取操作的出现顺序一致。该对是绝对值,因此 (1, 2) 和 (2, 4) 是两种不同的设置:公式会将位置除以权重,因此同时缩放两个权重会改变所有评分。在 WANDS 上使用 k=5 时,(1, 2) 得分为 0.7390,(2, 4) 得分为 0.7508。

首先确定 k 值,因为一个权重对仅对其测试的 k 值有效。在 WANDS 上,当 k=5 时,(2, 4) 超过等权重;但在该数据集的最佳 k=61 时,等权重表现更优:0.7614 对比 0.7567。

随后尝试几个权重对,让标签选择胜者。单个预取的评分无法说明倾向。权重作用于每个列表中的位置,因此权重对的选择取决于哪个预取在另一个预取遗漏的查询中能对相关文档进行高排名。

在 DBPedia-entity 上,密集检索得分 0.4677,而稀疏检索得分为 0.3857,但胜出的 (1, 3) 给稀疏检索的权重是密集检索的三倍,提升了 0.0060。CodeSearchNet 的表现相反,在 (2, 1) 时提升了 0.0096。两个区间均不包含零。

等权重是真实结果。在每个数据集的最佳 k 值上,六组权重对进行了测试,其中 (1, 1) 在五个数据集中的两个上直接胜出。ArguAna 的最佳权重对提升了 0.0029,其置信区间跨越零。

权重为 0.0 时,该预取的所有文档都会被排除,每个文档得分为 0.0。这些文档会保留在融合列表底部,而不是消失。

在保留查询上确认所选配置

配置可能在用于选择它的查询上表现最佳,但在保留查询上仍可能失败。请运行预调优文章中提到的两项检查:每个查询增益的引导区间,以及选择集与保留查询的划分。当配置的区间不包含零且在保留查询部分保持选定增益时,方可部署该配置。

在 SciFact 的 300 个查询中,我们尝试的所有配置的 95% 置信区间均包含零,包括 DBSF 的 0.0148 增益。在 200 次随机划分中,选定的融合配置在保留查询上保持了 67% 到 95% 的增益。保留默认配置是一个真实选项,且在我们五个数据集中的一个上是正确选择。

按以下顺序进行调优

每一步的成本都足够低,可以在单个会话中运行。

  • 确认融合效果优于任一预取单独使用的效果。
  • 根据标签选择 RRF 或 DBSF。
  • 根据每个查询的相关文档数量设置 k 值。
  • 在该 k 值下尝试几个权重对。
  • 在部署前,在保留查询上验证胜出者。

接下来,如果下游模型可以提升你检索到的候选结果的排序,请测试重排序器是否值得其成本。