|
@@ -0,0 +1,163 @@
|
|
|
+/*
|
|
|
+ * Copyright (c) 2025 GaoKunW
|
|
|
+ *
|
|
|
+ */
|
|
|
+
|
|
|
+package org.eco.vip.ai.knowledge.service;
|
|
|
+
|
|
|
+
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.nimbusds.jose.shaded.gson.Gson;
|
|
|
+import io.milvus.v2.client.MilvusClientV2;
|
|
|
+import io.milvus.v2.common.DataType;
|
|
|
+import io.milvus.v2.common.IndexParam;
|
|
|
+import io.milvus.v2.service.collection.request.AddFieldReq;
|
|
|
+import io.milvus.v2.service.collection.request.CreateCollectionReq;
|
|
|
+import io.milvus.v2.service.collection.request.HasCollectionReq;
|
|
|
+import io.milvus.v2.service.index.request.CreateIndexReq;
|
|
|
+import io.milvus.v2.service.vector.request.InsertReq;
|
|
|
+import io.milvus.v2.service.vector.response.InsertResp;
|
|
|
+import jakarta.annotation.Resource;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import org.eco.vip.ai.knowledge.constant.MilvusConstant;
|
|
|
+import org.springframework.ai.ollama.OllamaEmbeddingModel;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.List;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+import java.util.stream.IntStream;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author GaoKunW
|
|
|
+ * @description MilvusService
|
|
|
+ * @date 2025/3/18 15:23
|
|
|
+ */
|
|
|
+@Service
|
|
|
+@RequiredArgsConstructor
|
|
|
+public class MilvusService implements IMilvusService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private MilvusClientV2 milvusClientV2;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private OllamaEmbeddingModel ollamaEmbeddingModel;
|
|
|
+
|
|
|
+ // private final
|
|
|
+ @Override
|
|
|
+ public void hasCollection() {
|
|
|
+ Boolean b = milvusClientV2.hasCollection(HasCollectionReq.builder().collectionName(MilvusConstant.COLLECTION_NAME).build());
|
|
|
+ if (!b) {
|
|
|
+ this.createCollection();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public InsertResp insert(float[] vectorParam, String text, String metadata, String fileName) {
|
|
|
+ // 校验集合是否存在
|
|
|
+ this.hasCollection();
|
|
|
+ JSONObject jsonObject = new JSONObject();
|
|
|
+ // 数组转换成JsonElement
|
|
|
+ // 使用 Stream API 转换
|
|
|
+ List<Float> floatList = IntStream.range(0, vectorParam.length)
|
|
|
+ .mapToObj(i -> vectorParam[i])
|
|
|
+ .toList();
|
|
|
+ jsonObject.put(MilvusConstant.Field.FEATURE, floatList);
|
|
|
+ jsonObject.put(MilvusConstant.Field.TEXT, text);
|
|
|
+ jsonObject.put(MilvusConstant.Field.METADATA, metadata);
|
|
|
+ jsonObject.put(MilvusConstant.Field.FILE_NAME, fileName);
|
|
|
+ InsertReq insertReq = InsertReq.builder()
|
|
|
+ // 集合名称
|
|
|
+ .collectionName(MilvusConstant.COLLECTION_NAME)
|
|
|
+ .data(Collections.singletonList(jsonObject))
|
|
|
+ .build();
|
|
|
+
|
|
|
+ return milvusClientV2.insert(insertReq);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建集合
|
|
|
+ */
|
|
|
+ public void createCollection() {
|
|
|
+ // 创建字段
|
|
|
+ CreateCollectionReq.CollectionSchema schema = milvusClientV2.createSchema();
|
|
|
+ // 创建主键字段
|
|
|
+ schema.addField(AddFieldReq.builder()
|
|
|
+ // 字段名
|
|
|
+ .fieldName(MilvusConstant.Field.ID)
|
|
|
+ // 字段描述
|
|
|
+ .description("主键ID")
|
|
|
+ // 字段类型
|
|
|
+ .dataType(DataType.Int64)
|
|
|
+ // 是否为主键
|
|
|
+ .isPrimaryKey(true)
|
|
|
+ // 设置主键自增
|
|
|
+ .autoID(true)
|
|
|
+ .build());
|
|
|
+ schema.addField(AddFieldReq.builder()
|
|
|
+ // 字段名
|
|
|
+ .fieldName(MilvusConstant.Field.FILE_NAME)
|
|
|
+ // 字段描述
|
|
|
+ .description("文件名")
|
|
|
+ // 字段类型
|
|
|
+ .dataType(DataType.VarChar)
|
|
|
+ .build());
|
|
|
+ // 创建特征向量字段
|
|
|
+ schema.addField(AddFieldReq.builder()
|
|
|
+ // 字段名
|
|
|
+ .fieldName(MilvusConstant.Field.FEATURE)
|
|
|
+ // 字段描述
|
|
|
+ .description("特征向量")
|
|
|
+ // 字段类型
|
|
|
+ .dataType(DataType.FloatVector)
|
|
|
+ // 设置向量维度
|
|
|
+ .dimension(MilvusConstant.FEATURE_DIM)
|
|
|
+ .build());
|
|
|
+ schema.addField(AddFieldReq.builder()
|
|
|
+ // 字段名
|
|
|
+ .fieldName(MilvusConstant.Field.TEXT)
|
|
|
+ // 字段描述
|
|
|
+ .description("文本")
|
|
|
+ // 字段类型
|
|
|
+ .dataType(DataType.VarChar)
|
|
|
+ .build());
|
|
|
+ schema.addField(AddFieldReq.builder()
|
|
|
+ // 字段名
|
|
|
+ .fieldName(MilvusConstant.Field.METADATA)
|
|
|
+ // 字段描述
|
|
|
+ .description("元数据")
|
|
|
+ // 字段类型
|
|
|
+ .dataType(DataType.VarChar)
|
|
|
+ .build());
|
|
|
+ // 创建集合
|
|
|
+ CreateCollectionReq collectionReq = CreateCollectionReq.builder()
|
|
|
+ // 集合名称
|
|
|
+ .collectionName(MilvusConstant.COLLECTION_NAME)
|
|
|
+ // 集合描述
|
|
|
+ .description("自定义知识库")
|
|
|
+ // 集合字段
|
|
|
+ .collectionSchema(schema)
|
|
|
+ // 分片数量
|
|
|
+ .numShards(MilvusConstant.SHARDS_NUM)
|
|
|
+ .build();
|
|
|
+ milvusClientV2.createCollection(collectionReq);
|
|
|
+
|
|
|
+ // 创建索引
|
|
|
+ IndexParam indexParam = IndexParam.builder()
|
|
|
+ // 索引字段名
|
|
|
+ .fieldName(MilvusConstant.Field.FEATURE)
|
|
|
+ // 索引类型
|
|
|
+ .indexType(IndexParam.IndexType.IVF_FLAT)
|
|
|
+ // 索引距离度量
|
|
|
+ .metricType(IndexParam.MetricType.COSINE)
|
|
|
+ .build();
|
|
|
+ CreateIndexReq createIndexReq = CreateIndexReq.builder()
|
|
|
+ .collectionName(MilvusConstant.COLLECTION_NAME)
|
|
|
+ .indexParams(Collections.singletonList(indexParam))
|
|
|
+ .build();
|
|
|
+
|
|
|
+ milvusClientV2.createIndex(createIndexReq);
|
|
|
+ }
|
|
|
+}
|