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

一、前言

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


二、术语

2.1、向量数据库

    向量数据库是一种专门用于存储和处理高维向量数据的数据库系统。与传统的关系型数据库或文档数据库不同,向量数据库的设计目标是高效地支持向量数据的索引和相似性搜索。

    在传统数据库中,数据通常是以结构化的表格形式存储,每个记录都有预定义的字段。但是,对于包含大量高维向量的数据,如图像、音频、文本等,传统的数据库模型往往无法有效地处理。向量数据库通过引入特定的数据结构和索引算法,允许高效地存储和查询向量数据。

    向量数据库的核心概念是向量索引。它使用一种称为向量空间模型的方法,将向量映射到多维空间中的点,并利用这种映射关系构建索引结构。这样,当需要搜索相似向量时,可以通过计算向量之间的距离或相似度来快速定位相似的向量。

2.5、Milvus

    是一个开源的向量数据库引擎,专门用于存储和处理大规模高维向量数据。它提供了高效的向量索引和相似性搜索功能,使用户能够快速地进行向量数据的存储、查询和分析。

    Milvus的设计目标是为了满足现代应用中对大规模向量数据的需求,例如人脸识别、图像搜索、推荐系统等。它采用了向量空间模型和多种索引算法,包括倒排索引、近似最近邻(Approximate Nearest Neighbor,ANN)等,以支持高效的相似性搜索。

    Milvus提供了易于使用的编程接口和丰富的功能,使用户可以方便地插入、查询和分析向量数据。它支持多种数据类型的向量,包括浮点型、整型等,也支持多种距离度量方法,如欧氏距离、余弦相似度等。

    Milvus还提供了分布式部署和横向扩展的能力,可以在多台机器上构建高可用性和高性能的向量数据库集群。它支持数据的分片和负载均衡,可以处理大规模数据集和高并发查询。

2.2、Milvus Lite

    是Milvus向量数据库的一个轻量级版本。旨在提供在资源受限的环境中快速、高效地进行向量存储和相似性搜索的能力。

    与完整版的Milvus相比,它具有以下特点:

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

2.3、Attu

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

2.4、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 模块启动

from milvus import default_serverdef start_server():default_server.start()def stop_server():default_server.stop()if __name__ == '__main__':with default_server:start_server()input("按下任意键继续...")

3.4、启动Milvus Lite服务

    python -u 上述代码的文件名

    

    启动完成后,会监听19530端口

3.5、安装Milvus客户端管理工具

    下载地址:Releases · zilliztech/attu · GitHub

3.6、登录Milvus Lite服务端

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

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


四、业务整合

业务数据需要提前初始化到向量数据库中

4.1、导入maven依赖

<dependency><groupId>io.milvus</groupId><artifactId>milvus-sdk-java</artifactId><version>2.2.2</version>
</dependency>

PS: 我的JDK是1.8版本,若milvus版本太高,会出现兼容性问题,需要注意

maven仓库地址:Maven Repository: io.milvus » milvus-sdk-java

4.2、连接milvus服务端

 public static MilvusServiceClient connect_db(String uri) {MilvusServiceClient milvusClient = new MilvusServiceClient(ConnectParam.newBuilder().withUri(uri)
//                    .withToken("root:Milvus").build());return milvusClient;
}

4.3、创建集合

public static Map<String, String> create_collection(MilvusServiceClient milvusClient, String collection_name, String description, int shardsNum, List<FieldType> fieldTypes) {if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {log.warn("集合名称为空.");return MapUtil.builder("status", "1").build();}if (CollUtil.isEmpty(fieldTypes)) {log.warn("集合字段为空.");return MapUtil.builder("status", "1").build();}CreateCollectionParam.Builder builder = CreateCollectionParam.newBuilder().withCollectionName(collection_name).withShardsNum(shardsNum);for (FieldType fieldType : fieldTypes) {builder.addFieldType(fieldType);}if (StringUtils.isNotEmpty(description) && StringUtils.isNotBlank(description)) {builder.withDescription(description);}CreateCollectionParam createCollectionReq = builder.build();R<RpcStatus> rstatus = milvusClient.createCollection(createCollectionReq);return buildResult(rstatus);}

创建成功后:

4.4、插入数据

public static Map<String, String>  insert_data(MilvusServiceClient milvusClient, String collection_name,List<InsertParam.Field> fields){if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {log.warn("集合名称为空.");return MapUtil.builder("status", "1").build();}if (CollUtil.isEmpty(fields)) {log.warn("插入数据为空.");return MapUtil.builder("status", "1").build();}InsertParam insertParam = InsertParam.newBuilder().withCollectionName(collection_name).withFields(fields).build();R<MutationResult> mutationResultR = milvusClient.insert(insertParam);String status = String.valueOf(mutationResultR.getStatus());MapBuilder<String, String> mapBuilder = MapUtil.builder("status", status);MutationResult mutationResult = mutationResultR.getData();if(null != mutationResult){long insert_cnt = mutationResult.getInsertCnt();if(insert_cnt > 0){mapBuilder.put("msg","插入成功");}}milvusClient.flush(FlushParam.newBuilder().addCollectionName(collection_name)
//                .withSyncFlush(true).build());log.info("MutationResult: {}",mutationResultR);return mapBuilder.build();}

插入成功后(需要调用flush才能立刻看到数据):

4.5、创建索引

public static Map<String, String> create_index(MilvusServiceClient milvusClient, String collection_name, String index_column, String index_name, String params) {if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {log.warn("集合名称为空.");return MapUtil.builder("status", "1").build();}if (StringUtils.isEmpty(index_column) || StringUtils.isBlank(index_column)) {log.warn("索引字段为空.");return MapUtil.builder("status", "1").build();}if (StringUtils.isEmpty(index_name) || StringUtils.isBlank(index_name)) {log.warn("索引名称为空.");return MapUtil.builder("status", "1").build();}CreateIndexParam.Builder builder = CreateIndexParam.newBuilder().withIndexName(index_name).withCollectionName(collection_name).withFieldName(index_column).withIndexType(IndexType.IVF_FLAT).withMetricType(MetricType.IP).withSyncMode(Boolean.FALSE);if (StringUtils.isNotEmpty(index_name) && StringUtils.isNotBlank(index_name)) {builder = builder.withExtraParam(params);}R<RpcStatus> rstatus = milvusClient.createIndex(builder.build());return buildResult(rstatus);}

metric_type说明:

IP(内积)是一种表示向量之间相似程度的度量方式,它的计算方式是将两个向量中对应位置的元素相乘后求和。IP 的值越大,表示两个向量越相似;IP 的值越小,表示两个向量越不相似。IP 适用于只需要考虑向量之间的相似度,而不需要考虑各个维度之间的权重关系的场景,例如自然语言处理、计算机视觉等领域。

L2(欧氏距离)是一种表示向量之间直线距离的度量方式,它的计算方式是将两个向量中对应位置的元素相减后平方,再将平方和求和并开平方;L2 的值越小,表示两个向量越相似;L2 的值越大,表示两个向量越不相似。L2 适用于需要考虑各个维度之间的权重关系,或者需要将向量转化为单位向量进行相似度计算的场景,例如数值计算、信号处理、图像处理、机器学习等领域。
 

创建成功后:

4.6、加载数据至缓存

public static Map<String, String> load_in_memory(MilvusServiceClient milvusClient, String collection_name) {if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {log.warn("集合名称为空.");return MapUtil.builder("status", "1").build();}R<RpcStatus> rstatus = milvusClient.loadCollection(LoadCollectionParam.newBuilder().withCollectionName(collection_name).build());return buildResult(rstatus);}

4.7、根据向量检索数据

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) {if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {log.warn("集合名称为空.");return MapUtil.builder("status", "1").build();}if (StringUtils.isEmpty(fieldName) || StringUtils.isBlank(fieldName)) {log.warn("检索字段为空.");return MapUtil.builder("status", "1").build();}if (CollUtil.isEmpty(search_vectors) || CollUtil.isEmpty(search_vectors.get(0))) {log.warn("检索向量为空.");return MapUtil.builder("status", "1").build();}if (CollUtil.isEmpty(search_output_fields)) {log.warn("输出字段为空.");return MapUtil.builder("status", "1").build();}if (topK <= 1) {log.warn("topK少于1.");topK = 1;}SearchParam.Builder builder = SearchParam.newBuilder().withCollectionName(collection_name).withConsistencyLevel(ConsistencyLevelEnum.STRONG).withMetricType(MetricType.IP).withOutFields(search_output_fields).withTopK(topK).withVectors(search_vectors).withVectorFieldName(fieldName);if (StringUtils.isNotEmpty(params) && StringUtils.isNotBlank(params)) {builder.withParams(params);}SearchParam searchParam = builder.build();R<SearchResults> respSearch = milvusClient.search(searchParam);String status = String.valueOf(respSearch.getStatus());MapBuilder<String, String> mapBuilder = MapUtil.builder("status", status);if (StringUtils.equals(status, "0")) {SearchResults searchResults = respSearch.getData();if (null != searchResults) {SearchResultData searchResultData = searchResults.getResults();if (null != searchResultData) {long num_queries = searchResultData.getNumQueries();
//                    log.info("num_queries: {}", num_queries);if (num_queries > 0) {FieldData fieldData = searchResultData.getFieldsData(0);if (null != fieldData) {ScalarField scalarField = fieldData.getScalars();if (null != scalarField.getStringData()) {String content = scalarField.getStringData().getData(0);mapBuilder.put("content", content);
//                                log.info("content: {}", content);}}}}}}return mapBuilder.build();}

4.8、删除索引

public static Map<String, String> drop_index(MilvusServiceClient milvusClient, String collection_name, String index_name) {if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {log.warn("集合名称为空.");return MapUtil.builder("status", "1").build();}if (StringUtils.isEmpty(index_name) || StringUtils.isBlank(index_name)) {log.warn("索引名称为空.");return MapUtil.builder("status", "1").build();}R<RpcStatus> rstatus = milvusClient.dropIndex(DropIndexParam.newBuilder().withCollectionName(collection_name).withIndexName(index_name).build());return buildResult(rstatus);}

4.9、删除集合

 public static Map<String, String> drop_collection(MilvusServiceClient milvusClient, String collection_name) {R<RpcStatus> rstatus = milvusClient.dropCollection(DropCollectionParam.newBuilder().withCollectionName(collection_name).build());return buildResult(rstatus);}

4.10、释放缓存

public static Map<String, String> unload_in_memory(MilvusServiceClient milvusClient, String collection_name) {if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {log.warn("集合名称为空.");return MapUtil.builder("status", "1").build();}R<RpcStatus> rstatus = milvusClient.releaseCollection(ReleaseCollectionParam.newBuilder().withCollectionName(collection_name).build());return buildResult(rstatus);}


五、附带说明

5.1、高维向量表示的优劣

优势:

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

劣势

  • 维度灾难:高维度数据可能导致维度灾难问题,即数据稀疏性增加,对于有限的训练数据而言,模型的泛化能力可能会受到影响。
  • 计算复杂性增加:高维度数据需要更多的计算资源和时间来处理和分析,可能会增加计算的复杂性和开销。
  • 数据稀疏性:在高维空间中,数据点之间的距离变得更远,可能会导致数据稀疏性增加,从而影响模型的准确性和可靠性。

5.2、插入数据成功但无法检索

     需要调用flush

     milvusClient.flush(FlushParam.newBuilder() .addCollectionName(collection_name) .build());

5.3、如何批量插入数据

     集合中放入多条数据即可

5.4、受限于篇幅过长,如何提升向量检索精度、如何获取文本向量及如何对向量进行预处理(向量长度补全、归一化、标准化)将另文讲解

5.5、完整代码

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;@Slf4j
public 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) {if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {log.warn("集合名称为空.");return MapUtil.builder("status", "1").build();}if (CollUtil.isEmpty(fieldTypes)) {log.warn("集合字段为空.");return MapUtil.builder("status", "1").build();}CreateCollectionParam.Builder builder = CreateCollectionParam.newBuilder().withCollectionName(collection_name).withShardsNum(shardsNum);for (FieldType fieldType : fieldTypes) {builder.addFieldType(fieldType);}if (StringUtils.isNotEmpty(description) && StringUtils.isNotBlank(description)) {builder.withDescription(description);}CreateCollectionParam createCollectionReq = builder.build();R<RpcStatus> rstatus = milvusClient.createCollection(createCollectionReq);return buildResult(rstatus);}public static Map<String, String> drop_collection(MilvusServiceClient milvusClient, String collection_name) {R<RpcStatus> rstatus = milvusClient.dropCollection(DropCollectionParam.newBuilder().withCollectionName(collection_name).build());return buildResult(rstatus);}public static Map<String, String> create_index(MilvusServiceClient milvusClient, String collection_name, String index_column, String index_name, String params) {if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {log.warn("集合名称为空.");return MapUtil.builder("status", "1").build();}if (StringUtils.isEmpty(index_column) || StringUtils.isBlank(index_column)) {log.warn("索引字段为空.");return MapUtil.builder("status", "1").build();}if (StringUtils.isEmpty(index_name) || StringUtils.isBlank(index_name)) {log.warn("索引名称为空.");return MapUtil.builder("status", "1").build();}CreateIndexParam.Builder builder = CreateIndexParam.newBuilder().withIndexName(index_name).withCollectionName(collection_name).withFieldName(index_column).withIndexType(IndexType.IVF_FLAT).withMetricType(MetricType.IP).withSyncMode(Boolean.FALSE);if (StringUtils.isNotEmpty(index_name) && StringUtils.isNotBlank(index_name)) {builder = builder.withExtraParam(params);}R<RpcStatus> rstatus = milvusClient.createIndex(builder.build());return buildResult(rstatus);}public static Map<String, String> drop_index(MilvusServiceClient milvusClient, String collection_name, String index_name) {if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {log.warn("集合名称为空.");return MapUtil.builder("status", "1").build();}if (StringUtils.isEmpty(index_name) || StringUtils.isBlank(index_name)) {log.warn("索引名称为空.");return MapUtil.builder("status", "1").build();}R<RpcStatus> rstatus = milvusClient.dropIndex(DropIndexParam.newBuilder().withCollectionName(collection_name).withIndexName(index_name).build());return buildResult(rstatus);}public static Map<String, String> load_in_memory(MilvusServiceClient milvusClient, String collection_name) {if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {log.warn("集合名称为空.");return MapUtil.builder("status", "1").build();}R<RpcStatus> rstatus = milvusClient.loadCollection(LoadCollectionParam.newBuilder().withCollectionName(collection_name).build());return buildResult(rstatus);}public static Map<String, String> unload_in_memory(MilvusServiceClient milvusClient, String collection_name) {if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {log.warn("集合名称为空.");return MapUtil.builder("status", "1").build();}R<RpcStatus> rstatus = milvusClient.releaseCollection(ReleaseCollectionParam.newBuilder().withCollectionName(collection_name).build());return buildResult(rstatus);}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) {if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {log.warn("集合名称为空.");return MapUtil.builder("status", "1").build();}if (StringUtils.isEmpty(fieldName) || StringUtils.isBlank(fieldName)) {log.warn("检索字段为空.");return MapUtil.builder("status", "1").build();}if (CollUtil.isEmpty(search_vectors) || CollUtil.isEmpty(search_vectors.get(0))) {log.warn("检索向量为空.");return MapUtil.builder("status", "1").build();}if (CollUtil.isEmpty(search_output_fields)) {log.warn("输出字段为空.");return MapUtil.builder("status", "1").build();}if (topK <= 1) {log.warn("topK少于1.");topK = 1;}SearchParam.Builder builder = SearchParam.newBuilder().withCollectionName(collection_name).withConsistencyLevel(ConsistencyLevelEnum.STRONG).withMetricType(MetricType.IP).withOutFields(search_output_fields).withTopK(topK).withVectors(search_vectors).withVectorFieldName(fieldName);if (StringUtils.isNotEmpty(params) && StringUtils.isNotBlank(params)) {builder.withParams(params);}SearchParam searchParam = builder.build();R<SearchResults> respSearch = milvusClient.search(searchParam);String status = String.valueOf(respSearch.getStatus());MapBuilder<String, String> mapBuilder = MapUtil.builder("status", status);if (StringUtils.equals(status, "0")) {SearchResults searchResults = respSearch.getData();if (null != searchResults) {SearchResultData searchResultData = searchResults.getResults();if (null != searchResultData) {long num_queries = searchResultData.getNumQueries();
//                    log.info("num_queries: {}", num_queries);if (num_queries > 0) {FieldData fieldData = searchResultData.getFieldsData(0);if (null != fieldData) {ScalarField scalarField = fieldData.getScalars();if (null != scalarField.getStringData()) {String content = scalarField.getStringData().getData(0);mapBuilder.put("content", content);
//                                log.info("content: {}", content);}}}}}}return mapBuilder.build();}public static Map<String, String>  insert_data(MilvusServiceClient milvusClient, String collection_name,List<InsertParam.Field> fields){if (StringUtils.isEmpty(collection_name) || StringUtils.isBlank(collection_name)) {log.warn("集合名称为空.");return MapUtil.builder("status", "1").build();}if (CollUtil.isEmpty(fields)) {log.warn("插入数据为空.");return MapUtil.builder("status", "1").build();}InsertParam insertParam = InsertParam.newBuilder().withCollectionName(collection_name).withFields(fields).build();R<MutationResult> mutationResultR = milvusClient.insert(insertParam);String status = String.valueOf(mutationResultR.getStatus());MapBuilder<String, String> mapBuilder = MapUtil.builder("status", status);MutationResult mutationResult = mutationResultR.getData();if(null != mutationResult){long insert_cnt = mutationResult.getInsertCnt();if(insert_cnt > 0){mapBuilder.put("msg","插入成功");}}milvusClient.flush(FlushParam.newBuilder().addCollectionName(collection_name)
//                .withSyncFlush(true).build());log.info("MutationResult: {}",mutationResultR);return mapBuilder.build();}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);}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2803962.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

游泳耳机品牌排行榜前十名:十大爆款火热机型超高性价比

在当今这个科技日新月异的时代&#xff0c;游泳已经不再仅仅是一项简单的运动&#xff0c;而是一种生活方式的体现。随着人们对于健康生活的追求日益增强&#xff0c;游泳耳机也成为了许多游泳爱好者的必备装备之一。然而&#xff0c;市场上琳琅满目的游泳耳机品牌和型号让人眼…

网络安全8-11天笔记

内容安全&#xff1a; 攻击可能只是一个点&#xff0c;防御需要全方面进行。 IAE引擎&#xff1a; DFI和DPI技术&#xff1a;深度检测技术 DPI——深度包检测技术&#xff1a;主要针对完整的数据包&#xff08;数据包分片&#xff0c;分段需要重组&#xff09;&#xff0c;之…

2024年阿里云服务器优惠价格表和活动整理

2024阿里云服务器优惠活动政策整理&#xff0c;轻量2核2G3M服务器61元一年、2核4G4M带宽165元1年&#xff0c;云服务器4核16G10M带宽26元1个月、149元半年&#xff0c;阿里云ECS云服务器2核2G3M新老用户均可99元一年续费不涨价&#xff0c;企业用户2核4G5M带宽199元一年&#x…

Excel之index、MATCH面试题、VLOOKUP函数,

VLOOKUP() 在表格的首列查找指定的数值&#xff0c;并返回表格当前行中指定列处的数值。 结构&#xff1a;VLOOKUP(查找值,查找区域,列序数,匹配条件) 解释&#xff1a;VLOOKUP(找谁,在哪里找,第几列,0或1) 1.目的&#xff1a;根据【产品】查找【销量】 公式&#xff1a;V…

C++从入门到精通 第十二章(C++流)

写在前面&#xff1a; 本系列专栏主要介绍C的相关知识&#xff0c;思路以下面的参考链接教程为主&#xff0c;大部分笔记也出自该教程&#xff0c;笔者的原创部分主要在示例代码的注释部分。除了参考下面的链接教程以外&#xff0c;笔者还参考了其它的一些C教材&#xff08;比…

Vue 图片轮播第三方库 介绍

Vue图片轮播是一种在网页上以自动或手动方式展示图片的组件&#xff0c;常用于产品展示、网站banner等场景。有许多第三方库可以帮助Vue开发者轻松实现图片轮播功能。以下是一些流行的Vue图片轮播第三方库的介绍&#xff1a; 1. Vue-awesome-swiper - **简介**&#xff1a;V…

滚雪球学Java(70):深入理解Java中的PriorityQueue底层实现与源码分析

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴——bug菌&#xff0c;今天又来给大家普及Java SE相关知识点了&#xff0c;别躲起来啊&#xff0c;听我讲干货还不快点赞&#xff0c;赞多了我就有动力讲得更嗨啦&#xff01;所以呀&#xff0c;养成先点赞后阅读的好…

Linux之ACL权限管理

文章目录 1.ACL权限介绍二、操作步骤1. 添加测试目录、用户、组&#xff0c;并将用户添加到组2. 修改目录的所有者和所属组3. 设定权限4. 为临时用户分配权限5. 验证acl权限6. 控制组的acl权限 1.ACL权限介绍 每个项目成员有一个自己的项目目录&#xff0c;对自己的目录有完全…

【Django】Django自定义后台表单——对一个关联外键对象同时添加多个内容

以官方文档为例&#xff1a; 一个投票问题包含多个选项&#xff0c;基本的表单设计只能一个选项一个选项添加&#xff0c;效率较低&#xff0c;如何在表单设计中一次性添加多个关联选项&#xff1f; 示例代码&#xff1a; from django.contrib import adminfrom .models impo…

森林安全新保障:智能高压应急消防泵的应用

随着城市化进程的加快&#xff0c;森林资源的保护和利用日益受到重视。然而&#xff0c;森林火灾时有发生&#xff0c;给生态环境带来严重破坏。为了有效应对森林火灾&#xff0c;保障森林资源安全&#xff0c;智能高压森林应急消防泵应运而生&#xff0c;成为守护绿色生命的钢…

Python列表:灵活多变的数据结构

文章目录 一、列表1.创建列表2.访问列表元素3.修改列表元素4.添加元素5.删除元素 二、列表脚本操作符1.连接运算符 2.重复运算符 * 三、列表函数&方法1.函数1.1 len() 函数1.2 max() 函数1.3 min() 函数1.4 sum() 函数1.5 list() 函数 2.方法2.1 append() 方法2.2 extend()…

DSL Query基本语法

DSL Query基本语法 查询的基本语法如下&#xff1a; GET /indexName/_search {"query":{"查询类型":{"查询条件":"条件值"}} }查询所有 GET /indexName/_search {"query":{"match_all":{}} }match查询&#xf…

2、Web攻防-SQL注入-联合查询注入

用途&#xff1a;个人学习笔记&#xff0c;有所借鉴&#xff0c;欢迎指正&#xff01; 声明&#xff1a;只用于学习交流&#xff0c;点到为止&#xff0c;请勿非法测试。 概念&#xff1a; 联合查询注入&#xff1a;联合注入是回显注入的一种&#xff0c;也就是说联合注入的前…

Gemma模型论文详解(附源码)

原文链接&#xff1a;Gemma模型论文详解&#xff08;附源码&#xff09; 1. 背景介绍 Gemma模型是在2023.2.21号Google新发布的大语言模型, Gemma复用了Gemini相同的技术(Gemini也是Google发布的多模态模型)&#xff0c;Gemma这次发布了了2B和7B两个版本的参数&#xff0c;不…

嵌入式Linux中apt、apt-get命令用法汇总

在Linux环境开发过程中接触ubuntu虚拟机时&#xff0c;在安装软件或者更新软件时apt和apt-get命令使用相对较频繁&#xff0c;下面对这两个命令的用法进行汇总。 apt&#xff08;Advanced Package Tool&#xff09;和 apt-get 是用于在基于 Debian 的 Linux 发行版中进行软件包…

什么是favicon.ico图标?如何在线生成ICO图标?如何安装favicon.ico图标?

在本站首页的活跃博客中经常看到有部分博客网站没有 favicon.ico 图标&#xff0c;所以今天打算普及一下相关知识&#xff0c;希望还没有 favicon.ico 图标的博主们&#xff0c;能够制作出自己独特的图标。 那么到底什么是favicon.ico&#xff1f; 好搜百科给出的解释&#xf…

electron学习和新建窗口

首先我们要先下载electron npm install --save-dev electron 建立入口文件main.js 新建一个入口文件 main.js&#xff0c;然后导入eletron新建一个窗口。 const { app, BrowserWindow, ipcMain } require("electron"); const path require("path");func…

Nginx 反向代理配置

Nginx就不废话了&#xff0c;web服务器。 最近在备案一个域名&#xff0c;想要备案&#xff0c;部署一个服务器&#xff0c;平常很少自己配置Nginx&#xff0c;今天记录下。 1、反向代理 正向代理 指 客户端通过代理访问后端服务 反向代理 指 服务器推出一个客户&#xff0…

6.网络游戏逆向分析与漏洞攻防-游戏网络架构逆向分析-通过逆向分析确定游戏明文发送数据过程

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;测试需求与需求拆解 在开始之前要了解一个小知识&#xff0c;在逆向开始之前要很清楚知道要找的东西是什么&#xff0c;大概长什么样子&#xff0c;只有这样才能看到它第一眼发现它&#xff0c;现在我…

Unable to make field private JavacProcessingEnvironment$DiscoveredPro报错解决办法

maven项目打包报错 报错信息 Unable to make field private com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors com.sun.tools.javac.processing.JavacProcessingEnvironment.discoveredProcs accessible: module jdk.compiler does not &q…