SpringBoot 整合Redis Stack 构建本地向量数据库相似性查询的方法
一、前言
AI工具的使用让数据检索的需求场景变得越来越多,也越来越复杂,传统的关系型数据库尽管可以满足日常各类关系数据的存储,但是遇到一些文档类型,非结构化的数据时,其作用和效果就会打折扣,而且数据不仅仅是存储的需要,也需要能够满足数据分析的场景,这种情况下,就可以考虑使用向量数据库了。
二、向量数据库介绍
2.1 什么是向量数据库
向量数据库是一种优化后的数据库系统,专门设计用于高效地存储和检索高维向量数据。这些向量数据通常是从原始数据(如文本、图像、音频等)中提取的特征表示。向量数据库的核心优势在于其能够快速地进行相似性搜索,即找到与给定向量最相似的向量。
2.2 向量数据库特点
向量数据库主要具备如下特征:
- 高效相似性搜索
- 支持多种相似性度量,如欧氏距离(L2)、余弦相似度、Jaccard 相似度等。
- 使用特殊的索引结构(如局部敏感哈希LSH、近似最近邻ANN等)来加速相似性搜索。
- 高维数据处理:
- 优化了高维向量数据的存储和检索,能够在大规模数据集中高效地进行相似性搜索。
- 支持分布式存储和计算,能够轻松扩展到多个节点。
- 灵活的数据模型:
- 通常采用无模式或半结构化数据模型,允许灵活地存储和处理不同类型的向量数据。
- 支持元数据存储,可以将向量数据与相关的元数据(如标签、时间戳等)一起存储。
- 实时和批量处理:
- 支持实时插入和查询,适用于在线推荐系统等实时应用场景。
- 也支持批量数据插入和查询,适用于离线数据分析和处理。
2.3 向量数据库使用场景
在下面的一些场景中可以考虑使用向量数据库
- 推荐系统:
- 通过用户行为数据生成用户和物品的向量表示,用于推荐相似的物品或用户。
- 例如,电商网站可以根据用户的浏览和购买历史生成用户向量,推荐相似的商品。
- 图像搜索:
- 将图像转换为向量表示,用于相似图像的搜索和检索。
- 例如,搜索引擎可以根据上传的图片找到相似的图片。
- 生物信息学:
- 将DNA序列或其他生物数据转换为向量表示,用于基因相似性搜索和分析。
- 例如,研究人员可以使用向量数据库来寻找与已知基因序列相似的新基因。
- 自然语言处理:
- 将文本转换为向量表示,用于文本相似性搜索、情感分析、机器翻译等任务。
- 例如,聊天机器人可以根据用户输入的文本生成向量,找到最合适的回复。
- 广告推荐:
- 根据用户的兴趣和行为生成用户向量,推荐相关的广告。
- 例如,社交媒体平台可以根据用户的兴趣生成用户向量,推荐相关的广告内容。
三、常用的向量数据库解决方案
向量数据库的选择也比较多,下面列举几种常用的向量数据库解决方案。
3.1 Milvus
3.1.1 Milvus是什么
Milvus 是一个高性能的向量数据库,由 Zilliz 开发并维护。它支持多种相似性度量(如欧氏距离、余弦相似度等),并使用高效的索引结构(如 IVF、HNSW 等)来加速相似性搜索。Milvus 可以处理大规模的向量数据集,并支持分布式部署,适用于多种应用场景。Milvus 在推荐系统、图像搜索、自然语言处理等领域表现出色,能够快速地进行相似性搜索,找到与给定向量最相似的向量。
3.1.2 Milvus主要特点
Milvus具有如下特点:
- 高效的相似性搜索
- 多种相似性度量:支持欧氏距离(L2)、余弦相似度、内积等相似性度量。
- 高效的索引结构:支持多种索引结构,如 IVF(Inverted File)、HNSW(Hierarchical Navigable Small World)等,能够显著加速相似性搜索。
- 使用简单
- 丰富的 API 和 SDK:提供多种编程语言的 SDK,包括 Python、Java、C++、Go 等,方便开发者集成。
- 详细的文档和社区支持:提供详细的文档和活跃的社区支持,帮助开发者快速上手。
- 多样化的数据源支持
- 多种数据源:支持多种数据源,可以与 TensorFlow、PyTorch 等深度学习框架集成,方便数据预处理和特征提取。
- 扩展性和可伸缩性好
- 分布式部署:支持分布式部署,能够处理大规模数据集,支持水平扩展。
- 高可用性:支持自动故障恢复和数据备份,保证系统的高可用性。
3.2 Faiss
3.2.1 Faiss是什么
Faiss 是一个开源库,专注于大规模向量相似性搜索和聚类。它支持多种相似性度量(如欧氏距离、余弦相似度等),并使用高效的索引结构(如 IVF(Inverted File)、HNSW(Hierarchical Navigable Small World)等)来加速搜索过程。Faiss 可以在 CPU 和 GPU 上运行,适用于多种应用场景。
3.2.2 Faiss主要特点
Faiss具有如下特点:
- 高效的相似性搜索
- 多种相似性度量:支持欧氏距离(L2)、余弦相似度、内积等相似性度量。
- 高效的索引结构:支持多种索引结构,如 IVF(Inverted File)、HNSW(Hierarchical Navigable Small World)、PQ(Product Quantization)等,能够显著加速相似性搜索。
- 高性能
- CPU 和 GPU 支持:可以在 CPU 和 GPU 上运行,利用硬件加速提高搜索性能。
- 内存优化:对内存使用进行了优化,能够在有限的内存中处理大规模数据集。
- 灵活性好
- 多种索引方法:提供了多种索引方法,可以根据具体需求选择合适的索引结构。
- 自定义索引:支持自定义索引结构和搜索算法,满足特定应用的需求。
- 易于使用
- 丰富的 API:提供了 C++ 和 Python API,方便开发者集成。
- 详细的文档和社区支持:提供详细的文档和活跃的社区支持,帮助开发者快速上手。
3.3 Pinecone
3.3.1 Pinecone是什么
Pinecone 是一个云原生的向量数据库,专为高效地存储和检索大规模向量数据而设计。它旨在简化向量数据的存储和检索过程,提供高性能的相似性搜索功能。Pinecone 提供了高性能的相似性搜索功能,支持实时和批量处理,适用于推荐系统、图像搜索、自然语言处理等多种应用场景。
官方地址:The vector database to build knowledgeable AI | Pinecone
3.3.2 Pinecone主要特点
Pinecone具备如下特点:
- 高性能
- 高效的相似性搜索:支持多种相似性度量,如余弦相似度、欧氏距离等,使用高效的索引结构(如 HNSW、IVF 等)来加速搜索过程。
- 低延迟:优化了搜索性能,能够在毫秒级别内返回结果,适用于实时应用场景。
- 使用简单
- 简单的 API 和 SDK:提供丰富的 API 和 SDK,支持多种编程语言(如 Python、JavaScript 等),方便开发者集成。
- 详细的文档和社区支持:提供详细的文档和活跃的社区支持,帮助开发者快速上手。
- 扩展性和可伸缩性好
- 云原生:提供托管服务,支持自动扩展和故障恢复,保证系统的高可用性。
- 水平扩展:支持水平扩展,能够处理大规模数据集,适用于企业级应用。
- 多样化的数据源支持
- 多种数据源:支持多种数据源,可以与 TensorFlow、PyTorch 等深度学习框架集成,方便数据预处理和特征提取。
3.4 Weaviate
3.4.1 Weaviate介绍
Weaviate 是一个开源的向量搜索引擎,由 Semitechnologies 开发并维护。它不仅支持高效的向量数据存储和检索,还结合了图数据模型,使其在处理复杂数据关系方面表现出色。Weaviate 适用于推荐系统、图像搜索、自然语言处理等多种应用场景。Weaviate 支持多种相似性度量(如余弦相似度、欧氏距离等),并使用高效的索引结构来加速搜索过程。Weaviate 提供了丰富的 API 和 SDK,支持多种编程语言,方便开发者集成。
3.4.2 Weaviate主要特点
Weaviate具备如下特点
- 图数据模型
- 图数据模型:支持图数据模型,可以表示和查询复杂的数据关系。
- 灵活的数据模型:支持多种数据类型和格式,可以轻松适应各种用例。
- 高效的相似性搜索
- 多种相似性度量:支持余弦相似度、欧氏距离等相似性度量。
- 高效的索引结构:使用高效的索引结构(如 HNSW)来加速相似性搜索。
- 使用简单
- 丰富的 API 和 SDK:提供丰富的 API 和 SDK,支持多种编程语言(如 Python、JavaScript、Go 等),方便开发者集成。
- 详细的文档和社区支持:提供详细的文档和活跃的社区支持,帮助开发者快速上手。
- 扩展性和可伸缩性好
- 云原生支持:提供托管服务,支持自动扩展和故障恢复,保证系统的高可用性。
- 水平扩展:支持水平扩展,能够处理大规模数据集,适用于企业级应用。
- 查询语言
- 支持 GraphQL:提供强大的 GraphQL 查询功能,支持复杂的查询和过滤条件。
3.5 Redis Stack
3.5.1 Redis Stack介绍
Redis Stack 是 Redis 的一个扩展版本,它不仅包含了 Redis 的核心功能,还增加了多个模块,如 RediSearch(全文搜索)、RedisGraph(图数据库)、RedisTimeSeries(时间序列数据库)和 RedisAI(AI推理)。这些模块使得 Redis Stack 成为一个功能更加强大的数据库系统,适用于多种应用场景。
3.5.2 Redis Stack核心模块
- Redis Stack核心模块主要包括下面几块
- RediSearch
- 全文搜索:提供全文搜索功能,支持复杂的查询和过滤条件。
- 向量搜索:支持向量数据的存储和相似性搜索,适用于推荐系统、图像搜索等场景。
- 性能优化:使用倒排索引和 BM25 算法优化搜索性能。
- RedisGraph
- 图数据库:提供图数据模型,支持节点和边的存储和查询。
- Cypher 查询语言:支持 Cypher 查询语言,方便进行复杂的图数据查询。
- 高性能:优化了图数据的存储和查询性能。
- RedisTimeSeries
- 时间序列数据:提供时间序列数据的存储和查询功能,适用于监控、日志分析等场景。
- 压缩和聚合:支持数据压缩和聚合,节省存储空间和提高查询性能。
- RedisAI
- AI 推理:提供 AI 推理功能,支持 TensorFlow、PyTorch 等深度学习框架。
- 模型管理和执行:支持模型的加载、管理和执行,适用于实时推理和预测。
3.5.3 Redis Stack主要特点
- Redis Stack主要具备如下特点:
- 高性能
- 内存优化:Redis Stack 优化了内存使用,能够在有限的内存中处理大规模数据集。
- 低延迟:Redis Stack 提供低延迟的数据访问,适用于实时应用场景。
- 使用简单
- 丰富的 API 和 SDK:提供丰富的 API 和 SDK,支持多种编程语言(如 Python、Java、C++、Go 等),方便开发者集成。
- 详细的文档和社区支持:提供详细的文档和活跃的社区支持,帮助开发者快速上手。
- 多样化的数据源支持
- 多种数据源:支持多种数据源,可以与 TensorFlow、PyTorch 等深度学习框架集成,方便数据预处理和特征提取。
- 扩展性和可伸缩性
- 分布式部署:支持分布式部署,能够处理大规模数据集,支持水平扩展。
- 高可用性:支持自动故障恢复和数据备份,保证系统的高可用性。
3.5.4 Redis Stack应用场景
Redis Stack主要有下面的应用场景
- 全文搜索
- 电子商务:支持商品搜索和推荐。
- 内容管理系统:支持文章和文档的搜索和管理。
- 图数据库
- 社交网络:支持用户关系和社交图谱的存储和查询。
- 推荐系统:支持基于图数据的推荐算法。
- 时间序列数据
- 监控系统:支持系统监控和日志分析。
- 物联网:支持 IoT 设备的数据收集和分析。
- AI 推理
- 实时推荐:支持基于 AI 的实时推荐系统。
- 图像识别:支持图像识别和分类。
四、Redis向量数据库介绍
4.1 redis向量数据库是什么
Redis 是一个开源(BSD 许可)的内存数据结构存储,用作数据库、缓存、消息代理和流式处理引擎。Redis 提供数据结构,例如字符串、哈希、列表、集合、带范围查询的有序集合、位图、超对数日志、地理空间索引和流。
Redis 搜索和查询, 扩展了 Redis OSS 的核心功能,因此可以将 Redis 用作向量数据库
- 在哈希或 JSON 文档中存储向量和关联的元数据
- 检索向量
- 执行向量搜索
4.2 向量检索核心原理
向量检索(Vector Search)的核心原理是通过将文本或数据表示为高维向量,并在查询时根据向量的相似度进行搜索。具体来说,向量检索过程涉及以下核心几点。
4.2.1 匹配原理
- 检索的核心是将文本或数据转换成向量,在高维向量空间中查找与查询最相似的向量。
- 在存储数据时将指定的字段通过嵌入模型生成了向量。
- 在检索时,查询文本被向量化,然后与 Redis 中存储的向量进行相似度比较,找到相似度最高的向量(即相关的文档)。
技术关键点:
- 嵌入模型
- 将文本转换成向量。
- 相似度计算
- 通过余弦相似度或欧几里得距离来度量相似性。
- Top K
- 返回相似度最高的 K 个文档。
4.2.2 具体实现过程
在代码中操作时,主要包括下面几步:
- 向量化数据:
- 当你将 JSON 中的字段存入 Redis 时,向量化工具(例如 vectorStore)会将指定的字段转换为高维向量。每个字段的内容会通过某种嵌入模型(如 Word2Vec、BERT、OpenAI Embeddings 等)转换成向量表示。每个向量表示的是该字段内容的语义特征。
- 搜索时向量生成:
- 当执行 SearchRequest.query(message) 时,系统会将输入的 message 转换为一个查询向量。这一步是通过同样的嵌入模型,将查询文本转换为与存储在 Redis 中相同维度的向量。
- 相似度匹配:
- vectorStore.similaritySearch(request) 函数使用了一个向量相似度计算方法来查找最相似的向量。这通常是通过 余弦相似度 或 欧几里得距离 来度量查询向量和存储向量之间的距离。然后返回与查询最相似的前 K 个文档,即 withTopK(topK) 所指定的 K 个最相关的结果。
- 返回匹配的文档:
- 匹配的结果是根据相似度得分排序的 List<Document>。这些文档是你最初存储在 Redis 中的记录,包含了 JSON 中指定的字段。
五、整合springboot 实现向量数据库相似性搜索
接下来使用Redis Stack作为向量数据库,并整合springboot 实现向量数据库相似性搜索的过程。
5.1 前置准备
5.1.1 docker搭建Redis-Stack
使用下面的docker命令搭建Redis-Stack
docker run -d --name redis-stack -v /redis-data:/data -p 6379:6379 -p 8001:8001 redis/redis-stack:latest
也可以使用下面的docker compose命令启动容器
version: '3' services: redis-stack: image: redis/redis-stack ports: - 6379:6379 redis-insight: image: redislabs/redisinsight:latest ports: - 5540:5540
可以通过 IP:8001 访问 Redis-Stack 的web控制台,这里在后面将会用于存储程序中的文本嵌入数据
5.1.2 导入maven依赖
在你的maven工程中导入如下依赖
<properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.4</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>com.alibaba.cloud.ai</groupId> <artifactId>spring-ai-alibaba-starter</artifactId> <version>1.0.0-M2.1</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>2.0.35</version> </dependency> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.12.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/dashscope-sdk-java --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dashscope-sdk-java</artifactId> <version>2.16.9</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency> <!-- https://mvnrepository.com/artifact/io.milvus/milvus-sdk-java --> <dependency> <groupId>io.milvus</groupId> <artifactId>milvus-sdk-java</artifactId> <version>2.4.6</version> </dependency> </dependencies> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
5.1.3 获取apikey
下文中将会先演示使用云厂商提供的向量数据库,所以这里使用百炼平台的,需要先获取apikey
获取apikey,可以去阿里云的百炼平台获取,然后在模型广场中向量模型那里选择一种文本向量使用
5.1.4 添加配置文件
在工程的配置文件中增加下面的配置内容
server: port: 8081 spring: ai: dashscope: api-key: 你的apikey embedding: options: model: text-embedding-v2
5.2 文本嵌入代码实现过程
如何用一段话去数据库查找数据?答案是向量求相似度。相似度越高,返回的数据就越靠前,比如大家熟知的搜索引擎es,你输入一段文本去查询,es会根据算分将得分最高的文档放在前面返回给你,在大模型中,嵌入模型就可以帮我们做到这件事,所以第一件事情需要将文本中的句子向量化,然后和向量数据库中的向量进行比较,找到最相似的向量。下面使用代码演示下这个过程。
5.2.1 添加一个测试接口
添加一个测试接口,参考下面的代码
package com.congge.web; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.ai.embedding.EmbeddingResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.Map; @RestController @Slf4j public class DocumentController { private final EmbeddingModel embeddingModel; @Autowired public DocumentController(EmbeddingModel embeddingModel) { this.embeddingModel = embeddingModel; } @GetMapping("/ai/embedding") public Map embed(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) { EmbeddingResponse embeddingResponse = this.embeddingModel.embedForResponse(List.of(message)); return Map.of("embedding", embeddingResponse); } //localhost:8081/embedding @GetMapping("/embedding") public Object embeddingTest() { // 文本嵌入 float[] embed = embeddingModel.embed("你好,我是小码农叔叔"); log.info("文本转换得到的向量: {}", embed); return embed; } }
两个接口均可用于测试,选择第二个测试,请求之后,返回了很多向量的参数
5.3 ETL Pipeline
ETL是提取、转换、加载的缩写,从原始的文档到数据库需要经历提取(.doc、.ppt、.xlsx等)、转换(数据结构化、清理数据、数据分块)、写入向量数据库。这个过程可以进行多种处理,确保最后的数据适合AI问答。
SpringAI提供了ETL框架。它是搭建知识库框架的基石。
5.3.1 Spring AI ETL 介绍
在AI应用程序中,数据处理是至关重要的一部分。Spring AI提供了一个强大的ETL框架,帮助开发者高效地进行数据提取、转换和加载操作。通过这个框架,你可以轻松地将数据准备好用于AI模型的训练和推理。
5.3.2 Spring AI 处理ETL完整过程
与传统的etl过程稍有不同,springai 中etl 的完整过程如下:
- 数据提取
- 数据提取是ETL流程的第一步。在这个阶段,你需要从各种数据源中提取原始数据。Spring AI支持多种数据源,包括数据库、文件系统、API等。
- 数据转换
- 数据转换是ETL流程的第二步。在这个阶段,你需要将原始数据转换为适合AI模型使用的格式。Spring AI提供了多种数据转换工具,帮助你高效地处理数据。
- 向量化数据
- 对于AI模型来说,向量化数据是必不可少的步骤。只有经过向量化之后的数据才能在后续的检索中正常检索出结果。
- 数据加载
- 数据加载是ETL流程的最后一步。在这个阶段,你需要将转换后的数据加载到目标存储系统中,以便AI模型使用。Spring AI支持将数据加载到多种目标存储系统中。
5.3.3 Spring AI ETL 技术框架
5.3.3.1 读取器 DocumentReader
DocumentReader ,文档读取器:
- 用于读取文档,比如PDF、Word、Excel等
- 如:JsonReader(读取JSON),TextReader(读取文本),PagePdfDocumentReader(读取PDF),TikaDocumentReader(读取各种文件,大部分都可以支持.pdf,.xlsx,.docx,.pptx,.md,.json等)。
- 这些reader都是DocumentReader的实现类。
5.3.3.2 文档转换器 DocumentTransformer
文档转换器,处理文档:
- TextSplitter(文档切割成小块),ContentFormatTransformer(将文档变成键值对),SummaryMetadataEnricher(使用大模型总结文档),KeywordMetadataEnricher(使用大模型提取文档关键词)
5.3.3.3 文档写入器 DocumentWriter
文档写入器:
- 将文档写入向量数据库或者本地文件。
- VectorStore(向量数据库写入器),FileDocumentWriter(文件写入器)。
使用这几个组件,完整的执行流程如下:
5.4 Spring AI 文档读取操作演示
5.4.1 文件读取代码演示
TikaDocumentReader 比较全能,大部分文件都可读取,支持的文件格式可以参考官方文档。如果是比较个性化文档的场景,最好自己实现一个Reader,便于业务扩展。pom文件中导入下面的依赖。
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-tika-document-reader</artifactId> </dependency>
从输入流读取文件,参考下面的接口代码
@SneakyThrows @PostMapping("read/multipart-file") public void readMultipartFile(@RequestParam MultipartFile file) { // 从IO流中读取文件 Resource resource = new InputStreamResource(file.getInputStream()); List<Document> documents = new TikaDocumentReader(resource) .read(); }
上传一个本地的文档,接口测试效果,可以看到被分割成很多片段了
从本地文件读取,参考下面的接口代码
/** * 从本地文件读取 * @return */ @GetMapping("/read/from-local-file") public Object readLocalFile() { FileSystemResource resource = new FileSystemResource("E:\\工作空间\\wzlocal\\Java编码规范V1.0.pdf"); List<Document> documents = new TikaDocumentReader(resource) .read(); return documents; }
调用一下接口,使用相同的文件,得到类似的效果
5.5 Spring AI 文档转换操作演示
在上一步的操作中,读取返回的是Document对象,而是DocumentETL Pipeline的核心对象,它包含了文档的元数据和内容。接下来就需要对文档进行转换。此时就要用到内容转换器。包括内容转换器和元数据转换器。
内容转换器
- TokenTextSplitter:可以把内容切割成更小的块方便RAG的时候提升响应速度节省Token。
- ContentFormatTransformer:可以把元数据的内容变成键值对字符串。
元数据转换器
- SummaryMetadataEnricher:使用大模型总结文档。会在元数据里面增加一个summary字段。
- KeywordMetadataEnricher:使用大模型提取文档关键词。可以在元数据里面增加一个keywords字段。
5.5.1 添加测试接口
参考下面的代码
/** * 分割后的文档列表 localhost:8081/doc/split * @param file * @return * @throws Exception */ @PostMapping("/doc/split") public Object docSplit(@RequestParam MultipartFile file) throws Exception{ InputStreamResource inputStreamResource = new InputStreamResource(file.getInputStream()); List<Document> documentList = new TikaDocumentReader(inputStreamResource).read(); // 分割后的文档列表 List<Document> splitDocList = new TokenTextSplitter().split(documentList); List<String> contentList = splitDocList.stream().map(Document::getContent).collect(Collectors.toList()); return contentList; }
测试一下接口,可以看到被转换后的文档分割成多个片段
5.6 文档存储
经过前面的步骤,我们得到了一个文档列表,为了方便后续的文档搜索,需要将文档进行存储,文档存储到哪里去呢?即向量数据库。上面准备阶段搭建的Redis-Stack即是用于做向量数据库使用的。下面看代码中的操作过程。
5.6.1 导入依赖文件
导入下面的依赖坐标
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-tika-document-reader</artifactId> <version>1.0.0-M3</version> </dependency> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-redis-store</artifactId> <version>1.0.0-M3</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency>
5.6.2 配置redis信息
在配置文件中添加redis的信息
spring: ai: dashscope: api-key: 你的apikey embedding: options: model: text-embedding-v2 vectorstore: redis: uri: redis://IP:6379 data: redis: database: 0 timeout: 10s lettuce: pool: # 连接池最大连接数 max-active: 200 # 连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: -1ms # 连接池中的最大空闲连接 max-idle: 10 # 连接池中的最小空闲连接 min-idle: 0 repositories: enabled: false host: redis地址
5.6.3 增加一个redis的向量数据库配置类
如果在你的项目里面有用到redis,需要先禁用RedisVectorStoreAutoConfiguration。这是SpringAI自动配置RedisStack的向量数据库连接,会导致Redis的连接配置冲突。参考下面的代码。
package com.congge.config; import lombok.AllArgsConstructor; import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreAutoConfiguration; import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreProperties; import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.ai.vectorstore.RedisVectorStore; import org.springframework.ai.vectorstore.VectorStore; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.data.redis.RedisConnectionDetails; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import redis.clients.jedis.JedisPooled; @Configuration // 禁用SpringAI提供的RedisStack向量数据库的自动配置,会和Redis的配置冲突。 @EnableAutoConfiguration(exclude = {RedisVectorStoreAutoConfiguration.class}) // 读取RedisStack的配置信息 @EnableConfigurationProperties({RedisVectorStoreProperties.class}) @AllArgsConstructor public class RedisVectorConfig { /** * 创建RedisStack向量数据库 * * @param embeddingModel 嵌入模型 * @param properties redis-stack的配置信息 * @return vectorStore 向量数据库 */ @Bean public VectorStore vectorStore(EmbeddingModel embeddingModel, RedisVectorStoreProperties properties, RedisConnectionDetails redisConnectionDetails) { RedisVectorStore.RedisVectorStoreConfig config = RedisVectorStore.RedisVectorStoreConfig.builder().withIndexName(properties.getIndex()).withPrefix(properties.getPrefix()).build(); return new RedisVectorStore(config, embeddingModel, new JedisPooled(redisConnectionDetails.getStandalone().getHost(), redisConnectionDetails.getStandalone().getPort() , redisConnectionDetails.getUsername(), redisConnectionDetails.getPassword()), properties.isInitializeSchema()); } }
5.6.4 增加嵌入文档接口
在上面的VectorStore配置中我们提供了EmbeddingModel,调用vectorStore.add(splitDocuments)底层会把文档给EmbeddingModel把文本变成向量然后再存入向量数据库。参考下面的代码。
/** * 文档保存到向量数据库 localhost:8081/doc/embedding * @param file * @return * @throws Exception */ @PostMapping("/doc/embedding") public Object docEmbedding(@RequestParam MultipartFile file) throws Exception{ TikaDocumentReader tikaDocumentReader = new TikaDocumentReader(new InputStreamResource(file.getInputStream())); List<Document> splitDocuments = new TokenTextSplitter().apply(tikaDocumentReader.read()); // 存入向量数据库,这个过程会自动调用embeddingModel,将文本变成向量存入 vectorStore.add(splitDocuments); return true; }
调用一下接口
接口执行成功后,在Redis-Stack的控制台界面可以看到数据存入了redis中
5.6.5 增加文档检索接口
数据存入进去之后接下来就可以进行搜索了,添加下面文档检索的接口
/** * 关键字检索文档 localhost:8081/doc/query?keyword=面向对象 * @param keyword * @return */ @GetMapping("/doc/query") public List<Document> query(@RequestParam String keyword) { List<Document> documentList = vectorStore.similaritySearch(keyword); return documentList; }
六、写在文末
本文通过较大的篇幅详细介绍了常用的向量数据库解决方案,并通过搭建redis stack环境,结合代码演示了如何基于redis stack作为向量数据库进行使用,希望对看到的同学有用,本篇到此介绍,感谢观看。
到此这篇关于SpringBoot 整合Redis Stack 构建本地向量数据库相似性查询的文章就介绍到这了,更多相关SpringBoot 整合Redis Stack 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
详解手把手Maven搭建SpringMVC+Spring+MyBatis框架(超级详细版)
本篇文章主要介绍了手把手Maven搭建SpringMVC+Spring+MyBatis框架(超级详细版),具有一定的参考价值,感兴趣的小伙伴们可以参考一下2017-12-12
最新评论