RediSearch 开发实战 之 向量检索
摘要
- 本文介绍 Redis 扩展模块 – RediSearch 操作 向量检索 的方法(
非 Redis8 中新增的向量功能) - 本文基于
redis-7.4.7,springboot-3.5.8 - Redis官网:https://redis.io/
- Redis 命令文档:https://redis.io/docs/latest/commands/
- RediSearch 的安装参见 Redis 扩展模块 -- RediSearch 的安装方法
- 示例代码:GitHub
向量是什么?
-
在现代人工智能系统中,文本、图片、音频、视频等非结构化数据并不能直接被计算机理解和比较。
-
向量(Vector)是将这些复杂信息转换为数学可计算形式的核心载体,也是大模型检索、推荐、搜索、RAG、语义理解等能力的基础。
数学意义上的向量
-
在数学中,向量是一个有序的数值集合,例如:
1 | [0.12, -0.87, 1.45, 0.003, ...] |
-
每一个数字称为一个维度(dimension),整体可以看作是在高维空间中的一个点。
-
如果一个向量有 1024 个数字,则它位于一个 1024 维空间中。
向量在 AI 中的含义
-
在 AI 领域,向量并不是随意的数字,而是 对某个对象语义特征的数值化表达,例如:
| 对象 | 向量表达含义 |
|---|---|
| 一句话 | 语义含义、主题、情感、上下文关系 |
| 一张图片 | 纹理、颜色、形状、语义对象 |
| 一段音频 | 音色、节奏、频谱特征 |
| 一个用户 | 兴趣偏好、行为模式 |
-
模型通过学习大量数据,将“相似的语义”映射到“空间中距离接近的向量”。
向量为什么可以比较相似度?
-
向量之间可以通过距离函数进行比较,常见距离指标:
| 指标 | 含义 | 适用场景 |
|---|---|---|
| Cosine Similarity | 余弦相似度 | 文本语义、Embedding |
| Euclidean Distance | 欧式距离 | 图像、空间特征 |
| Dot Product | 点积 | 推荐系统 |
| L2 / L1 | 范数距离 | 通用计算 |
1 | 向量A ≈ 向量B → 表示语义相似 |
-
向量相似度计算代码示例
1 | package com.example.langchain4j.embeding; |
向量模型(Embedding Model)
-
向量模型非常多,常用的向量模型可以参考向量模型
-
向量模型,也称为 Embedding 模型,是一种:把原始数据映射为固定长度向量的深度学习模型。
-
输入可以是:文本、图片、音频、视频、多模态组合
-
输出是:
float[] embedding
向量维度的意义
-
常见维度范围:
| 模型类型 | 向量维度 |
|---|---|
| Mini Embedding | 256 ~ 384 |
| 通用文本模型 | 512 ~ 1024 |
| 高精度模型 | 1536 ~ 4096 |
-
维度越高:表达能力越强、存储和计算成本越高、检索延迟越大
向量模型的典型应用
| 场景 | 作用 |
|---|---|
| 语义搜索 | 搜索语义相关内容 |
| RAG | 文档召回 |
| 推荐系统 | 用户兴趣匹配 |
| 聚类分析 | 自动分类 |
| 去重 | 内容相似性检测 |
| 多模态检索 | 文搜图 / 图搜文 |
向量数据库
为什么需要向量数据库?
-
普通数据库擅长:等值查询、范围查询、排序、聚合,但对:“在百万向量中找最相似的10个” 效率极低。
-
向量数据库专门解决:高维向量的相似度检索问题(ANN Search)。
-
向量数据库的能力
| 能力 | 说明 |
|---|---|
| 向量存储 | 高维 float 向量 |
| 相似度索引 | HNSW、IVF、PQ |
| KNN 查询 | TopK 最近邻 |
| 混合检索 | 向量 + 结构化过滤 |
| 持久化 | 磁盘存储 |
| 分布式 | 横向扩展 |
| 实时写入 | 在线更新 |
常见向量索引算法
| 算法 | 全称 | 核心原理 | 查询性能 | 检索精度 | 内存占用 | 构建成本 | 适用场景 | 典型系统 |
|---|---|---|---|---|---|---|---|---|
| HNSW | Hierarchical Navigable Small World | 分层小世界图结构,通过多层图实现快速导航 | 极快(毫秒级) | 极高(接近精确搜索) | 较高 | 中等 | 实时检索、高 QPS、低延迟系统 | Redis, Milvus, Faiss |
| IVF | Inverted File Index | 先聚类分桶,再在桶内进行向量搜索 | 快 | 中等~高(可调) | 中等~低 | 较高(需要训练聚类) | 大规模离线检索、成本敏感场景 | Faiss, Milvus |
| PQ | Product Quantization | 向量分块压缩,用码本近似原始向量 | 快 | 较低(有量化误差) | 极低 | 高(训练码本) | 海量数据、内存受限系统 | Faiss, Milvus |
主流向量数据库
-
向量数据库非常多,常用的向量数据库可以参考向量数据库
-
这里只列出一些主流的向量数据库
| 产品 | 特点 |
|---|---|
| Milvus | 专业向量数据库 |
| Qdrant | Rust 高性能 |
| Weaviate | Graph + Vector |
| Elasticsearch | 向量扩展 |
| Redis | 内存级向量 |
| PGVector | PostgreSQL 插件 |
| Faiss | 本地库 |
-
向量数据库在 RAG 架构中的位置
1 | 用户问题 |
-
向量数据库的能力决定了如下指标:
| 指标 | 含义 |
|---|---|
| 检索精度 | 检索结果质量,召回准确率 |
| 检索延迟 | 检索耗时 |
| 存储空间 | 索引大小 |
| 索引构建时间 | 索引构建耗时 |
| 系统吞吐能力 | 系统处理能力 |
RediSearch 创建向量索引
-
前提是安装了 RedisJSON 和 RediSearch 模块,具体安装方法参见 Redis 扩展模块 -- RedisJSON 的安装方法 和 Redis 扩展模块 -- RediSearch 的安装方法
-
在 Redis7 中,向量数据存储在 JSON 数据类型中,然后通过 RediSearch 对其创建索引,实现向量的搜索功能。
-
示例
1 | # 创建 JSON 数据 示例 |
-
创建索引的参数说明
| 参数 | 含义 |
|---|---|
| VECTOR | 向量字段 |
| HNSW | 一种索引算法,可以把查询复杂度降低到近似 O(log N),牺牲极少精度换取极高性能。 |
| 10 | 表示后面紧跟的 10 个参数是用于创建向量索引的参数 |
| TYPE FLOAT32 | 向量数据类型 |
| DIM 10 | 向量维度,一般由向量模型的输出维度决定,如:1024 |
| COSINE | 相似度度量 |
| M 16 | 每个节点在 HNSW 图中允许建立的最大邻居连接数 每个向量最多和多少个其它向量建立边关系 在插入一个新向量时: 算法会搜索一批候选邻居, 从候选集合中选择最多 M 个最合适的邻居建立双向连接 |
| EF_CONSTRUCTION 200 | 建索引时搜索宽度 在构建索引(插入向量)时,用于搜索候选邻居的动态候选队列大小 |
-
M的大小影响的维度
| 维度 | M 增大 | M 减小 |
|---|---|---|
| 查询召回率 | ↑ 提升 | ↓ 降低 |
| 查询延迟 | ↑ 略增 | ↓ 更快 |
| 内存占用 | ↑ 明显增加 | ↓ 减少 |
| 构建时间 | ↑ 增加 | ↓ 更快 |
| 图稳定性 | ↑ 更稳健 | ↓ 容易断裂 |
-
M常见取值经验
| 场景 | 推荐 M |
|---|---|
| 小规模数据(<100万) | 16 ~ 32 |
| 高召回要求(搜索、推荐) | 32 ~ 64 |
| 内存敏感 | 8 ~ 16 |
| 向量维度很高(>1024) | 24 ~ 48 |
Redis 官方示例一般使用 M = 16,属于平衡型配置。
-
EF_CONSTRUCTION影响维度
| 维度 | EF_CONSTRUCTION 增大 | EF_CONSTRUCTION 减小 |
|---|---|---|
| 索引质量 | ↑ 提升 | ↓ 下降 |
| 构建时间 | ↑ 明显变慢 | ↓ 更快 |
| 构建 CPU | ↑ 占用增加 | ↓ 减少 |
| 查询性能 | ↑ 更稳定 | ↓ 容易退化 |
| 内存 | ≈ 基本不变 | ≈ |
⚠️ 注意:EF_CONSTRUCTION 只影响建索引阶段,不影响查询阶段的实时性能。
-
EF_CONSTRUCTION常见取值经验
经验公式:
EF_CONSTRUCTION ≥ 2 × M
| M | 推荐 EF_CONSTRUCTION |
|---|---|
| 16 | 100 ~ 200 |
| 32 | 200 ~ 400 |
| 48 | 300 ~ 600 |
搜索向量
1 | # 搜索示例: 🔍 查询一个向量,找 Top 2 个最相似向量,并返回 text 和相似度距离 score。 |
-
查询表达式:
*=>[KNN 2 @vector $vec AS score]
| 参数 | 含义 |
|---|---|
*=> |
这是 RediSearch 向量检索语法,这里表示匹配所有文档。 向量搜索通常不需要文本过滤,所以直接使用 *。 |
KNN |
执行最近邻搜索(K-Nearest Neighbors) |
2 |
返回最相近的 2 条记录 |
@vector |
索引中的向量字段名 |
$vec |
查询向量参数(来自 PARAMS) |
AS score |
将“距离结果”保存到字段名 score |
-
PARAMS 参数绑定
1 | # 语法 |
float数组转换为FLOAT32二进制数据的方法
1 | package com.example.langchain4j; |
-
SORTBY score 排序规则
1 | # 按 score 字段排序(默认升序)。 |
-
RETURN 2 text score: 返回字段控制
-
DIALECT 2: Dialect 版本,向量搜索语法:
=>[KNN ...]必须使用 Dialect ≥ 2,否则会报语法错误。
使用 Redis 向量搜索的示例(基于 LangChain4j)
1 | package com.example.langchain4j.embeding; |
-
rag.txt 内容
1 | 问题:Redis 7 如何开启向量检索功能? |