Commit f2ee2008e6d84bf9d30113592a239803ff0fa5d5

Authored by YunaiV
1 parent 588c9fe3

【功能新增】AI:增加 MilvusVectorStore 向量库的接入

yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiModelServiceImpl.java
@@ -17,7 +17,7 @@ import org.springframework.ai.chat.model.ChatModel; @@ -17,7 +17,7 @@ import org.springframework.ai.chat.model.ChatModel;
17 import org.springframework.ai.embedding.EmbeddingModel; 17 import org.springframework.ai.embedding.EmbeddingModel;
18 import org.springframework.ai.image.ImageModel; 18 import org.springframework.ai.image.ImageModel;
19 import org.springframework.ai.vectorstore.VectorStore; 19 import org.springframework.ai.vectorstore.VectorStore;
20 -import org.springframework.ai.vectorstore.qdrant.QdrantVectorStore; 20 +import org.springframework.ai.vectorstore.milvus.MilvusVectorStore;
21 import org.springframework.stereotype.Service; 21 import org.springframework.stereotype.Service;
22 import org.springframework.validation.annotation.Validated; 22 import org.springframework.validation.annotation.Validated;
23 23
@@ -114,8 +114,7 @@ public class AiModelServiceImpl implements AiModelService { @@ -114,8 +114,7 @@ public class AiModelServiceImpl implements AiModelService {
114 } 114 }
115 115
116 @Override 116 @Override
117 - public List<AiModelDO> getModelListByStatusAndType(Integer status, Integer type,  
118 - String platform) { 117 + public List<AiModelDO> getModelListByStatusAndType(Integer status, Integer type, String platform) {
119 return modelMapper.selectListByStatusAndType(status, type, platform); 118 return modelMapper.selectListByStatusAndType(status, type, platform);
120 } 119 }
121 120
@@ -163,9 +162,10 @@ public class AiModelServiceImpl implements AiModelService { @@ -163,9 +162,10 @@ public class AiModelServiceImpl implements AiModelService {
163 platform, apiKey.getApiKey(), apiKey.getUrl(), model.getModel()); 162 platform, apiKey.getApiKey(), apiKey.getUrl(), model.getModel());
164 163
165 // 创建或获取 VectorStore 对象 164 // 创建或获取 VectorStore 对象
166 -// return modelFactory.getOrCreateVectorStore(SimpleVectorStore.class, embeddingModel, metadataFields);  
167 - return modelFactory.getOrCreateVectorStore(QdrantVectorStore.class, embeddingModel, metadataFields);  
168 -// return modelFactory.getOrCreateVectorStore(RedisVectorStore.class, embeddingModel, metadataFields); 165 + // return modelFactory.getOrCreateVectorStore(SimpleVectorStore.class, embeddingModel, metadataFields);
  166 + // return modelFactory.getOrCreateVectorStore(QdrantVectorStore.class, embeddingModel, metadataFields);
  167 + // return modelFactory.getOrCreateVectorStore(RedisVectorStore.class, embeddingModel, metadataFields);
  168 + return modelFactory.getOrCreateVectorStore(MilvusVectorStore.class, embeddingModel, metadataFields);
169 } 169 }
170 170
171 } 171 }
172 \ No newline at end of file 172 \ No newline at end of file
yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml
@@ -70,7 +70,6 @@ @@ -70,7 +70,6 @@
70 <groupId>${spring-ai.groupId}</groupId> 70 <groupId>${spring-ai.groupId}</groupId>
71 <artifactId>spring-ai-qdrant-store</artifactId> 71 <artifactId>spring-ai-qdrant-store</artifactId>
72 <version>${spring-ai.version}</version> 72 <version>${spring-ai.version}</version>
73 -<!-- <optional>true</optional>-->  
74 </dependency> 73 </dependency>
75 74
76 <dependency> 75 <dependency>
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java
@@ -11,8 +11,12 @@ import cn.iocoder.yudao.framework.ai.core.model.siliconflow.SiliconFlowChatModel @@ -11,8 +11,12 @@ import cn.iocoder.yudao.framework.ai.core.model.siliconflow.SiliconFlowChatModel
11 import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; 11 import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi;
12 import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; 12 import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel;
13 import lombok.extern.slf4j.Slf4j; 13 import lombok.extern.slf4j.Slf4j;
  14 +import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusServiceClientProperties;
  15 +import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreProperties;
14 import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreProperties; 16 import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreProperties;
15 import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreProperties; 17 import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreProperties;
  18 +import org.springframework.ai.embedding.BatchingStrategy;
  19 +import org.springframework.ai.embedding.TokenCountBatchingStrategy;
16 import org.springframework.ai.openai.OpenAiChatModel; 20 import org.springframework.ai.openai.OpenAiChatModel;
17 import org.springframework.ai.openai.OpenAiChatOptions; 21 import org.springframework.ai.openai.OpenAiChatOptions;
18 import org.springframework.ai.openai.api.OpenAiApi; 22 import org.springframework.ai.openai.api.OpenAiApi;
@@ -22,7 +26,6 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; @@ -22,7 +26,6 @@ import org.springframework.boot.autoconfigure.AutoConfiguration;
22 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 26 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
23 import org.springframework.boot.context.properties.EnableConfigurationProperties; 27 import org.springframework.boot.context.properties.EnableConfigurationProperties;
24 import org.springframework.context.annotation.Bean; 28 import org.springframework.context.annotation.Bean;
25 -import org.springframework.context.annotation.Lazy;  
26 29
27 /** 30 /**
28 * 芋道 AI 自动配置 31 * 芋道 AI 自动配置
@@ -33,6 +36,7 @@ import org.springframework.context.annotation.Lazy; @@ -33,6 +36,7 @@ import org.springframework.context.annotation.Lazy;
33 @EnableConfigurationProperties({YudaoAiProperties.class, 36 @EnableConfigurationProperties({YudaoAiProperties.class,
34 QdrantVectorStoreProperties.class, // 解析 Qdrant 配置 37 QdrantVectorStoreProperties.class, // 解析 Qdrant 配置
35 RedisVectorStoreProperties.class, // 解析 Redis 配置 38 RedisVectorStoreProperties.class, // 解析 Redis 配置
  39 + MilvusVectorStoreProperties.class, MilvusServiceClientProperties.class // 解析 Milvus 配置
36 }) 40 })
37 @Slf4j 41 @Slf4j
38 public class YudaoAiAutoConfiguration { 42 public class YudaoAiAutoConfiguration {
@@ -193,18 +197,16 @@ public class YudaoAiAutoConfiguration { @@ -193,18 +197,16 @@ public class YudaoAiAutoConfiguration {
193 return new SunoApi(yudaoAiProperties.getSuno().getBaseUrl()); 197 return new SunoApi(yudaoAiProperties.getSuno().getBaseUrl());
194 } 198 }
195 199
196 - // ========== rag 相关 ==========  
197 - // TODO @xin 免费版本  
198 -// @Bean  
199 -// @Lazy // TODO 芋艿:临时注释,避免无法启动」  
200 -// public TransformersEmbeddingModel transformersEmbeddingClient() {  
201 -// return new TransformersEmbeddingModel(MetadataMode.EMBED);  
202 -// } 200 + // ========== RAG 相关 ==========
203 201
204 @Bean 202 @Bean
205 - @Lazy // TODO 芋艿:临时注释,避免无法启动  
206 public TokenCountEstimator tokenCountEstimator() { 203 public TokenCountEstimator tokenCountEstimator() {
207 return new JTokkitTokenCountEstimator(); 204 return new JTokkitTokenCountEstimator();
208 } 205 }
209 206
  207 + @Bean
  208 + public BatchingStrategy batchingStrategy() {
  209 + return new TokenCountBatchingStrategy();
  210 + }
  211 +
210 } 212 }
211 \ No newline at end of file 213 \ No newline at end of file
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java
@@ -5,7 +5,6 @@ import cn.hutool.core.lang.Assert; @@ -5,7 +5,6 @@ import cn.hutool.core.lang.Assert;
5 import cn.hutool.core.lang.Singleton; 5 import cn.hutool.core.lang.Singleton;
6 import cn.hutool.core.lang.func.Func0; 6 import cn.hutool.core.lang.func.Func0;
7 import cn.hutool.core.util.ArrayUtil; 7 import cn.hutool.core.util.ArrayUtil;
8 -import cn.hutool.core.util.ReflectUtil;  
9 import cn.hutool.core.util.RuntimeUtil; 8 import cn.hutool.core.util.RuntimeUtil;
10 import cn.hutool.core.util.StrUtil; 9 import cn.hutool.core.util.StrUtil;
11 import cn.hutool.extra.spring.SpringUtil; 10 import cn.hutool.extra.spring.SpringUtil;
@@ -29,6 +28,7 @@ import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingOptions; @@ -29,6 +28,7 @@ import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingOptions;
29 import com.alibaba.cloud.ai.dashscope.image.DashScopeImageModel; 28 import com.alibaba.cloud.ai.dashscope.image.DashScopeImageModel;
30 import com.azure.ai.openai.OpenAIClientBuilder; 29 import com.azure.ai.openai.OpenAIClientBuilder;
31 import io.micrometer.observation.ObservationRegistry; 30 import io.micrometer.observation.ObservationRegistry;
  31 +import io.milvus.client.MilvusServiceClient;
32 import io.qdrant.client.QdrantClient; 32 import io.qdrant.client.QdrantClient;
33 import io.qdrant.client.QdrantGrpcClient; 33 import io.qdrant.client.QdrantGrpcClient;
34 import lombok.SneakyThrows; 34 import lombok.SneakyThrows;
@@ -38,6 +38,10 @@ import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiConnectionPr @@ -38,6 +38,10 @@ import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiConnectionPr
38 import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration; 38 import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration;
39 import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; 39 import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration;
40 import org.springframework.ai.autoconfigure.qianfan.QianFanAutoConfiguration; 40 import org.springframework.ai.autoconfigure.qianfan.QianFanAutoConfiguration;
  41 +import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusServiceClientConnectionDetails;
  42 +import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusServiceClientProperties;
  43 +import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration;
  44 +import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreProperties;
41 import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration; 45 import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration;
42 import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreProperties; 46 import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreProperties;
43 import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreAutoConfiguration; 47 import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreAutoConfiguration;
@@ -47,6 +51,7 @@ import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiConnectionProperties; @@ -47,6 +51,7 @@ import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiConnectionProperties;
47 import org.springframework.ai.azure.openai.AzureOpenAiChatModel; 51 import org.springframework.ai.azure.openai.AzureOpenAiChatModel;
48 import org.springframework.ai.chat.model.ChatModel; 52 import org.springframework.ai.chat.model.ChatModel;
49 import org.springframework.ai.document.MetadataMode; 53 import org.springframework.ai.document.MetadataMode;
  54 +import org.springframework.ai.embedding.BatchingStrategy;
50 import org.springframework.ai.embedding.EmbeddingModel; 55 import org.springframework.ai.embedding.EmbeddingModel;
51 import org.springframework.ai.image.ImageModel; 56 import org.springframework.ai.image.ImageModel;
52 import org.springframework.ai.ollama.OllamaChatModel; 57 import org.springframework.ai.ollama.OllamaChatModel;
@@ -66,6 +71,7 @@ import org.springframework.ai.stabilityai.StabilityAiImageModel; @@ -66,6 +71,7 @@ import org.springframework.ai.stabilityai.StabilityAiImageModel;
66 import org.springframework.ai.stabilityai.api.StabilityAiApi; 71 import org.springframework.ai.stabilityai.api.StabilityAiApi;
67 import org.springframework.ai.vectorstore.SimpleVectorStore; 72 import org.springframework.ai.vectorstore.SimpleVectorStore;
68 import org.springframework.ai.vectorstore.VectorStore; 73 import org.springframework.ai.vectorstore.VectorStore;
  74 +import org.springframework.ai.vectorstore.milvus.MilvusVectorStore;
69 import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention; 75 import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention;
70 import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention; 76 import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention;
71 import org.springframework.ai.vectorstore.qdrant.QdrantVectorStore; 77 import org.springframework.ai.vectorstore.qdrant.QdrantVectorStore;
@@ -247,6 +253,9 @@ public class AiModelFactoryImpl implements AiModelFactory { @@ -247,6 +253,9 @@ public class AiModelFactoryImpl implements AiModelFactory {
247 if (type == RedisVectorStore.class) { 253 if (type == RedisVectorStore.class) {
248 return buildRedisVectorStore(embeddingModel, metadataFields); 254 return buildRedisVectorStore(embeddingModel, metadataFields);
249 } 255 }
  256 + if (type == MilvusVectorStore.class) {
  257 + return buildMilvusVectorStore(embeddingModel);
  258 + }
250 throw new IllegalArgumentException(StrUtil.format("未知类型({})", type)); 259 throw new IllegalArgumentException(StrUtil.format("未知类型({})", type));
251 }); 260 });
252 } 261 }
@@ -482,8 +491,7 @@ public class AiModelFactoryImpl implements AiModelFactory { @@ -482,8 +491,7 @@ public class AiModelFactoryImpl implements AiModelFactory {
482 QdrantClient qdrantClient = new QdrantClient(grpcClientBuilder.build()); 491 QdrantClient qdrantClient = new QdrantClient(grpcClientBuilder.build());
483 // 创建 QdrantVectorStore 对象 492 // 创建 QdrantVectorStore 对象
484 QdrantVectorStore vectorStore = configuration.vectorStore(embeddingModel, properties, qdrantClient, 493 QdrantVectorStore vectorStore = configuration.vectorStore(embeddingModel, properties, qdrantClient,
485 - getObservationRegistry(), getCustomObservationConvention(),  
486 - ReflectUtil.invoke(configuration, "batchingStrategy")); 494 + getObservationRegistry(), getCustomObservationConvention(), getBatchingStrategy());
487 // 初始化索引 495 // 初始化索引
488 vectorStore.afterPropertiesSet(); 496 vectorStore.afterPropertiesSet();
489 return vectorStore; 497 return vectorStore;
@@ -516,13 +524,48 @@ public class AiModelFactoryImpl implements AiModelFactory { @@ -516,13 +524,48 @@ public class AiModelFactoryImpl implements AiModelFactory {
516 })) 524 }))
517 .observationRegistry(getObservationRegistry().getObject()) 525 .observationRegistry(getObservationRegistry().getObject())
518 .customObservationConvention(getCustomObservationConvention().getObject()) 526 .customObservationConvention(getCustomObservationConvention().getObject())
519 - .batchingStrategy(ReflectUtil.invoke(configuration, "batchingStrategy")) 527 + .batchingStrategy(getBatchingStrategy())
520 .build(); 528 .build();
521 // 初始化索引 529 // 初始化索引
522 redisVectorStore.afterPropertiesSet(); 530 redisVectorStore.afterPropertiesSet();
523 return redisVectorStore; 531 return redisVectorStore;
524 } 532 }
525 533
  534 + /**
  535 + * 参考 {@link MilvusVectorStoreAutoConfiguration} 的 vectorStore 方法
  536 + */
  537 + @SneakyThrows
  538 + private MilvusVectorStore buildMilvusVectorStore(EmbeddingModel embeddingModel) {
  539 + MilvusVectorStoreAutoConfiguration configuration = new MilvusVectorStoreAutoConfiguration();
  540 + // 获取配置属性
  541 + MilvusVectorStoreProperties serverProperties = SpringUtil.getBean(MilvusVectorStoreProperties.class);
  542 + MilvusServiceClientProperties clientProperties = SpringUtil.getBean(MilvusServiceClientProperties.class);
  543 +
  544 + // 创建 MilvusServiceClient 对象
  545 + MilvusServiceClient milvusClient = configuration.milvusClient(serverProperties, clientProperties,
  546 + new MilvusServiceClientConnectionDetails() {
  547 +
  548 + @Override
  549 + public String getHost() {
  550 + return clientProperties.getHost();
  551 + }
  552 +
  553 + @Override
  554 + public int getPort() {
  555 + return clientProperties.getPort();
  556 + }
  557 +
  558 + }
  559 + );
  560 + // 创建 MilvusVectorStore 对象
  561 + MilvusVectorStore vectorStore = configuration.vectorStore(milvusClient, embeddingModel, serverProperties,
  562 + getBatchingStrategy(), getObservationRegistry(), getCustomObservationConvention());
  563 +
  564 + // 初始化索引
  565 + vectorStore.afterPropertiesSet();
  566 + return vectorStore;
  567 + }
  568 +
526 private static ObjectProvider<ObservationRegistry> getObservationRegistry() { 569 private static ObjectProvider<ObservationRegistry> getObservationRegistry() {
527 return new ObjectProvider<>() { 570 return new ObjectProvider<>() {
528 571
@@ -543,4 +586,8 @@ public class AiModelFactoryImpl implements AiModelFactory { @@ -543,4 +586,8 @@ public class AiModelFactoryImpl implements AiModelFactory {
543 }; 586 };
544 } 587 }
545 588
  589 + private static BatchingStrategy getBatchingStrategy() {
  590 + return SpringUtil.getBean(BatchingStrategy.class);
  591 + }
  592 +
546 } 593 }
yudao-server/src/main/resources/application.yaml
@@ -157,8 +157,13 @@ spring: @@ -157,8 +157,13 @@ spring:
157 collection-name: knowledge_segment # Qdrant 中向量集合的名称:用于存储向量数据的集合标识符,所有相关的向量操作都会在这个集合中进行 157 collection-name: knowledge_segment # Qdrant 中向量集合的名称:用于存储向量数据的集合标识符,所有相关的向量操作都会在这个集合中进行
158 host: 127.0.0.1 158 host: 127.0.0.1
159 port: 6334 159 port: 6334
160 - use-tls: false  
161 - api-key: 160 + milvus:
  161 + initialize-schema: true
  162 + database-name: default # Milvus 中数据库的名称
  163 + collection-name: knowledge_segment # Milvus 中集合的名称:用于存储向量数据的集合标识符,所有相关的向量操作都会在这个集合中进行
  164 + client:
  165 + host: 127.0.0.1
  166 + port: 19530
162 qianfan: # 文心一言 167 qianfan: # 文心一言
163 api-key: x0cuLZ7XsaTCU08vuJWO87Lg 168 api-key: x0cuLZ7XsaTCU08vuJWO87Lg
164 secret-key: R9mYF9dl9KASgi5RUq0FQt3wRisSnOcK 169 secret-key: R9mYF9dl9KASgi5RUq0FQt3wRisSnOcK