feat:【AI 大模型】deepseek、azure、baichuan、moonshot 适配 1.0.0

This commit is contained in:
YunaiV 2025-07-14 21:40:00 +08:00
parent 3d0eb77148
commit 750709d706
6 changed files with 160 additions and 113 deletions

View File

@ -8,11 +8,11 @@ import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.RuntimeUtil; import cn.hutool.core.util.RuntimeUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil; 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.AiAutoConfiguration;
import cn.iocoder.yudao.module.ai.framework.ai.config.YudaoAiProperties; import cn.iocoder.yudao.module.ai.framework.ai.config.YudaoAiProperties;
import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum;
import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel; import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel;
import cn.iocoder.yudao.module.ai.framework.ai.core.model.deepseek.DeepSeekChatModel;
import cn.iocoder.yudao.module.ai.framework.ai.core.model.doubao.DouBaoChatModel; 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.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.midjourney.api.MidjourneyApi;
@ -22,8 +22,9 @@ import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlo
import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowImageModel; import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowImageModel;
import cn.iocoder.yudao.module.ai.framework.ai.core.model.suno.api.SunoApi; 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.xinghuo.XingHuoChatModel;
import cn.iocoder.yudao.framework.common.util.spring.SpringUtils; import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeChatAutoConfiguration;
import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeAutoConfiguration; 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.DashScopeApi;
import com.alibaba.cloud.ai.dashscope.api.DashScopeImageApi; import com.alibaba.cloud.ai.dashscope.api.DashScopeImageApi;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel; import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
@ -32,47 +33,55 @@ import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingModel;
import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingOptions; import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingOptions;
import com.alibaba.cloud.ai.dashscope.image.DashScopeImageModel; import com.alibaba.cloud.ai.dashscope.image.DashScopeImageModel;
import com.azure.ai.openai.OpenAIClientBuilder; import com.azure.ai.openai.OpenAIClientBuilder;
import com.azure.core.credential.KeyCredential;
import io.micrometer.observation.ObservationRegistry; import io.micrometer.observation.ObservationRegistry;
import io.milvus.client.MilvusServiceClient; import io.milvus.client.MilvusServiceClient;
import io.qdrant.client.QdrantClient; import io.qdrant.client.QdrantClient;
import io.qdrant.client.QdrantGrpcClient; import io.qdrant.client.QdrantGrpcClient;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiAutoConfiguration; import org.springaicommunity.moonshot.MoonshotChatModel;
import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiChatProperties; import org.springaicommunity.moonshot.MoonshotChatOptions;
import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiConnectionProperties; import org.springaicommunity.moonshot.api.MoonshotApi;
import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiEmbeddingProperties; import org.springaicommunity.moonshot.autoconfigure.MoonshotChatAutoConfiguration;
import org.springframework.ai.autoconfigure.minimax.MiniMaxAutoConfiguration; import org.springaicommunity.qianfan.QianFanChatModel;
import org.springframework.ai.autoconfigure.moonshot.MoonshotAutoConfiguration; import org.springaicommunity.qianfan.QianFanEmbeddingModel;
import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration; import org.springaicommunity.qianfan.QianFanEmbeddingOptions;
import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; import org.springaicommunity.qianfan.QianFanImageModel;
import org.springframework.ai.autoconfigure.qianfan.QianFanAutoConfiguration; import org.springaicommunity.qianfan.api.QianFanApi;
import org.springframework.ai.autoconfigure.stabilityai.StabilityAiImageAutoConfiguration; import org.springaicommunity.qianfan.api.QianFanImageApi;
import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusServiceClientConnectionDetails; import org.springaicommunity.qianfan.autoconfigure.QianFanChatAutoConfiguration;
import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusServiceClientProperties; import org.springaicommunity.qianfan.autoconfigure.QianFanEmbeddingAutoConfiguration;
import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration;
import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreProperties;
import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration;
import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreProperties;
import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreAutoConfiguration;
import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreProperties;
import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiAutoConfiguration;
import org.springframework.ai.azure.openai.AzureOpenAiChatModel; import org.springframework.ai.azure.openai.AzureOpenAiChatModel;
import org.springframework.ai.azure.openai.AzureOpenAiEmbeddingModel; import org.springframework.ai.azure.openai.AzureOpenAiEmbeddingModel;
import org.springframework.ai.chat.model.ChatModel; 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.document.MetadataMode;
import org.springframework.ai.embedding.BatchingStrategy; import org.springframework.ai.embedding.BatchingStrategy;
import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.embedding.observation.EmbeddingModelObservationConvention;
import org.springframework.ai.image.ImageModel; import org.springframework.ai.image.ImageModel;
import org.springframework.ai.minimax.MiniMaxChatModel; import org.springframework.ai.minimax.MiniMaxChatModel;
import org.springframework.ai.minimax.MiniMaxChatOptions; import org.springframework.ai.minimax.MiniMaxChatOptions;
import org.springframework.ai.minimax.MiniMaxEmbeddingModel; import org.springframework.ai.minimax.MiniMaxEmbeddingModel;
import org.springframework.ai.minimax.MiniMaxEmbeddingOptions; import org.springframework.ai.minimax.MiniMaxEmbeddingOptions;
import org.springframework.ai.minimax.api.MiniMaxApi; import org.springframework.ai.minimax.api.MiniMaxApi;
import org.springframework.ai.model.function.FunctionCallbackResolver; 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.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.tool.ToolCallingManager;
import org.springframework.ai.moonshot.MoonshotChatModel; import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiChatAutoConfiguration;
import org.springframework.ai.moonshot.MoonshotChatOptions; import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiEmbeddingAutoConfiguration;
import org.springframework.ai.moonshot.api.MoonshotApi; import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiImageAutoConfiguration;
import org.springframework.ai.ollama.OllamaChatModel; import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.ai.ollama.OllamaEmbeddingModel; import org.springframework.ai.ollama.OllamaEmbeddingModel;
import org.springframework.ai.ollama.api.OllamaApi; import org.springframework.ai.ollama.api.OllamaApi;
@ -84,21 +93,23 @@ import org.springframework.ai.openai.OpenAiImageModel;
import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.ai.openai.api.OpenAiImageApi; import org.springframework.ai.openai.api.OpenAiImageApi;
import org.springframework.ai.openai.api.common.OpenAiApiConstants; import org.springframework.ai.openai.api.common.OpenAiApiConstants;
import org.springframework.ai.qianfan.QianFanChatModel;
import org.springframework.ai.qianfan.QianFanEmbeddingModel;
import org.springframework.ai.qianfan.QianFanEmbeddingOptions;
import org.springframework.ai.qianfan.QianFanImageModel;
import org.springframework.ai.qianfan.api.QianFanApi;
import org.springframework.ai.qianfan.api.QianFanImageApi;
import org.springframework.ai.stabilityai.StabilityAiImageModel; import org.springframework.ai.stabilityai.StabilityAiImageModel;
import org.springframework.ai.stabilityai.api.StabilityAiApi; import org.springframework.ai.stabilityai.api.StabilityAiApi;
import org.springframework.ai.vectorstore.SimpleVectorStore; import org.springframework.ai.vectorstore.SimpleVectorStore;
import org.springframework.ai.vectorstore.VectorStore; import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.ai.vectorstore.milvus.MilvusVectorStore; 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.DefaultVectorStoreObservationConvention;
import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention; import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention;
import org.springframework.ai.vectorstore.qdrant.QdrantVectorStore; 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.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.*;
import org.springframework.ai.zhipuai.api.ZhiPuAiApi; import org.springframework.ai.zhipuai.api.ZhiPuAiApi;
import org.springframework.ai.zhipuai.api.ZhiPuAiImageApi; import org.springframework.ai.zhipuai.api.ZhiPuAiImageApi;
@ -190,7 +201,7 @@ public class AiModelFactoryImpl implements AiModelFactory {
case XING_HUO: case XING_HUO:
return SpringUtil.getBean(XingHuoChatModel.class); return SpringUtil.getBean(XingHuoChatModel.class);
case BAI_CHUAN: case BAI_CHUAN:
return SpringUtil.getBean(AzureOpenAiChatModel.class); return SpringUtil.getBean(BaiChuanChatModel.class);
case OPENAI: case OPENAI:
return SpringUtil.getBean(OpenAiChatModel.class); return SpringUtil.getBean(OpenAiChatModel.class);
case AZURE_OPENAI: case AZURE_OPENAI:
@ -319,27 +330,34 @@ public class AiModelFactoryImpl implements AiModelFactory {
// ========== 各种创建 spring-ai 客户端的方法 ========== // ========== 各种创建 spring-ai 客户端的方法 ==========
/** /**
* 可参考 {@link DashScopeAutoConfiguration} dashscopeChatModel 方法 * 可参考 {@link DashScopeChatAutoConfiguration} dashscopeChatModel 方法
*/ */
private static DashScopeChatModel buildTongYiChatModel(String key) { private static DashScopeChatModel buildTongYiChatModel(String key) {
DashScopeApi dashScopeApi = new DashScopeApi(key); DashScopeApi dashScopeApi = DashScopeApi.builder().apiKey(key).build();
DashScopeChatOptions options = DashScopeChatOptions.builder().withModel(DashScopeApi.DEFAULT_CHAT_MODEL) DashScopeChatOptions options = DashScopeChatOptions.builder().withModel(DashScopeApi.DEFAULT_CHAT_MODEL)
.withTemperature(0.7).build(); .withTemperature(0.7).build();
return new DashScopeChatModel(dashScopeApi, options, getFunctionCallbackResolver(), DEFAULT_RETRY_TEMPLATE); return DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.defaultOptions(options)
.toolCallingManager(getToolCallingManager())
.build();
} }
/** /**
* 可参考 {@link DashScopeAutoConfiguration} dashScopeImageModel 方法 * 可参考 {@link DashScopeImageAutoConfiguration} dashScopeImageModel 方法
*/ */
private static DashScopeImageModel buildTongYiImagesModel(String key) { private static DashScopeImageModel buildTongYiImagesModel(String key) {
DashScopeImageApi dashScopeImageApi = new DashScopeImageApi(key); DashScopeImageApi dashScopeImageApi = new DashScopeImageApi(key);
return new DashScopeImageModel(dashScopeImageApi); return DashScopeImageModel.builder()
.dashScopeApi(dashScopeImageApi)
.build();
} }
/** /**
* 可参考 {@link QianFanAutoConfiguration} qianFanChatModel 方法 * 可参考 {@link QianFanChatAutoConfiguration} qianFanChatModel 方法
*/ */
private static QianFanChatModel buildYiYanChatModel(String key) { private static QianFanChatModel buildYiYanChatModel(String key) {
// TODO @芋艿未测试
List<String> keys = StrUtil.split(key, '|'); List<String> keys = StrUtil.split(key, '|');
Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式"); Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式");
String appKey = keys.get(0); String appKey = keys.get(0);
@ -349,9 +367,10 @@ public class AiModelFactoryImpl implements AiModelFactory {
} }
/** /**
* 可参考 {@link QianFanAutoConfiguration} qianFanImageModel 方法 * 可参考 {@link QianFanEmbeddingAutoConfiguration} qianFanImageModel 方法
*/ */
private QianFanImageModel buildQianFanImageModel(String key) { private QianFanImageModel buildQianFanImageModel(String key) {
// TODO @芋艿未测试
List<String> keys = StrUtil.split(key, '|'); List<String> keys = StrUtil.split(key, '|');
Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式"); Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式");
String appKey = keys.get(0); String appKey = keys.get(0);
@ -361,12 +380,17 @@ public class AiModelFactoryImpl implements AiModelFactory {
} }
/** /**
* 可参考 {@link AiAutoConfiguration#deepSeekChatModel(YudaoAiProperties)} * 可参考 {@link DeepSeekChatAutoConfiguration} deepSeekChatModel 方法
*/ */
private static DeepSeekChatModel buildDeepSeekChatModel(String apiKey) { private static DeepSeekChatModel buildDeepSeekChatModel(String apiKey) {
YudaoAiProperties.DeepSeekProperties properties = new YudaoAiProperties.DeepSeekProperties() DeepSeekApi deepSeekApi = DeepSeekApi.builder().apiKey(apiKey).build();
.setApiKey(apiKey); DeepSeekChatOptions options = DeepSeekChatOptions.builder().model(DeepSeekApi.DEFAULT_CHAT_MODEL)
return new AiAutoConfiguration().buildDeepSeekChatModel(properties); .temperature(0.7).build();
return DeepSeekChatModel.builder()
.deepSeekApi(deepSeekApi)
.defaultOptions(options)
.toolCallingManager(getToolCallingManager())
.build();
} }
/** /**
@ -397,17 +421,18 @@ public class AiModelFactoryImpl implements AiModelFactory {
} }
/** /**
* 可参考 {@link ZhiPuAiAutoConfiguration} zhiPuAiChatModel 方法 * 可参考 {@link ZhiPuAiChatAutoConfiguration} zhiPuAiChatModel 方法
*/ */
private ZhiPuAiChatModel buildZhiPuChatModel(String apiKey, String url) { private ZhiPuAiChatModel buildZhiPuChatModel(String apiKey, String url) {
ZhiPuAiApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiApi(apiKey) ZhiPuAiApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiApi(apiKey)
: new ZhiPuAiApi(url, apiKey); : new ZhiPuAiApi(url, apiKey);
ZhiPuAiChatOptions options = ZhiPuAiChatOptions.builder().model(ZhiPuAiApi.DEFAULT_CHAT_MODEL).temperature(0.7).build(); ZhiPuAiChatOptions options = ZhiPuAiChatOptions.builder().model(ZhiPuAiApi.DEFAULT_CHAT_MODEL).temperature(0.7).build();
return new ZhiPuAiChatModel(zhiPuAiApi, options, getFunctionCallbackResolver(), DEFAULT_RETRY_TEMPLATE); return new ZhiPuAiChatModel(zhiPuAiApi, options, getToolCallingManager(), DEFAULT_RETRY_TEMPLATE,
getObservationRegistry().getIfAvailable());
} }
/** /**
* 可参考 {@link ZhiPuAiAutoConfiguration} zhiPuAiImageModel 方法 * 可参考 {@link ZhiPuAiImageAutoConfiguration} zhiPuAiImageModel 方法
*/ */
private ZhiPuAiImageModel buildZhiPuAiImageModel(String apiKey, String url) { private ZhiPuAiImageModel buildZhiPuAiImageModel(String apiKey, String url) {
ZhiPuAiImageApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiImageApi(apiKey) ZhiPuAiImageApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiImageApi(apiKey)
@ -416,23 +441,30 @@ public class AiModelFactoryImpl implements AiModelFactory {
} }
/** /**
* 可参考 {@link MiniMaxAutoConfiguration} miniMaxChatModel 方法 * 可参考 {@link MiniMaxChatAutoConfiguration} miniMaxChatModel 方法
*/ */
private MiniMaxChatModel buildMiniMaxChatModel(String apiKey, String url) { private MiniMaxChatModel buildMiniMaxChatModel(String apiKey, String url) {
MiniMaxApi miniMaxApi = StrUtil.isEmpty(url) ? new MiniMaxApi(apiKey) MiniMaxApi miniMaxApi = StrUtil.isEmpty(url) ? new MiniMaxApi(apiKey)
: new MiniMaxApi(url, apiKey); : new MiniMaxApi(url, apiKey);
MiniMaxChatOptions options = MiniMaxChatOptions.builder().model(MiniMaxApi.DEFAULT_CHAT_MODEL).temperature(0.7).build(); MiniMaxChatOptions options = MiniMaxChatOptions.builder().model(MiniMaxApi.DEFAULT_CHAT_MODEL).temperature(0.7).build();
return new MiniMaxChatModel(miniMaxApi, options, getFunctionCallbackResolver(), DEFAULT_RETRY_TEMPLATE); return new MiniMaxChatModel(miniMaxApi, options, getToolCallingManager(), DEFAULT_RETRY_TEMPLATE);
} }
/** /**
* 可参考 {@link MoonshotAutoConfiguration} moonshotChatModel 方法 * 可参考 {@link MoonshotChatAutoConfiguration} moonshotChatModel 方法
*/ */
private MoonshotChatModel buildMoonshotChatModel(String apiKey, String url) { private MoonshotChatModel buildMoonshotChatModel(String apiKey, String url) {
MoonshotApi moonshotApi = StrUtil.isEmpty(url)? new MoonshotApi(apiKey) MoonshotApi.Builder moonshotApiBuilder = MoonshotApi.builder()
: new MoonshotApi(url, apiKey); .apiKey(apiKey);
if (StrUtil.isNotEmpty(url)) {
moonshotApiBuilder.baseUrl(url);
}
MoonshotChatOptions options = MoonshotChatOptions.builder().model(MoonshotApi.DEFAULT_CHAT_MODEL).build(); MoonshotChatOptions options = MoonshotChatOptions.builder().model(MoonshotApi.DEFAULT_CHAT_MODEL).build();
return new MoonshotChatModel(moonshotApi, options, getFunctionCallbackResolver(), DEFAULT_RETRY_TEMPLATE); return MoonshotChatModel.builder()
.moonshotApi(moonshotApiBuilder.build())
.defaultOptions(options)
.toolCallingManager(getToolCallingManager())
.build();
} }
/** /**
@ -456,33 +488,32 @@ public class AiModelFactoryImpl implements AiModelFactory {
} }
/** /**
* 可参考 {@link OpenAiAutoConfiguration} openAiChatModel 方法 * 可参考 {@link OpenAiChatAutoConfiguration} openAiChatModel 方法
*/ */
private static OpenAiChatModel buildOpenAiChatModel(String openAiToken, String url) { private static OpenAiChatModel buildOpenAiChatModel(String openAiToken, String url) {
url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL); url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL);
OpenAiApi openAiApi = OpenAiApi.builder().baseUrl(url).apiKey(openAiToken).build(); OpenAiApi openAiApi = OpenAiApi.builder().baseUrl(url).apiKey(openAiToken).build();
return OpenAiChatModel.builder().openAiApi(openAiApi).toolCallingManager(getToolCallingManager()).build(); return OpenAiChatModel.builder()
.openAiApi(openAiApi)
.toolCallingManager(getToolCallingManager())
.build();
} }
// TODO @芋艿手头暂时没密钥使用建议再测试下
/** /**
* 可参考 {@link AzureOpenAiAutoConfiguration} * 可参考 {@link AzureOpenAiChatAutoConfiguration}
*/ */
private static AzureOpenAiChatModel buildAzureOpenAiChatModel(String apiKey, String url) { private static AzureOpenAiChatModel buildAzureOpenAiChatModel(String apiKey, String url) {
AzureOpenAiAutoConfiguration azureOpenAiAutoConfiguration = new AzureOpenAiAutoConfiguration(); // TODO @芋艿使用前请测试暂时没密钥
// 创建 OpenAIClient 对象 OpenAIClientBuilder openAIClientBuilder = new OpenAIClientBuilder()
AzureOpenAiConnectionProperties connectionProperties = new AzureOpenAiConnectionProperties(); .endpoint(url).credential(new KeyCredential(apiKey));
connectionProperties.setApiKey(apiKey); return AzureOpenAiChatModel.builder()
connectionProperties.setEndpoint(url); .openAIClientBuilder(openAIClientBuilder)
OpenAIClientBuilder openAIClient = azureOpenAiAutoConfiguration.openAIClientBuilder(connectionProperties, null); .toolCallingManager(getToolCallingManager())
// 获取 AzureOpenAiChatProperties 对象 .build();
AzureOpenAiChatProperties chatProperties = SpringUtil.getBean(AzureOpenAiChatProperties.class);
return azureOpenAiAutoConfiguration.azureOpenAiChatModel(openAIClient, chatProperties,
getToolCallingManager(), null, null);
} }
/** /**
* 可参考 {@link OpenAiAutoConfiguration} openAiImageModel 方法 * 可参考 {@link OpenAiImageAutoConfiguration} openAiImageModel 方法
*/ */
private OpenAiImageModel buildOpenAiImageModel(String openAiToken, String url) { private OpenAiImageModel buildOpenAiImageModel(String openAiToken, String url) {
url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL); url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL);
@ -494,16 +525,18 @@ public class AiModelFactoryImpl implements AiModelFactory {
* 创建 SiliconFlowImageModel 对象 * 创建 SiliconFlowImageModel 对象
*/ */
private SiliconFlowImageModel buildSiliconFlowImageModel(String apiToken, String url) { private SiliconFlowImageModel buildSiliconFlowImageModel(String apiToken, String url) {
// TODO @芋艿未测试
url = StrUtil.blankToDefault(url, SiliconFlowApiConstants.DEFAULT_BASE_URL); url = StrUtil.blankToDefault(url, SiliconFlowApiConstants.DEFAULT_BASE_URL);
SiliconFlowImageApi openAiApi = new SiliconFlowImageApi(url, apiToken); SiliconFlowImageApi openAiApi = new SiliconFlowImageApi(url, apiToken);
return new SiliconFlowImageModel(openAiApi); return new SiliconFlowImageModel(openAiApi);
} }
/** /**
* 可参考 {@link OllamaAutoConfiguration} ollamaApi 方法 * 可参考 {@link OllamaChatAutoConfiguration} ollamaChatModel 方法
*/ */
private static OllamaChatModel buildOllamaChatModel(String url) { private static OllamaChatModel buildOllamaChatModel(String url) {
OllamaApi ollamaApi = new OllamaApi(url); // TODO @芋艿未测试
OllamaApi ollamaApi = OllamaApi.builder().baseUrl(url).build();
return OllamaChatModel.builder().ollamaApi(ollamaApi).toolCallingManager(getToolCallingManager()).build(); return OllamaChatModel.builder().ollamaApi(ollamaApi).toolCallingManager(getToolCallingManager()).build();
} }
@ -519,16 +552,16 @@ public class AiModelFactoryImpl implements AiModelFactory {
// ========== 各种创建 EmbeddingModel 的方法 ========== // ========== 各种创建 EmbeddingModel 的方法 ==========
/** /**
* 可参考 {@link DashScopeAutoConfiguration} dashscopeEmbeddingModel 方法 * 可参考 {@link DashScopeEmbeddingAutoConfiguration} dashscopeEmbeddingModel 方法
*/ */
private DashScopeEmbeddingModel buildTongYiEmbeddingModel(String apiKey, String model) { private DashScopeEmbeddingModel buildTongYiEmbeddingModel(String apiKey, String model) {
DashScopeApi dashScopeApi = new DashScopeApi(apiKey); DashScopeApi dashScopeApi = DashScopeApi.builder().apiKey(apiKey).build();
DashScopeEmbeddingOptions dashScopeEmbeddingOptions = DashScopeEmbeddingOptions.builder().withModel(model).build(); DashScopeEmbeddingOptions dashScopeEmbeddingOptions = DashScopeEmbeddingOptions.builder().withModel(model).build();
return new DashScopeEmbeddingModel(dashScopeApi, MetadataMode.EMBED, dashScopeEmbeddingOptions); return new DashScopeEmbeddingModel(dashScopeApi, MetadataMode.EMBED, dashScopeEmbeddingOptions);
} }
/** /**
* 可参考 {@link ZhiPuAiAutoConfiguration} zhiPuAiEmbeddingModel 方法 * 可参考 {@link ZhiPuAiEmbeddingAutoConfiguration} zhiPuAiEmbeddingModel 方法
*/ */
private ZhiPuAiEmbeddingModel buildZhiPuEmbeddingModel(String apiKey, String url, String model) { private ZhiPuAiEmbeddingModel buildZhiPuEmbeddingModel(String apiKey, String url, String model) {
ZhiPuAiApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiApi(apiKey) ZhiPuAiApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiApi(apiKey)
@ -538,7 +571,7 @@ public class AiModelFactoryImpl implements AiModelFactory {
} }
/** /**
* 可参考 {@link MiniMaxAutoConfiguration} miniMaxEmbeddingModel 方法 * 可参考 {@link MiniMaxEmbeddingAutoConfiguration} miniMaxEmbeddingModel 方法
*/ */
private EmbeddingModel buildMiniMaxEmbeddingModel(String apiKey, String url, String model) { private EmbeddingModel buildMiniMaxEmbeddingModel(String apiKey, String url, String model) {
MiniMaxApi miniMaxApi = StrUtil.isEmpty(url)? new MiniMaxApi(apiKey) MiniMaxApi miniMaxApi = StrUtil.isEmpty(url)? new MiniMaxApi(apiKey)
@ -548,7 +581,7 @@ public class AiModelFactoryImpl implements AiModelFactory {
} }
/** /**
* 可参考 {@link QianFanAutoConfiguration} qianFanEmbeddingModel 方法 * 可参考 {@link QianFanEmbeddingAutoConfiguration} qianFanEmbeddingModel 方法
*/ */
private QianFanEmbeddingModel buildYiYanEmbeddingModel(String key, String model) { private QianFanEmbeddingModel buildYiYanEmbeddingModel(String key, String model) {
List<String> keys = StrUtil.split(key, '|'); List<String> keys = StrUtil.split(key, '|');
@ -561,13 +594,13 @@ public class AiModelFactoryImpl implements AiModelFactory {
} }
private OllamaEmbeddingModel buildOllamaEmbeddingModel(String url, String model) { private OllamaEmbeddingModel buildOllamaEmbeddingModel(String url, String model) {
OllamaApi ollamaApi = new OllamaApi(url); OllamaApi ollamaApi = OllamaApi.builder().baseUrl(url).build();
OllamaOptions ollamaOptions = OllamaOptions.builder().model(model).build(); OllamaOptions ollamaOptions = OllamaOptions.builder().model(model).build();
return OllamaEmbeddingModel.builder().ollamaApi(ollamaApi).defaultOptions(ollamaOptions).build(); return OllamaEmbeddingModel.builder().ollamaApi(ollamaApi).defaultOptions(ollamaOptions).build();
} }
/** /**
* 可参考 {@link OpenAiAutoConfiguration} openAiEmbeddingModel 方法 * 可参考 {@link OpenAiEmbeddingAutoConfiguration} openAiEmbeddingModel 方法
*/ */
private OpenAiEmbeddingModel buildOpenAiEmbeddingModel(String openAiToken, String url, String model) { private OpenAiEmbeddingModel buildOpenAiEmbeddingModel(String openAiToken, String url, String model) {
url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL); url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL);
@ -576,21 +609,19 @@ public class AiModelFactoryImpl implements AiModelFactory {
return new OpenAiEmbeddingModel(openAiApi, MetadataMode.EMBED, openAiEmbeddingProperties); return new OpenAiEmbeddingModel(openAiApi, MetadataMode.EMBED, openAiEmbeddingProperties);
} }
// TODO @芋艿手头暂时没密钥使用建议再测试下
/** /**
* 可参考 {@link AzureOpenAiAutoConfiguration} azureOpenAiEmbeddingModel 方法 * 可参考 {@link AzureOpenAiEmbeddingAutoConfiguration} azureOpenAiEmbeddingModel 方法
*/ */
private AzureOpenAiEmbeddingModel buildAzureOpenAiEmbeddingModel(String apiKey, String url, String model) { private AzureOpenAiEmbeddingModel buildAzureOpenAiEmbeddingModel(String apiKey, String url, String model) {
AzureOpenAiAutoConfiguration azureOpenAiAutoConfiguration = new AzureOpenAiAutoConfiguration(); // TODO @芋艿手头暂时没密钥使用建议再测试下
// 创建 OpenAIClient 对象 AzureOpenAiEmbeddingAutoConfiguration azureOpenAiAutoConfiguration = new AzureOpenAiEmbeddingAutoConfiguration();
AzureOpenAiConnectionProperties connectionProperties = new AzureOpenAiConnectionProperties(); // 创建 OpenAIClientBuilder 对象
connectionProperties.setApiKey(apiKey); OpenAIClientBuilder openAIClientBuilder = new OpenAIClientBuilder()
connectionProperties.setEndpoint(url); .endpoint(url).credential(new KeyCredential(apiKey));
OpenAIClientBuilder openAIClient = azureOpenAiAutoConfiguration.openAIClientBuilder(connectionProperties, null);
// 获取 AzureOpenAiChatProperties 对象 // 获取 AzureOpenAiChatProperties 对象
AzureOpenAiEmbeddingProperties embeddingProperties = SpringUtil.getBean(AzureOpenAiEmbeddingProperties.class); AzureOpenAiEmbeddingProperties embeddingProperties = SpringUtil.getBean(AzureOpenAiEmbeddingProperties.class);
return azureOpenAiAutoConfiguration.azureOpenAiEmbeddingModel(openAIClient, embeddingProperties, return azureOpenAiAutoConfiguration.azureOpenAiEmbeddingModel(openAIClientBuilder, embeddingProperties,
null, null); getObservationRegistry(), getEmbeddingModelObservationConvention());
} }
// ========== 各种创建 VectorStore 的方法 ========== // ========== 各种创建 VectorStore 的方法 ==========
@ -657,10 +688,11 @@ public class AiModelFactoryImpl implements AiModelFactory {
RedisProperties redisProperties = SpringUtils.getBean(RedisProperties.class); RedisProperties redisProperties = SpringUtils.getBean(RedisProperties.class);
JedisPooled jedisPooled = new JedisPooled(redisProperties.getHost(), redisProperties.getPort()); JedisPooled jedisPooled = new JedisPooled(redisProperties.getHost(), redisProperties.getPort());
// 创建 RedisVectorStoreProperties 对象 // 创建 RedisVectorStoreProperties 对象
// TODO @芋艿index-name 可能影响索引名
RedisVectorStoreAutoConfiguration configuration = new RedisVectorStoreAutoConfiguration(); RedisVectorStoreAutoConfiguration configuration = new RedisVectorStoreAutoConfiguration();
RedisVectorStoreProperties properties = SpringUtil.getBean(RedisVectorStoreProperties.class); RedisVectorStoreProperties properties = SpringUtil.getBean(RedisVectorStoreProperties.class);
RedisVectorStore redisVectorStore = RedisVectorStore.builder(jedisPooled, embeddingModel) RedisVectorStore redisVectorStore = RedisVectorStore.builder(jedisPooled, embeddingModel)
.indexName(properties.getIndex()).prefix(properties.getPrefix()) .indexName(properties.getIndexName()).prefix(properties.getPrefix())
.initializeSchema(properties.isInitializeSchema()) .initializeSchema(properties.isInitializeSchema())
.metadataFields(convertList(metadataFields.entrySet(), entry -> { .metadataFields(convertList(metadataFields.entrySet(), entry -> {
String fieldName = entry.getKey(); String fieldName = entry.getKey();
@ -730,10 +762,12 @@ public class AiModelFactoryImpl implements AiModelFactory {
private static ObjectProvider<VectorStoreObservationConvention> getCustomObservationConvention() { private static ObjectProvider<VectorStoreObservationConvention> getCustomObservationConvention() {
return new ObjectProvider<>() { return new ObjectProvider<>() {
@Override @Override
public VectorStoreObservationConvention getObject() throws BeansException { public VectorStoreObservationConvention getObject() throws BeansException {
return new DefaultVectorStoreObservationConvention(); return new DefaultVectorStoreObservationConvention();
} }
}; };
} }
@ -745,8 +779,15 @@ public class AiModelFactoryImpl implements AiModelFactory {
return SpringUtil.getBean(ToolCallingManager.class); return SpringUtil.getBean(ToolCallingManager.class);
} }
private static FunctionCallbackResolver getFunctionCallbackResolver() { private static ObjectProvider<EmbeddingModelObservationConvention> getEmbeddingModelObservationConvention() {
return SpringUtil.getBean(FunctionCallbackResolver.class); return new ObjectProvider<>() {
@Override
public EmbeddingModelObservationConvention getObject() throws BeansException {
return SpringUtil.getBean(EmbeddingModelObservationConvention.class);
}
};
} }
} }

View File

@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat;
import com.azure.ai.openai.OpenAIClientBuilder; import com.azure.ai.openai.OpenAIClientBuilder;
import com.azure.core.credential.AzureKeyCredential; import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.util.ClientOptions;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.ai.azure.openai.AzureOpenAiChatModel; import org.springframework.ai.azure.openai.AzureOpenAiChatModel;
@ -17,7 +16,7 @@ import reactor.core.publisher.Flux;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiChatProperties.DEFAULT_DEPLOYMENT_NAME; import static org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiChatProperties.DEFAULT_DEPLOYMENT_NAME;
/** /**
* {@link AzureOpenAiChatModel} 集成测试 * {@link AzureOpenAiChatModel} 集成测试
@ -29,10 +28,13 @@ public class AzureOpenAIChatModelTests {
// TODO @芋艿晚点在调整 // TODO @芋艿晚点在调整
private final OpenAIClientBuilder openAiApi = new OpenAIClientBuilder() private final OpenAIClientBuilder openAiApi = new OpenAIClientBuilder()
.endpoint("https://eastusprejade.openai.azure.com") .endpoint("https://eastusprejade.openai.azure.com")
.credential(new AzureKeyCredential("xxx")) .credential(new AzureKeyCredential("xxx"));
.clientOptions((new ClientOptions()).setApplicationId("spring-ai")); private final AzureOpenAiChatModel chatModel = AzureOpenAiChatModel.builder()
private final AzureOpenAiChatModel chatModel = new AzureOpenAiChatModel(openAiApi, .openAIClientBuilder(openAiApi)
AzureOpenAiChatOptions.builder().deploymentName(DEFAULT_DEPLOYMENT_NAME).build()); .defaultOptions(AzureOpenAiChatOptions.builder()
.deploymentName(DEFAULT_DEPLOYMENT_NAME)
.build())
.build();
@Test @Test
@Disabled @Disabled

View File

@ -1,7 +1,6 @@
package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat; package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat;
import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel; import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel;
import cn.iocoder.yudao.module.ai.framework.ai.core.model.deepseek.DeepSeekChatModel;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.ai.chat.messages.Message; import org.springframework.ai.chat.messages.Message;
@ -35,7 +34,7 @@ public class BaiChuanChatModelTests {
.build()) .build())
.build(); .build();
private final DeepSeekChatModel chatModel = new DeepSeekChatModel(openAiChatModel); private final BaiChuanChatModel chatModel = new BaiChuanChatModel(openAiChatModel);
@Test @Test
@Disabled @Disabled

View File

@ -2,14 +2,14 @@ package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springaicommunity.moonshot.MoonshotChatModel;
import org.springaicommunity.moonshot.MoonshotChatOptions;
import org.springaicommunity.moonshot.api.MoonshotApi;
import org.springframework.ai.chat.messages.Message; import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage; import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.moonshot.MoonshotChatModel;
import org.springframework.ai.moonshot.MoonshotChatOptions;
import org.springframework.ai.moonshot.api.MoonshotApi;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import java.util.ArrayList; import java.util.ArrayList;
@ -22,11 +22,15 @@ import java.util.List;
*/ */
public class MoonshotChatModelTests { public class MoonshotChatModelTests {
private final MoonshotChatModel chatModel = new MoonshotChatModel( private final MoonshotChatModel chatModel = MoonshotChatModel.builder()
new MoonshotApi("sk-aHYYV1SARscItye5QQRRNbXij4fy65Ee7pNZlC9gsSQnUKXA"), // 密钥 .moonshotApi(MoonshotApi.builder()
MoonshotChatOptions.builder() .apiKey("sk-aHYYV1SARscItye5QQRRNbXij4fy65Ee7pNZlC9gsSQnUKXA") // 密钥
.model("moonshot-v1-8k") // 模型 .build())
.build()); .defaultOptions(MoonshotChatOptions.builder()
.model("kimi-k2-0711-preview") // 模型
.build())
.build();
@Test @Test
@Disabled @Disabled
public void testCall() { public void testCall() {

View File

@ -31,8 +31,8 @@ public class StabilityAiImageModelTests {
public void testCall() { public void testCall() {
// 准备参数 // 准备参数
ImageOptions options = OpenAiImageOptions.builder() ImageOptions options = OpenAiImageOptions.builder()
.withModel("stable-diffusion-v1-6") .model("stable-diffusion-v1-6")
.withHeight(320).withWidth(320) .height(320).width(320)
.build(); .build();
ImagePrompt prompt = new ImagePrompt("great wall", options); ImagePrompt prompt = new ImagePrompt("great wall", options);

View File

@ -188,13 +188,14 @@ spring:
api-key: xxxx api-key: xxxx
moonshot: # 月之暗灭KIMI moonshot: # 月之暗灭KIMI
api-key: sk-abc api-key: sk-abc
deepseek: # DeepSeek
api-key: sk-e94db327cc7d457d99a8de8810fc6b12
chat:
options:
model: deepseek-chat
yudao: yudao:
ai: ai:
deep-seek: # DeepSeek
enable: true
api-key: sk-e94db327cc7d457d99a8de8810fc6b12
model: deepseek-chat
doubao: # 字节豆包 doubao: # 字节豆包
enable: true enable: true
api-key: 5c1b5747-26d2-4ebd-a4e0-dd0e8d8b4272 api-key: 5c1b5747-26d2-4ebd-a4e0-dd0e8d8b4272