当前位置: 首页 > java >正文

使用 Redis 作为向量数据库

一、什么是向量数据库?

  • 向量(Vector):在机器学习和 AI 中,向量是由一系列数字组成的序列,用于数值化地描述数据的特征或语义。文本、图像、音频等非结构化数据可以通过模型转换成固定长度的向量。

  • 向量数据库:专门存储、索引和检索向量的数据库系统。可以基于向量之间的距离度量(如余弦相似度、欧氏距离等)进行高效的近邻搜索(Nearest Neighbor Search),从而实现“语义搜索”或“相似度搜索”。

  • 与传统搜索的区别

    • 传统搜索依赖于关键词精确匹配,无法识别同义词、上下文或语义抽象。
    • 向量搜索通过将数据空间映射到高维向量空间,使语义相近的内容在向量空间中距离更近,从而返回更符合用户意图的结果。

二、准备工作

本文示例使用 Python 客户端库 RedisVL,以及常见的 Python 生态组件:

# 建议在虚拟环境中安装
pip install redis pandas sentence-transformers tabulate redisvl

说明

  • redis:官方 Python 客户端。
  • pandas:用于结果展示。
  • sentence-transformers:生成文本向量。
  • tabulate:渲染 Markdown 表格。
  • redisvl:Redis 向量搜索专用扩展(可选,本文使用原生 redis.commands.search API)。

三、连接 Redis

如果你使用本地 Redis:

import redisclient = redis.Redis(host="localhost", port=6379, decode_responses=True)

如果使用 Redis Cloud,则将 hostportpassword 替换为云端实例参数:

client = redis.Redis(host="redis-16379.c283.us-east-1-4.ec2.cloud.redislabs.com",port=16379,password="your_password_here",decode_responses=True,
)

四、准备示例数据集

本文使用开源的 bikes 数据集,每条记录包含如下字段:

{"model": "Jigger","brand": "Velorim","price": 270,"type": "Kids bikes","specs": {"material": "aluminium","weight": "10"},"description": "Small and powerful, the Jigger is the best ride for the smallest of tikes! ..."
}

1. 拉取数据

import requestsURL = ("https://raw.githubusercontent.com/""bsbodden/redis_vss_getting_started""/main/data/bikes.json")
response = requests.get(URL, timeout=10)
bikes = response.json()

2. 存储到 Redis(JSON 文档)

pipeline = client.pipeline()
for i, bike in enumerate(bikes, start=1):key = f"bikes:{i:03}"pipeline.json().set(key, "$", bike)
pipeline.execute()

你可以这样读取某个字段:

client.json().get("bikes:010", "$.model")
# => ['Summit']

五、生成并存储向量嵌入

1. 选择文本嵌入模型

from sentence_transformers import SentenceTransformerembedder = SentenceTransformer('msmarco-distilbert-base-v4')

2. 批量获取描述并生成向量

import numpy as np# 获取所有 key
keys = sorted(client.keys("bikes:*"))# 批量读取 description
descs = client.json().mget(keys, "$.description")
# 扁平化列表
descriptions = [item for sublist in descs for item in sublist]# 生成嵌入并转换为 float32 列表
embeddings = embedder.encode(descriptions).astype(np.float32).tolist()
VECTOR_DIM = len(embeddings[0])  # 768

3. 插入向量字段

pipeline = client.pipeline()
for key, vec in zip(keys, embeddings):pipeline.json().set(key, "$.description_embeddings", vec)
pipeline.execute()

此时,每条记录都多了一个 $.description_embeddings 数组字段。

六、创建检索索引

为了同时支持基于字段和基于向量的搜索,需要创建一个 Redis Search 索引:

# 在 Redis CLI 环境中执行
FT.CREATE idx:bikes_vss ON JSONPREFIX 1 bikes:SCHEMA$.model                TEXT    WEIGHT 1.0 NOSTEM$.brand                TEXT    WEIGHT 1.0 NOSTEM$.price                NUMERIC$.type                 TAG     SEPARATOR ","$.description          TEXT    WEIGHT 1.0$.description_embeddings AS vector VECTOR FLAT \TYPE FLOAT32 DIM 768 DISTANCE_METRIC COSINE
  • FLAT:扁平索引;也可使用 HNSW(图索引)以提高速度与扩展性。
  • TYPE FLOAT32:32 位浮点。
  • DIM 768:向量维度。
  • DISTANCE_METRIC COSINE:余弦相似度。

创建完成后,通过 FT.INFO idx:bikes_vss 可以查看索引状态,确认文档是否全部就绪。

七、执行向量搜索

1. 嵌入查询文本

queries = ["Bike for small kids","Best Mountain bikes for kids","Cheap Mountain bike for kids",# ... 共 11 条
]
encoded_queries = embedder.encode(queries)

注意:必须使用与文档相同的模型和参数,否则语义相似度会大打折扣。

2. 构造 KNN 查询模板

from redis.commands.search.query import Queryknn_query = (Query("(*)=>[KNN 3 @vector $qvector AS score]").sort_by("score").return_fields("score", "id", "brand", "model", "description").dialect(2)
)
  • (*):不过滤,检索全集。
  • KNN 3:返回最相近的 3 个向量。
  • @vector $qvector:向量字段名与占位符。
  • dialect(2):必要参数以支持向量查询语法。

3. 执行查询并展示

import pandas as pddef run_search(queries, encoded_qs):rows = []for q, vec in zip(queries, encoded_qs):docs = client.ft("idx:bikes_vss") \.search(knn_query, {"qvector": np.array(vec, dtype=np.float32).tobytes()}) \.docsfor doc in docs:rows.append({"query": q,"score": round(1 - float(doc.score), 2),"id":    doc.id,"brand": doc.brand,"model": doc.model,"desc":  doc.description[:100] + "..."})df = pd.DataFrame(rows)return df.sort_values(["query","score"], ascending=[True,False])table = run_search(queries, encoded_queries)
print(table.to_markdown(index=False))
queryscoreidbrandmodeldesc
Best Mountain bikes for kids0.54bikes:003NordChook air 5The Chook Air 5 gives kids aged six years and …

八、总结与后续

Redis 强大的模块化生态(如 RedisJSON、RediSearch)让其成为轻量级、易上手的向量数据库方案。想深入了解更多:

  • 向量索引参数:扁平 VS HNSW、距离度量、并行构建等。
  • 多模态数据:结合 RedisAI,直接在 Redis 中进行模型推理。
  • 扩展语言客户端:C#、JavaScript、Java、Go 等,满足多种开发场景。

欢迎访问 Redis University 和 Redis AI 资源库 以获得更多学习资料。

http://www.xdnf.cn/news/9238.html

相关文章:

  • 5G 核心网 UE 状态深度剖析:机制、迁移与演进
  • 新版Chrome浏览器加载eDrawings 3D Viewer控件网页查看DWG、DXF
  • 利用Tushare+pyEcharts进行沪深证券数据采集与分析
  • 单向循环链表与双向链表
  • 洗鞋店干洗店线上预约管理系统;
  • 【OS安装与使用】part7-ubuntu22.04LTS 的 docker 安装与使用(实例:MTransServer服务部署)
  • AI辅助写作 从提笔难到高效创作的智能升级
  • WPF事件处理器+x名称空间
  • 基于多流特征融合与领域知识整合的CNN-xLSTM-xAtt网络用于光电容积脉搏波信号的无创血压估计【代码已复现】
  • C语言学习笔记三 --- V
  • 深信服防火墙拦截了DELETE、PUT请求,未达到nginx及后端服务
  • brep2seq 论文笔记
  • 《软件工程》第 16 章 - 软件项目管理与过程改进
  • C-字符串函数
  • 解析极限编程-拥抱变化(第2版)笔记
  • 【C/C++】多线程下自旋锁的行为逻辑
  • C语言创意编程:用趣味实例玩转基础语法(2)
  • ES 在大查询场景下导致 GC 频繁,如何定位和解决?
  • webstorm调试vite工程(后端开发人员版)
  • 从十进制到二进制:深入理解定点数与浮点数表示
  • 高压单端探头,如何实现大比例的衰减?
  • 【NLP基础知识系列课程-Tokenizer的前世今生第二课】NLP 中的 Tokenizer 技术发展史
  • 【Vue3】生命周期 hook函数 toRef
  • 通义智文开源QwenLong-L1: 迈向长上下文大推理模型的强化学习
  • 浅解Vue 数据可视化开发建议与速度优化
  • 【华为云物联网】如何实现在 MQTT.fx 上模拟数据间隔上传一次,并按设定系数变动数据
  • HTML 表单与输入:基础语法到核心应用全解析
  • UBUNTU20.04 配置以QT界面程序代替系统界面启动,以及如何在tty模式下以linuxfb形式启动
  • Halcon 霍夫变换
  • 获取页面上当前激活(获得焦点)的元素