Commit f2ee2008e6d84bf9d30113592a239803ff0fa5d5
1 parent
588c9fe3
【功能新增】AI:增加 MilvusVectorStore 向量库的接入
Showing
5 changed files
with
75 additions
and
22 deletions
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 | 17 | import org.springframework.ai.embedding.EmbeddingModel; |
| 18 | 18 | import org.springframework.ai.image.ImageModel; |
| 19 | 19 | import org.springframework.ai.vectorstore.VectorStore; |
| 20 | -import org.springframework.ai.vectorstore.qdrant.QdrantVectorStore; | |
| 20 | +import org.springframework.ai.vectorstore.milvus.MilvusVectorStore; | |
| 21 | 21 | import org.springframework.stereotype.Service; |
| 22 | 22 | import org.springframework.validation.annotation.Validated; |
| 23 | 23 | |
| ... | ... | @@ -114,8 +114,7 @@ public class AiModelServiceImpl implements AiModelService { |
| 114 | 114 | } |
| 115 | 115 | |
| 116 | 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 | 118 | return modelMapper.selectListByStatusAndType(status, type, platform); |
| 120 | 119 | } |
| 121 | 120 | |
| ... | ... | @@ -163,9 +162,10 @@ public class AiModelServiceImpl implements AiModelService { |
| 163 | 162 | platform, apiKey.getApiKey(), apiKey.getUrl(), model.getModel()); |
| 164 | 163 | |
| 165 | 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 | 172 | \ No newline at end of file | ... | ... |
yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml
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 | 11 | import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; |
| 12 | 12 | import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; |
| 13 | 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 | 16 | import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreProperties; |
| 15 | 17 | import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreProperties; |
| 18 | +import org.springframework.ai.embedding.BatchingStrategy; | |
| 19 | +import org.springframework.ai.embedding.TokenCountBatchingStrategy; | |
| 16 | 20 | import org.springframework.ai.openai.OpenAiChatModel; |
| 17 | 21 | import org.springframework.ai.openai.OpenAiChatOptions; |
| 18 | 22 | import org.springframework.ai.openai.api.OpenAiApi; |
| ... | ... | @@ -22,7 +26,6 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; |
| 22 | 26 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| 23 | 27 | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| 24 | 28 | import org.springframework.context.annotation.Bean; |
| 25 | -import org.springframework.context.annotation.Lazy; | |
| 26 | 29 | |
| 27 | 30 | /** |
| 28 | 31 | * 芋道 AI 自动配置 |
| ... | ... | @@ -33,6 +36,7 @@ import org.springframework.context.annotation.Lazy; |
| 33 | 36 | @EnableConfigurationProperties({YudaoAiProperties.class, |
| 34 | 37 | QdrantVectorStoreProperties.class, // 解析 Qdrant 配置 |
| 35 | 38 | RedisVectorStoreProperties.class, // 解析 Redis 配置 |
| 39 | + MilvusVectorStoreProperties.class, MilvusServiceClientProperties.class // 解析 Milvus 配置 | |
| 36 | 40 | }) |
| 37 | 41 | @Slf4j |
| 38 | 42 | public class YudaoAiAutoConfiguration { |
| ... | ... | @@ -193,18 +197,16 @@ public class YudaoAiAutoConfiguration { |
| 193 | 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 | 202 | @Bean |
| 205 | - @Lazy // TODO 芋艿:临时注释,避免无法启动 | |
| 206 | 203 | public TokenCountEstimator tokenCountEstimator() { |
| 207 | 204 | return new JTokkitTokenCountEstimator(); |
| 208 | 205 | } |
| 209 | 206 | |
| 207 | + @Bean | |
| 208 | + public BatchingStrategy batchingStrategy() { | |
| 209 | + return new TokenCountBatchingStrategy(); | |
| 210 | + } | |
| 211 | + | |
| 210 | 212 | } |
| 211 | 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 | 5 | import cn.hutool.core.lang.Singleton; |
| 6 | 6 | import cn.hutool.core.lang.func.Func0; |
| 7 | 7 | import cn.hutool.core.util.ArrayUtil; |
| 8 | -import cn.hutool.core.util.ReflectUtil; | |
| 9 | 8 | import cn.hutool.core.util.RuntimeUtil; |
| 10 | 9 | import cn.hutool.core.util.StrUtil; |
| 11 | 10 | import cn.hutool.extra.spring.SpringUtil; |
| ... | ... | @@ -29,6 +28,7 @@ import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingOptions; |
| 29 | 28 | import com.alibaba.cloud.ai.dashscope.image.DashScopeImageModel; |
| 30 | 29 | import com.azure.ai.openai.OpenAIClientBuilder; |
| 31 | 30 | import io.micrometer.observation.ObservationRegistry; |
| 31 | +import io.milvus.client.MilvusServiceClient; | |
| 32 | 32 | import io.qdrant.client.QdrantClient; |
| 33 | 33 | import io.qdrant.client.QdrantGrpcClient; |
| 34 | 34 | import lombok.SneakyThrows; |
| ... | ... | @@ -38,6 +38,10 @@ import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiConnectionPr |
| 38 | 38 | import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration; |
| 39 | 39 | import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; |
| 40 | 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 | 45 | import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration; |
| 42 | 46 | import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreProperties; |
| 43 | 47 | import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreAutoConfiguration; |
| ... | ... | @@ -47,6 +51,7 @@ import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiConnectionProperties; |
| 47 | 51 | import org.springframework.ai.azure.openai.AzureOpenAiChatModel; |
| 48 | 52 | import org.springframework.ai.chat.model.ChatModel; |
| 49 | 53 | import org.springframework.ai.document.MetadataMode; |
| 54 | +import org.springframework.ai.embedding.BatchingStrategy; | |
| 50 | 55 | import org.springframework.ai.embedding.EmbeddingModel; |
| 51 | 56 | import org.springframework.ai.image.ImageModel; |
| 52 | 57 | import org.springframework.ai.ollama.OllamaChatModel; |
| ... | ... | @@ -66,6 +71,7 @@ import org.springframework.ai.stabilityai.StabilityAiImageModel; |
| 66 | 71 | import org.springframework.ai.stabilityai.api.StabilityAiApi; |
| 67 | 72 | import org.springframework.ai.vectorstore.SimpleVectorStore; |
| 68 | 73 | import org.springframework.ai.vectorstore.VectorStore; |
| 74 | +import org.springframework.ai.vectorstore.milvus.MilvusVectorStore; | |
| 69 | 75 | import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention; |
| 70 | 76 | import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention; |
| 71 | 77 | import org.springframework.ai.vectorstore.qdrant.QdrantVectorStore; |
| ... | ... | @@ -247,6 +253,9 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 247 | 253 | if (type == RedisVectorStore.class) { |
| 248 | 254 | return buildRedisVectorStore(embeddingModel, metadataFields); |
| 249 | 255 | } |
| 256 | + if (type == MilvusVectorStore.class) { | |
| 257 | + return buildMilvusVectorStore(embeddingModel); | |
| 258 | + } | |
| 250 | 259 | throw new IllegalArgumentException(StrUtil.format("未知类型({})", type)); |
| 251 | 260 | }); |
| 252 | 261 | } |
| ... | ... | @@ -482,8 +491,7 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 482 | 491 | QdrantClient qdrantClient = new QdrantClient(grpcClientBuilder.build()); |
| 483 | 492 | // 创建 QdrantVectorStore 对象 |
| 484 | 493 | QdrantVectorStore vectorStore = configuration.vectorStore(embeddingModel, properties, qdrantClient, |
| 485 | - getObservationRegistry(), getCustomObservationConvention(), | |
| 486 | - ReflectUtil.invoke(configuration, "batchingStrategy")); | |
| 494 | + getObservationRegistry(), getCustomObservationConvention(), getBatchingStrategy()); | |
| 487 | 495 | // 初始化索引 |
| 488 | 496 | vectorStore.afterPropertiesSet(); |
| 489 | 497 | return vectorStore; |
| ... | ... | @@ -516,13 +524,48 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 516 | 524 | })) |
| 517 | 525 | .observationRegistry(getObservationRegistry().getObject()) |
| 518 | 526 | .customObservationConvention(getCustomObservationConvention().getObject()) |
| 519 | - .batchingStrategy(ReflectUtil.invoke(configuration, "batchingStrategy")) | |
| 527 | + .batchingStrategy(getBatchingStrategy()) | |
| 520 | 528 | .build(); |
| 521 | 529 | // 初始化索引 |
| 522 | 530 | redisVectorStore.afterPropertiesSet(); |
| 523 | 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 | 569 | private static ObjectProvider<ObservationRegistry> getObservationRegistry() { |
| 527 | 570 | return new ObjectProvider<>() { |
| 528 | 571 | |
| ... | ... | @@ -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 | 157 | collection-name: knowledge_segment # Qdrant 中向量集合的名称:用于存储向量数据的集合标识符,所有相关的向量操作都会在这个集合中进行 |
| 158 | 158 | host: 127.0.0.1 |
| 159 | 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 | 167 | qianfan: # 文心一言 |
| 163 | 168 | api-key: x0cuLZ7XsaTCU08vuJWO87Lg |
| 164 | 169 | secret-key: R9mYF9dl9KASgi5RUq0FQt3wRisSnOcK | ... | ... |