mirror of
https://gitcode.com/ageerle/ruoyi-ai.git
synced 2026-03-13 20:53:42 +08:00
feat(milvus): 实现Milvus向量数据库集成
- 添加Milvus Java SDK依赖 - 实现MilvusVectorStoreStrategy核心功能 - 支持集合管理、数据存储、向量搜索和数据删除 - 添加Milvus实现指南文档 - 更新数据库连接配置 - 修改VectorStoreService接口添加异常声明
This commit is contained in:
237
MILVUS_IMPLEMENTATION_GUIDE.md
Normal file
237
MILVUS_IMPLEMENTATION_GUIDE.md
Normal file
@@ -0,0 +1,237 @@
|
||||
# Milvus向量库实现指南
|
||||
|
||||
## 概述
|
||||
|
||||
本项目已完成Milvus向量库的集成,基于Milvus SDK 2.6.4版本实现。Milvus是一个开源的向量数据库,专为AI应用和相似性搜索而设计。
|
||||
|
||||
## 实现特性
|
||||
|
||||
### ✅ 已实现功能
|
||||
|
||||
1. **集合管理**
|
||||
- 自动创建集合(Collection)
|
||||
- 检查集合是否存在
|
||||
- 删除集合
|
||||
|
||||
2. **数据存储**
|
||||
- 批量插入向量数据
|
||||
- 支持文本、fid、kid、docId等元数据
|
||||
- 自动生成向量嵌入
|
||||
|
||||
3. **向量搜索**
|
||||
- 基于相似性的向量搜索
|
||||
- 支持TopK结果返回
|
||||
- 返回相关文本内容
|
||||
|
||||
4. **数据删除**
|
||||
- 按文档ID删除
|
||||
- 按片段ID删除
|
||||
- 删除整个集合
|
||||
|
||||
## 架构设计
|
||||
|
||||
### 策略模式实现
|
||||
|
||||
```
|
||||
AbstractVectorStoreStrategy (抽象基类)
|
||||
↓
|
||||
MilvusVectorStoreStrategy (Milvus实现)
|
||||
WeaviateVectorStoreStrategy (Weaviate实现)
|
||||
```
|
||||
|
||||
### 核心类说明
|
||||
|
||||
- **MilvusVectorStoreStrategy**: Milvus向量库策略实现
|
||||
- **VectorStoreStrategyFactory**: 向量库策略工厂,支持动态切换
|
||||
- **VectorStoreService**: 向量库服务接口
|
||||
|
||||
## 配置说明
|
||||
|
||||
### 必需配置项
|
||||
|
||||
在系统配置中需要设置以下Milvus相关配置:
|
||||
|
||||
```properties
|
||||
# Milvus服务地址
|
||||
milvus.url=http://localhost:19530
|
||||
|
||||
# 集合名称前缀
|
||||
milvus.collectionname=LocalKnowledge
|
||||
|
||||
# 向量库类型选择
|
||||
vector.store_type=milvus
|
||||
```
|
||||
|
||||
### 集合Schema设计
|
||||
|
||||
每个集合包含以下字段:
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| id | Int64 | 主键,自动生成 |
|
||||
| text | VarChar(65535) | 文本内容 |
|
||||
| fid | VarChar(255) | 片段ID |
|
||||
| kid | VarChar(255) | 知识库ID |
|
||||
| docId | VarChar(255) | 文档ID |
|
||||
| vector | FloatVector(1024) | 向量数据 |
|
||||
|
||||
### 索引配置
|
||||
|
||||
- **索引类型**: IVF_FLAT
|
||||
- **距离度量**: L2 (欧几里得距离)
|
||||
- **参数**: nlist=1024
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 1. 创建集合
|
||||
|
||||
```java
|
||||
MilvusVectorStoreStrategy strategy = new MilvusVectorStoreStrategy(configService);
|
||||
strategy.createSchema("bge-large-zh-v1.5", "test001", "test-model");
|
||||
```
|
||||
|
||||
### 2. 存储向量数据
|
||||
|
||||
```java
|
||||
StoreEmbeddingBo storeEmbeddingBo = new StoreEmbeddingBo();
|
||||
storeEmbeddingBo.setVectorModelName("bge-large-zh-v1.5");
|
||||
storeEmbeddingBo.setKid("test001");
|
||||
storeEmbeddingBo.setDocId("doc001");
|
||||
storeEmbeddingBo.setChunkList(Arrays.asList("文本1", "文本2"));
|
||||
storeEmbeddingBo.setFids(Arrays.asList("fid001", "fid002"));
|
||||
|
||||
strategy.storeEmbeddings(storeEmbeddingBo);
|
||||
```
|
||||
|
||||
### 3. 查询向量数据
|
||||
|
||||
```java
|
||||
QueryVectorBo queryVectorBo = new QueryVectorBo();
|
||||
queryVectorBo.setQuery("查询文本");
|
||||
queryVectorBo.setKid("test001");
|
||||
queryVectorBo.setMaxResults(5);
|
||||
|
||||
List<String> results = strategy.getQueryVector(queryVectorBo);
|
||||
```
|
||||
|
||||
### 4. 删除数据
|
||||
|
||||
```java
|
||||
// 按文档ID删除
|
||||
strategy.removeByDocId("doc001", "test001");
|
||||
|
||||
// 按片段ID删除
|
||||
strategy.removeByFid("fid001", "test001");
|
||||
|
||||
// 删除整个集合
|
||||
strategy.removeById("test001", "model");
|
||||
```
|
||||
|
||||
## 部署要求
|
||||
|
||||
### Milvus服务部署
|
||||
|
||||
1. **Docker部署** (推荐)
|
||||
```bash
|
||||
# 下载docker-compose文件
|
||||
wget https://github.com/milvus-io/milvus/releases/download/v2.6.4/milvus-standalone-docker-compose.yml -O docker-compose.yml
|
||||
|
||||
# 启动Milvus
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
2. **验证部署**
|
||||
```bash
|
||||
# 检查服务状态
|
||||
docker-compose ps
|
||||
|
||||
# 查看日志
|
||||
docker-compose logs milvus-standalone
|
||||
```
|
||||
|
||||
### 系统要求
|
||||
|
||||
- **内存**: 最少8GB,推荐16GB+
|
||||
- **存储**: SSD推荐,至少50GB可用空间
|
||||
- **CPU**: 4核心以上
|
||||
- **网络**: 确保19530端口可访问
|
||||
|
||||
## 性能优化
|
||||
|
||||
### 1. 索引优化
|
||||
|
||||
根据数据量调整索引参数:
|
||||
- 小数据集(<100万): nlist=1024
|
||||
- 中等数据集(100万-1000万): nlist=4096
|
||||
- 大数据集(>1000万): nlist=16384
|
||||
|
||||
### 2. 批量操作
|
||||
|
||||
- 批量插入:建议每批1000-10000条记录
|
||||
- 批量查询:避免频繁的单条查询
|
||||
|
||||
### 3. 内存管理
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml中的内存配置
|
||||
environment:
|
||||
MILVUS_CONFIG_PATH: /milvus/configs/milvus.yaml
|
||||
volumes:
|
||||
- ./milvus.yaml:/milvus/configs/milvus.yaml
|
||||
```
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 常见问题
|
||||
|
||||
1. **连接失败**
|
||||
- 检查Milvus服务是否启动
|
||||
- 验证网络连接和端口
|
||||
- 确认配置中的URL正确
|
||||
|
||||
2. **集合创建失败**
|
||||
- 检查集合名称是否符合规范
|
||||
- 验证字段定义是否正确
|
||||
- 查看Milvus日志获取详细错误
|
||||
|
||||
3. **插入数据失败**
|
||||
- 确认向量维度与schema一致
|
||||
- 检查数据格式是否正确
|
||||
- 验证集合是否已加载
|
||||
|
||||
4. **查询无结果**
|
||||
- 确认集合中有数据
|
||||
- 检查查询参数设置
|
||||
- 验证向量化模型一致性
|
||||
|
||||
### 日志调试
|
||||
|
||||
启用详细日志:
|
||||
```properties
|
||||
logging.level.org.ruoyi.service.strategy.impl.MilvusVectorStoreStrategy=DEBUG
|
||||
logging.level.io.milvus=DEBUG
|
||||
```
|
||||
|
||||
## 与Weaviate对比
|
||||
|
||||
| 特性 | Milvus | Weaviate |
|
||||
|------|--------|----------|
|
||||
| 性能 | 高性能,专为大规模设计 | 中等性能 |
|
||||
| 部署 | 需要独立部署 | 可独立部署或云服务 |
|
||||
| 生态 | 专注向量搜索 | 集成更多AI功能 |
|
||||
| 学习成本 | 中等 | 较低 |
|
||||
| 扩展性 | 优秀 | 良好 |
|
||||
|
||||
## 后续优化建议
|
||||
|
||||
1. **连接池管理**: 实现MilvusClient连接池
|
||||
2. **异步操作**: 支持异步插入和查询
|
||||
3. **分片策略**: 大数据集的分片管理
|
||||
4. **监控告警**: 集成性能监控
|
||||
5. **备份恢复**: 数据备份和恢复机制
|
||||
|
||||
## 参考资料
|
||||
|
||||
- [Milvus官方文档](https://milvus.io/docs)
|
||||
- [Milvus Java SDK](https://github.com/milvus-io/milvus-sdk-java)
|
||||
- [向量数据库最佳实践](https://milvus.io/docs/performance_faq.md)
|
||||
@@ -16,9 +16,9 @@ spring:
|
||||
master:
|
||||
type: ${spring.datasource.type}
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://127.0.0.1:3306/ruoyi-ai?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
||||
url: jdbc:mysql://127.0.0.1:3306/ruoyi-ai-github?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
||||
username: root
|
||||
password: root
|
||||
password: qxyg1010
|
||||
|
||||
hikari:
|
||||
# 最大连接池数量
|
||||
|
||||
@@ -74,6 +74,12 @@
|
||||
<version>1.19.6</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.milvus</groupId>
|
||||
<artifactId>milvus-sdk-java</artifactId>
|
||||
<version>2.6.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.langchain4j</groupId>
|
||||
<artifactId>langchain4j-open-ai</artifactId>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.ruoyi.service;
|
||||
|
||||
import com.google.protobuf.ServiceException;
|
||||
import org.ruoyi.domain.bo.QueryVectorBo;
|
||||
import org.ruoyi.domain.bo.StoreEmbeddingBo;
|
||||
|
||||
@@ -11,15 +12,15 @@ import java.util.List;
|
||||
*/
|
||||
public interface VectorStoreService {
|
||||
|
||||
void storeEmbeddings(StoreEmbeddingBo storeEmbeddingBo);
|
||||
void storeEmbeddings(StoreEmbeddingBo storeEmbeddingBo) throws ServiceException;
|
||||
|
||||
List<String> getQueryVector(QueryVectorBo queryVectorBo);
|
||||
|
||||
void createSchema(String vectorModelName, String kid,String modelName);
|
||||
|
||||
void removeById(String id,String modelName);
|
||||
void removeById(String id,String modelName) throws ServiceException;
|
||||
|
||||
void removeByDocId(String docId, String kid);
|
||||
void removeByDocId(String docId, String kid) throws ServiceException;
|
||||
|
||||
void removeByFid(String fid, String kid);
|
||||
void removeByFid(String fid, String kid) throws ServiceException;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,28 @@
|
||||
package org.ruoyi.service.strategy.impl;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.protobuf.ServiceException;
|
||||
import dev.langchain4j.data.embedding.Embedding;
|
||||
import dev.langchain4j.model.embedding.EmbeddingModel;
|
||||
import io.milvus.v2.client.ConnectConfig;
|
||||
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.DescribeCollectionReq;
|
||||
import io.milvus.v2.service.collection.request.DropCollectionReq;
|
||||
import io.milvus.v2.service.collection.request.HasCollectionReq;
|
||||
import io.milvus.v2.service.collection.response.DescribeCollectionResp;
|
||||
import io.milvus.v2.service.vector.request.DeleteReq;
|
||||
import io.milvus.v2.service.vector.request.InsertReq;
|
||||
import io.milvus.v2.service.vector.request.SearchReq;
|
||||
import io.milvus.v2.service.vector.request.data.BaseVector;
|
||||
import io.milvus.v2.service.vector.request.data.FloatVec;
|
||||
import io.milvus.v2.service.vector.response.DeleteResp;
|
||||
import io.milvus.v2.service.vector.response.InsertResp;
|
||||
import io.milvus.v2.service.vector.response.SearchResp;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.ruoyi.common.core.service.ConfigService;
|
||||
import org.ruoyi.domain.bo.QueryVectorBo;
|
||||
@@ -10,10 +30,7 @@ import org.ruoyi.domain.bo.StoreEmbeddingBo;
|
||||
import org.ruoyi.service.strategy.AbstractVectorStoreStrategy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Milvus向量库策略实现
|
||||
@@ -24,8 +41,7 @@ import java.util.Map;
|
||||
@Component
|
||||
public class MilvusVectorStoreStrategy extends AbstractVectorStoreStrategy {
|
||||
|
||||
// Milvus客户端和相关配置
|
||||
// private MilvusClient milvusClient;
|
||||
private MilvusClientV2 client;
|
||||
|
||||
public MilvusVectorStoreStrategy(ConfigService configService) {
|
||||
super(configService);
|
||||
@@ -41,106 +57,89 @@ public class MilvusVectorStoreStrategy extends AbstractVectorStoreStrategy {
|
||||
log.info("Milvus创建schema: vectorModelName={}, kid={}, modelName={}", vectorModelName, kid, modelName);
|
||||
|
||||
// 1. 获取Milvus配置
|
||||
String host = configService.getConfigValue("milvus", "host");
|
||||
String port = configService.getConfigValue("milvus", "port");
|
||||
String host = configService.getConfigValue("milvus", "url");
|
||||
String collectionName = configService.getConfigValue("milvus", "collectionname") + kid;
|
||||
|
||||
// 2. 初始化Milvus客户端
|
||||
// ConnectParam connectParam = ConnectParam.newBuilder()
|
||||
// .withHost(host)
|
||||
// .withPort(Integer.parseInt(port))
|
||||
// .build();
|
||||
// milvusClient = new MilvusClient(connectParam);
|
||||
ConnectConfig config = ConnectConfig.builder()
|
||||
.uri(host)
|
||||
.build();
|
||||
client = new MilvusClientV2(config);
|
||||
|
||||
// 2. 检查集合是否存在
|
||||
HasCollectionReq hasCollectionReq = HasCollectionReq.builder()
|
||||
.collectionName(collectionName)
|
||||
.build();
|
||||
|
||||
// 3. 检查集合是否存在,如果不存在则创建
|
||||
// HasCollectionParam hasCollectionParam = HasCollectionParam.newBuilder()
|
||||
// .withCollectionName(collectionName)
|
||||
// .build();
|
||||
// R<Boolean> hasCollectionResponse = milvusClient.hasCollection(hasCollectionParam);
|
||||
//
|
||||
// if (!hasCollectionResponse.getData()) {
|
||||
// // 创建集合
|
||||
// List<FieldType> fieldsSchema = new ArrayList<>();
|
||||
//
|
||||
// // 主键字段
|
||||
// fieldsSchema.add(FieldType.newBuilder()
|
||||
// .withName("id")
|
||||
// .withDataType(DataType.Int64)
|
||||
// .withPrimaryKey(true)
|
||||
// .withAutoID(true)
|
||||
// .build());
|
||||
//
|
||||
// // 文本字段
|
||||
// fieldsSchema.add(FieldType.newBuilder()
|
||||
// .withName("text")
|
||||
// .withDataType(DataType.VarChar)
|
||||
// .withMaxLength(65535)
|
||||
// .build());
|
||||
//
|
||||
// // fid字段
|
||||
// fieldsSchema.add(FieldType.newBuilder()
|
||||
// .withName("fid")
|
||||
// .withDataType(DataType.VarChar)
|
||||
// .withMaxLength(255)
|
||||
// .build());
|
||||
//
|
||||
// // kid字段
|
||||
// fieldsSchema.add(FieldType.newBuilder()
|
||||
// .withName("kid")
|
||||
// .withDataType(DataType.VarChar)
|
||||
// .withMaxLength(255)
|
||||
// .build());
|
||||
//
|
||||
// // docId字段
|
||||
// fieldsSchema.add(FieldType.newBuilder()
|
||||
// .withName("docId")
|
||||
// .withDataType(DataType.VarChar)
|
||||
// .withMaxLength(255)
|
||||
// .build());
|
||||
//
|
||||
// // 向量字段
|
||||
// fieldsSchema.add(FieldType.newBuilder()
|
||||
// .withName("vector")
|
||||
// .withDataType(DataType.FloatVector)
|
||||
// .withDimension(1536) // 根据实际embedding维度调整
|
||||
// .build());
|
||||
//
|
||||
// CreateCollectionParam createCollectionParam = CreateCollectionParam.newBuilder()
|
||||
// .withCollectionName(collectionName)
|
||||
// .withDescription("Knowledge base collection for " + kid)
|
||||
// .withShardsNum(2)
|
||||
// .withFieldTypes(fieldsSchema)
|
||||
// .build();
|
||||
//
|
||||
// R<RpcStatus> createCollectionResponse = milvusClient.createCollection(createCollectionParam);
|
||||
// if (createCollectionResponse.getStatus() == R.Status.Success.getCode()) {
|
||||
// log.info("Milvus集合创建成功: {}", collectionName);
|
||||
//
|
||||
// // 创建索引
|
||||
// IndexParam indexParam = IndexParam.newBuilder()
|
||||
// .withCollectionName(collectionName)
|
||||
// .withFieldName("vector")
|
||||
// .withIndexType(IndexType.IVF_FLAT)
|
||||
// .withMetricType(MetricType.L2)
|
||||
// .withExtraParam("{\"nlist\":1024}")
|
||||
// .build();
|
||||
//
|
||||
// R<RpcStatus> createIndexResponse = milvusClient.createIndex(indexParam);
|
||||
// if (createIndexResponse.getStatus() == R.Status.Success.getCode()) {
|
||||
// log.info("Milvus索引创建成功: {}", collectionName);
|
||||
// } else {
|
||||
// log.error("Milvus索引创建失败: {}", createIndexResponse.getMessage());
|
||||
// }
|
||||
// } else {
|
||||
// log.error("Milvus集合创建失败: {}", createCollectionResponse.getMessage());
|
||||
// }
|
||||
// }
|
||||
Boolean hasCollection = client.hasCollection(hasCollectionReq);
|
||||
|
||||
log.info("Milvus schema创建完成: {}", collectionName);
|
||||
if (!hasCollection) {
|
||||
// 3. 创建集合schema
|
||||
CreateCollectionReq.CollectionSchema schema = CreateCollectionReq.CollectionSchema.builder()
|
||||
.build();
|
||||
|
||||
// 添加字段定义
|
||||
schema.addField(AddFieldReq.builder()
|
||||
.fieldName("id")
|
||||
.dataType(DataType.Int64)
|
||||
.isPrimaryKey(true)
|
||||
.autoID(true)
|
||||
.build());
|
||||
|
||||
schema.addField(AddFieldReq.builder()
|
||||
.fieldName("text")
|
||||
.dataType(DataType.VarChar)
|
||||
.maxLength(65535)
|
||||
.build());
|
||||
|
||||
schema.addField(AddFieldReq.builder()
|
||||
.fieldName("fid")
|
||||
.dataType(DataType.VarChar)
|
||||
.maxLength(255)
|
||||
.build());
|
||||
|
||||
schema.addField(AddFieldReq.builder()
|
||||
.fieldName("kid")
|
||||
.dataType(DataType.VarChar)
|
||||
.maxLength(255)
|
||||
.build());
|
||||
|
||||
schema.addField(AddFieldReq.builder()
|
||||
.fieldName("docId")
|
||||
.dataType(DataType.VarChar)
|
||||
.maxLength(255)
|
||||
.build());
|
||||
|
||||
schema.addField(AddFieldReq.builder()
|
||||
.fieldName("vector")
|
||||
.dataType(DataType.FloatVector)
|
||||
.dimension(1024) // 根据实际embedding维度调整
|
||||
.build());
|
||||
|
||||
// 4. 创建索引参数
|
||||
List<IndexParam> indexParams = new ArrayList<>();
|
||||
indexParams.add(IndexParam.builder()
|
||||
.fieldName("vector")
|
||||
.indexType(IndexParam.IndexType.IVF_FLAT)
|
||||
.metricType(IndexParam.MetricType.L2)
|
||||
.extraParams(Map.of("nlist", 1024))
|
||||
.build());
|
||||
|
||||
// 5. 创建集合
|
||||
CreateCollectionReq createCollectionReq = CreateCollectionReq.builder()
|
||||
.collectionName(collectionName)
|
||||
.collectionSchema(schema)
|
||||
.indexParams(indexParams)
|
||||
.build();
|
||||
|
||||
client.createCollection(createCollectionReq);
|
||||
log.info("Milvus集合创建成功: {}", collectionName);
|
||||
} else {
|
||||
log.info("Milvus集合已存在: {}", collectionName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeEmbeddings(StoreEmbeddingBo storeEmbeddingBo) {
|
||||
public void storeEmbeddings(StoreEmbeddingBo storeEmbeddingBo) throws ServiceException {
|
||||
createSchema(storeEmbeddingBo.getVectorModelName(), storeEmbeddingBo.getKid(), storeEmbeddingBo.getVectorModelName());
|
||||
|
||||
EmbeddingModel embeddingModel = getEmbeddingModel(storeEmbeddingBo.getEmbeddingModelName(),
|
||||
@@ -155,48 +154,56 @@ public class MilvusVectorStoreStrategy extends AbstractVectorStoreStrategy {
|
||||
log.info("Milvus向量存储条数记录: " + chunkList.size());
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
// List<InsertParam.Field> fields = new ArrayList<>();
|
||||
// List<String> textList = new ArrayList<>();
|
||||
// List<String> fidListData = new ArrayList<>();
|
||||
// List<String> kidList = new ArrayList<>();
|
||||
// List<String> docIdList = new ArrayList<>();
|
||||
// List<List<Float>> vectorList = new ArrayList<>();
|
||||
// 准备批量插入数据
|
||||
List<String> textList = new ArrayList<>();
|
||||
List<String> fidListData = new ArrayList<>();
|
||||
List<String> kidList = new ArrayList<>();
|
||||
List<String> docIdList = new ArrayList<>();
|
||||
List<List<Float>> vectorList = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < chunkList.size(); i++) {
|
||||
String text = chunkList.get(i);
|
||||
String fid = fidList.get(i);
|
||||
Embedding embedding = embeddingModel.embed(text).content();
|
||||
|
||||
// textList.add(text);
|
||||
// fidListData.add(fid);
|
||||
// kidList.add(kid);
|
||||
// docIdList.add(docId);
|
||||
//
|
||||
// List<Float> vector = new ArrayList<>();
|
||||
// for (float f : embedding.vector()) {
|
||||
// vector.add(f);
|
||||
// }
|
||||
// vectorList.add(vector);
|
||||
textList.add(text);
|
||||
fidListData.add(fid);
|
||||
kidList.add(kid);
|
||||
docIdList.add(docId);
|
||||
|
||||
List<Float> vector = new ArrayList<>();
|
||||
for (float f : embedding.vector()) {
|
||||
vector.add(f);
|
||||
}
|
||||
vectorList.add(vector);
|
||||
}
|
||||
|
||||
// fields.add(new InsertParam.Field("text", textList));
|
||||
// fields.add(new InsertParam.Field("fid", fidListData));
|
||||
// fields.add(new InsertParam.Field("kid", kidList));
|
||||
// fields.add(new InsertParam.Field("docId", docIdList));
|
||||
// fields.add(new InsertParam.Field("vector", vectorList));
|
||||
//
|
||||
// InsertParam insertParam = InsertParam.newBuilder()
|
||||
// .withCollectionName(collectionName)
|
||||
// .withFields(fields)
|
||||
// .build();
|
||||
//
|
||||
// R<MutationResult> insertResponse = milvusClient.insert(insertParam);
|
||||
// if (insertResponse.getStatus() == R.Status.Success.getCode()) {
|
||||
// log.info("Milvus向量存储成功,插入条数: {}", insertResponse.getData().getInsertCnt());
|
||||
// } else {
|
||||
// log.error("Milvus向量存储失败: {}", insertResponse.getMessage());
|
||||
// throw new ServiceException("Milvus向量存储失败: " + insertResponse.getMessage());
|
||||
// }
|
||||
// 构建插入数据
|
||||
List<JsonObject> data = new ArrayList<>();
|
||||
Gson gson = new Gson();
|
||||
for (int i = 0; i < textList.size(); i++) {
|
||||
JsonObject row = new JsonObject();
|
||||
row.addProperty("text", textList.get(i));
|
||||
row.addProperty("fid", fidListData.get(i));
|
||||
row.addProperty("kid", kidList.get(i));
|
||||
row.addProperty("docId", docIdList.get(i));
|
||||
row.add("vector", gson.toJsonTree(vectorList.get(i)));
|
||||
data.add(row);
|
||||
}
|
||||
|
||||
// 执行插入
|
||||
InsertReq insertReq = InsertReq.builder()
|
||||
.collectionName(collectionName)
|
||||
.data(data)
|
||||
.build();
|
||||
|
||||
InsertResp insertResp = client.insert(insertReq);
|
||||
if (insertResp.getInsertCnt() > 0) {
|
||||
log.info("Milvus向量存储成功,插入条数: {}", insertResp.getInsertCnt());
|
||||
} else {
|
||||
log.error("Milvus向量存储失败");
|
||||
throw new ServiceException("Milvus向量存储失败");
|
||||
}
|
||||
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("Milvus向量存储完成消耗时间:" + (endTime - startTime) / 1000 + "秒");
|
||||
@@ -214,99 +221,95 @@ public class MilvusVectorStoreStrategy extends AbstractVectorStoreStrategy {
|
||||
|
||||
List<String> resultList = new ArrayList<>();
|
||||
|
||||
// List<String> searchOutputFields = List.of("text", "fid", "kid", "docId");
|
||||
// List<List<Float>> searchVectors = new ArrayList<>();
|
||||
// List<Float> queryVector = new ArrayList<>();
|
||||
// for (float f : queryEmbedding.vector()) {
|
||||
// queryVector.add(f);
|
||||
// }
|
||||
// searchVectors.add(queryVector);
|
||||
//
|
||||
// SearchParam searchParam = SearchParam.newBuilder()
|
||||
// .withCollectionName(collectionName)
|
||||
// .withMetricType(MetricType.L2)
|
||||
// .withOutFields(searchOutputFields)
|
||||
// .withTopK(queryVectorBo.getMaxResults())
|
||||
// .withVectors(searchVectors)
|
||||
// .withVectorFieldName("vector")
|
||||
// .withParams("{\"nprobe\":10}")
|
||||
// .build();
|
||||
//
|
||||
// R<SearchResults> searchResponse = milvusClient.search(searchParam);
|
||||
// if (searchResponse.getStatus() == R.Status.Success.getCode()) {
|
||||
// SearchResults searchResults = searchResponse.getData();
|
||||
// List<SearchResults.QueryResult> queryResults = searchResults.getResults();
|
||||
//
|
||||
// for (SearchResults.QueryResult queryResult : queryResults) {
|
||||
// List<SearchResults.QueryResult.Row> rows = queryResult.getRows();
|
||||
// for (SearchResults.QueryResult.Row row : rows) {
|
||||
// String text = (String) row.get("text");
|
||||
// resultList.add(text);
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// log.error("Milvus查询失败: {}", searchResponse.getMessage());
|
||||
// }
|
||||
// 准备查询向量
|
||||
List<BaseVector> searchVectors = new ArrayList<>();
|
||||
float[] queryVectorArray = new float[queryEmbedding.vector().length];
|
||||
for (int i = 0; i < queryEmbedding.vector().length; i++) {
|
||||
queryVectorArray[i] = queryEmbedding.vector()[i];
|
||||
}
|
||||
searchVectors.add(new FloatVec(queryVectorArray));
|
||||
|
||||
// 构建搜索请求
|
||||
SearchReq searchReq = SearchReq.builder()
|
||||
.collectionName(collectionName)
|
||||
.data(searchVectors)
|
||||
.topK(queryVectorBo.getMaxResults())
|
||||
.outputFields(Arrays.asList("text", "fid", "kid", "docId"))
|
||||
.build();
|
||||
|
||||
SearchResp searchResp = client.search(searchReq);
|
||||
if (searchResp != null && searchResp.getSearchResults() != null) {
|
||||
List<List<SearchResp.SearchResult>> searchResults = searchResp.getSearchResults();
|
||||
|
||||
for (List<SearchResp.SearchResult> results : searchResults) {
|
||||
for (SearchResp.SearchResult result : results) {
|
||||
Map<String, Object> entity = result.getEntity();
|
||||
String text = (String) entity.get("text");
|
||||
if (text != null) {
|
||||
resultList.add(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.error("Milvus查询失败或无结果");
|
||||
}
|
||||
|
||||
return resultList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeById(String id, String modelName) {
|
||||
public void removeById(String id, String modelName) throws ServiceException {
|
||||
String collectionName = configService.getConfigValue("milvus", "collectionname") + id;
|
||||
|
||||
// DropCollectionParam dropCollectionParam = DropCollectionParam.newBuilder()
|
||||
// .withCollectionName(collectionName)
|
||||
// .build();
|
||||
//
|
||||
// R<RpcStatus> dropResponse = milvusClient.dropCollection(dropCollectionParam);
|
||||
// if (dropResponse.getStatus() == R.Status.Success.getCode()) {
|
||||
// log.info("Milvus集合删除成功: {}", collectionName);
|
||||
// } else {
|
||||
// log.error("Milvus集合删除失败: {}", dropResponse.getMessage());
|
||||
// throw new ServiceException("Milvus集合删除失败: " + dropResponse.getMessage());
|
||||
// }
|
||||
// 删除整个集合
|
||||
DropCollectionReq dropCollectionReq = DropCollectionReq.builder()
|
||||
.collectionName(collectionName)
|
||||
.build();
|
||||
|
||||
log.info("Milvus删除集合: {}", collectionName);
|
||||
try {
|
||||
client.dropCollection(dropCollectionReq);
|
||||
log.info("Milvus集合删除成功: {}", collectionName);
|
||||
} catch (Exception e) {
|
||||
log.error("Milvus集合删除失败: {}", e.getMessage());
|
||||
throw new ServiceException("Milvus集合删除失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeByDocId(String docId, String kid) {
|
||||
public void removeByDocId(String docId, String kid) throws ServiceException {
|
||||
String collectionName = configService.getConfigValue("milvus", "collectionname") + kid;
|
||||
|
||||
// String expr = "docId == \"" + docId + "\"";
|
||||
// DeleteParam deleteParam = DeleteParam.newBuilder()
|
||||
// .withCollectionName(collectionName)
|
||||
// .withExpr(expr)
|
||||
// .build();
|
||||
//
|
||||
// R<MutationResult> deleteResponse = milvusClient.delete(deleteParam);
|
||||
// if (deleteResponse.getStatus() == R.Status.Success.getCode()) {
|
||||
// log.info("Milvus成功删除 docId={} 的所有向量数据,删除条数: {}", docId, deleteResponse.getData().getDeleteCnt());
|
||||
// } else {
|
||||
// log.error("Milvus删除失败: {}", deleteResponse.getMessage());
|
||||
// }
|
||||
String expr = "docId == \"" + docId + "\"";
|
||||
DeleteReq deleteReq = DeleteReq.builder()
|
||||
.collectionName(collectionName)
|
||||
.filter(expr)
|
||||
.build();
|
||||
|
||||
log.info("Milvus删除docId={}的数据", docId);
|
||||
try {
|
||||
DeleteResp deleteResp = client.delete(deleteReq);
|
||||
log.info("Milvus成功删除 docId={} 的所有向量数据,删除条数: {}", docId, deleteResp.getDeleteCnt());
|
||||
} catch (Exception e) {
|
||||
log.error("Milvus删除失败: {}", e.getMessage());
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeByFid(String fid, String kid) {
|
||||
public void removeByFid(String fid, String kid) throws ServiceException {
|
||||
String collectionName = configService.getConfigValue("milvus", "collectionname") + kid;
|
||||
|
||||
// String expr = "fid == \"" + fid + "\"";
|
||||
// DeleteParam deleteParam = DeleteParam.newBuilder()
|
||||
// .withCollectionName(collectionName)
|
||||
// .withExpr(expr)
|
||||
// .build();
|
||||
//
|
||||
// R<MutationResult> deleteResponse = milvusClient.delete(deleteParam);
|
||||
// if (deleteResponse.getStatus() == R.Status.Success.getCode()) {
|
||||
// log.info("Milvus成功删除 fid={} 的所有向量数据,删除条数: {}", fid, deleteResponse.getData().getDeleteCnt());
|
||||
// } else {
|
||||
// log.error("Milvus删除失败: {}", deleteResponse.getMessage());
|
||||
// }
|
||||
String expr = "fid == \"" + fid + "\"";
|
||||
DeleteReq deleteReq = DeleteReq.builder()
|
||||
.collectionName(collectionName)
|
||||
.filter(expr)
|
||||
.build();
|
||||
|
||||
log.info("Milvus删除fid={}的数据", fid);
|
||||
try {
|
||||
DeleteResp deleteResp = client.delete(deleteReq);
|
||||
log.info("Milvus成功删除 fid={} 的所有向量数据,删除条数: {}", fid, deleteResp.getDeleteCnt());
|
||||
} catch (Exception e) {
|
||||
log.error("Milvus删除失败: {}", e.getMessage());
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user