From 24681c81c09022f584a57006f2534b5f74723414 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期二, 30 六月 2026 09:27:31 +0800
Subject: [PATCH] 初始化项目
---
yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/AiModelFactoryImpl.java | 437 +++++++++++++++++++++++-------------------------------
1 files changed, 189 insertions(+), 248 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 c2f96ae..ec9d404 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
@@ -8,52 +8,40 @@
import cn.hutool.core.util.RuntimeUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
-import cn.iocoder.yudao.framework.common.util.spring.SpringUtils;
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.gemini.GeminiChatModel;
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.api.DashScopeApi;
-import com.alibaba.cloud.ai.dashscope.api.DashScopeImageApi;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
-import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
import com.alibaba.cloud.ai.dashscope.embedding.text.DashScopeEmbeddingModel;
-import com.alibaba.cloud.ai.dashscope.embedding.text.DashScopeEmbeddingOptions;
import com.alibaba.cloud.ai.dashscope.image.DashScopeImageModel;
-import com.anthropic.client.okhttp.AnthropicOkHttpClient;
-import com.azure.ai.openai.OpenAIClientBuilder;
-import com.azure.core.credential.KeyCredential;
-import com.openai.client.OpenAIClient;
-import com.openai.client.okhttp.OpenAIOkHttpClient;
+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.springaicommunity.moonshot.MoonshotChatModel;
-import org.springaicommunity.moonshot.MoonshotChatOptions;
-import org.springaicommunity.moonshot.api.MoonshotApi;
-import org.springaicommunity.qianfan.QianFanChatModel;
-import org.springaicommunity.qianfan.QianFanEmbeddingModel;
-import org.springaicommunity.qianfan.QianFanEmbeddingOptions;
-import org.springaicommunity.qianfan.QianFanImageModel;
-import org.springaicommunity.qianfan.api.QianFanApi;
-import org.springaicommunity.qianfan.api.QianFanImageApi;
-import org.springframework.ai.azure.openai.AzureOpenAiChatModel;
-import org.springframework.ai.azure.openai.AzureOpenAiEmbeddingModel;
+import org.springframework.ai.anthropic.AnthropicChatModel;
+import org.springframework.ai.anthropic.AnthropicChatOptions;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.deepseek.DeepSeekChatModel;
import org.springframework.ai.deepseek.DeepSeekChatOptions;
@@ -62,37 +50,24 @@
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.minimax.MiniMaxChatModel;
-import org.springframework.ai.minimax.MiniMaxChatOptions;
-import org.springframework.ai.minimax.MiniMaxEmbeddingModel;
-import org.springframework.ai.minimax.MiniMaxEmbeddingOptions;
-import org.springframework.ai.minimax.api.MiniMaxApi;
import org.springframework.ai.model.anthropic.autoconfigure.AnthropicChatAutoConfiguration;
-import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiChatAutoConfiguration;
-import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiEmbeddingAutoConfiguration;
-import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiEmbeddingProperties;
import org.springframework.ai.model.deepseek.autoconfigure.DeepSeekChatAutoConfiguration;
-import org.springframework.ai.model.minimax.autoconfigure.MiniMaxChatAutoConfiguration;
-import org.springframework.ai.model.minimax.autoconfigure.MiniMaxEmbeddingAutoConfiguration;
+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.model.zhipuai.autoconfigure.ZhiPuAiChatAutoConfiguration;
-import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiEmbeddingAutoConfiguration;
-import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiImageAutoConfiguration;
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.OpenAiChatModel;
-import org.springframework.ai.openai.OpenAiEmbeddingModel;
-import org.springframework.ai.openai.OpenAiEmbeddingOptions;
-import org.springframework.ai.openai.OpenAiImageModel;
-import org.springframework.ai.anthropic.AnthropicChatModel;
+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;
@@ -110,18 +85,17 @@
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.ai.zhipuai.*;
-import org.springframework.ai.zhipuai.api.ZhiPuAiApi;
-import org.springframework.ai.zhipuai.api.ZhiPuAiImageApi;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.data.redis.autoconfigure.DataRedisProperties;
-import org.springframework.web.client.RestClient;
-import redis.clients.jedis.JedisPooled;
+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.List;
+import java.util.Collections;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
@@ -136,7 +110,9 @@
public class AiModelFactoryImpl implements AiModelFactory {
@Override
- public ChatModel getOrCreateChatModel(AiPlatformEnum platform, String apiKey, String url) {
+ 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);
return Singleton.get(cacheKey, (Func0<ChatModel>) () -> {
// noinspection EnhancedSwitchMigration
@@ -159,6 +135,8 @@
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:
@@ -170,11 +148,11 @@
case ANTHROPIC:
return buildAnthropicChatModel(apiKey, url);
case GEMINI:
- return buildGeminiChatModel(apiKey);
+ return buildGeminiChatModel(apiKey, url);
case OLLAMA:
return buildOllamaChatModel(url);
case GROK:
- return buildGrokChatModel(apiKey,url);
+ return buildGrokChatModel(apiKey, url);
default:
throw new IllegalArgumentException(StrUtil.format("鏈煡骞冲彴({})", platform));
}
@@ -188,7 +166,7 @@
case TONG_YI:
return SpringUtil.getBean(DashScopeChatModel.class);
case YI_YAN:
- return SpringUtil.getBean(QianFanChatModel.class);
+ return SpringUtil.getBean(YiYanChatModel.class);
case DEEP_SEEK:
return SpringUtil.getBean(DeepSeekChatModel.class);
case DOU_BAO:
@@ -198,23 +176,23 @@
case SILICON_FLOW:
return SpringUtil.getBean(SiliconFlowChatModel.class);
case ZHI_PU:
- return SpringUtil.getBean(ZhiPuAiChatModel.class);
+ 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 AZURE_OPENAI:
- return SpringUtil.getBean(AzureOpenAiChatModel.class);
case ANTHROPIC:
return SpringUtil.getBean(AnthropicChatModel.class);
case GEMINI:
- return SpringUtil.getBean(GeminiChatModel.class);
+ return SpringUtil.getBean(GoogleGenAiChatModel.class);
case OLLAMA:
return SpringUtil.getBean(OllamaChatModel.class);
default:
@@ -228,10 +206,6 @@
switch (platform) {
case TONG_YI:
return SpringUtil.getBean(DashScopeImageModel.class);
- case YI_YAN:
- return SpringUtil.getBean(QianFanImageModel.class);
- case ZHI_PU:
- return SpringUtil.getBean(ZhiPuAiImageModel.class);
case SILICON_FLOW:
return SpringUtil.getBean(SiliconFlowImageModel.class);
case OPENAI:
@@ -244,19 +218,17 @@
}
@Override
- public ImageModel getOrCreateImageModel(AiPlatformEnum platform, String apiKey, String url) {
+ 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 YI_YAN:
- return buildQianFanImageModel(apiKey);
- case ZHI_PU:
- return buildZhiPuAiImageModel(apiKey, url);
case OPENAI:
return buildOpenAiImageModel(apiKey, url);
case SILICON_FLOW:
- return buildSiliconFlowImageModel(apiKey,url);
+ return buildSiliconFlowImageModel(apiKey, url);
case STABLE_DIFFUSION:
return buildStabilityAiImageModel(apiKey, url);
default:
@@ -265,9 +237,11 @@
}
@Override
- public MidjourneyApi getOrCreateMidjourneyApi(String apiKey, String url) {
- String cacheKey = buildClientCacheKey(MidjourneyApi.class, AiPlatformEnum.MIDJOURNEY.getPlatform(), apiKey,
- url);
+ 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();
@@ -276,25 +250,23 @@
}
@Override
- public SunoApi getOrCreateSunoApi(String apiKey, String url) {
+ 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 apiKey, String url, String model) {
+ 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);
return Singleton.get(cacheKey, (Func0<EmbeddingModel>) () -> {
switch (platform) {
case TONG_YI:
return buildTongYiEmbeddingModel(apiKey, model);
- case YI_YAN:
- return buildYiYanEmbeddingModel(apiKey, model);
- case ZHI_PU:
- return buildZhiPuEmbeddingModel(apiKey, url, model);
- case MINI_MAX:
- return buildMiniMaxEmbeddingModel(apiKey, url, model);
case OPENAI:
return buildOpenAiEmbeddingModel(apiKey, url, model);
case AZURE_OPENAI:
@@ -336,60 +308,31 @@
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) {
- DashScopeApi dashScopeApi = DashScopeApi.builder().apiKey(key).build();
- DashScopeChatOptions options = DashScopeChatOptions
- .builder()
- .model(DashScopeApi.DEFAULT_CHAT_MODEL)
- .temperature(0.7)
- .build();
- return DashScopeChatModel
- .builder()
- .dashScopeApi(dashScopeApi)
- .defaultOptions(options)
- .toolCallingManager(getToolCallingManager())
- .build();
+ return AiAutoConfiguration.buildTongYiChatModel(key);
}
/**
* 鍙弬鑰� {@link DashScopeImageAutoConfiguration} 鐨� dashScopeImageModel 鏂规硶
*/
private static DashScopeImageModel buildTongYiImagesModel(String key) {
- DashScopeImageApi dashScopeImageApi = DashScopeImageApi.builder().apiKey(key).build();
- return DashScopeImageModel.builder()
- .dashScopeApi(dashScopeImageApi)
- .build();
+ return AiAutoConfiguration.buildTongYiImagesModel(key);
}
- /**
- * 鍙弬鑰� QianFanChatAutoConfiguration 鐨� qianFanChatModel 鏂规硶
- */
- private static QianFanChatModel buildYiYanChatModel(String key) {
- // TODO spring ai qianfan 鏈� bug锛屾棤娉曚娇鐢� https://github.com/spring-ai-community/qianfan/issues/6
- List<String> keys = StrUtil.split(key, '|');
- Assert.equals(keys.size(), 2, "YiYanChatClient 鐨勫瘑閽ラ渶瑕� (appKey|secretKey) 鏍煎紡");
- String appKey = keys.get(0);
- String secretKey = keys.get(1);
- QianFanApi qianFanApi = new QianFanApi(appKey, secretKey);
- return new QianFanChatModel(qianFanApi);
- }
-
- /**
- * 鍙弬鑰� QianFanEmbeddingAutoConfiguration 鐨� qianFanImageModel 鏂规硶
- */
- private QianFanImageModel buildQianFanImageModel(String key) {
- // TODO spring ai qianfan 鏈� bug锛屾棤娉曚娇鐢� https://github.com/spring-ai-community/qianfan/issues/6
- List<String> keys = StrUtil.split(key, '|');
- Assert.equals(keys.size(), 2, "YiYanChatClient 鐨勫瘑閽ラ渶瑕� (appKey|secretKey) 鏍煎紡");
- String appKey = keys.get(0);
- String secretKey = keys.get(1);
- QianFanImageApi qianFanApi = new QianFanImageApi(appKey, secretKey);
- return new QianFanImageModel(qianFanApi);
+ private ChatModel buildYiYanChatModel(String apiKey) {
+ YudaoAiProperties.YiYan properties = new YudaoAiProperties.YiYan()
+ .setApiKey(apiKey);
+ return new AiAutoConfiguration().buildYiYanChatClient(properties);
}
/**
@@ -401,8 +344,7 @@
.temperature(0.7).build();
return DeepSeekChatModel.builder()
.deepSeekApi(deepSeekApi)
- .defaultOptions(options)
- .toolCallingManager(getToolCallingManager())
+ .options(options)
.build();
}
@@ -434,62 +376,47 @@
}
/**
- * 鍙弬鑰� {@link ZhiPuAiChatAutoConfiguration} 鐨� zhiPuAiChatModel 鏂规硶
+ * 鍙弬鑰� {@link AiAutoConfiguration#zhiPuChatClient(YudaoAiProperties)}
*/
- private ZhiPuAiChatModel buildZhiPuChatModel(String apiKey, String url) {
- ZhiPuAiApi.Builder zhiPuAiApiBuilder = ZhiPuAiApi.builder().apiKey(apiKey);
- if (StrUtil.isNotEmpty(url)) {
- zhiPuAiApiBuilder.baseUrl(url);
- }
- ZhiPuAiChatOptions options = ZhiPuAiChatOptions.builder().model(ZhiPuAiApi.DEFAULT_CHAT_MODEL).temperature(0.7).build();
- return new ZhiPuAiChatModel(zhiPuAiApiBuilder.build(), options, getToolCallingManager(), new org.springframework.core.retry.RetryTemplate(),
- getObservationRegistry().getIfAvailable());
+ private ZhiPuChatModel buildZhiPuChatModel(String apiKey, String url) {
+ YudaoAiProperties.ZhiPu properties = new YudaoAiProperties.ZhiPu()
+ .setBaseUrl(url).setApiKey(apiKey);
+ return new AiAutoConfiguration().buildZhiPuChatClient(properties);
}
/**
- * 鍙弬鑰� {@link ZhiPuAiImageAutoConfiguration} 鐨� zhiPuAiImageModel 鏂规硶
- */
- private ZhiPuAiImageModel buildZhiPuAiImageModel(String apiKey, String url) {
- ZhiPuAiImageApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiImageApi(apiKey)
- : new ZhiPuAiImageApi(url, apiKey, RestClient.builder());
- return new ZhiPuAiImageModel(zhiPuAiApi);
- }
-
- /**
- * 鍙弬鑰� {@link MiniMaxChatAutoConfiguration} 鐨� miniMaxChatModel 鏂规硶
+ * 鍙弬鑰� {@link AiAutoConfiguration#miniMaxChatClient(YudaoAiProperties)}
*/
private MiniMaxChatModel buildMiniMaxChatModel(String apiKey, String url) {
- MiniMaxApi miniMaxApi = StrUtil.isEmpty(url) ? new MiniMaxApi(apiKey)
- : new MiniMaxApi(url, apiKey);
- MiniMaxChatOptions options = MiniMaxChatOptions.builder().model(MiniMaxApi.DEFAULT_CHAT_MODEL).temperature(0.7).build();
- return new MiniMaxChatModel(miniMaxApi, options, getToolCallingManager(), new org.springframework.core.retry.RetryTemplate());
+ YudaoAiProperties.MiniMax properties = new YudaoAiProperties.MiniMax()
+ .setBaseUrl(url).setApiKey(apiKey);
+ return new AiAutoConfiguration().buildMiniMaxChatClient(properties);
}
/**
- * 鍙弬鑰� MoonshotChatAutoConfiguration 鐨� moonshotChatModel 鏂规硶
+ * 鍙弬鑰� {@link AiAutoConfiguration#moonshotChatClient(YudaoAiProperties)}
*/
private MoonshotChatModel buildMoonshotChatModel(String apiKey, String url) {
- MoonshotApi.Builder moonshotApiBuilder = MoonshotApi.builder()
- .apiKey(apiKey);
- if (StrUtil.isNotEmpty(url)) {
- moonshotApiBuilder.baseUrl(url);
- }
- MoonshotChatOptions options = MoonshotChatOptions.builder().model(MoonshotApi.DEFAULT_CHAT_MODEL).build();
- return MoonshotChatModel.builder()
- .moonshotApi(moonshotApiBuilder.build())
- .defaultOptions(options)
- .toolCallingManager(getToolCallingManager())
- .build();
+ 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 key) {
- List<String> keys = StrUtil.split(key, '|');
- Assert.equals(keys.size(), 2, "XingHuoChatClient 鐨勫瘑閽ラ渶瑕� (appKey|secretKey) 鏍煎紡");
+ private static XingHuoChatModel buildXingHuoChatModel(String apiKey) {
YudaoAiProperties.XingHuo properties = new YudaoAiProperties.XingHuo()
- .setAppKey(keys.get(0)).setSecretKey(keys.get(1));
+ .setApiKey(apiKey).setModel(XingHuoChatModel.MODEL_DEFAULT);
return new AiAutoConfiguration().buildXingHuoChatClient(properties);
}
@@ -507,52 +434,73 @@
*/
private static OpenAiChatModel buildOpenAiChatModel(String openAiToken, String url) {
return OpenAiChatModel.builder()
- .openAiClient(buildOpenAiClient(openAiToken, url))
- .toolCallingManager(getToolCallingManager())
+ .options(buildOpenAiChatOptions(openAiToken, url).build())
.build();
}
- /**
- * 鍙弬鑰� {@link AzureOpenAiChatAutoConfiguration}
- */
- private static AzureOpenAiChatModel buildAzureOpenAiChatModel(String apiKey, String url) {
- // TODO @鑺嬭壙锛氫娇鐢ㄥ墠锛岃娴嬭瘯锛屾殏鏃舵病瀵嗛挜锛侊紒锛�
- OpenAIClientBuilder openAIClientBuilder = new OpenAIClientBuilder()
- .endpoint(url).credential(new KeyCredential(apiKey));
- return AzureOpenAiChatModel.builder()
- .openAIClientBuilder(openAIClientBuilder)
- .toolCallingManager(getToolCallingManager())
+ 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) {
- AnthropicOkHttpClient.Builder builder = AnthropicOkHttpClient.builder().apiKey(apiKey);
+ AnthropicChatOptions.Builder optionsBuilder = AnthropicChatOptions.builder().apiKey(apiKey);
if (StrUtil.isNotEmpty(url)) {
- builder.baseUrl(url);
+ optionsBuilder.baseUrl(url);
}
return AnthropicChatModel.builder()
- .anthropicClient(builder.build())
- .toolCallingManager(getToolCallingManager())
+ .options(optionsBuilder.build())
.build();
}
/**
- * 鍙弬鑰� {@link AiAutoConfiguration#buildGeminiChatClient(YudaoAiProperties.Gemini)}
+ * 鍙弬鑰� {@link GoogleGenAiChatAutoConfiguration} 鐨� googleGenAiChatModel 鏂规硶
*/
- private static GeminiChatModel buildGeminiChatModel(String apiKey) {
- YudaoAiProperties.Gemini properties = SpringUtil.getBean(YudaoAiProperties.class)
- .getGemini().setApiKey(apiKey);
- return new AiAutoConfiguration().buildGeminiChatClient(properties);
+ 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) {
- return new OpenAiImageModel(buildOpenAiClient(openAiToken, url));
+ OpenAiImageOptions.Builder optionsBuilder = OpenAiImageOptions.builder().apiKey(openAiToken);
+ if (StrUtil.isNotEmpty(url)) {
+ optionsBuilder.baseUrl(url);
+ }
+ return OpenAiImageModel.builder()
+ .options(optionsBuilder.build())
+ .build();
}
/**
@@ -571,7 +519,6 @@
OllamaApi ollamaApi = OllamaApi.builder().baseUrl(url).build();
return OllamaChatModel.builder()
.ollamaApi(ollamaApi)
- .toolCallingManager(getToolCallingManager())
.build();
}
@@ -597,44 +544,7 @@
* 鍙弬鑰� {@link DashScopeEmbeddingAutoConfiguration} 鐨� DashScopeEmbeddingModel 鏂规硶
*/
private DashScopeEmbeddingModel buildTongYiEmbeddingModel(String apiKey, String model) {
- DashScopeApi dashScopeApi = DashScopeApi.builder().apiKey(apiKey).build();
- DashScopeEmbeddingOptions dashScopeEmbeddingOptions = DashScopeEmbeddingOptions.builder().model(model).build();
- return new DashScopeEmbeddingModel(dashScopeApi, MetadataMode.EMBED, dashScopeEmbeddingOptions);
- }
-
- /**
- * 鍙弬鑰� {@link ZhiPuAiEmbeddingAutoConfiguration} 鐨� ZhiPuAiEmbeddingModel 鏂规硶
- */
- private ZhiPuAiEmbeddingModel buildZhiPuEmbeddingModel(String apiKey, String url, String model) {
- ZhiPuAiApi.Builder zhiPuAiApiBuilder = ZhiPuAiApi.builder().apiKey(apiKey);
- if (StrUtil.isNotEmpty(url)) {
- zhiPuAiApiBuilder.baseUrl(url);
- }
- ZhiPuAiEmbeddingOptions zhiPuAiEmbeddingOptions = ZhiPuAiEmbeddingOptions.builder().model(model).build();
- return new ZhiPuAiEmbeddingModel(zhiPuAiApiBuilder.build(), MetadataMode.EMBED, zhiPuAiEmbeddingOptions);
- }
-
- /**
- * 鍙弬鑰� {@link MiniMaxEmbeddingAutoConfiguration} 鐨� miniMaxEmbeddingModel 鏂规硶
- */
- private EmbeddingModel buildMiniMaxEmbeddingModel(String apiKey, String url, String model) {
- MiniMaxApi miniMaxApi = StrUtil.isEmpty(url)? new MiniMaxApi(apiKey)
- : new MiniMaxApi(url, apiKey);
- MiniMaxEmbeddingOptions miniMaxEmbeddingOptions = MiniMaxEmbeddingOptions.builder().model(model).build();
- return new MiniMaxEmbeddingModel(miniMaxApi, MetadataMode.EMBED, miniMaxEmbeddingOptions);
- }
-
- /**
- * 鍙弬鑰� {@link QianFanEmbeddingModel} 鐨� qianFanEmbeddingModel 鏂规硶
- */
- private QianFanEmbeddingModel buildYiYanEmbeddingModel(String key, String model) {
- List<String> keys = StrUtil.split(key, '|');
- Assert.equals(keys.size(), 2, "YiYanChatClient 鐨勫瘑閽ラ渶瑕� (appKey|secretKey) 鏍煎紡");
- String appKey = keys.get(0);
- String secretKey = keys.get(1);
- QianFanApi qianFanApi = new QianFanApi(appKey, secretKey);
- QianFanEmbeddingOptions qianFanEmbeddingOptions = QianFanEmbeddingOptions.builder().model(model).build();
- return new QianFanEmbeddingModel(qianFanApi, MetadataMode.EMBED, qianFanEmbeddingOptions);
+ return AiAutoConfiguration.buildTongYiEmbeddingModel(apiKey, model);
}
private OllamaEmbeddingModel buildOllamaEmbeddingModel(String url, String model) {
@@ -642,7 +552,7 @@
OllamaEmbeddingOptions ollamaOptions = OllamaEmbeddingOptions.builder().model(model).build();
return OllamaEmbeddingModel.builder()
.ollamaApi(ollamaApi)
- .defaultOptions(ollamaOptions)
+ .options(ollamaOptions)
.build();
}
@@ -650,31 +560,31 @@
* 鍙弬鑰� {@link OpenAiEmbeddingAutoConfiguration} 鐨� openAiEmbeddingModel 鏂规硶
*/
private OpenAiEmbeddingModel buildOpenAiEmbeddingModel(String openAiToken, String url, String model) {
- OpenAiEmbeddingOptions openAiEmbeddingProperties = OpenAiEmbeddingOptions.builder().model(model).build();
- return new OpenAiEmbeddingModel(buildOpenAiClient(openAiToken, url), MetadataMode.EMBED, openAiEmbeddingProperties);
- }
-
- private static OpenAIClient buildOpenAiClient(String apiKey, String url) {
- OpenAIOkHttpClient.Builder builder = OpenAIOkHttpClient.builder().apiKey(apiKey);
+ OpenAiEmbeddingOptions.Builder optionsBuilder = OpenAiEmbeddingOptions.builder()
+ .apiKey(openAiToken)
+ .model(model);
if (StrUtil.isNotEmpty(url)) {
- builder.baseUrl(url);
+ optionsBuilder.baseUrl(url);
}
- return builder.build();
+ return OpenAiEmbeddingModel.builder()
+ .metadataMode(MetadataMode.EMBED)
+ .options(optionsBuilder.build())
+ .build();
}
- /**
- * 鍙弬鑰� {@link AzureOpenAiEmbeddingAutoConfiguration} 鐨� azureOpenAiEmbeddingModel 鏂规硶
- */
- private AzureOpenAiEmbeddingModel buildAzureOpenAiEmbeddingModel(String apiKey, String url, String model) {
- // TODO @鑺嬭壙锛氭墜澶存殏鏃舵病瀵嗛挜锛屼娇鐢ㄥ缓璁啀娴嬭瘯涓�
- AzureOpenAiEmbeddingAutoConfiguration azureOpenAiAutoConfiguration = new AzureOpenAiEmbeddingAutoConfiguration();
- // 鍒涘缓 OpenAIClientBuilder 瀵硅薄
- OpenAIClientBuilder openAIClientBuilder = new OpenAIClientBuilder()
- .endpoint(url).credential(new KeyCredential(apiKey));
- // 鑾峰彇 AzureOpenAiChatProperties 瀵硅薄
- AzureOpenAiEmbeddingProperties embeddingProperties = SpringUtil.getBean(AzureOpenAiEmbeddingProperties.class);
- return azureOpenAiAutoConfiguration.azureOpenAiEmbeddingModel(openAIClientBuilder, embeddingProperties,
- getObservationRegistry(), getEmbeddingModelObservationConvention());
+ 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 鐨勬柟娉� ==========
@@ -737,13 +647,11 @@
*/
private RedisVectorStore buildRedisVectorStore(EmbeddingModel embeddingModel,
Map<String, Class<?>> metadataFields) {
- // 鍒涘缓 JedisPooled 瀵硅薄
- DataRedisProperties redisProperties = SpringUtils.getBean(DataRedisProperties.class);
- JedisPooled jedisPooled = new JedisPooled(redisProperties.getHost(), redisProperties.getPort(),
- redisProperties.getUsername(), redisProperties.getPassword());
+ // 鍒涘缓 RedisClient 瀵硅薄
+ RedisClient redisClient = buildRedisClient();
// 鍒涘缓 RedisVectorStoreProperties 瀵硅薄
RedisVectorStoreProperties properties = SpringUtil.getBean(RedisVectorStoreProperties.class);
- RedisVectorStore redisVectorStore = RedisVectorStore.builder(jedisPooled, embeddingModel)
+ RedisVectorStore redisVectorStore = RedisVectorStore.builder(redisClient, embeddingModel)
.indexName(properties.getIndexName()).prefix(properties.getPrefix())
.initializeSchema(properties.isInitializeSchema())
.metadataFields(convertList(metadataFields.entrySet(), entry -> {
@@ -764,6 +672,43 @@
// 鍒濆鍖栫储寮�
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());
}
/**
@@ -825,10 +770,6 @@
private static BatchingStrategy getBatchingStrategy() {
return SpringUtil.getBean(BatchingStrategy.class);
- }
-
- private static ToolCallingManager getToolCallingManager() {
- return SpringUtil.getBean(ToolCallingManager.class);
}
private static ObjectProvider<EmbeddingModelObservationConvention> getEmbeddingModelObservationConvention() {
--
Gitblit v1.9.3