Redis Vector Set 怎么按相似度过滤结果
来源:17golang原创
时间:2026-10-06 00:12:48 433浏览 收藏
Redis Vector Set 要按相似度过滤结果,直接在 VSIM 中使用 EPSILON。它接收的不是“最低相似度”,而是最大距离:如果业务要求相似度至少为 0.85,应设置 EPSILON 0.15。换算公式是 EPSILON = 1 - 最低相似度。
EPSILON:按相似度门槛过滤,值越小,要求越严格。COUNT:只限制最多返回多少条,不保证这些结果足够相似。WITHSCORES:把分数返回给客户端,便于观察和调参,本身不做过滤。FILTER:过滤 JSON 属性,不是过滤相似度分数。
官方文档:https://redis.io/docs/latest/commands/vsim/
前置条件:先确认是 Vector Set 的阈值问题
VSIM 属于 Redis Vector Set 命令,官方命令页标注其从 Redis Open Source 8.0.0 起可用。本文只讨论 Vector Set 中的相似度门槛;如果你使用的是 Redis Search 的向量索引,查询语法和距离字段并不是同一套接口。
Vector Set 的分数范围是 1 到 0:1 表示向量相同,0 表示方向相反。EPSILON 的范围同样是 0 到 1,但含义是“允许离查询向量多远”。因此两者方向相反。
| 最低相似度 | 对应 EPSILON | 筛选含义 |
|---|---|---|
0.95 | 0.05 | 只保留非常接近的候选 |
0.85 | 0.15 | 保留相似度不低于 0.85 的候选 |
0.70 | 0.30 | 放宽召回范围,结果通常更多 |
第一步:初始化一个最小 Vector Set
下面用三维向量创建实验集合。VALUES 3 中的 3 是维度,后面必须紧跟三个浮点值和元素名。所有元素维度要保持一致:
# 写入四个三维向量,首次 VADD 会创建 Vector Set VADD demo:articles VALUES 3 1.00 0.00 0.00 article:redis VADD demo:articles VALUES 3 0.96 0.18 0.00 article:cache VADD demo:articles VALUES 3 0.72 0.69 0.00 article:database VADD demo:articles VALUES 3 -1.00 0.00 0.00 article:travel # 检查元素数量和向量维度,排除初始化错误 VCARD demo:articles VDIM demo:articles
预期结构是 VCARD 返回 4,VDIM 返回 3。如果维度不一致,先修正写入数据,不要用搜索参数掩盖输入问题。
第二步:先用 WITHSCORES 观察分数
阈值不应凭感觉直接写死。先使用较大的 COUNT 返回一批候选,再通过 WITHSCORES 观察业务中的正例、边界例和负例大致落在哪个区间:
# 以外部查询向量搜索,返回最多 10 条并附带相似度分数 VSIM demo:articles VALUES 3 1.00 0.00 0.00 WITHSCORES COUNT 10
RESP2 返回时,元素名与分数通常交替出现;RESP3 可以返回成员到分数的映射。不要把数组位置写死成唯一协议,客户端解析时应按所用 RESP 版本处理。
WITHSCORES 的作用只是让分数可见。若只写 COUNT 10,Redis 会尽量返回最相似的十条,但第十条可能远低于业务可接受的门槛;这就是需要 EPSILON 的原因。
第三步:用 EPSILON 设定相似度门槛
假设实验观察后决定“相似度至少 0.85”,先换算为距离上限 1 - 0.85 = 0.15,再把它写进同一个 VSIM:
# EPSILON 0.15 等价于只保留相似度不低于 0.85 的候选 VSIM demo:articles VALUES 3 1.00 0.00 0.00 \ WITHSCORES COUNT 10 EPSILON 0.15
这里的 COUNT 10 仍是结果数量上限,而 EPSILON 0.15 才是质量下限。满足门槛的元素只有三条时,命令可以少于十条;没有元素达到门槛时,结果可以为空。这比先取固定十条再在客户端按分数删除更直接,也减少了无用结果传输。

如果查询基准已经是集合中的元素,可以把 VALUES 改成 ELE:
# 以集合内已有元素为查询基准,仍使用同一距离门槛 VSIM demo:articles ELE article:redis \ WITHSCORES COUNT 10 EPSILON 0.15
使用 ELE 时,查询元素自身可能以接近 1 的分数出现在结果里。如果业务不想返回自身,应在应用层按元素名排除;不要为了排除自身而错误地收紧相似度阈值。
第四步:区分 EPSILON、COUNT 和 FILTER
名称相近的“过滤”其实作用在不同层。EPSILON 处理向量距离,FILTER 处理元素 JSON 属性,COUNT 处理返回数量。三者可以组合,但不能互相替代。
按属性过滤不是按分数过滤
先用 VSETATTR 给元素关联 JSON 属性,再把属性表达式放进 FILTER。例如只检索已发布的中文内容:
# 为候选元素写入 JSON 属性,供 FILTER 使用
VSETATTR demo:articles article:redis '{"lang":"zh","published":true}'
VSETATTR demo:articles article:cache '{"lang":"zh","published":true}'
VSETATTR demo:articles article:database '{"lang":"en","published":true}'
VSETATTR demo:articles article:travel '{"lang":"zh","published":false}'
# 同时应用相似度门槛、属性条件和返回数量上限
VSIM demo:articles VALUES 3 1.00 0.00 0.00 \
WITHSCORES COUNT 10 EPSILON 0.15 \
FILTER '.lang == "zh" and .published == true'
这条命令先定义“够不够相似”和“属性是否匹配”两个独立条件。FILTER-EF 控制属性过滤最多尝试多少次,也不是相似度阈值。

第五步:检查近似搜索边界
VSIM 默认可以执行近似搜索。EPSILON 只规定“返回结果必须满足什么距离门槛”,并不保证近似搜索一定找全所有满足门槛的元素。若发现已知正例偶尔没有被召回,应先把阈值和召回问题分开处理:
- 门槛太严格:适当增大
EPSILON,相当于降低最低相似度。 - 召回不足:增大
EF,让搜索探索更多节点,但延迟和计算量会增加。 - 需要基准:临时用
TRUTH做精确线性扫描,对比近似结果;它是 O(N) 且明显更慢,不适合作为默认线上方案。
# 提高探索量,阈值仍保持相似度至少 0.85 VSIM demo:articles VALUES 3 1.00 0.00 0.00 \ WITHSCORES COUNT 10 EPSILON 0.15 EF 200 # 仅用于小规模基准对照,TRUTH 会执行精确线性扫描 VSIM demo:articles VALUES 3 1.00 0.00 0.00 \ WITHSCORES COUNT 10 EPSILON 0.15 TRUTH
调参时应固定查询集,分别记录满足业务定义的正例是否被召回、返回数量和延迟。不要只看单次分数排序,也不要把提高 EF 误认为提高相似度门槛。
扩展实验:把业务阈值写成可检查规则
实际项目可以先建立三组查询样本:必须命中的正例、刚好可接受的边界例、必须排除的负例。选择阈值时,让边界例尽量稳定地位于门槛内,同时让负例位于门槛外。若不同业务场景的分数分布差异明显,应使用不同阈值,不要让一个全局 EPSILON 服务所有检索意图。
| 目标 | 使用选项 | 判断标准 |
|---|---|---|
| 只保留足够相似的结果 | EPSILON | score >= 1 - epsilon |
| 控制最多返回多少条 | COUNT | 结果条数不超过上限 |
| 查看分数并调阈值 | WITHSCORES | 客户端能读取成员与分数 |
| 限定语言、状态、年份 | FILTER | 元素 JSON 属性符合表达式 |
| 改善近似搜索召回 | EF | 已知正例召回更稳定,成本可接受 |
| 建立精确结果基准 | TRUTH | 与近似结果对照,不作为默认线上查询 |
清理实验数据
确认命令和阈值后,删除本次实验键,避免它与正式集合混在一起:
# 删除本文实验使用的 Vector Set 键 DEL demo:articles
相关问题
为什么相似度 0.8 要写 EPSILON 0.2
因为 EPSILON 表示距离上限,而 Vector Set 的相似度与这里的距离满足 similarity = 1 - distance。相似度至少 0.8,等价于距离小于等于 0.2。
只用 COUNT 能过滤低分结果吗
不能。COUNT 只保留最靠前的若干候选;如果整个集合都不够相似,它仍可能返回低分结果。质量门槛要用 EPSILON。
FILTER 能直接写相似度条件吗
不能把它当分数表达式使用。FILTER 面向 VSETATTR 保存的 JSON 属性;相似度门槛由 EPSILON 负责。
加了 EPSILON 为什么已知相似元素仍没返回
先确认换算方向和向量维度,再区分门槛与近似召回。阈值正确但召回不足时,可以提高 EF,并用小规模 TRUTH 结果建立对照。
-
117 收藏
-
426 收藏
-
171 收藏
-
113 收藏
-
195 收藏
-
228 收藏
-
295 收藏
-
198 收藏
-
401 收藏
-
216 收藏
-
152 收藏
-
295 收藏
-
267 收藏
-
158 收藏
-
260 收藏
-
348 收藏
-
269 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习