Spring Boot AI使用Redis Vector Database作为向量数据库

deepseek > AI (17) 2025-02-20 17:41:04

目标

使用Redis Stack中间件作为向量数据库(Vector Database)实现文档数据的存储和查询功能。

先决条件

已安装好的 redis stack ,redis stack 安装可参考:redis-stack 安装(Docker)

增加redis stock部分maven依赖

该项目基于Spring Boot 接入Ollama实现与Deepseek简单对话修改

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-redis-store-spring-boot-starter</artifactId>
</dependency>

application.yml增加redis相关配置

spring:
  application:
    name: demo-boot-ollama
  ai:
    vectorstore:
      redis:
        initialize-schema: true
        prefix: custom-prefix
        index: custom-index
    ollama: # ai 提供者 ollama
      init:
        pull-model-strategy: never # 下载策略
        embedding:
          additional-models:
            - mxbai-embed-large #redis 向量库默认嵌入模型必须存在否则报错
            - nomic-embed-text
            - chroma/all-minilm-l6-v2-f32
      base-url: http://192.168.31.162:11434
      chat:
        options:
          model: deepseek-r1:8b
  data:
    redis:
      host: 192.168.31.162

Redis Vector Database 写入/查询测试示例

@SpringBootTest
public class RedisVectorTests {
   @Resource
   VectorStore vectorStore;
   @Test
   public void saveDocumentsAndQuery() {
       List<Document> documents = List.of(
               new Document("Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!!", Map.of("meta1", "meta1")),
               new Document("The World is Big and Salvation Lurks Around the Corner"),
               new Document("You walk forward facing the past and you turn back toward the future.", Map.of("meta2", "meta2")));
       // 文档添加到redis
       vectorStore.add(documents);
      // 检索文档类似于查询
       List<Document> results = this.vectorStore.similaritySearch(SearchRequest.builder().query("Spring").topK(5).build());
   }
}

执行结果

Spring Boot AI使用Redis Vector Database作为向量数据库_图示-1cb9ba8e4a664a1a9a4643a978cf43ee.png
第一次执行
Spring Boot AI使用Redis Vector Database作为向量数据库_图示-19fc9bbc0b6745ae9994f6f1d7497bff.png
第二次执行

提示:第二次执行,由于重复写入了两次所以数据有两份,但是查询结果确实根据相关度分数来的,且一共6个数据只查询了分数高的5个

Redis 数据查看:

Spring Boot AI使用Redis Vector Database作为向量数据库_图示-9559bacdc1444c3a9661fe22f4d2d425.png
Redis 数据查看

向量数据库数据存储流程解析

Spring Boot AI使用Redis Vector Database作为向量数据库_图示-c7c7574e44424ddfa732b8a1554d5d97.png
向量数据转换+存储大致流程

通过源码可以看到在存入redis之前,对数据进行了大模型嵌入化,使用了mxbai-embed-large模型

Spring Boot AI使用Redis Vector Database作为向量数据库_图示-752019932c964f819e42af3712fa59c6.png
源码断点调试

 

自定义向量数据库嵌入解析模型

自定义RedisVectorStore, 添加以下配置文件:

@Configuration
public class CustomVectorEmbeddingModelConfig {
    @Bean
    public EmbeddingModel embeddingModel(OllamaApi ollamaApi) {
        return new OllamaEmbeddingModel(
                ollamaApi,
                OllamaOptions.builder()
                        .model(OllamaModel.NOMIC_EMBED_TEXT.id()) //自定义嵌入模型 nomic-embed-text
                        .build(),
                ObservationRegistry.NOOP,
                ModelManagementOptions.defaults()
        );
    }
}

参考:org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreAutoConfiguration 中配置

Spring Boot AI使用Redis Vector Database作为向量数据库_图示-afc38134b8774a81941a703369d1c03b.png
org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreAutoConfiguration

可知,嵌入模型是通过外部已有的bean传递进来的,所以如果只是切换模型就直接重写EmbeddingModel实现即可,参考上方。

 

启动之后断点查看

Spring Boot AI使用Redis Vector Database作为向量数据库_图示-f9f58e7423e04e80ba2ba2f583adf8d9.png
嵌入量化模型已修改为自定义的:nomic-embed-text

注意:修改模型会导致已有数据不兼容!!!

自定义之后就可以继续玩复杂查询了

重写自定义RedisVectorStore(目前版本好像没有其他方法配置增加metadata过滤字段让查询时候生效),添加过滤metadata过滤字段

@Bean
public RedisVectorStore vectorStore(EmbeddingModel embeddingModel, RedisVectorStoreProperties properties, JedisConnectionFactory jedisConnectionFactory, ObjectProvider<ObservationRegistry> observationRegistry, ObjectProvider<VectorStoreObservationConvention> customObservationConvention, BatchingStrategy batchingStrategy) {
    JedisPooled jedisPooled = this.jedisPooled(jedisConnectionFactory);
    return ((RedisVectorStore.Builder)((RedisVectorStore.Builder)((RedisVectorStore.Builder)RedisVectorStore.builder(jedisPooled, embeddingModel)
            .metadataFields(//定义 metadata 用于过滤(filtering)的数据字段
                    RedisVectorStore.MetadataField.tag("m1"),
                    RedisVectorStore.MetadataField.tag("m2")
            )
            .initializeSchema(properties.isInitializeSchema()).observationRegistry((ObservationRegistry)observationRegistry.getIfUnique(() -> {
        return ObservationRegistry.NOOP;
    }))).customObservationConvention((VectorStoreObservationConvention)customObservationConvention.getIfAvailable(() -> {
        return null;
    }))).batchingStrategy(batchingStrategy)).indexName(properties.getIndex()).prefix(properties.getPrefix()).build();
}
private JedisPooled jedisPooled(JedisConnectionFactory jedisConnectionFactory) {
    String host = jedisConnectionFactory.getHostName();
    int port = jedisConnectionFactory.getPort();
    JedisClientConfig clientConfig = DefaultJedisClientConfig.builder().ssl(jedisConnectionFactory.isUseSsl()).clientName(jedisConnectionFactory.getClientName()).timeoutMillis(jedisConnectionFactory.getTimeout()).password(jedisConnectionFactory.getPassword()).build();
    return new JedisPooled(new HostAndPort(host, port), clientConfig);
}

重点代码:



...其他忽略...
        return ((RedisVectorStore.Builder)((RedisVectorStore.Builder)((RedisVectorStore.Builder)
        RedisVectorStore.builder(jedisPooled, embeddingModel)
                .metadataFields(//定义 metadata 用于过滤(filtering)的数据字段
                        RedisVectorStore.MetadataField.tag("m1"),
                        RedisVectorStore.MetadataField.tag("m2")
                )
...其他忽略...

其余代码参考:org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreAutoConfiguration

 

生成新数据:

List<Document> documents = List.of(
        new Document("Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!!", Map.of("m2", "meta1")),
        new Document("The World is Big and Salvation Lurks Around the Corner"),
        new Document("You walk forward facing the past and you turn back toward the future.", Map.of("m1", "meta2")));

metadata 过滤查询:

        List<Document> result = redisVectorStore.similaritySearch(
                SearchRequest.builder()
                .query("Spring")
                .topK(5)
                .similarityThreshold(SearchRequest.SIMILARITY_THRESHOLD_ACCEPT_ALL)
                .filterExpression(
//                        "m2 in ['meta1'] || m1 in ['meta2']"
                        b.or(
                        b.in("m2", "meta1"),
                        b.in("m1","meta2")
                        ).build()
                ).build());

执行结果:

Spring Boot AI使用Redis Vector Database作为向量数据库_图示-23ded4ce9b964a9e801085f3a93fd245.png
2个记录

 

注意哈:虽然只匹配到了一个metadata但是评分高0.7***。评分和算法有关。

 

更多玩法:


评论
User Image
提示:请评论与当前内容相关的回复,广告、推广或无关内容将被删除。

相关文章
目标使用Redis Stack中间件作为向量数据库(Vector Database)实现文档数据的存储和查询功能。先决条件已安装好的 redis stack ,
概述本文讲解Java编程中如何通过Spring AI框架 集成 Redis Stack 向量数据库和Ollama模型服务提供者实现RAG本地外挂知识库。前置条件
继上一篇deepseek Windows安装和入门使用 本地部署deepseek只能在cmd窗口使用,体验感不好。这里使用一个可视化工具Cherry Studi
在科技领域,新兴公司的涌现几乎每天都有,而每一家公司背后都有着独特的故事和潜力。最近,一家名为“深度求索”(DeepSeek)的中国公司引发了广泛关注。这家公司
Ollama 简介Ollama 是一个用于部署本地 AI 模型的工具,开发者可以在自己的机器上运行模型,并通过 API 接口调用。在本地搭建 Ollama 服务
问题ollama国内拉取模型慢,断点续传也蛮怎么办,当然是修改ollama镜像源 配置ollama模型国内镜像源
一 了解什么是 RAGRAG(Retrieval Augmented Generation)检索增强生成,是 2023 年最火热的 LLM 应用系统架构,它的作
LM Studio官网打开连接 LM Studio - Discover, download, and run local LLMs(https://lmstu
安装环境windows 11ollama工具下载ollama工具ollama官网 Download Ollama on Windows注:ollama同时支持L
deepseek-r1的1.5b、7b、8b、14b、32b、70b和671b有啥区别?1.5B、7B、8B、14B、32B、70B是蒸馏后的小模型
Ollama 模型动辄xxGB,默认位置可能不满足需求,特别是Windows,默认的C盘,所以一般都需要调整下Ollama 模型存放位置。ollama 默认的模
确认Ollama兼容您的GPUNvidiaOllama 支持计算能力 5.0 及以上的 Nvidia GPU。要检查您的显卡是否受支持,请查看您的计算兼容性:h
GPUNvidiaOllama 支持计算能力为 5.0 及以上的 Nvidia GPU。检查你的计算兼容性,以确认你的显卡是否受支持: https://deve
概述Ollama官方最新版0.5.7,默认是不支持AMD 780m(代号:gfx1103)集成显卡的,已知方法都是基于一个开源项目ollama-for-amd来
LM Studio 离线模型下载和导入接上一篇LM Studio 安装配置后,使用大模型还得下载模型文件,由于内嵌模型库下载难用(网络原因)这里讲解离线下载后导