From fb5dcaeb2ab91d0f9ffea26fd15ddcbbe5d36bb9 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期五, 31 七月 2026 17:57:27 +0800
Subject: [PATCH] feat(aftersales): 售后工单新增问题类型和严重程度字段
---
yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/AiModelFactoryImpl.java | 766 +++-------------------------------------------------------
1 files changed, 42 insertions(+), 724 deletions(-)
diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/AiModelFactoryImpl.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/AiModelFactoryImpl.java
index ec9d404..86b307a 100644
--- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/AiModelFactoryImpl.java
+++ b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/AiModelFactoryImpl.java
@@ -1,281 +1,59 @@
package cn.iocoder.yudao.module.ai.framework.ai.core.model;
-import cn.hutool.core.io.FileUtil;
-import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Singleton;
import cn.hutool.core.lang.func.Func0;
import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.core.util.RuntimeUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum;
import cn.iocoder.yudao.module.ai.framework.ai.config.AiAutoConfiguration;
-import cn.iocoder.yudao.module.ai.framework.ai.config.YudaoAiProperties;
-import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel;
-import cn.iocoder.yudao.module.ai.framework.ai.core.model.doubao.DouBaoChatModel;
-import cn.iocoder.yudao.module.ai.framework.ai.core.model.hunyuan.HunYuanChatModel;
-import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi;
-import cn.iocoder.yudao.module.ai.framework.ai.core.model.minimax.MiniMaxChatModel;
-import cn.iocoder.yudao.module.ai.framework.ai.core.model.moonshot.MoonshotChatModel;
-import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowApiConstants;
-import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowChatModel;
-import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowImageApi;
-import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowImageModel;
-import cn.iocoder.yudao.module.ai.framework.ai.core.model.stepfun.StepFunChatModel;
-import cn.iocoder.yudao.module.ai.framework.ai.core.model.suno.api.SunoApi;
-import cn.iocoder.yudao.module.ai.framework.ai.core.model.xinghuo.XingHuoChatModel;
-import cn.iocoder.yudao.module.ai.framework.ai.core.model.yiyan.YiYanChatModel;
-import cn.iocoder.yudao.module.ai.framework.ai.core.model.zhipu.ZhiPuChatModel;
-import cn.iocoder.yudao.module.ai.util.AiUtils;
-import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeChatAutoConfiguration;
-import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeEmbeddingAutoConfiguration;
-import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeImageAutoConfiguration;
-import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
-import com.alibaba.cloud.ai.dashscope.embedding.text.DashScopeEmbeddingModel;
-import com.alibaba.cloud.ai.dashscope.image.DashScopeImageModel;
-import com.google.genai.Client;
-import com.google.genai.types.HttpOptions;
-import io.micrometer.observation.ObservationRegistry;
-import io.milvus.client.MilvusServiceClient;
-import io.qdrant.client.QdrantClient;
-import io.qdrant.client.QdrantGrpcClient;
-import lombok.SneakyThrows;
-import org.springframework.ai.anthropic.AnthropicChatModel;
-import org.springframework.ai.anthropic.AnthropicChatOptions;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.model.ChatModel;
-import org.springframework.ai.deepseek.DeepSeekChatModel;
-import org.springframework.ai.deepseek.DeepSeekChatOptions;
-import org.springframework.ai.deepseek.api.DeepSeekApi;
-import org.springframework.ai.document.MetadataMode;
import org.springframework.ai.embedding.BatchingStrategy;
import org.springframework.ai.embedding.EmbeddingModel;
-import org.springframework.ai.embedding.observation.EmbeddingModelObservationConvention;
-import org.springframework.ai.google.genai.GoogleGenAiChatModel;
-import org.springframework.ai.google.genai.GoogleGenAiChatOptions;
-import org.springframework.ai.image.ImageModel;
-import org.springframework.ai.model.anthropic.autoconfigure.AnthropicChatAutoConfiguration;
-import org.springframework.ai.model.deepseek.autoconfigure.DeepSeekChatAutoConfiguration;
-import org.springframework.ai.model.google.genai.autoconfigure.chat.GoogleGenAiChatAutoConfiguration;
-import org.springframework.ai.model.ollama.autoconfigure.OllamaChatAutoConfiguration;
-import org.springframework.ai.model.openai.autoconfigure.OpenAiChatAutoConfiguration;
-import org.springframework.ai.model.openai.autoconfigure.OpenAiEmbeddingAutoConfiguration;
-import org.springframework.ai.model.openai.autoconfigure.OpenAiImageAutoConfiguration;
-import org.springframework.ai.model.stabilityai.autoconfigure.StabilityAiImageAutoConfiguration;
-import org.springframework.ai.model.tool.ToolCallingManager;
-import org.springframework.ai.ollama.OllamaChatModel;
-import org.springframework.ai.ollama.OllamaEmbeddingModel;
-import org.springframework.ai.ollama.api.OllamaApi;
-import org.springframework.ai.ollama.api.OllamaEmbeddingOptions;
-import org.springframework.ai.openai.*;
-import org.springframework.ai.retry.RetryUtils;
-import org.springframework.ai.stabilityai.StabilityAiImageModel;
-import org.springframework.ai.stabilityai.api.StabilityAiApi;
-import org.springframework.ai.vectorstore.SimpleVectorStore;
+import org.springframework.ai.embedding.TokenCountBatchingStrategy;
+import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.ai.vectorstore.milvus.MilvusVectorStore;
-import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusServiceClientConnectionDetails;
import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusServiceClientProperties;
-import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration;
import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreProperties;
-import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention;
-import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention;
-import org.springframework.ai.vectorstore.qdrant.QdrantVectorStore;
-import org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration;
-import org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreProperties;
-import org.springframework.ai.vectorstore.redis.RedisVectorStore;
-import org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreAutoConfiguration;
-import org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreProperties;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.ObjectProvider;
-import org.springframework.boot.data.redis.autoconfigure.DataRedisProperties;
-import redis.clients.jedis.DefaultJedisClientConfig;
-import redis.clients.jedis.HostAndPort;
-import redis.clients.jedis.JedisClientConfig;
-import redis.clients.jedis.RedisClient;
-
-import java.io.File;
-import java.time.Duration;
-import java.util.Collections;
import java.util.Map;
-import java.util.Timer;
-import java.util.TimerTask;
-
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
/**
- * AI Model 妯″瀷宸ュ巶鐨勫疄鐜扮被
+ * AI Model 妯″瀷宸ュ巶瀹炵幇绫�
*
- * @author 鑺嬮亾婧愮爜
+ * 浣跨敤 OpenAI 鍏煎鎺ュ彛瀵规帴閫氫箟鍗冮棶 + Milvus 鍚戦噺瀛樺偍
*/
+@Slf4j
public class AiModelFactoryImpl implements AiModelFactory {
@Override
- public ChatModel getOrCreateChatModel(AiPlatformEnum platform, String rawApiKey, String rawUrl) {
- final String apiKey = resolveSpringPlaceholders(rawApiKey);
- final String url = resolveSpringPlaceholders(rawUrl);
- String cacheKey = buildClientCacheKey(ChatModel.class, platform, apiKey, url);
+ public ChatModel getOrCreateChatModel(AiPlatformEnum platform, String apiKey, String url, String model) {
+ String cacheKey = buildCacheKey(ChatModel.class, platform, apiKey, url, model);
return Singleton.get(cacheKey, (Func0<ChatModel>) () -> {
- // noinspection EnhancedSwitchMigration
- switch (platform) {
- case TONG_YI:
- return buildTongYiChatModel(apiKey);
- case YI_YAN:
- return buildYiYanChatModel(apiKey);
- case DEEP_SEEK:
- return buildDeepSeekChatModel(apiKey);
- case DOU_BAO:
- return buildDouBaoChatModel(apiKey);
- case HUN_YUAN:
- return buildHunYuanChatModel(apiKey, url);
- case SILICON_FLOW:
- return buildSiliconFlowChatModel(apiKey);
- case ZHI_PU:
- return buildZhiPuChatModel(apiKey, url);
- case MINI_MAX:
- return buildMiniMaxChatModel(apiKey, url);
- case MOONSHOT:
- return buildMoonshotChatModel(apiKey, url);
- case STEP_FUN:
- return buildStepFunChatModel(apiKey, url);
- case XING_HUO:
- return buildXingHuoChatModel(apiKey);
- case BAI_CHUAN:
- return buildBaiChuanChatModel(apiKey);
- case OPENAI:
- return buildOpenAiChatModel(apiKey, url);
- case AZURE_OPENAI:
- return buildAzureOpenAiChatModel(apiKey, url);
- case ANTHROPIC:
- return buildAnthropicChatModel(apiKey, url);
- case GEMINI:
- return buildGeminiChatModel(apiKey, url);
- case OLLAMA:
- return buildOllamaChatModel(url);
- case GROK:
- return buildGrokChatModel(apiKey, url);
- default:
- throw new IllegalArgumentException(StrUtil.format("鏈煡骞冲彴({})", platform));
+ if (platform == AiPlatformEnum.TONG_YI) {
+ return AiAutoConfiguration.buildTongYiChatModel(apiKey, model);
}
+ throw new IllegalArgumentException(StrUtil.format("涓嶆敮鎸佺殑骞冲彴({})", platform));
});
}
@Override
public ChatModel getDefaultChatModel(AiPlatformEnum platform) {
- // noinspection EnhancedSwitchMigration
- switch (platform) {
- case TONG_YI:
- return SpringUtil.getBean(DashScopeChatModel.class);
- case YI_YAN:
- return SpringUtil.getBean(YiYanChatModel.class);
- case DEEP_SEEK:
- return SpringUtil.getBean(DeepSeekChatModel.class);
- case DOU_BAO:
- return SpringUtil.getBean(DouBaoChatModel.class);
- case HUN_YUAN:
- return SpringUtil.getBean(HunYuanChatModel.class);
- case SILICON_FLOW:
- return SpringUtil.getBean(SiliconFlowChatModel.class);
- case ZHI_PU:
- return SpringUtil.getBean(ZhiPuChatModel.class);
- case MINI_MAX:
- return SpringUtil.getBean(MiniMaxChatModel.class);
- case MOONSHOT:
- return SpringUtil.getBean(MoonshotChatModel.class);
- case STEP_FUN:
- return SpringUtil.getBean(StepFunChatModel.class);
- case XING_HUO:
- return SpringUtil.getBean(XingHuoChatModel.class);
- case BAI_CHUAN:
- return SpringUtil.getBean(BaiChuanChatModel.class);
- case OPENAI:
- return SpringUtil.getBean(OpenAiChatModel.class);
- case ANTHROPIC:
- return SpringUtil.getBean(AnthropicChatModel.class);
- case GEMINI:
- return SpringUtil.getBean(GoogleGenAiChatModel.class);
- case OLLAMA:
- return SpringUtil.getBean(OllamaChatModel.class);
- default:
- throw new IllegalArgumentException(StrUtil.format("鏈煡骞冲彴({})", platform));
+ if (platform == AiPlatformEnum.TONG_YI) {
+ return SpringUtil.getBean(OpenAiChatModel.class);
}
+ throw new IllegalArgumentException(StrUtil.format("涓嶆敮鎸佺殑骞冲彴({})", platform));
}
@Override
- public ImageModel getDefaultImageModel(AiPlatformEnum platform) {
- // noinspection EnhancedSwitchMigration
- switch (platform) {
- case TONG_YI:
- return SpringUtil.getBean(DashScopeImageModel.class);
- case SILICON_FLOW:
- return SpringUtil.getBean(SiliconFlowImageModel.class);
- case OPENAI:
- return SpringUtil.getBean(OpenAiImageModel.class);
- case STABLE_DIFFUSION:
- return SpringUtil.getBean(StabilityAiImageModel.class);
- default:
- throw new IllegalArgumentException(StrUtil.format("鏈煡骞冲彴({})", platform));
- }
- }
-
- @Override
- public ImageModel getOrCreateImageModel(AiPlatformEnum platform, String rawApiKey, String rawUrl) {
- String apiKey = resolveSpringPlaceholders(rawApiKey);
- String url = resolveSpringPlaceholders(rawUrl);
- // noinspection EnhancedSwitchMigration
- switch (platform) {
- case TONG_YI:
- return buildTongYiImagesModel(apiKey);
- case OPENAI:
- return buildOpenAiImageModel(apiKey, url);
- case SILICON_FLOW:
- return buildSiliconFlowImageModel(apiKey, url);
- case STABLE_DIFFUSION:
- return buildStabilityAiImageModel(apiKey, url);
- default:
- throw new IllegalArgumentException(StrUtil.format("鏈煡骞冲彴({})", platform));
- }
- }
-
- @Override
- public MidjourneyApi getOrCreateMidjourneyApi(String rawApiKey, String rawUrl) {
- final String apiKey = resolveSpringPlaceholders(rawApiKey);
- final String url = resolveSpringPlaceholders(rawUrl);
- String cacheKey = buildClientCacheKey(MidjourneyApi.class, AiPlatformEnum.MIDJOURNEY.getPlatform(),
- apiKey, url);
- return Singleton.get(cacheKey, (Func0<MidjourneyApi>) () -> {
- YudaoAiProperties.Midjourney properties = SpringUtil.getBean(YudaoAiProperties.class)
- .getMidjourney();
- return new MidjourneyApi(url, apiKey, properties.getNotifyUrl());
- });
- }
-
- @Override
- public SunoApi getOrCreateSunoApi(String rawApiKey, String rawUrl) {
- final String apiKey = resolveSpringPlaceholders(rawApiKey);
- final String url = resolveSpringPlaceholders(rawUrl);
- String cacheKey = buildClientCacheKey(SunoApi.class, AiPlatformEnum.SUNO.getPlatform(), apiKey, url);
- return Singleton.get(cacheKey, (Func0<SunoApi>) () -> new SunoApi(url));
- }
-
- @Override
- @SuppressWarnings("EnhancedSwitchMigration")
- public EmbeddingModel getOrCreateEmbeddingModel(AiPlatformEnum platform, String rawApiKey, String rawUrl, String model) {
- final String apiKey = resolveSpringPlaceholders(rawApiKey);
- final String url = resolveSpringPlaceholders(rawUrl);
- String cacheKey = buildClientCacheKey(EmbeddingModel.class, platform, apiKey, url, model);
+ public EmbeddingModel getOrCreateEmbeddingModel(AiPlatformEnum platform, String apiKey, String url, String model) {
+ String cacheKey = buildCacheKey(EmbeddingModel.class, platform, apiKey, url, model);
return Singleton.get(cacheKey, (Func0<EmbeddingModel>) () -> {
- switch (platform) {
- case TONG_YI:
- return buildTongYiEmbeddingModel(apiKey, model);
- case OPENAI:
- return buildOpenAiEmbeddingModel(apiKey, url, model);
- case AZURE_OPENAI:
- return buildAzureOpenAiEmbeddingModel(apiKey, url, model);
- case OLLAMA:
- return buildOllamaEmbeddingModel(url, model);
- default:
- throw new IllegalArgumentException(StrUtil.format("鏈煡骞冲彴({})", platform));
+ if (platform == AiPlatformEnum.TONG_YI) {
+ return AiAutoConfiguration.buildTongYiEmbeddingModel(apiKey, model);
}
+ throw new IllegalArgumentException(StrUtil.format("涓嶆敮鎸佺殑骞冲彴({})", platform));
});
}
@@ -283,504 +61,44 @@
public VectorStore getOrCreateVectorStore(Class<? extends VectorStore> type,
EmbeddingModel embeddingModel,
Map<String, Class<?>> metadataFields) {
- String cacheKey = buildClientCacheKey(VectorStore.class, embeddingModel, type);
+ // metadataFields 鍙備笌缂撳瓨 key锛岀‘淇濅笉鍚岀煡璇嗗簱浣跨敤涓嶅悓閰嶇疆鏃朵笉浼氬鐢�
+ String cacheKey = buildCacheKey(VectorStore.class, embeddingModel, type, metadataFields.hashCode());
return Singleton.get(cacheKey, (Func0<VectorStore>) () -> {
- if (type == SimpleVectorStore.class) {
- return buildSimpleVectorStore(embeddingModel);
- }
- if (type == QdrantVectorStore.class) {
- return buildQdrantVectorStore(embeddingModel);
- }
- if (type == RedisVectorStore.class) {
- return buildRedisVectorStore(embeddingModel, metadataFields);
- }
if (type == MilvusVectorStore.class) {
return buildMilvusVectorStore(embeddingModel);
}
- throw new IllegalArgumentException(StrUtil.format("鏈煡绫诲瀷({})", type));
+ throw new IllegalArgumentException(StrUtil.format("涓嶆敮鎸佺殑鍚戦噺瀛樺偍绫诲瀷({})", type));
});
}
- private static String buildClientCacheKey(Class<?> clazz, Object... params) {
- if (ArrayUtil.isEmpty(params)) {
- return clazz.getName();
- }
- return StrUtil.format("{}#{}", clazz.getName(), ArrayUtil.join(params, "_"));
- }
-
- private static String resolveSpringPlaceholders(String value) {
- // yml 閰嶇疆鐨勫崰浣嶇鐢� Spring 鑷姩瑙f瀽锛汥B 閲屼繚瀛樼殑 ${xxx} 闇�瑕佸湪杩欓噷鎵嬪姩瑙f瀽銆�
- return AiUtils.resolveSpringPlaceholders(value);
- }
-
- // ========== 鍚勭鍒涘缓 spring-ai 瀹㈡埛绔殑鏂规硶 ==========
-
- /**
- * 鍙弬鑰� {@link DashScopeChatAutoConfiguration} 鐨� dashscopeChatModel 鏂规硶
- */
- private static DashScopeChatModel buildTongYiChatModel(String key) {
- return AiAutoConfiguration.buildTongYiChatModel(key);
- }
-
- /**
- * 鍙弬鑰� {@link DashScopeImageAutoConfiguration} 鐨� dashScopeImageModel 鏂规硶
- */
- private static DashScopeImageModel buildTongYiImagesModel(String key) {
- return AiAutoConfiguration.buildTongYiImagesModel(key);
- }
-
- private ChatModel buildYiYanChatModel(String apiKey) {
- YudaoAiProperties.YiYan properties = new YudaoAiProperties.YiYan()
- .setApiKey(apiKey);
- return new AiAutoConfiguration().buildYiYanChatClient(properties);
- }
-
- /**
- * 鍙弬鑰� {@link DeepSeekChatAutoConfiguration} 鐨� deepSeekChatModel 鏂规硶
- */
- private static DeepSeekChatModel buildDeepSeekChatModel(String apiKey) {
- DeepSeekApi deepSeekApi = DeepSeekApi.builder().apiKey(apiKey).build();
- DeepSeekChatOptions options = DeepSeekChatOptions.builder().model(DeepSeekApi.DEFAULT_CHAT_MODEL)
- .temperature(0.7).build();
- return DeepSeekChatModel.builder()
- .deepSeekApi(deepSeekApi)
- .options(options)
- .build();
- }
-
- /**
- * 鍙弬鑰� {@link AiAutoConfiguration#douBaoChatClient(YudaoAiProperties)}
- */
- private ChatModel buildDouBaoChatModel(String apiKey) {
- YudaoAiProperties.DouBao properties = new YudaoAiProperties.DouBao()
- .setApiKey(apiKey);
- return new AiAutoConfiguration().buildDouBaoChatClient(properties);
- }
-
- /**
- * 鍙弬鑰� {@link AiAutoConfiguration#hunYuanChatClient(YudaoAiProperties)}
- */
- private ChatModel buildHunYuanChatModel(String apiKey, String url) {
- YudaoAiProperties.HunYuan properties = new YudaoAiProperties.HunYuan()
- .setBaseUrl(url).setApiKey(apiKey);
- return new AiAutoConfiguration().buildHunYuanChatClient(properties);
- }
-
- /**
- * 鍙弬鑰� {@link AiAutoConfiguration#siliconFlowChatClient(YudaoAiProperties)}
- */
- private ChatModel buildSiliconFlowChatModel(String apiKey) {
- YudaoAiProperties.SiliconFlow properties = new YudaoAiProperties.SiliconFlow()
- .setApiKey(apiKey);
- return new AiAutoConfiguration().buildSiliconFlowChatClient(properties);
- }
-
- /**
- * 鍙弬鑰� {@link AiAutoConfiguration#zhiPuChatClient(YudaoAiProperties)}
- */
- private ZhiPuChatModel buildZhiPuChatModel(String apiKey, String url) {
- YudaoAiProperties.ZhiPu properties = new YudaoAiProperties.ZhiPu()
- .setBaseUrl(url).setApiKey(apiKey);
- return new AiAutoConfiguration().buildZhiPuChatClient(properties);
- }
-
- /**
- * 鍙弬鑰� {@link AiAutoConfiguration#miniMaxChatClient(YudaoAiProperties)}
- */
- private MiniMaxChatModel buildMiniMaxChatModel(String apiKey, String url) {
- YudaoAiProperties.MiniMax properties = new YudaoAiProperties.MiniMax()
- .setBaseUrl(url).setApiKey(apiKey);
- return new AiAutoConfiguration().buildMiniMaxChatClient(properties);
- }
-
- /**
- * 鍙弬鑰� {@link AiAutoConfiguration#moonshotChatClient(YudaoAiProperties)}
- */
- private MoonshotChatModel buildMoonshotChatModel(String apiKey, String url) {
- YudaoAiProperties.Moonshot properties = new YudaoAiProperties.Moonshot()
- .setBaseUrl(url).setApiKey(apiKey);
- return new AiAutoConfiguration().buildMoonshotChatClient(properties);
- }
-
- /**
- * 鍙弬鑰� {@link AiAutoConfiguration#stepFunChatClient(YudaoAiProperties)}
- */
- private StepFunChatModel buildStepFunChatModel(String apiKey, String url) {
- YudaoAiProperties.StepFun properties = new YudaoAiProperties.StepFun()
- .setBaseUrl(url).setApiKey(apiKey);
- return new AiAutoConfiguration().buildStepFunChatClient(properties);
- }
-
- /**
- * 鍙弬鑰� {@link AiAutoConfiguration#xingHuoChatClient(YudaoAiProperties)}
- */
- private static XingHuoChatModel buildXingHuoChatModel(String apiKey) {
- YudaoAiProperties.XingHuo properties = new YudaoAiProperties.XingHuo()
- .setApiKey(apiKey).setModel(XingHuoChatModel.MODEL_DEFAULT);
- return new AiAutoConfiguration().buildXingHuoChatClient(properties);
- }
-
- /**
- * 鍙弬鑰� {@link AiAutoConfiguration#baiChuanChatClient(YudaoAiProperties)}
- */
- private BaiChuanChatModel buildBaiChuanChatModel(String apiKey) {
- YudaoAiProperties.BaiChuan properties = new YudaoAiProperties.BaiChuan()
- .setApiKey(apiKey);
- return new AiAutoConfiguration().buildBaiChuanChatClient(properties);
- }
-
- /**
- * 鍙弬鑰� {@link OpenAiChatAutoConfiguration} 鐨� openAiChatModel 鏂规硶
- */
- private static OpenAiChatModel buildOpenAiChatModel(String openAiToken, String url) {
- return OpenAiChatModel.builder()
- .options(buildOpenAiChatOptions(openAiToken, url).build())
- .build();
- }
-
- private static OpenAiChatModel buildAzureOpenAiChatModel(String openAiToken, String url) {
- return OpenAiChatModel.builder()
- .options(buildOpenAiChatOptions(openAiToken, url)
- .azure(true)
- .build())
- .build();
- }
-
- private static OpenAiChatOptions.Builder buildOpenAiChatOptions(String apiKey, String url) {
- OpenAiChatOptions.Builder optionsBuilder = OpenAiChatOptions.builder().apiKey(apiKey);
- if (StrUtil.isNotEmpty(url)) {
- optionsBuilder.baseUrl(url);
- }
- return optionsBuilder;
- }
-
- /**
- * 鍙弬鑰� {@link AnthropicChatAutoConfiguration} 鐨� anthropicApi 鏂规硶
- */
- private static AnthropicChatModel buildAnthropicChatModel(String apiKey, String url) {
- AnthropicChatOptions.Builder optionsBuilder = AnthropicChatOptions.builder().apiKey(apiKey);
- if (StrUtil.isNotEmpty(url)) {
- optionsBuilder.baseUrl(url);
- }
- return AnthropicChatModel.builder()
- .options(optionsBuilder.build())
- .build();
- }
-
- /**
- * 鍙弬鑰� {@link GoogleGenAiChatAutoConfiguration} 鐨� googleGenAiChatModel 鏂规硶
- */
- private static GoogleGenAiChatModel buildGeminiChatModel(String apiKey, String url) {
- Client.Builder clientBuilder = Client.builder().apiKey(apiKey);
- if (StrUtil.isNotBlank(url)) {
- clientBuilder.httpOptions(HttpOptions.builder()
- .baseUrl(url)
- // TeamOrouter 鐨� Gemini 鍘熺敓鍗忚浣跨敤 Authorization Bearer 閴存潈
- .headers(Collections.singletonMap("Authorization", "Bearer " + apiKey))
- .build());
- }
- return GoogleGenAiChatModel.builder()
- .genAiClient(clientBuilder.build())
- .options(GoogleGenAiChatOptions.builder()
- .model("gemini-2.5-flash")
- .build())
- .toolCallingManager(SpringUtil.getBean(ToolCallingManager.class))
- .retryTemplate(RetryUtils.DEFAULT_RETRY_TEMPLATE)
- .observationRegistry(SpringUtil.getBean(ObservationRegistry.class))
- .build();
- }
-
- /**
- * 鍙弬鑰� {@link OpenAiImageAutoConfiguration} 鐨� openAiImageModel 鏂规硶
- */
- private OpenAiImageModel buildOpenAiImageModel(String openAiToken, String url) {
- OpenAiImageOptions.Builder optionsBuilder = OpenAiImageOptions.builder().apiKey(openAiToken);
- if (StrUtil.isNotEmpty(url)) {
- optionsBuilder.baseUrl(url);
- }
- return OpenAiImageModel.builder()
- .options(optionsBuilder.build())
- .build();
- }
-
- /**
- * 鍒涘缓 SiliconFlowImageModel 瀵硅薄
- */
- private SiliconFlowImageModel buildSiliconFlowImageModel(String apiToken, String url) {
- url = StrUtil.blankToDefault(url, SiliconFlowApiConstants.DEFAULT_BASE_URL);
- SiliconFlowImageApi openAiApi = new SiliconFlowImageApi(url, apiToken);
- return new SiliconFlowImageModel(openAiApi);
- }
-
- /**
- * 鍙弬鑰� {@link OllamaChatAutoConfiguration} 鐨� ollamaChatModel 鏂规硶
- */
- private static OllamaChatModel buildOllamaChatModel(String url) {
- OllamaApi ollamaApi = OllamaApi.builder().baseUrl(url).build();
- return OllamaChatModel.builder()
- .ollamaApi(ollamaApi)
- .build();
- }
-
- /**
- * 鍙弬鑰� {@link StabilityAiImageAutoConfiguration} 鐨� stabilityAiImageModel 鏂规硶
- */
- private StabilityAiImageModel buildStabilityAiImageModel(String apiKey, String url) {
- url = StrUtil.blankToDefault(url, StabilityAiApi.DEFAULT_BASE_URL);
- StabilityAiApi stabilityAiApi = new StabilityAiApi(apiKey, StabilityAiApi.DEFAULT_IMAGE_MODEL, url);
- return new StabilityAiImageModel(stabilityAiApi);
- }
-
- private ChatModel buildGrokChatModel(String apiKey,String url) {
- YudaoAiProperties.Grok properties = new YudaoAiProperties.Grok()
- .setBaseUrl(url)
- .setApiKey(apiKey);
- return new AiAutoConfiguration().buildGrokChatClient(properties);
- }
-
- // ========== 鍚勭鍒涘缓 EmbeddingModel 鐨勬柟娉� ==========
-
- /**
- * 鍙弬鑰� {@link DashScopeEmbeddingAutoConfiguration} 鐨� DashScopeEmbeddingModel 鏂规硶
- */
- private DashScopeEmbeddingModel buildTongYiEmbeddingModel(String apiKey, String model) {
- return AiAutoConfiguration.buildTongYiEmbeddingModel(apiKey, model);
- }
-
- private OllamaEmbeddingModel buildOllamaEmbeddingModel(String url, String model) {
- OllamaApi ollamaApi = OllamaApi.builder().baseUrl(url).build();
- OllamaEmbeddingOptions ollamaOptions = OllamaEmbeddingOptions.builder().model(model).build();
- return OllamaEmbeddingModel.builder()
- .ollamaApi(ollamaApi)
- .options(ollamaOptions)
- .build();
- }
-
- /**
- * 鍙弬鑰� {@link OpenAiEmbeddingAutoConfiguration} 鐨� openAiEmbeddingModel 鏂规硶
- */
- private OpenAiEmbeddingModel buildOpenAiEmbeddingModel(String openAiToken, String url, String model) {
- OpenAiEmbeddingOptions.Builder optionsBuilder = OpenAiEmbeddingOptions.builder()
- .apiKey(openAiToken)
- .model(model);
- if (StrUtil.isNotEmpty(url)) {
- optionsBuilder.baseUrl(url);
- }
- return OpenAiEmbeddingModel.builder()
- .metadataMode(MetadataMode.EMBED)
- .options(optionsBuilder.build())
- .build();
- }
-
- private OpenAiEmbeddingModel buildAzureOpenAiEmbeddingModel(String openAiToken, String url, String model) {
- OpenAiEmbeddingOptions.Builder optionsBuilder = OpenAiEmbeddingOptions.builder()
- .apiKey(openAiToken)
- .model(model)
- .deploymentName(model)
- .azure(true);
- if (StrUtil.isNotEmpty(url)) {
- optionsBuilder.baseUrl(url);
- }
- return OpenAiEmbeddingModel.builder()
- .metadataMode(MetadataMode.EMBED)
- .options(optionsBuilder.build())
- .build();
- }
-
- // ========== 鍚勭鍒涘缓 VectorStore 鐨勬柟娉� ==========
-
- /**
- * 娉ㄦ剰锛氫粎閫傚悎鏈湴娴嬭瘯浣跨敤锛岀敓浜у缓璁繕鏄娇鐢� Qdrant銆丮ilvus 绛�
- */
- @SneakyThrows
- @SuppressWarnings("ResultOfMethodCallIgnored")
- private SimpleVectorStore buildSimpleVectorStore(EmbeddingModel embeddingModel) {
- SimpleVectorStore vectorStore = SimpleVectorStore.builder(embeddingModel).build();
- // 鍚姩鍔犺浇
- File file = new File(StrUtil.format("{}/vector_store/simple_{}.json",
- FileUtil.getUserHomePath(), embeddingModel.getClass().getSimpleName()));
- if (!file.exists()) {
- FileUtil.mkParentDirs(file);
- file.createNewFile();
- } else if (file.length() > 0) {
- vectorStore.load(file);
- }
- // 瀹氭椂鎸佷箙鍖栵紝姣忓垎閽熶竴娆�
- Timer timer = new Timer("SimpleVectorStoreTimer-" + file.getAbsolutePath());
- timer.scheduleAtFixedRate(new TimerTask() {
-
- @Override
- public void run() {
- vectorStore.save(file);
- }
-
- }, Duration.ofMinutes(1).toMillis(), Duration.ofMinutes(1).toMillis());
- // 鍏抽棴鏃讹紝杩涜鎸佷箙鍖�
- RuntimeUtil.addShutdownHook(() -> vectorStore.save(file));
- return vectorStore;
- }
-
- /**
- * 鍙傝�� {@link QdrantVectorStoreAutoConfiguration} 鐨� vectorStore 鏂规硶
- */
- @SneakyThrows
- private QdrantVectorStore buildQdrantVectorStore(EmbeddingModel embeddingModel) {
- QdrantVectorStoreAutoConfiguration configuration = new QdrantVectorStoreAutoConfiguration();
- QdrantVectorStoreProperties properties = SpringUtil.getBean(QdrantVectorStoreProperties.class);
- // 鍙傝�� QdrantVectorStoreAutoConfiguration 瀹炵幇锛屽垱寤� QdrantClient 瀵硅薄
- QdrantGrpcClient.Builder grpcClientBuilder = QdrantGrpcClient.newBuilder(
- properties.getHost(), properties.getPort(), properties.isUseTls());
- if (StrUtil.isNotEmpty(properties.getApiKey())) {
- grpcClientBuilder.withApiKey(properties.getApiKey());
- }
- QdrantClient qdrantClient = new QdrantClient(grpcClientBuilder.build());
- // 鍒涘缓 QdrantVectorStore 瀵硅薄
- QdrantVectorStore vectorStore = configuration.vectorStore(embeddingModel, properties, qdrantClient,
- getObservationRegistry(), getCustomObservationConvention(), getBatchingStrategy());
- // 鍒濆鍖栫储寮�
- vectorStore.afterPropertiesSet();
- return vectorStore;
- }
-
- /**
- * 鍙傝�� {@link RedisVectorStoreAutoConfiguration} 鐨� vectorStore 鏂规硶
- */
- private RedisVectorStore buildRedisVectorStore(EmbeddingModel embeddingModel,
- Map<String, Class<?>> metadataFields) {
- // 鍒涘缓 RedisClient 瀵硅薄
- RedisClient redisClient = buildRedisClient();
- // 鍒涘缓 RedisVectorStoreProperties 瀵硅薄
- RedisVectorStoreProperties properties = SpringUtil.getBean(RedisVectorStoreProperties.class);
- RedisVectorStore redisVectorStore = RedisVectorStore.builder(redisClient, embeddingModel)
- .indexName(properties.getIndexName()).prefix(properties.getPrefix())
- .initializeSchema(properties.isInitializeSchema())
- .metadataFields(convertList(metadataFields.entrySet(), entry -> {
- String fieldName = entry.getKey();
- Class<?> fieldType = entry.getValue();
- if (Number.class.isAssignableFrom(fieldType)) {
- return RedisVectorStore.MetadataField.numeric(fieldName);
- }
- if (Boolean.class.isAssignableFrom(fieldType)) {
- return RedisVectorStore.MetadataField.tag(fieldName);
- }
- return RedisVectorStore.MetadataField.text(fieldName);
- }))
- .observationRegistry(getObservationRegistry().getObject())
- .customObservationConvention(getCustomObservationConvention().getObject())
- .batchingStrategy(getBatchingStrategy())
- .build();
- // 鍒濆鍖栫储寮�
- redisVectorStore.afterPropertiesSet();
- return redisVectorStore;
- }
-
- private RedisClient buildRedisClient() {
- DataRedisProperties redisProperties = SpringUtil.getBean(DataRedisProperties.class);
- Assert.isNull(redisProperties.getCluster(), "RedisVectorStore 鏆備笉鏀寔 Redis Cluster 妯″紡");
- Assert.isNull(redisProperties.getSentinel(), "RedisVectorStore 鏆備笉鏀寔 Redis Sentinel 妯″紡");
- Assert.isNull(redisProperties.getMasterreplica(), "RedisVectorStore 鏆備笉鏀寔 Redis Master-Replica 妯″紡");
- if (StrUtil.isNotEmpty(redisProperties.getUrl())) {
- return RedisClient.create(redisProperties.getUrl());
- }
- DefaultJedisClientConfig.Builder clientConfigBuilder = DefaultJedisClientConfig.builder()
- .ssl(redisProperties.getSsl().isEnabled())
- .database(redisProperties.getDatabase());
- if (StrUtil.isNotEmpty(redisProperties.getUsername())) {
- clientConfigBuilder.user(redisProperties.getUsername());
- }
- if (StrUtil.isNotEmpty(redisProperties.getPassword())) {
- clientConfigBuilder.password(redisProperties.getPassword());
- }
- if (StrUtil.isNotEmpty(redisProperties.getClientName())) {
- clientConfigBuilder.clientName(redisProperties.getClientName());
- }
- if (redisProperties.getTimeout() != null) {
- clientConfigBuilder.socketTimeoutMillis(toMillis(redisProperties.getTimeout()));
- }
- if (redisProperties.getConnectTimeout() != null) {
- clientConfigBuilder.connectionTimeoutMillis(toMillis(redisProperties.getConnectTimeout()));
- }
- JedisClientConfig clientConfig = clientConfigBuilder.build();
- return RedisClient.builder()
- .hostAndPort(new HostAndPort(redisProperties.getHost(), redisProperties.getPort()))
- .clientConfig(clientConfig)
- .build();
- }
-
- private static int toMillis(Duration duration) {
- return Math.toIntExact(duration.toMillis());
- }
-
- /**
- * 鍙傝�� {@link MilvusVectorStoreAutoConfiguration} 鐨� vectorStore 鏂规硶
- */
- @SneakyThrows
private MilvusVectorStore buildMilvusVectorStore(EmbeddingModel embeddingModel) {
- MilvusVectorStoreAutoConfiguration configuration = new MilvusVectorStoreAutoConfiguration();
- // 鑾峰彇閰嶇疆灞炴��
MilvusVectorStoreProperties serverProperties = SpringUtil.getBean(MilvusVectorStoreProperties.class);
MilvusServiceClientProperties clientProperties = SpringUtil.getBean(MilvusServiceClientProperties.class);
- // 鍒涘缓 MilvusServiceClient 瀵硅薄
- MilvusServiceClient milvusClient = configuration.milvusClient(serverProperties, clientProperties,
- new MilvusServiceClientConnectionDetails() {
+ var connectParam = io.milvus.param.ConnectParam.newBuilder()
+ .withHost(clientProperties.getHost())
+ .withPort(clientProperties.getPort())
+ .withDatabaseName(serverProperties.getDatabaseName())
+ .build();
+ var milvusClient = new io.milvus.client.MilvusServiceClient(connectParam);
- @Override
- public String getHost() {
- return clientProperties.getHost();
- }
-
- @Override
- public int getPort() {
- return clientProperties.getPort();
- }
-
- }
- );
- // 鍒涘缓 MilvusVectorStore 瀵硅薄
- MilvusVectorStore vectorStore = configuration.vectorStore(milvusClient, embeddingModel, serverProperties,
- getBatchingStrategy(), getObservationRegistry(), getCustomObservationConvention());
-
- // 鍒濆鍖栫储寮�
- vectorStore.afterPropertiesSet();
+ MilvusVectorStore vectorStore = MilvusVectorStore.builder(milvusClient, embeddingModel)
+ .databaseName(serverProperties.getDatabaseName())
+ .collectionName(serverProperties.getCollectionName())
+ .initializeSchema(serverProperties.isInitializeSchema())
+ .batchingStrategy(new TokenCountBatchingStrategy())
+ .build();
+ try {
+ vectorStore.afterPropertiesSet();
+ } catch (Exception e) {
+ throw new RuntimeException("Milvus 鍚戦噺瀛樺偍鍒濆鍖栧け璐�: " + e.getMessage(), e);
+ }
return vectorStore;
}
- private static ObjectProvider<ObservationRegistry> getObservationRegistry() {
- return new ObjectProvider<>() {
-
- @Override
- public ObservationRegistry getObject() throws BeansException {
- return SpringUtil.getBean(ObservationRegistry.class);
- }
-
- };
- }
-
- private static ObjectProvider<VectorStoreObservationConvention> getCustomObservationConvention() {
- return new ObjectProvider<>() {
-
- @Override
- public VectorStoreObservationConvention getObject() throws BeansException {
- return new DefaultVectorStoreObservationConvention();
- }
-
- };
- }
-
- private static BatchingStrategy getBatchingStrategy() {
- return SpringUtil.getBean(BatchingStrategy.class);
- }
-
- private static ObjectProvider<EmbeddingModelObservationConvention> getEmbeddingModelObservationConvention() {
- return new ObjectProvider<>() {
-
- @Override
- public EmbeddingModelObservationConvention getObject() throws BeansException {
- return SpringUtil.getBean(EmbeddingModelObservationConvention.class);
- }
-
- };
+ private static String buildCacheKey(Class<?> clazz, Object... params) {
+ if (ArrayUtil.isEmpty(params)) return clazz.getName();
+ return StrUtil.format("{}#{}", clazz.getName(), ArrayUtil.join(params, "_"));
}
}
--
Gitblit v1.9.3