Commit 8e012b10bb28d16cdde68c715babbcddb88e17b7
1 parent
059f64ac
【优化】AI 知识库: VectorStore 获取 抽到 AiModelFactory
Showing
6 changed files
with
42 additions
and
91 deletions
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java
| ... | ... | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.ai.service.model; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; |
| 4 | 4 | import cn.iocoder.yudao.framework.ai.core.factory.AiModelFactory; |
| 5 | -import cn.iocoder.yudao.framework.ai.core.factory.AiVectorStoreFactory; | |
| 6 | 5 | import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi; |
| 7 | 6 | import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; |
| 8 | 7 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| ... | ... | @@ -39,8 +38,6 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { |
| 39 | 38 | |
| 40 | 39 | @Resource |
| 41 | 40 | private AiModelFactory modelFactory; |
| 42 | - @Resource | |
| 43 | - private AiVectorStoreFactory vectorFactory; | |
| 44 | 41 | |
| 45 | 42 | @Override |
| 46 | 43 | public Long createApiKey(AiApiKeySaveReqVO createReqVO) { |
| ... | ... | @@ -149,7 +146,7 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { |
| 149 | 146 | public VectorStore getOrCreateVectorStore(Long id) { |
| 150 | 147 | AiApiKeyDO apiKey = validateApiKey(id); |
| 151 | 148 | AiPlatformEnum platform = AiPlatformEnum.validatePlatform(apiKey.getPlatform()); |
| 152 | - return vectorFactory.getOrCreateVectorStore(getEmbeddingModel(id), platform, apiKey.getApiKey(), apiKey.getUrl()); | |
| 149 | + return modelFactory.getOrCreateVectorStore(getEmbeddingModel(id), platform, apiKey.getApiKey(), apiKey.getUrl()); | |
| 153 | 150 | } |
| 154 | 151 | |
| 155 | 152 | } |
| 156 | 153 | \ No newline at end of file | ... | ... |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java
| ... | ... | @@ -2,8 +2,6 @@ package cn.iocoder.yudao.framework.ai.config; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.ai.core.factory.AiModelFactory; |
| 4 | 4 | import cn.iocoder.yudao.framework.ai.core.factory.AiModelFactoryImpl; |
| 5 | -import cn.iocoder.yudao.framework.ai.core.factory.AiVectorStoreFactory; | |
| 6 | -import cn.iocoder.yudao.framework.ai.core.factory.AiVectorStoreFactoryImpl; | |
| 7 | 5 | import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatModel; |
| 8 | 6 | import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatOptions; |
| 9 | 7 | import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi; |
| ... | ... | @@ -38,11 +36,6 @@ public class YudaoAiAutoConfiguration { |
| 38 | 36 | return new AiModelFactoryImpl(); |
| 39 | 37 | } |
| 40 | 38 | |
| 41 | - @Bean | |
| 42 | - public AiVectorStoreFactory aiVectorFactory() { | |
| 43 | - return new AiVectorStoreFactoryImpl(); | |
| 44 | - } | |
| 45 | - | |
| 46 | 39 | |
| 47 | 40 | // ========== 各种 AI Client 创建 ========== |
| 48 | 41 | ... | ... |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactory.java
| ... | ... | @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; |
| 6 | 6 | import org.springframework.ai.chat.model.ChatModel; |
| 7 | 7 | import org.springframework.ai.embedding.EmbeddingModel; |
| 8 | 8 | import org.springframework.ai.image.ImageModel; |
| 9 | +import org.springframework.ai.vectorstore.VectorStore; | |
| 9 | 10 | |
| 10 | 11 | /** |
| 11 | 12 | * AI Model 模型工厂的接口类 |
| ... | ... | @@ -92,4 +93,17 @@ public interface AiModelFactory { |
| 92 | 93 | */ |
| 93 | 94 | EmbeddingModel getOrCreateEmbeddingModel(AiPlatformEnum platform, String apiKey, String url); |
| 94 | 95 | |
| 96 | + /** | |
| 97 | + * 基于指定配置,获得 VectorStore 对象 | |
| 98 | + * <p> | |
| 99 | + * 如果不存在,则进行创建 | |
| 100 | + * | |
| 101 | + * @param embeddingModel 嵌入模型 | |
| 102 | + * @param platform 平台 | |
| 103 | + * @param apiKey API KEY | |
| 104 | + * @param url API URL | |
| 105 | + * @return VectorStore 对象 | |
| 106 | + */ | |
| 107 | + VectorStore getOrCreateVectorStore(EmbeddingModel embeddingModel, AiPlatformEnum platform, String apiKey, String url); | |
| 108 | + | |
| 95 | 109 | } | ... | ... |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java
| ... | ... | @@ -13,6 +13,7 @@ import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatModel; |
| 13 | 13 | import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi; |
| 14 | 14 | import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; |
| 15 | 15 | import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; |
| 16 | +import cn.iocoder.yudao.framework.common.util.spring.SpringUtils; | |
| 16 | 17 | import com.alibaba.cloud.ai.tongyi.TongYiAutoConfiguration; |
| 17 | 18 | import com.alibaba.cloud.ai.tongyi.TongYiConnectionProperties; |
| 18 | 19 | import com.alibaba.cloud.ai.tongyi.chat.TongYiChatModel; |
| ... | ... | @@ -54,13 +55,17 @@ import org.springframework.ai.qianfan.api.QianFanApi; |
| 54 | 55 | import org.springframework.ai.qianfan.api.QianFanImageApi; |
| 55 | 56 | import org.springframework.ai.stabilityai.StabilityAiImageModel; |
| 56 | 57 | import org.springframework.ai.stabilityai.api.StabilityAiApi; |
| 58 | +import org.springframework.ai.vectorstore.RedisVectorStore; | |
| 59 | +import org.springframework.ai.vectorstore.VectorStore; | |
| 57 | 60 | import org.springframework.ai.zhipuai.ZhiPuAiChatModel; |
| 58 | 61 | import org.springframework.ai.zhipuai.ZhiPuAiImageModel; |
| 59 | 62 | import org.springframework.ai.zhipuai.api.ZhiPuAiApi; |
| 60 | 63 | import org.springframework.ai.zhipuai.api.ZhiPuAiImageApi; |
| 64 | +import org.springframework.boot.autoconfigure.data.redis.RedisProperties; | |
| 61 | 65 | import org.springframework.retry.support.RetryTemplate; |
| 62 | 66 | import org.springframework.web.client.ResponseErrorHandler; |
| 63 | 67 | import org.springframework.web.client.RestClient; |
| 68 | +import redis.clients.jedis.JedisPooled; | |
| 64 | 69 | |
| 65 | 70 | import java.util.List; |
| 66 | 71 | |
| ... | ... | @@ -191,6 +196,28 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 191 | 196 | }); |
| 192 | 197 | } |
| 193 | 198 | |
| 199 | + @Override | |
| 200 | + public VectorStore getOrCreateVectorStore(EmbeddingModel embeddingModel, AiPlatformEnum platform, String apiKey, String url) { | |
| 201 | + String cacheKey = buildClientCacheKey(VectorStore.class, platform, apiKey, url); | |
| 202 | + return Singleton.get(cacheKey, (Func0<VectorStore>) () -> { | |
| 203 | + // TODO 芋艿 @xin 这两个配置取哪好呢 | |
| 204 | + // TODO 不同模型的向量维度可能会不一样,目前看貌似是以 index 来做区分的,维度不一样存不到一个 index 上 | |
| 205 | + // TODO 回复:好的哈 | |
| 206 | + String index = "default-index"; | |
| 207 | + String prefix = "default:"; | |
| 208 | + var config = RedisVectorStore.RedisVectorStoreConfig.builder() | |
| 209 | + .withIndexName(index) | |
| 210 | + .withPrefix(prefix) | |
| 211 | + .build(); | |
| 212 | + RedisProperties redisProperties = SpringUtils.getBean(RedisProperties.class); | |
| 213 | + RedisVectorStore redisVectorStore = new RedisVectorStore(config, embeddingModel, | |
| 214 | + new JedisPooled(redisProperties.getHost(), redisProperties.getPort()), | |
| 215 | + true); | |
| 216 | + redisVectorStore.afterPropertiesSet(); | |
| 217 | + return redisVectorStore; | |
| 218 | + }); | |
| 219 | + } | |
| 220 | + | |
| 194 | 221 | private static String buildClientCacheKey(Class<?> clazz, Object... params) { |
| 195 | 222 | if (ArrayUtil.isEmpty(params)) { |
| 196 | 223 | return clazz.getName(); | ... | ... |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiVectorStoreFactory.java deleted
| 1 | -package cn.iocoder.yudao.framework.ai.core.factory; | |
| 2 | - | |
| 3 | -import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; | |
| 4 | -import org.springframework.ai.embedding.EmbeddingModel; | |
| 5 | -import org.springframework.ai.vectorstore.VectorStore; | |
| 6 | - | |
| 7 | -// TODO @xin:也放到 AiModelFactory 里面好了,后续改成 AiFactory | |
| 8 | -/** | |
| 9 | - * AI Vector 模型工厂的接口类 | |
| 10 | - * | |
| 11 | - * @author xiaoxin | |
| 12 | - */ | |
| 13 | -public interface AiVectorStoreFactory { | |
| 14 | - | |
| 15 | - /** | |
| 16 | - * 基于指定配置,获得 VectorStore 对象 | |
| 17 | - * <p> | |
| 18 | - * 如果不存在,则进行创建 | |
| 19 | - * | |
| 20 | - * @param embeddingModel 嵌入模型 | |
| 21 | - * @param platform 平台 | |
| 22 | - * @param apiKey API KEY | |
| 23 | - * @param url API URL | |
| 24 | - * @return VectorStore 对象 | |
| 25 | - */ | |
| 26 | - VectorStore getOrCreateVectorStore(EmbeddingModel embeddingModel, AiPlatformEnum platform, String apiKey, String url); | |
| 27 | - | |
| 28 | -} |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiVectorStoreFactoryImpl.java deleted
| 1 | -package cn.iocoder.yudao.framework.ai.core.factory; | |
| 2 | - | |
| 3 | -import cn.hutool.core.lang.Singleton; | |
| 4 | -import cn.hutool.core.lang.func.Func0; | |
| 5 | -import cn.hutool.core.util.ArrayUtil; | |
| 6 | -import cn.hutool.core.util.StrUtil; | |
| 7 | -import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; | |
| 8 | -import cn.iocoder.yudao.framework.common.util.spring.SpringUtils; | |
| 9 | -import org.springframework.ai.embedding.EmbeddingModel; | |
| 10 | -import org.springframework.ai.vectorstore.RedisVectorStore; | |
| 11 | -import org.springframework.ai.vectorstore.VectorStore; | |
| 12 | -import org.springframework.boot.autoconfigure.data.redis.RedisProperties; | |
| 13 | -import redis.clients.jedis.JedisPooled; | |
| 14 | - | |
| 15 | -/** | |
| 16 | - * AI Vector 模型工厂的实现类 | |
| 17 | - * 使用 redisVectorStore 实现 VectorStore | |
| 18 | - * | |
| 19 | - * @author xiaoxin | |
| 20 | - */ | |
| 21 | -public class AiVectorStoreFactoryImpl implements AiVectorStoreFactory { | |
| 22 | - | |
| 23 | - @Override | |
| 24 | - public VectorStore getOrCreateVectorStore(EmbeddingModel embeddingModel, AiPlatformEnum platform, String apiKey, String url) { | |
| 25 | - String cacheKey = buildClientCacheKey(VectorStore.class, platform, apiKey, url); | |
| 26 | - return Singleton.get(cacheKey, (Func0<VectorStore>) () -> { | |
| 27 | - // TODO 芋艿 @xin 这两个配置取哪好呢 | |
| 28 | - // TODO 不同模型的向量维度可能会不一样,目前看貌似是以 index 来做区分的,维度不一样存不到一个 index 上 | |
| 29 | - // TODO 回复:好的哈 | |
| 30 | - String index = "default-index"; | |
| 31 | - String prefix = "default:"; | |
| 32 | - var config = RedisVectorStore.RedisVectorStoreConfig.builder() | |
| 33 | - .withIndexName(index) | |
| 34 | - .withPrefix(prefix) | |
| 35 | - .build(); | |
| 36 | - RedisProperties redisProperties = SpringUtils.getBean(RedisProperties.class); | |
| 37 | - RedisVectorStore redisVectorStore = new RedisVectorStore(config, embeddingModel, | |
| 38 | - new JedisPooled(redisProperties.getHost(), redisProperties.getPort()), | |
| 39 | - true); | |
| 40 | - redisVectorStore.afterPropertiesSet(); | |
| 41 | - return redisVectorStore; | |
| 42 | - }); | |
| 43 | - } | |
| 44 | - | |
| 45 | - private static String buildClientCacheKey(Class<?> clazz, Object... params) { | |
| 46 | - if (ArrayUtil.isEmpty(params)) { | |
| 47 | - return clazz.getName(); | |
| 48 | - } | |
| 49 | - return StrUtil.format("{}#{}", clazz.getName(), ArrayUtil.join(params, "_")); | |
| 50 | - } | |
| 51 | - | |
| 52 | -} |