开源模型应用落地-工具使用篇-向量数据库进阶(四) ...

打印 上一主题 下一主题

主题 1005|帖子 1005|积分 3015

一、前言

    通过学习"开源模型应用落地"系列文章,我们成功地建立了一个完整可实行的AI交付流程。现在,我们要引入向量数据库,作为我们AI服务的二级缓存。本文将继续基于上一篇“开源模型应用落地-工具使用篇-向量数据库(三)”详细介绍怎样通过Java来使用Milvus Lite来为我们的AI服务部署一个前置缓存。

二、术语

2.1、向量数据库

    向量数据库是一种专门用于存储和处理高维向量数据的数据库系统。与传统的关系型数据库或文档数据库差别,向量数据库的计划目标是高效地支持向量数据的索引和相似性搜索。
    在传统数据库中,数据通常是以布局化的表格形式存储,每个记录都有预定义的字段。但是,对于包罗大量高维向量的数据,如图像、音频、文本等,传统的数据库模型往往无法有效地处理。向量数据库通过引入特定的数据布局和索引算法,答应高效地存储和查询向量数据。
    向量数据库的核心概念是向量索引。它使用一种称为向量空间模型的方法,将向量映射到多维空间中的点,并利用这种映射关系构建索引布局。这样,当需要搜索相似向量时,可以通过计算向量之间的距离或相似度来快速定位相似的向量。
2.2、Milvus

    是一个开源的向量数据库引擎,专门用于存储和处理大规模高维向量数据。它提供了高效的向量索引和相似性搜索功能,使用户可以或许快速地举行向量数据的存储、查询和分析。
    Milvus的计划目标是为了满足今世应用中对大规模向量数据的需求,例如人脸识别、图像搜索、推荐系统等。它接纳了向量空间模型和多种索引算法,包括倒排索引、近似近来邻(Approximate Nearest Neighbor,ANN)等,以支持高效的相似性搜索。
    Milvus提供了易于使用的编程接口和丰富的功能,使用户可以方便地插入、查询和分析向量数据。它支持多种数据范例的向量,包括浮点型、整型等,也支持多种距离度量方法,如欧氏距离、余弦相似度等。
    Milvus还提供了分布式部署和横向扩展的能力,可以在多台呆板上构建高可用性和高性能的向量数据库集群。它支持数据的分片和负载平衡,可以处理大规模数据集和高并发查询。
2.3、Milvus Lite

    是Milvus向量数据库的一个轻量级版本。旨在提供在资源受限的情况中快速、高效地举行向量存储和相似性搜索的能力。
    与完整版的Milvus相比,它具有以下特点:


  • 轻量级:Milvus Lite具有较小的存储占用和内存消耗,适合在资源受限的设备上部署和运行。
  • 快速部署:Milvus Lite提供了简化的部署和配置过程,使其更易于在嵌入式设备和边缘服务器上举行部署和集成。
  • 高效的向量索引和搜索:尽管是轻量级版本,Milvus Lite仍旧提供了高效的向量索引和相似性搜索功能,以支持快速的向量数据查询。
  • 离线模式:Milvus Lite支持在离线模式下举行向量索引和搜索,无需及时毗连到远程服务器。
2.4、Attu

    是Milvus 的高效开源管理工具。 它具有直观的图形用户界面(GUI),使您可以轻松地与数据库举行交互。
2.5、Milvus 支持的索引范例



  • FLAT: 是一种无索引的范例,它会对全部的向量举行暴力搜索,保证 100% 的召回率,但是查询速度较慢,适用于数据量较小或者对精度要求很高的场景
  • IVF_FLAT: 是一种基于倒排文件(Inverted File)的索引范例,它会先对向量举行聚类,然后在每个聚类中建立 FLAT 索引,查询时只需要在近来的聚类中搜索,可以加速查询,但是需要指定聚类数量和查询数量,适用于数据量较大或者对速度要求较高的场景
  • IVF_SQ8: 是一种基于倒排文件和量化(Quantization)的索引范例,它会先对向量举行聚类,然后在每个聚类中使用乘积量化(Product Quantization)将向量压缩为 8 位整数,查询时只需要在近来的聚类中搜索,并使用查找表(Lookup Table)举行距离计算,可以节省存储空间和加速查询,但是会丧失肯定的精度,适用于数据量很大或者对存储空间要求较高的场景
  •  IVF_PQ: 是一种基于倒排文件和量化的索引范例,它会先对向量举行聚类,然后在每个聚类中使用乘积量化将向量压缩为 8 位整数,并使用倒排表(Inverted List)存储压缩后的向量,查询时只需要在近来的聚类中搜索,并使用查找表举行距离计算,可以节省存储空间和加速查询,但是会丧失肯定的精度,适用于数据量很大或者对存储空间要求较高的场景
  • GPU_IVF_FLAT: 是一种基于 GPU 的倒排文件索引范例,它与 IVF_FLAT 索引相似,但是可以利用 GPU 的并行计算能力来加速查询,适用于数据量较大或者对速度要求很高的场景
  • GPU_IVF_PQ: 是一种基于 GPU 的倒排文件和量化索引范例,它与 IVF_PQ 索引相似,但是可以利用 GPU 的并行计算能力来加速查询,适用于数据量很大或者对速度要求很高的场景
  •  HNSW :是一种基于层次化导航图(Hierarchical Navigable Small World)的索引范例,它会构建一个多层次的图布局来表示向量之间的近邻关系,并使用启发式搜索算法来快速找到近来邻向量,可以实现高速高召回的查询,但是需要指定树的数量和搜索深度等参数,适用于数据维度较高或者对精度要求较高的场景
  • DISKANN :是一种基于磁盘分区和近似近来邻搜索(Disk-based Partitioned Approximate Nearest Neighbor Search)的索引范例,它会将向量划分为多个磁盘分区,并在每个分区中构建 HNSW 索引,并使用多线程并行搜索算法来快速找到近来邻向量,可以实现高效地检索海量数据,但是需要指定分区数量和线程数量等参数,适用于数据量极大或者对存储空间要求较高的场景。

 三、使用方式

3.1、架构示意图

这里的Milvus Lite部署在内网,位于业务服务和AI服务的中间,作为AI服务的二级缓存(一级缓存为Redis),为AI服务减缓负载压力。


3.2、安装Milvus Lite

     1. 创建假造情况
         conda create --name milvus python=3.10
     2. 激活假造情况
        conda activate milvus
     3.  安装milvus包
        pip install milvus

3.3、编写Milvus Lite服务端代码

   此处将Milvus Lite作为 Python 模块启动
  
  1. from milvus import default_server
  2. def start_server():
  3.     default_server.start()
  4. def stop_server():
  5.     default_server.stop()
  6. if __name__ == '__main__':
  7.     with default_server:
  8.         start_server()
  9.         input("按下任意键继续...")
复制代码
3.4、启动Milvus Lite服务

    python -u 上述代码的文件名
    

    启动完成后,会监听19530端口
3.5、安装Milvus客户端管理工具

    下载地址:Releases · zilliztech/attu · GitHub
3.6、登录Milvus Lite服务端

    注意根据实际情况调解IP和端口,默认端口为19530

登录进去,就能看到如下信息:



四、业务整合

业务数据需要提前初始化到向量数据库中
4.1、导入maven依赖

  
  1. <dependency>
  2.     <groupId>io.milvus</groupId>
  3.     <artifactId>milvus-sdk-java</artifactId>
  4.     <version>2.2.2</version>
  5. </dependency>
复制代码
PS: 我的JDK是1.8版本,若milvus版本太高,会出现兼容性问题,需要注意
maven堆栈地址:Maven Repository: io.milvus » milvus-sdk-java

4.2、毗连milvus服务端

  
  1. public static MilvusServiceClient connect_db(String uri) {
  2.         MilvusServiceClient milvusClient = new MilvusServiceClient(
  3.                 ConnectParam.newBuilder()
  4.                         .withUri(uri)
  5. //                    .withToken("root:Milvus")
  6.                         .build()
  7.         );
  8.         return milvusClient;
  9. }
复制代码
4.3、创建集合

  
  1. public static Map<String, String> create_collection(MilvusServiceClient milvusClient, String collection_name, String description, int shardsNum, List<FieldType> fieldTypes) {
  2.         if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {
  3.             log.warn("集合名称为空.");
  4.             return MapUtil.builder("status", "1").build();
  5.         }
  6.         if (CollUtil.isEmpty(fieldTypes)) {
  7.             log.warn("集合字段为空.");
  8.             return MapUtil.builder("status", "1").build();
  9.         }
  10.         CreateCollectionParam.Builder builder = CreateCollectionParam.newBuilder().withCollectionName(collection_name)
  11.                 .withShardsNum(shardsNum);
  12.         for (FieldType fieldType : fieldTypes) {
  13.             builder.addFieldType(fieldType);
  14.         }
  15.         if (StringUtils.isNotEmpty(description) && StringUtils.isNotBlank(description)) {
  16.             builder.withDescription(description);
  17.         }
  18.         CreateCollectionParam createCollectionReq = builder.build();
  19.         R<RpcStatus> rstatus = milvusClient.createCollection(createCollectionReq);
  20.         return buildResult(rstatus);
  21.     }
复制代码
创建成功后:

4.4、插入数据

  
  1. public static Map<String, String>  insert_data(MilvusServiceClient milvusClient, String collection_name,List<InsertParam.Field> fields){
  2.         if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {
  3.             log.warn("集合名称为空.");
  4.             return MapUtil.builder("status", "1").build();
  5.         }
  6.         if (CollUtil.isEmpty(fields)) {
  7.             log.warn("插入数据为空.");
  8.             return MapUtil.builder("status", "1").build();
  9.         }
  10.         InsertParam insertParam = InsertParam.newBuilder()
  11.                 .withCollectionName(collection_name)
  12.                 .withFields(fields)
  13.                 .build();
  14.         R<MutationResult> mutationResultR = milvusClient.insert(insertParam);
  15.         String status = String.valueOf(mutationResultR.getStatus());
  16.         MapBuilder<String, String> mapBuilder = MapUtil.builder("status", status);
  17.         MutationResult mutationResult = mutationResultR.getData();
  18.         if(null != mutationResult){
  19.             long insert_cnt = mutationResult.getInsertCnt();
  20.             if(insert_cnt > 0){
  21.                 mapBuilder.put("msg","插入成功");
  22.             }
  23.         }
  24.         milvusClient.flush(FlushParam.newBuilder()
  25.                 .addCollectionName(collection_name)
  26. //                .withSyncFlush(true)
  27.                 .build());
  28.         log.info("MutationResult: {}",mutationResultR);
  29.         return mapBuilder.build();
  30.     }
复制代码
插入成功后(需要调用flush才能立刻看到数据):

4.5、创建索引

  
  1. public static Map<String, String> create_index(MilvusServiceClient milvusClient, String collection_name, String index_column, String index_name, String params) {
  2.         if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {
  3.             log.warn("集合名称为空.");
  4.             return MapUtil.builder("status", "1").build();
  5.         }
  6.         if (StringUtils.isEmpty(index_column) || StringUtils.isBlank(index_column)) {
  7.             log.warn("索引字段为空.");
  8.             return MapUtil.builder("status", "1").build();
  9.         }
  10.         if (StringUtils.isEmpty(index_name) || StringUtils.isBlank(index_name)) {
  11.             log.warn("索引名称为空.");
  12.             return MapUtil.builder("status", "1").build();
  13.         }
  14.         CreateIndexParam.Builder builder = CreateIndexParam.newBuilder()
  15.                 .withIndexName(index_name)
  16.                 .withCollectionName(collection_name)
  17.                 .withFieldName(index_column)
  18.                 .withIndexType(IndexType.IVF_FLAT)
  19.                 .withMetricType(MetricType.IP)
  20.                 .withSyncMode(Boolean.FALSE);
  21.         if (StringUtils.isNotEmpty(index_name) && StringUtils.isNotBlank(index_name)) {
  22.             builder = builder.withExtraParam(params);
  23.         }
  24.         R<RpcStatus> rstatus = milvusClient.createIndex(
  25.                 builder.build()
  26.         );
  27.         return buildResult(rstatus);
  28.     }
复制代码
metric_type说明:
IP(内积)是一种表示向量之间相似程度的度量方式,它的计算方式是将两个向量中对应位置的元素相乘后求和。IP 的值越大,表示两个向量越相似;IP 的值越小,表示两个向量越不相似。IP 适用于只需要考虑向量之间的相似度,而不需要考虑各个维度之间的权重关系的场景,例如自然语言处理、计算机视觉等领域。
L2(欧氏距离)是一种表示向量之间直线距离的度量方式,它的计算方式是将两个向量中对应位置的元素相减后平方,再将平方和求和并开平方;L2 的值越小,表示两个向量越相似;L2 的值越大,表示两个向量越不相似。L2 适用于需要考虑各个维度之间的权重关系,或者需要将向量转化为单位向量举行相似度计算的场景,例如数值计算、信号处理、图像处理、呆板学习等领域。
 
创建成功后:

4.6、加载数据至缓存

  
  1. public static Map<String, String> load_in_memory(MilvusServiceClient milvusClient, String collection_name) {
  2.         if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {
  3.             log.warn("集合名称为空.");
  4.             return MapUtil.builder("status", "1").build();
  5.         }
  6.         R<RpcStatus> rstatus = milvusClient.loadCollection(
  7.                 LoadCollectionParam.newBuilder()
  8.                         .withCollectionName(collection_name)
  9.                         .build()
  10.         );
  11.         return buildResult(rstatus);
  12.     }
复制代码

4.7、根据向量检索数据

  
  1. public static Map<String, String> search_data_vector(MilvusServiceClient milvusClient, String collection_name, String fieldName, List<List<Float>> search_vectors, String params, int topK, List<String> search_output_fields) {
  2.         if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {
  3.             log.warn("集合名称为空.");
  4.             return MapUtil.builder("status", "1").build();
  5.         }
  6.         if (StringUtils.isEmpty(fieldName) || StringUtils.isBlank(fieldName)) {
  7.             log.warn("检索字段为空.");
  8.             return MapUtil.builder("status", "1").build();
  9.         }
  10.         if (CollUtil.isEmpty(search_vectors) || CollUtil.isEmpty(search_vectors.get(0))) {
  11.             log.warn("检索向量为空.");
  12.             return MapUtil.builder("status", "1").build();
  13.         }
  14.         if (CollUtil.isEmpty(search_output_fields)) {
  15.             log.warn("输出字段为空.");
  16.             return MapUtil.builder("status", "1").build();
  17.         }
  18.         if (topK <= 1) {
  19.             log.warn("topK少于1.");
  20.             topK = 1;
  21.         }
  22.         SearchParam.Builder builder = SearchParam.newBuilder().withCollectionName(collection_name)
  23.                 .withConsistencyLevel(ConsistencyLevelEnum.STRONG)
  24.                 .withMetricType(MetricType.IP)
  25.                 .withOutFields(search_output_fields)
  26.                 .withTopK(topK)
  27.                 .withVectors(search_vectors)
  28.                 .withVectorFieldName(fieldName);
  29.         if (StringUtils.isNotEmpty(params) && StringUtils.isNotBlank(params)) {
  30.             builder.withParams(params);
  31.         }
  32.         SearchParam searchParam = builder.build();
  33.         R<SearchResults> respSearch = milvusClient.search(searchParam);
  34.         String status = String.valueOf(respSearch.getStatus());
  35.         MapBuilder<String, String> mapBuilder = MapUtil.builder("status", status);
  36.         if (StringUtils.equals(status, "0")) {
  37.             SearchResults searchResults = respSearch.getData();
  38.             if (null != searchResults) {
  39.                 SearchResultData searchResultData = searchResults.getResults();
  40.                 if (null != searchResultData) {
  41.                     long num_queries = searchResultData.getNumQueries();
  42. //                    log.info("num_queries: {}", num_queries);
  43.                     if (num_queries > 0) {
  44.                         FieldData fieldData = searchResultData.getFieldsData(0);
  45.                         if (null != fieldData) {
  46.                             ScalarField scalarField = fieldData.getScalars();
  47.                             if (null != scalarField.getStringData()) {
  48.                                 String content = scalarField.getStringData().getData(0);
  49.                                 mapBuilder.put("content", content);
  50. //                                log.info("content: {}", content);
  51.                             }
  52.                         }
  53.                     }
  54.                 }
  55.             }
  56.         }
  57.         return mapBuilder.build();
  58.     }
复制代码
4.8、删除索引

  
  1. public static Map<String, String> drop_index(MilvusServiceClient milvusClient, String collection_name, String index_name) {
  2.         if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {
  3.             log.warn("集合名称为空.");
  4.             return MapUtil.builder("status", "1").build();
  5.         }
  6.         if (StringUtils.isEmpty(index_name) || StringUtils.isBlank(index_name)) {
  7.             log.warn("索引名称为空.");
  8.             return MapUtil.builder("status", "1").build();
  9.         }
  10.         R<RpcStatus> rstatus = milvusClient.dropIndex(
  11.                 DropIndexParam.newBuilder()
  12.                         .withCollectionName(collection_name)
  13.                         .withIndexName(index_name)
  14.                         .build()
  15.         );
  16.         return buildResult(rstatus);
  17.     }
复制代码
4.9、删除集合

  
  1. public static Map<String, String> drop_collection(MilvusServiceClient milvusClient, String collection_name) {
  2.         R<RpcStatus> rstatus = milvusClient.dropCollection(
  3.                 DropCollectionParam.newBuilder()
  4.                         .withCollectionName(collection_name)
  5.                         .build()
  6.         );
  7.         return buildResult(rstatus);
  8.     }
复制代码
4.10、开释缓存

  
  1. public static Map<String, String> unload_in_memory(MilvusServiceClient milvusClient, String collection_name) {
  2.         if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {
  3.             log.warn("集合名称为空.");
  4.             return MapUtil.builder("status", "1").build();
  5.         }
  6.         R<RpcStatus> rstatus = milvusClient.releaseCollection(
  7.                 ReleaseCollectionParam.newBuilder()
  8.                         .withCollectionName(collection_name)
  9.                         .build());
  10.         return buildResult(rstatus);
  11.     }
复制代码


五、附带说明

5.1、高维向量表示的优劣
上风:


  • 表示能力增强:高维向量可以提供更丰富的信息表示能力,可以或许捕捉更多的特征和关系,从而进步模型的表达能力。
  • 解决冗余信息:在高维空间中,冗余特征可能会被稀疏化,使得模型更容易识别和利用有效的特征。
  • 处理复杂问题:某些复杂问题可能需要更高维度的向量来表示,以便更好地捕捉问题的复杂性和多样性。
劣势


  • 维度灾难:高维度数据可能导致维度灾难问题,即数据稀疏性增加,对于有限的练习数据而言,模型的泛化能力可能会受到影响。
  • 计算复杂性增加:高维度数据需要更多的计算资源和时间来处理和分析,可能会增加计算的复杂性和开销。
  • 数据稀疏性:在高维空间中,数据点之间的距离变得更远,可能会导致数据稀疏性增加,从而影响模型的正确性和可靠性。
5.2、插入数据成功但无法检索
     需要调用flush
     milvusClient.flush(FlushParam.newBuilder() .addCollectionName(collection_name) .build());

5.3、怎样批量插入数据
     集合中放入多条数据即可

5.4、受限于篇幅过长,怎样提拔向量检索精度、怎样获取文本向量及怎样对向量举行预处理(向量长度补全、归一化、尺度化)将另文讲解
5.5、完整代码
  
  1. package com.zwzt.communication.netty.test;import cn.hutool.core.collection.CollUtil;import cn.hutool.core.map.MapBuilder;import cn.hutool.core.map.MapUtil;import cn.hutool.core.util.ObjectUtil;import io.milvus.client.MilvusServiceClient;import io.milvus.common.clientenum.ConsistencyLevelEnum;import io.milvus.grpc.*;import io.milvus.param.*;import io.milvus.param.collection.*;import io.milvus.param.dml.InsertParam;import io.milvus.param.dml.SearchParam;import io.milvus.param.index.CreateIndexParam;import io.milvus.param.index.DropIndexParam;import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang3.StringUtils;import java.util.ArrayList;import java.util.Arrays;import java.util.List;import java.util.Map;@Slf4jpublic class MilvusUtils {    public static MilvusServiceClient connect_db(String uri) {        MilvusServiceClient milvusClient = new MilvusServiceClient(                ConnectParam.newBuilder()                        .withUri(uri)//                    .withToken("root:Milvus")                        .build()        );        return milvusClient;    }    public static Map<String, String> create_collection(MilvusServiceClient milvusClient, String collection_name, String description, int shardsNum, List<FieldType> fieldTypes) {
  2.         if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {
  3.             log.warn("集合名称为空.");
  4.             return MapUtil.builder("status", "1").build();
  5.         }
  6.         if (CollUtil.isEmpty(fieldTypes)) {
  7.             log.warn("集合字段为空.");
  8.             return MapUtil.builder("status", "1").build();
  9.         }
  10.         CreateCollectionParam.Builder builder = CreateCollectionParam.newBuilder().withCollectionName(collection_name)
  11.                 .withShardsNum(shardsNum);
  12.         for (FieldType fieldType : fieldTypes) {
  13.             builder.addFieldType(fieldType);
  14.         }
  15.         if (StringUtils.isNotEmpty(description) && StringUtils.isNotBlank(description)) {
  16.             builder.withDescription(description);
  17.         }
  18.         CreateCollectionParam createCollectionReq = builder.build();
  19.         R<RpcStatus> rstatus = milvusClient.createCollection(createCollectionReq);
  20.         return buildResult(rstatus);
  21.     }    public static Map<String, String> drop_collection(MilvusServiceClient milvusClient, String collection_name) {
  22.         R<RpcStatus> rstatus = milvusClient.dropCollection(
  23.                 DropCollectionParam.newBuilder()
  24.                         .withCollectionName(collection_name)
  25.                         .build()
  26.         );
  27.         return buildResult(rstatus);
  28.     }    public static Map<String, String> create_index(MilvusServiceClient milvusClient, String collection_name, String index_column, String index_name, String params) {
  29.         if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {
  30.             log.warn("集合名称为空.");
  31.             return MapUtil.builder("status", "1").build();
  32.         }
  33.         if (StringUtils.isEmpty(index_column) || StringUtils.isBlank(index_column)) {
  34.             log.warn("索引字段为空.");
  35.             return MapUtil.builder("status", "1").build();
  36.         }
  37.         if (StringUtils.isEmpty(index_name) || StringUtils.isBlank(index_name)) {
  38.             log.warn("索引名称为空.");
  39.             return MapUtil.builder("status", "1").build();
  40.         }
  41.         CreateIndexParam.Builder builder = CreateIndexParam.newBuilder()
  42.                 .withIndexName(index_name)
  43.                 .withCollectionName(collection_name)
  44.                 .withFieldName(index_column)
  45.                 .withIndexType(IndexType.IVF_FLAT)
  46.                 .withMetricType(MetricType.IP)
  47.                 .withSyncMode(Boolean.FALSE);
  48.         if (StringUtils.isNotEmpty(index_name) && StringUtils.isNotBlank(index_name)) {
  49.             builder = builder.withExtraParam(params);
  50.         }
  51.         R<RpcStatus> rstatus = milvusClient.createIndex(
  52.                 builder.build()
  53.         );
  54.         return buildResult(rstatus);
  55.     }    public static Map<String, String> drop_index(MilvusServiceClient milvusClient, String collection_name, String index_name) {
  56.         if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {
  57.             log.warn("集合名称为空.");
  58.             return MapUtil.builder("status", "1").build();
  59.         }
  60.         if (StringUtils.isEmpty(index_name) || StringUtils.isBlank(index_name)) {
  61.             log.warn("索引名称为空.");
  62.             return MapUtil.builder("status", "1").build();
  63.         }
  64.         R<RpcStatus> rstatus = milvusClient.dropIndex(
  65.                 DropIndexParam.newBuilder()
  66.                         .withCollectionName(collection_name)
  67.                         .withIndexName(index_name)
  68.                         .build()
  69.         );
  70.         return buildResult(rstatus);
  71.     }    public static Map<String, String> load_in_memory(MilvusServiceClient milvusClient, String collection_name) {
  72.         if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {
  73.             log.warn("集合名称为空.");
  74.             return MapUtil.builder("status", "1").build();
  75.         }
  76.         R<RpcStatus> rstatus = milvusClient.loadCollection(
  77.                 LoadCollectionParam.newBuilder()
  78.                         .withCollectionName(collection_name)
  79.                         .build()
  80.         );
  81.         return buildResult(rstatus);
  82.     }    public static Map<String, String> unload_in_memory(MilvusServiceClient milvusClient, String collection_name) {
  83.         if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {
  84.             log.warn("集合名称为空.");
  85.             return MapUtil.builder("status", "1").build();
  86.         }
  87.         R<RpcStatus> rstatus = milvusClient.releaseCollection(
  88.                 ReleaseCollectionParam.newBuilder()
  89.                         .withCollectionName(collection_name)
  90.                         .build());
  91.         return buildResult(rstatus);
  92.     }    public static void disconnection_db(MilvusServiceClient milvusServiceClient) {        if (null != milvusServiceClient) {            milvusServiceClient.close();            milvusServiceClient = null;        }    }    public static Map<String, String> search_data_vector(MilvusServiceClient milvusClient, String collection_name, String fieldName, List<List<Float>> search_vectors, String params, int topK, List<String> search_output_fields) {
  93.         if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {
  94.             log.warn("集合名称为空.");
  95.             return MapUtil.builder("status", "1").build();
  96.         }
  97.         if (StringUtils.isEmpty(fieldName) || StringUtils.isBlank(fieldName)) {
  98.             log.warn("检索字段为空.");
  99.             return MapUtil.builder("status", "1").build();
  100.         }
  101.         if (CollUtil.isEmpty(search_vectors) || CollUtil.isEmpty(search_vectors.get(0))) {
  102.             log.warn("检索向量为空.");
  103.             return MapUtil.builder("status", "1").build();
  104.         }
  105.         if (CollUtil.isEmpty(search_output_fields)) {
  106.             log.warn("输出字段为空.");
  107.             return MapUtil.builder("status", "1").build();
  108.         }
  109.         if (topK <= 1) {
  110.             log.warn("topK少于1.");
  111.             topK = 1;
  112.         }
  113.         SearchParam.Builder builder = SearchParam.newBuilder().withCollectionName(collection_name)
  114.                 .withConsistencyLevel(ConsistencyLevelEnum.STRONG)
  115.                 .withMetricType(MetricType.IP)
  116.                 .withOutFields(search_output_fields)
  117.                 .withTopK(topK)
  118.                 .withVectors(search_vectors)
  119.                 .withVectorFieldName(fieldName);
  120.         if (StringUtils.isNotEmpty(params) && StringUtils.isNotBlank(params)) {
  121.             builder.withParams(params);
  122.         }
  123.         SearchParam searchParam = builder.build();
  124.         R<SearchResults> respSearch = milvusClient.search(searchParam);
  125.         String status = String.valueOf(respSearch.getStatus());
  126.         MapBuilder<String, String> mapBuilder = MapUtil.builder("status", status);
  127.         if (StringUtils.equals(status, "0")) {
  128.             SearchResults searchResults = respSearch.getData();
  129.             if (null != searchResults) {
  130.                 SearchResultData searchResultData = searchResults.getResults();
  131.                 if (null != searchResultData) {
  132.                     long num_queries = searchResultData.getNumQueries();
  133. //                    log.info("num_queries: {}", num_queries);
  134.                     if (num_queries > 0) {
  135.                         FieldData fieldData = searchResultData.getFieldsData(0);
  136.                         if (null != fieldData) {
  137.                             ScalarField scalarField = fieldData.getScalars();
  138.                             if (null != scalarField.getStringData()) {
  139.                                 String content = scalarField.getStringData().getData(0);
  140.                                 mapBuilder.put("content", content);
  141. //                                log.info("content: {}", content);
  142.                             }
  143.                         }
  144.                     }
  145.                 }
  146.             }
  147.         }
  148.         return mapBuilder.build();
  149.     }    public static Map<String, String>  insert_data(MilvusServiceClient milvusClient, String collection_name,List<InsertParam.Field> fields){
  150.         if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {
  151.             log.warn("集合名称为空.");
  152.             return MapUtil.builder("status", "1").build();
  153.         }
  154.         if (CollUtil.isEmpty(fields)) {
  155.             log.warn("插入数据为空.");
  156.             return MapUtil.builder("status", "1").build();
  157.         }
  158.         InsertParam insertParam = InsertParam.newBuilder()
  159.                 .withCollectionName(collection_name)
  160.                 .withFields(fields)
  161.                 .build();
  162.         R<MutationResult> mutationResultR = milvusClient.insert(insertParam);
  163.         String status = String.valueOf(mutationResultR.getStatus());
  164.         MapBuilder<String, String> mapBuilder = MapUtil.builder("status", status);
  165.         MutationResult mutationResult = mutationResultR.getData();
  166.         if(null != mutationResult){
  167.             long insert_cnt = mutationResult.getInsertCnt();
  168.             if(insert_cnt > 0){
  169.                 mapBuilder.put("msg","插入成功");
  170.             }
  171.         }
  172.         milvusClient.flush(FlushParam.newBuilder()
  173.                 .addCollectionName(collection_name)
  174. //                .withSyncFlush(true)
  175.                 .build());
  176.         log.info("MutationResult: {}",mutationResultR);
  177.         return mapBuilder.build();
  178.     }    private final static Map<String, String> buildResult(R<RpcStatus> rstatus) {//        log.info("status: {}", rstatus);        String status = String.valueOf(rstatus.getStatus());        MapBuilder<String, String> mapBuilder = MapUtil.builder("status", status);        RpcStatus data = rstatus.getData();        if (ObjectUtil.isNotEmpty(data)) {            String msg = data.getMsg();            if (StringUtils.isNotEmpty(msg) && StringUtils.isNotBlank(msg)) {                mapBuilder.put("msg", msg);            }        }        return mapBuilder.build();    }    public static void main(String[] args) {        String uri = "http://192.168.10.56:19530";        MilvusServiceClient milvusServiceClient = connect_db(uri);        String collection_name = "tb_test11";//        创建集合        FieldType fieldType1 = FieldType.newBuilder()                .withName("id")                .withDataType(DataType.Int64)                .withPrimaryKey(true)                .withAutoID(true)                .build();        FieldType fieldType2 = FieldType.newBuilder()                .withName("keyword")                .withDataType(DataType.FloatVector)                .withDimension(256)                .build();        FieldType fieldType3 = FieldType.newBuilder()                .withName("content")                .withDataType(DataType.VarChar)                .withMaxLength(4096)                .build();       List<FieldType> fieldTypes= CollUtil.list(Boolean.FALSE,fieldType1,fieldType2,fieldType3);        String description = "the table of tb_test11";        int shardsNum = 1;        Map<String,String> result = create_collection(milvusServiceClient, collection_name, description, shardsNum, fieldTypes);        log.info("result: {}",result);//      插入数据//        List<Float> vector = Arrays.asList(0.79558784f, 0.8433239f, -0.8132379f, -0.60343f, 0.8141689f, 0.49214464f, -1.3558795f, -1.5641332f, -1.5642508f, -1.5642508f, 0.90215206f, 0.79874355f, -0.5327561f, 0.8612926f, 0.84299415f, 0.79867285f, 0.8488582f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);//        String content = "标题:青春之光青春是一首歌,悠扬而激昂;青春是一幅画,斑斓而生动;青春是一部电影,感人至深。而在我心中,青春更是谁人在奥运赛场上奔跑的刘翔。记得那是2004年的雅典奥运会,刘翔以12.91秒的成绩打破了世界纪录,成为中国田径历史上第一位获得奥运金牌的运动员。那一刻,我被他的坚固和毅力深深打动,也深深地感受到了青春的力气。刘翔的青春,充满了挑战和奋斗。他曾经因为伤病困扰,一度想要放弃,但他没有。他知道,只有坚持下去,才能实现自己的空想。于是,他在痛苦中挣扎,用汗水和泪水灌溉着自己的青春。终于,他成功了,他站在了奥运的最高领奖台上,成为了全中国的得意。刘翔的青春,充满了豪情和活力。他是中国田径的一颗璀璨明星,他的每一次起跑都充满力气,他的每一次跨栏都充满速度。他的青春,就像一道闪电,照亮了整个赛场,也照亮了我们的心灵。刘翔的青春,充满了希望和空想。他的空想是成为最好的自己,他的希望是为中国赢得更多的荣誉。他的青春,就像一盏明灯,指引着他进步的方向,也激励着我们去寻求自己的空想。青春,就是要有空想,有希望,有勇气去追逐。刘翔的青春,就是这样,充满了空想、希望和勇气。他的青春,是我们全部人的青春,是我们全部人寻求空想的动力。青春,是一场无悔的路程,无论前方有多少困难和挫折,只要我们有空想,有希望,有勇气,就肯定可以或许到达我们的目的地。让我们一起,像刘翔一样,用自己的青春,去创造属于我们自己的辉煌!";////        List<String> contents =  CollUtil.list(Boolean.FALSE,content);//        List<List<Float>> vectors = new ArrayList<>();//        vectors.add(vector);////        List<InsertParam.Field> fields = new ArrayList<>();//        fields.add(new InsertParam.Field("keyword", vectors));//        fields.add(new InsertParam.Field("content", contents));////        Map<String,String> result = insert_data(milvusServiceClient,collection_name,fields);//        log.info("result: {}",result);//        创建索引//        String index_column = "keyword";//        String index_name = "idx_keyword";//        String params = "{"nlist":65536}";//        Map<String, String> result = create_index(milvusServiceClient, collection_name, index_column, index_name, params);//        log.info("result: {}", result);//      删除索引//        Map<String, String> result = drop_index(milvusServiceClient, collection_name,index_name);//        log.info("result: {}", result);//        装载至内存//        Map<String,String> result = load_in_memory(milvusServiceClient, collection_name);//        log.info("result: {}",result);//         向量查询//        List<String> search_output_fields = Arrays.asList("content");//        List<List<Float>> search_vectors = Arrays.asList(Arrays.asList(0.79558784f, 0.8433239f, -0.8132379f, -0.60343f, 0.8141689f, 0.49214464f, -1.3558795f, -1.5641332f, -1.5642508f, -1.5642508f, 0.90215206f, 0.79874355f, -0.5327561f, 0.8612926f, 0.84299415f, 0.79867285f, 0.8488582f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));//        String fieldName = "keyword";//        int topK = 1;////        Map<String, String> result = search_data_vector(milvusServiceClient, collection_name, fieldName, search_vectors, null, topK, search_output_fields);//        log.info("result: {}", result);//        删除集合//        Map<String, String> result = drop_collection(milvusServiceClient, collection_name);//        log.info("result: {}", result);        disconnection_db(milvusServiceClient);    }}
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

惊雷无声

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表