亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot集成Redis向量數(shù)據(jù)庫(kù)實(shí)現(xiàn)相似性搜索功能

 更新時(shí)間:2024年09月25日 08:31:07   作者:HBLOG  
Redis?是一個(gè)開(kāi)源(BSD?許可)的內(nèi)存數(shù)據(jù)結(jié)構(gòu)存儲(chǔ),用作數(shù)據(jù)庫(kù)、緩存、消息代理和流式處理引擎,向量檢索的核心原理是通過(guò)將文本或數(shù)據(jù)表示為高維向量,并在查詢時(shí)根據(jù)向量的相似度進(jìn)行搜索,本文給大家介紹了SpringBoot集成Redis向量數(shù)據(jù)庫(kù)實(shí)現(xiàn)相似性搜索功能

1.什么是Redis向量數(shù)據(jù)庫(kù)?

Redis 是一個(gè)開(kāi)源(BSD 許可)的內(nèi)存數(shù)據(jù)結(jié)構(gòu)存儲(chǔ),用作數(shù)據(jù)庫(kù)、緩存、消息代理和流式處理引擎。Redis 提供數(shù)據(jù)結(jié)構(gòu),例如字符串、哈希、列表、集合、帶范圍查詢的有序集合、位圖、超對(duì)數(shù)日志、地理空間索引和流。

Redis 搜索和查詢 擴(kuò)展了 Redis OSS 的核心功能,并允許您將 Redis 用作向量數(shù)據(jù)庫(kù)

  • 在哈?;?JSON 文檔中存儲(chǔ)向量和關(guān)聯(lián)的元數(shù)據(jù)
  • 檢索向量
  • 執(zhí)行向量搜索

2.向量檢索(Vector Search)的核心原理

向量檢索(Vector Search)的核心原理是通過(guò)將文本或數(shù)據(jù)表示為高維向量,并在查詢時(shí)根據(jù)向量的相似度進(jìn)行搜索。在你的代碼中,向量檢索過(guò)程涉及以下幾步:

匹配的原理:

  • 檢索的核心是將文本或數(shù)據(jù)轉(zhuǎn)換成向量,在高維向量空間中查找與查詢最相似的向量。
  • 在存儲(chǔ)數(shù)據(jù)時(shí)將指定的字段通過(guò)嵌入模型生成了向量。
  • 在檢索時(shí),查詢文本被向量化,然后與 Redis 中存儲(chǔ)的向量進(jìn)行相似度比較,找到相似度最高的向量(即相關(guān)的文檔)。

關(guān)鍵點(diǎn):

  • 嵌入模型 將文本轉(zhuǎn)換成向量。
  • 相似度計(jì)算 通過(guò)余弦相似度或歐幾里得距離來(lái)度量相似性。
  • Top K 返回相似度最高的 K 個(gè)文檔。

具體過(guò)程

1. 向量化數(shù)據(jù):

當(dāng)你將 JSON 中的字段存入 Redis 時(shí),向量化工具(例如 vectorStore)會(huì)將指定的字段轉(zhuǎn)換為高維向量。每個(gè)字段的內(nèi)容會(huì)通過(guò)某種嵌入模型(如 Word2Vec、BERT、OpenAI Embeddings 等)轉(zhuǎn)換成向量表示。每個(gè)向量表示的是該字段內(nèi)容的語(yǔ)義特征。

2. 搜索時(shí)的向量生成:

當(dāng)執(zhí)行 SearchRequest.query(message) 時(shí),系統(tǒng)會(huì)將輸入的 message 轉(zhuǎn)換為一個(gè)查詢向量。這一步是通過(guò)同樣的嵌入模型,將查詢文本轉(zhuǎn)換為與存儲(chǔ)在 Redis 中相同維度的向量。

3. 相似度匹配:

vectorStore.similaritySearch(request) 函數(shù)使用了一個(gè)向量相似度計(jì)算方法來(lái)查找最相似的向量。這通常是通過(guò) 余弦相似度歐幾里得距離 來(lái)度量查詢向量和存儲(chǔ)向量之間的距離。然后返回與查詢最相似的前 K 個(gè)文檔,即 withTopK(topK) 所指定的 K 個(gè)最相關(guān)的結(jié)果。

4. 返回匹配的文檔:

匹配的結(jié)果是根據(jù)相似度得分排序的 List<Document>。這些文檔是你最初存儲(chǔ)在 Redis 中的記錄,包含了 JSON 中指定的字段。

3.環(huán)境搭建

version: '3'
services:
  redis-stack:
    image: redis/redis-stack
    ports:
      - 6379:6379

  redis-insight:
    image: redislabs/redisinsight:latest
    ports:
      - 5540:5540

Run following command:

docker-compose up -d

訪問(wèn) http://localhost:5540

4.代碼工程

實(shí)驗(yàn)?zāi)繕?biāo)

實(shí)現(xiàn)文件數(shù)據(jù)向量化到redis,并進(jìn)行相似性搜索

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.1</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>RedisVectorStore</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <spring-ai.version>0.8.1</spring-ai.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-transformers-spring-boot-starter</artifactId>
            <version>${spring-ai.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-redis-spring-boot-starter</artifactId>
            <version>${spring-ai.version}</version>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>5.1.0</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>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <releases>
                <enabled>false</enabled>
            </releases>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
        <pluginRepository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <releases>
                <enabled>false</enabled>
            </releases>
        </pluginRepository>
    </pluginRepositories>
</project>

controller

package com.et.controller;

import com.et.service.SearchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.et.service.SearchService;
import java.util.HashMap;
import java.util.Map;

@RestController
public class HelloWorldController {
    @Autowired
    SearchService searchService;
    @RequestMapping("/hello")
    public Map<String, Object> showHelloWorld(){
        Map<String, Object> map = new HashMap<>();
        map.put("msg", searchService.retrieve("beer"));
        return map;
    }
}

configuration

加載文件數(shù)據(jù)到并將數(shù)據(jù)向量化到redis

JsonReader loader = new JsonReader(file, KEYS);

JsonReader 和 VectorStore 實(shí)現(xiàn)是將 KEYS 中指定的多個(gè)字段拼接在一起,生成一個(gè)統(tǒng)一的文本表示,然后通過(guò)嵌入模型將這些字段的組合文本轉(zhuǎn)換為一個(gè)單一的向量,那么這里就是將多個(gè)字段組合成 一個(gè)綜合向量。并將其處理后存入 Redis。

package com.et.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreProperties;
import org.springframework.ai.reader.JsonReader;
import org.springframework.ai.vectorstore.RedisVectorStore;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.zip.GZIPInputStream;

@Component
public class DataLoader implements ApplicationRunner {

   private static final Logger logger = LoggerFactory.getLogger(DataLoader.class);

   private static final String[] KEYS = { "name", "abv", "ibu", "description" };

   @Value("classpath:/data/beers.json.gz")
   private Resource data;

   private final RedisVectorStore vectorStore;

   private final RedisVectorStoreProperties properties;

   public DataLoader(RedisVectorStore vectorStore, RedisVectorStoreProperties properties) {
      this.vectorStore = vectorStore;
      this.properties = properties;
   }

   @Override
   public void run(ApplicationArguments args) throws Exception {
      Map<String, Object> indexInfo = vectorStore.getJedis().ftInfo(properties.getIndex());
      Long sss= (Long) indexInfo.getOrDefault("num_docs", "0");
      int numDocs=sss.intValue();
      if (numDocs > 20000) {
         logger.info("Embeddings already loaded. Skipping");
         return;
      }
      Resource file = data;
      if (data.getFilename().endsWith(".gz")) {
         GZIPInputStream inputStream = new GZIPInputStream(data.getInputStream());
         file = new InputStreamResource(inputStream, "beers.json.gz");
      }
      logger.info("Creating Embeddings...");
      // tag::loader[]
      // Create a JSON reader with fields relevant to our use case
      JsonReader loader = new JsonReader(file, KEYS);
      // Use the autowired VectorStore to insert the documents into Redis
      vectorStore.add(loader.get());
      // end::loader[]
      logger.info("Embeddings created.");
   }

}

配置redis vectorStore

package com.et.config;

import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreProperties;
import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.document.MetadataMode;
import org.springframework.ai.transformers.TransformersEmbeddingClient;
import org.springframework.ai.vectorstore.RedisVectorStore;
import org.springframework.ai.vectorstore.RedisVectorStore.RedisVectorStoreConfig;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RedisConfiguration {

    @Bean
    TransformersEmbeddingClient transformersEmbeddingClient() {
        return new TransformersEmbeddingClient(MetadataMode.EMBED);
    }

    @Bean
    VectorStore vectorStore(TransformersEmbeddingClient embeddingClient, RedisVectorStoreProperties properties) {
        var config = RedisVectorStoreConfig.builder().withURI(properties.getUri()).withIndexName(properties.getIndex())
                .withPrefix(properties.getPrefix()).build();
        RedisVectorStore vectorStore = new RedisVectorStore(config, embeddingClient);
        vectorStore.afterPropertiesSet();
        return vectorStore;
    }


}

service

查詢時(shí),查詢文本也會(huì)生成一個(gè)整體向量,與存儲(chǔ)的綜合向量進(jìn)行匹配。

package com.et.service;


import org.springframework.ai.document.Document;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class SearchService {


   @Value("${topk:10}")
   private int topK;

   @Autowired
   private  VectorStore vectorStore;



   public List<Document> retrieve(String message) {
      SearchRequest request = SearchRequest.query(message).withTopK(topK);
      // Query Redis for the top K documents most relevant to the input message
      List<Document> docs = vectorStore.similaritySearch(request);

      return docs;
   }

}

只是一些關(guān)鍵代碼,所有代碼請(qǐng)參見(jiàn)下面代碼倉(cāng)庫(kù)

代碼倉(cāng)庫(kù)

5.測(cè)試

啟動(dòng)Spring Boot應(yīng)用程序,查看日志

 . ____ _ __ _ _
 /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/ ___)| |_)| | | | | || (_| | ) ) ) )
 ' |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot :: (v3.2.1)

2024-09-24T14:03:48.217+08:00 INFO 23996 --- [ main] com.et.DemoApplication : Starting DemoApplication using Java 17.0.9 with PID 23996 (D:\IdeaProjects\ETFramework\RedisVectorStore\target\classes started by Dell in D:\IdeaProjects\ETFramework)
2024-09-24T14:03:48.221+08:00 INFO 23996 --- [ main] com.et.DemoApplication : No active profile set, falling back to 1 default profile: "default"
2024-09-24T14:03:49.186+08:00 INFO 23996 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8088 (http)
2024-09-24T14:03:49.199+08:00 INFO 23996 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2024-09-24T14:03:49.199+08:00 INFO 23996 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.17]
2024-09-24T14:03:49.289+08:00 INFO 23996 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2024-09-24T14:03:49.290+08:00 INFO 23996 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1033 ms
2024-09-24T14:03:49.406+08:00 WARN 23996 --- [ main] ai.djl.util.cuda.CudaUtils : Failed to detect GPU count: CUDA driver version is insufficient for CUDA runtime version (35)
2024-09-24T14:03:49.407+08:00 WARN 23996 --- [ main] ai.djl.util.cuda.CudaUtils : Failed to detect GPU count: CUDA driver version is insufficient for CUDA runtime version (35)
2024-09-24T14:03:49.408+08:00 INFO 23996 --- [ main] ai.djl.util.Platform : Found matching platform from: jar:file:/D:/jar_repository/ai/djl/huggingface/tokenizers/0.26.0/tokenizers-0.26.0.jar!/native/lib/tokenizers.properties
2024-09-24T14:03:49.867+08:00 INFO 23996 --- [ main] o.s.a.t.TransformersEmbeddingClient : Model input names: input_ids, attention_mask, token_type_ids
2024-09-24T14:03:49.867+08:00 INFO 23996 --- [ main] o.s.a.t.TransformersEmbeddingClient : Model output names: last_hidden_state
2024-09-24T14:03:50.346+08:00 INFO 23996 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8088 (http) with context path ''
2024-09-24T14:03:50.354+08:00 INFO 23996 --- [ main] com.et.DemoApplication : Started DemoApplication in 2.522 seconds (process running for 2.933)
2024-09-24T14:03:50.364+08:00 INFO 23996 --- [ main] com.et.config.DataLoader : Creating Embeddings...
2024-09-24T14:03:51.493+08:00 WARN 23996 --- [ main] ai.djl.util.cuda.CudaUtils : Failed to detect GPU count: CUDA driver version is insufficient for CUDA runtime version (35)
2024-09-24T14:03:51.800+08:00 INFO 23996 --- [ main] ai.djl.pytorch.engine.PtEngine : PyTorch graph executor optimizer is enabled, this may impact your inference latency and throughput. See: https://docs.djl.ai/docs/development/inference_performance_optimization.html#graph-executor-optimization
2024-09-24T14:03:51.802+08:00 INFO 23996 --- [ main] ai.djl.pytorch.engine.PtEngine : Number of inter-op threads is 6
2024-09-24T14:03:51.802+08:00 INFO 23996 --- [ main] ai.djl.pytorch.engine.PtEngine : Number of intra-op threads is 6
2024-09-24T14:04:26.212+08:00 INFO 23996 --- [nio-8088-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2024-09-24T14:04:26.213+08:00 INFO 23996 --- [nio-8088-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2024-09-24T14:04:26.215+08:00 INFO 23996 --- [nio-8088-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 2 ms
2024-09-24T14:09:48.846+08:00 INFO 23996 --- [ main] com.et.config.DataLoader : Embeddings created.

查看redis是否存在向量化的數(shù)據(jù)

訪問(wèn)http://127.0.0.1:8088/hello 進(jìn)行0 相似度搜索(top 10),返回得分前10的數(shù)據(jù)

以上就是SpringBoot集成Redis向量數(shù)據(jù)庫(kù)實(shí)現(xiàn)相似性搜索功能的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot Redis相似性搜索的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java使用ByteBuffer進(jìn)行多文件合并和拆分的代碼實(shí)現(xiàn)

    Java使用ByteBuffer進(jìn)行多文件合并和拆分的代碼實(shí)現(xiàn)

    因?yàn)轵?yàn)證證書(shū)的需要,需要把證書(shū)文件和公鑰給到客戶,考慮到多個(gè)文件交互的不便性,所以決定將2個(gè)文件合并成一個(gè)文件交互給客戶,但是由于是加密文件,采用字符串形式合并后,拆分后文件不可用,本文給大家介紹了Java使用ByteBuffer進(jìn)行多文件合并和拆分,需要的朋友可以參考下
    2024-09-09
  • JSP安全開(kāi)發(fā)之XSS漏洞詳解

    JSP安全開(kāi)發(fā)之XSS漏洞詳解

    XSS又叫CSS (Cross Site Script) ,跨站腳本攻擊。它指的是惡意攻擊者往Web頁(yè)面里插入惡意腳本代碼,而程序?qū)τ谟脩糨斎雰?nèi)容未過(guò)濾,當(dāng)用戶瀏覽該頁(yè)之時(shí),嵌入其中Web里面的腳本代碼會(huì)被執(zhí)行,從而達(dá)到惡意攻擊用戶的特殊目的。
    2016-09-09
  • Alibaba?Nacos配置中心動(dòng)態(tài)感知原理示例解析

    Alibaba?Nacos配置中心動(dòng)態(tài)感知原理示例解析

    這篇文章主要介紹了Alibaba?Nacos配置中心動(dòng)態(tài)感知原理示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • SpringBoot項(xiàng)目從18.18M瘦身到0.18M的實(shí)現(xiàn)

    SpringBoot項(xiàng)目從18.18M瘦身到0.18M的實(shí)現(xiàn)

    本文主要介紹了SpringBoot項(xiàng)目從18.18M瘦身到0.18M的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • Springboot使用異步請(qǐng)求提高系統(tǒng)的吞吐量詳解

    Springboot使用異步請(qǐng)求提高系統(tǒng)的吞吐量詳解

    這篇文章主要介紹了Springboot使用異步請(qǐng)求提高系統(tǒng)的吞吐量詳解,和同步請(qǐng)求相對(duì),異步不需要等待響應(yīng),隨時(shí)可以發(fā)送下一次請(qǐng)求,如果是同步請(qǐng)求,需要將信息填寫(xiě)完整,再發(fā)送請(qǐng)求,服務(wù)器響應(yīng)填寫(xiě)是否正確,再做修改,需要的朋友可以參考下
    2023-08-08
  • Java程序員必須知道的5個(gè)JVM命令行標(biāo)志

    Java程序員必須知道的5個(gè)JVM命令行標(biāo)志

    這篇文章主要介紹了每個(gè)Java程序員必須知道的5個(gè)JVM命令行標(biāo)志,需要的朋友可以參考下
    2015-03-03
  • java validation 后臺(tái)參數(shù)驗(yàn)證的使用詳解

    java validation 后臺(tái)參數(shù)驗(yàn)證的使用詳解

    本篇文章主要介紹了java validation 后臺(tái)參數(shù)驗(yàn)證的使用詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • java項(xiàng)目實(shí)現(xiàn)猜拳小游戲

    java項(xiàng)目實(shí)現(xiàn)猜拳小游戲

    這篇文章主要為大家詳細(xì)介紹了java項(xiàng)目實(shí)現(xiàn)猜拳小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • Java中的Phaser使用詳解

    Java中的Phaser使用詳解

    這篇文章主要介紹了Java中的Phaser使用詳解,與其他障礙不同,注冊(cè)在phaser上進(jìn)行同步的parties數(shù)量可能會(huì)隨時(shí)間變化,任務(wù)可以隨時(shí)進(jìn)行注冊(cè),需要的朋友可以參考下
    2023-11-11
  • IntelliJ IDEA 關(guān)閉多余項(xiàng)目的操作方法

    IntelliJ IDEA 關(guān)閉多余項(xiàng)目的操作方法

    這篇文章主要介紹了IntelliJ IDEA 關(guān)閉多余項(xiàng)目的操作方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04

最新評(píng)論