揭秘相关性评分提升与衰减函数
Evgeniya Sukhodolskaya
·2025年9月1日

在监控 Qdrant Discord 社区时,我们发现了一个问题:由于 评分提升功能提供了大量表达式,因此如何应用它存在混淆的空间。这可能会阻止您将相关性评分背后的业务逻辑移入 Qdrant 搜索引擎。我们不希望这样!
在本博客中,我们希望揭开评分提升中**衰减函数**部分的神秘面纱,更确切地说:LinDecayExpression、ExpDecayExpression 和 GaussDecayExpression —— 它们是 Discord _#ask-for-help_ 频道上的常客。
衰减函数的作用
衰减函数有助于将数据集项的数字属性(如大小或评分)转换为介于 1.0(最相关)和 0.0(不相关)之间的值。这使得这些属性能够有意义地影响最终的相关性评分。
当某个项的某个数字属性的变化应**平滑且成比例地**影响其相关性评分时,衰减函数非常有用。
可以这样理解:
- 新闻文章随着时间的推移变得不那么相关,因此相关性会随着出版日期后的天数而衰减。
- 更远的餐厅对于外卖订餐而言相关性较低,因此相关性会随着与用户距离的增加而衰减。
- 更好的声誉使电影更具相关性,因此相关性会随着 IMDb 好评数量的减少而衰减。
三种选择
Qdrant 已将三种衰减函数添加到评分提升功能中,每种函数都捕捉了相关性衰减的不同方式。

**图 1。**评分提升中使用的三种衰减函数。
此图的交互式版本可在此处 获取。
线性
相关性以恒定速率随变量变化。值的每个变化都具有相同的影响。
→ 例如,折扣百分比:越多越好!
高斯
相关性平稳而逐渐地衰减。与理想的小偏差是可以原谅的,但偏离越远,相关性越低。
→ 非常适合产品价格等情况;小差异通常对用户来说没问题,但当价格差距变大时,兴趣会迅速下降。
指数
即使是微小的变化,相关性也会急剧下降。偏离理想值会很快受到惩罚。
→ 配送时间是这里的一个很好的例子。如果物品需要太长时间才能送达,用户会立即失去兴趣。
Qdrant 中的所有三种衰减函数都是**对称的**。它们将 1.0 的相关性分配给变量的某个特定值,并随着变量偏离此目标而衰减到 0.0。
当存在明确的“理想”值时,这种对称性非常有用,任何或多或少于该值的情况都同样偏离。例如:
- 用户心中有一个目标价格。任何更昂贵的东西都不那么相关(显然),但任何更便宜的东西也可能引起质量担忧。(是的,并非总是如此,但许多人是这样认为的。)
- 您正在寻找一个 30 分钟的锻炼视频。25 分钟和 35 分钟都可以接受,但 5 分钟或 1 小时显然不是您想要的。
衰减函数参数
要使用衰减函数进行评分提升,您需要确定为其参数提供哪些值。
乍一看,它们可能有很多:x、target、midpoint、scale……
让我们揭开它们的神秘面纱。让我们从一个快速的胜利开始:其中两个,x 和 target,我们已经在上面的例子中多次使用。
x 参数
这正是您想要用衰减函数转换的变量:评分、时间、距离、年龄、评论数量、价格等。
您可以将其视为*输入值*。它可能来自项的有效载荷字段或嵌入相似度评分。基本上,它是衰减函数的 x 轴(y 是输出,相关性评分,从 1.0 衰减到 0.0)。

**图 2。**衰减函数的 x(x 轴)和 target(x 轴上的点)。
此图的交互式版本可在此处 获取。
target 参数
这是您的 x 变量需要匹配的值,以便该项被视为 **100% 相关**,从而从衰减函数中获得 1.0 的相关性评分。
默认情况下,target 为 0.0,这在许多情况下都是有意义的。例如:
- 配送距离为 0.0 米:越近越好。
- 发布时间为 0.0 秒:越新鲜越好。
但当然,target 可以是任何其他值,具体取决于您的用例:期望且最相关的价格、年龄、大小、评分等。
因此,简而言之,x 是当前值,target 是相关性最佳情况值。
scale & midpoint 参数
现在我们剩下 midpoint 和 scale。它们的目的是什么?控制您选择的衰减函数将如何……工作。它的形状需要符合您对相关性的定义以及您正在转换的变量的性质。

**图 3。**scale(x 轴上的线段)和 midpoint(y 轴上的点),定义了衰减函数的形状。
此图的交互式版本可在此处 获取。
scale 和 midpoint 共同定义了函数的斜率,即相关性衰减的速度或平滑程度。它表示:“x 应该改变多少 scale 才能达到 midpoint 的相关性值。”
衰减函数的形状由两个关键点定义:
- (
target, 1.0) — 理想用例 - (
target ± scale,midpoint) — 当x变量从理想的target值改变scale时,相关性如何下降。
scale 和 midpoint 的选择为每种衰减函数定义了特定的行为。
- 对于**高斯衰减**,相关性从 1.0 向
midpoint缓慢平稳下降,因为x变化了scale。之后,衰减加速。 - 对于**指数衰减**,情况正好相反:起初快速衰减直到
midpoint,然后变慢。 - 对于**线性衰减**,
midpoint和scale定义了相关性评分达到 0.0 的点,因为它是唯一实际达到零的衰减函数。
**注意 #1。**midpoint 默认为 0.5,但可以在 (0.0, 1.0) 范围内取任何值。对于线性衰减,将 midpoint 设置为 0.0 也是有效的。
**注意 #2。**scale 默认为 1.0,但它可以是任何反映变量 x 与您定义相关性之间关系的值。只有*您*知道这里什么是有意义的。
**注意 #3。**我们期望 scale 为**正**值;这样可以简化我们的计算。
**注意 #4。**指数和高斯衰减函数永远不会达到 0.0。相关性评分接近零但保持正值。只有线性衰减可以精确达到 0.0,并且只有在这种情况下将 midpoint 设置为 0.0 才是有效的。
如何选择参数:示例
示例 #1
**用例:** 用户正在搜索关于技术俱乐部文化的德语教育视频,以练习语言理解。他们选择 5 分钟作为理想视频时长。
**衰减:** 高斯
**x**:视频时长(分钟),存储在视频的有效载荷中
**target**:5 (_分钟_)
**scale**:4 (_分钟_)中点: 0.5
解释
我们假设,在所有内容相关的视频中,用户将容忍视频时长偏差最多 ±4 分钟,即 1 分钟到 9 分钟的视频。因此,相关性应以高斯方式**平稳缓慢地**从 1.0 衰减到 0.5。
任何超过 9 分钟或短于 1 分钟的视频都将迅速变得不那么相关,即使内容仍然匹配。
示例 #2
**用例:** 促销代码聚合器应用提升新鲜度,以始终显示产品和事件的最新促销代码。
**衰减:** 指数
**x**:促销代码上传的日期时间,存储在有效载荷中
**target**:当前日期时间(搜索时刻)
**scale**:604800(1 周,以秒为单位)中点: 0.1
解释
在所有不同产品/事件的促销代码中,用户会强烈偏好**刚刚**上传的促销代码,因为它们最有可能有效。但这种相关性会随着时间迅速下降:在一周内,它达到 0.1 的中点。之后,如果促销代码仍然有效,无论如何都是一场赌博:可能有效,也可能无效。所以那些旧但未过期的代码大致上同样不相关。
**注意 #5。**对于 Qdrant 日期时间 有效载荷,scale 应始终以**秒**为单位提供!
我无法预先知道所有参数
如您所见,在 Qdrant 的评分提升中使用衰减函数意味着您必须预先知道参数。
我们在 Discord 社区中多次看到,人们试图将衰减函数应用于规范化来自 预取 的相似度评分,通常作为融合不同类型相似度搜索结果的一种方式。
常见的问题是:
如果我无法预先知道
scale,如何使用衰减函数进行评分规范化?
答案是:**您无法动态设置 midpoint 和 scale 参数,因此您无法动态规范化评分,甚至可能不应该尝试。**
假设您正在预取由 ColBERT 等后期交互模型评分的项子集,其中较高的评分意味着较高的相似度。您获得的评分是 36、22 和 1。另外,您还有来自某些密集向量搜索的余弦相似度评分,并且您希望融合这两组结果。
如果您基于此子集动态规范化 ColBERT 评分,则 36 将变为 1.0,其他所有评分都会相应缩放。
但问题在于:36 可能根本不是一个“高”分。也许您的数据集中根本没有好的匹配项。规范化步骤将剥离该上下文,当您融合评分时,您将产生一种错误的高相关性感觉。
如果您计划使用衰减函数进行评分规范化,您需要提前知道预期的参数值。如果您不知道输入变量 (x) 的范围,您将无法可靠地使用衰减函数。
代码片段
现在让我们看看在 Qdrant 中使用衰减函数是什么样子。
我们将提供 HTTP 请求示例,但您可以在 Python、TypeScript、Rust、Java、C# 和 Go 客户端中 类似地使用衰减函数。
**注意 #6。**公式中使用的有效载荷变量受益于拥有 有效载荷索引。因此,我们要求您为公式中使用的任何变量设置有效载荷索引。
让我们以“德语教育视频”示例为例,看看它在 Qdrant 中如何体现:
POST collections/video/points/query
{
"prefetch": {
"query": <video_description_embedding>,
"limit": 10 // limit of prefetched results
},
"query": {
"formula": {
"sum": [
"$score", // so the final score = score + gauss_decay(duration)
{
"gauss_decay": {
"target": 5,
"scale": 4,
"midpoint": 0.5,
"x": "duration" // payload key
}
}
]
}
}
}
这是“新鲜促销代码”示例,以便您更好地掌握如何使用 Qdrant 的评分提升:
POST collections/promocodes/points/query
{
"prefetch": {
"query": <promocode_description_embedding>,
"limit": 10 // limit of prefetched results
},
"query": {
"formula": {
"sum": [
"$score", // so the final score = score + exp_decay(search_time - upload_time)
{
"exp_decay": {
"x": {
"datetime_key": "upload_time" // payload key
},
"target": {
"datetime": "2025-08-04T00:00:00Z" // time of the search
},
"scale": 604800, // 1 week in seconds
"midpoint": 0.1
}
}
]
}
}
}
注 #7。datetime_key 和 datetime 用于区分持有日期时间类型字符串的有效载荷键和直接提供的日期时间字符串。
总结
因此,我们已经涵盖了相当多的内容,包括:
- 什么是衰减函数以及它们为何重要;
target、x、scale和midpoint如何影响衰减行为;- 以及如何在 Qdrant 的评分提升中使用衰减函数。
我们真诚地希望这篇文档能帮助您理清一些困惑。现在您唯一需要做的就是亲自动手进行实验!
使用文章中的代码片段作为起点,并在 Qdrant Cloud 中尝试相关性评分提升。我们提供一个永久免费的 1GB 集群:足以测试、调整并查看衰减函数在您的数据上的表现。
如果您想深入了解衰减函数或评分提升,请查看我们的 文档,其中包含一个基于距离的衰减示例和更多值得学习的内容。
告诉我们您正在构建什么
我们很乐意听听您正在尝试什么!您认为什么是“相关”的?您喜欢最新版本的哪些功能?还缺少什么?
如果您仍有任何疑问,请随时 在 Discord 上 提问,或 在 LinkedIn 上与我联系。我们总是很乐意进一步解释,并很想知道接下来要写些什么!