diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml
index 5a10c137f9..f37f3709c6 100644
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml
@@ -14,7 +14,6 @@
${project.artifactId}
AI 大模型拓展,接入国内外大模型
- org.springframework.ai
1.0.0-M6
@@ -26,22 +25,22 @@
- ${spring-ai.groupId}
+ org.springframework.ai
spring-ai-openai-spring-boot-starter
${spring-ai.version}
- ${spring-ai.groupId}
+ org.springframework.ai
spring-ai-azure-openai-spring-boot-starter
${spring-ai.version}
- ${spring-ai.groupId}
+ org.springframework.ai
spring-ai-ollama-spring-boot-starter
${spring-ai.version}
- ${spring-ai.groupId}
+ org.springframework.ai
spring-ai-stability-ai-spring-boot-starter
${spring-ai.version}
@@ -53,28 +52,38 @@
- ${spring-ai.groupId}
+ org.springframework.ai
spring-ai-qianfan-spring-boot-starter
${spring-ai.version}
- ${spring-ai.groupId}
+ org.springframework.ai
spring-ai-zhipuai-spring-boot-starter
${spring-ai.version}
+
+ org.springframework.ai
+ spring-ai-minimax-spring-boot-starter
+ ${spring-ai.version}
+
+
+ org.springframework.ai
+ spring-ai-moonshot-spring-boot-starter
+ ${spring-ai.version}
+
- ${spring-ai.groupId}
+ org.springframework.ai
spring-ai-qdrant-store
${spring-ai.version}
- ${spring-ai.groupId}
+ org.springframework.ai
spring-ai-redis-store
${spring-ai.version}
@@ -92,7 +101,7 @@
- ${spring-ai.groupId}
+ org.springframework.ai
spring-ai-tika-document-reader
${spring-ai.version}
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java
index a154db8c88..5a8a5c4539 100644
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java
@@ -25,6 +25,8 @@ public enum AiPlatformEnum implements ArrayValuable {
DOU_BAO("DouBao", "豆包"), // 字节
HUN_YUAN("HunYuan", "混元"), // 腾讯
SILICON_FLOW("SiliconFlow", "硅基流动"), // 硅基流动
+ MINI_MAX("MiniMax", "MiniMax"), // 稀宇科技
+ MOONSHOT("Moonshot", "月之暗灭"), // KIMI
// ========== 国外平台 ==========
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java
index b588027cde..dbbbbe2241 100644
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java
@@ -36,6 +36,8 @@ import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiAutoConfigur
import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiChatProperties;
import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiConnectionProperties;
import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiEmbeddingProperties;
+import org.springframework.ai.autoconfigure.minimax.MiniMaxAutoConfiguration;
+import org.springframework.ai.autoconfigure.moonshot.MoonshotAutoConfiguration;
import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration;
import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration;
import org.springframework.ai.autoconfigure.qianfan.QianFanAutoConfiguration;
@@ -48,7 +50,6 @@ import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStore
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.autoconfigure.zhipuai.ZhiPuAiConnectionProperties;
import org.springframework.ai.azure.openai.AzureOpenAiChatModel;
import org.springframework.ai.azure.openai.AzureOpenAiEmbeddingModel;
import org.springframework.ai.chat.model.ChatModel;
@@ -56,6 +57,12 @@ import org.springframework.ai.document.MetadataMode;
import org.springframework.ai.embedding.BatchingStrategy;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.image.ImageModel;
+import org.springframework.ai.minimax.MiniMaxChatModel;
+import org.springframework.ai.minimax.MiniMaxEmbeddingModel;
+import org.springframework.ai.minimax.MiniMaxEmbeddingOptions;
+import org.springframework.ai.minimax.api.MiniMaxApi;
+import org.springframework.ai.moonshot.MoonshotChatModel;
+import org.springframework.ai.moonshot.api.MoonshotApi;
import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.ai.ollama.OllamaEmbeddingModel;
import org.springframework.ai.ollama.api.OllamaApi;
@@ -130,6 +137,10 @@ public class AiModelFactoryImpl implements AiModelFactory {
return buildSiliconFlowChatModel(apiKey);
case ZHI_PU:
return buildZhiPuChatModel(apiKey, url);
+ case MINI_MAX:
+ return buildMiniMaxChatModel(apiKey, url);
+ case MOONSHOT:
+ return buildMoonshotChatModel(apiKey, url);
case XING_HUO:
return buildXingHuoChatModel(apiKey);
case OPENAI:
@@ -162,6 +173,10 @@ public class AiModelFactoryImpl implements AiModelFactory {
return SpringUtil.getBean(SiliconFlowChatModel.class);
case ZHI_PU:
return SpringUtil.getBean(ZhiPuAiChatModel.class);
+ case MINI_MAX:
+ return SpringUtil.getBean(MiniMaxChatModel.class);
+ case MOONSHOT:
+ return SpringUtil.getBean(MoonshotChatModel.class);
case XING_HUO:
return SpringUtil.getBean(XingHuoChatModel.class);
case OPENAI:
@@ -242,6 +257,8 @@ public class AiModelFactoryImpl implements AiModelFactory {
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:
@@ -365,8 +382,8 @@ public class AiModelFactoryImpl implements AiModelFactory {
* 可参考 {@link ZhiPuAiAutoConfiguration} 的 zhiPuAiChatModel 方法
*/
private ZhiPuAiChatModel buildZhiPuChatModel(String apiKey, String url) {
- url = StrUtil.blankToDefault(url, ZhiPuAiConnectionProperties.DEFAULT_BASE_URL);
- ZhiPuAiApi zhiPuAiApi = new ZhiPuAiApi(url, apiKey);
+ ZhiPuAiApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiApi(apiKey)
+ : new ZhiPuAiApi(url, apiKey);
return new ZhiPuAiChatModel(zhiPuAiApi);
}
@@ -374,11 +391,29 @@ public class AiModelFactoryImpl implements AiModelFactory {
* 可参考 {@link ZhiPuAiAutoConfiguration} 的 zhiPuAiImageModel 方法
*/
private ZhiPuAiImageModel buildZhiPuAiImageModel(String apiKey, String url) {
- url = StrUtil.blankToDefault(url, ZhiPuAiConnectionProperties.DEFAULT_BASE_URL);
- ZhiPuAiImageApi zhiPuAiApi = new ZhiPuAiImageApi(url, apiKey, RestClient.builder());
+ ZhiPuAiImageApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiImageApi(apiKey)
+ : new ZhiPuAiImageApi(url, apiKey, RestClient.builder());
return new ZhiPuAiImageModel(zhiPuAiApi);
}
+ /**
+ * 可参考 {@link MiniMaxAutoConfiguration} 的 miniMaxChatModel 方法
+ */
+ private MiniMaxChatModel buildMiniMaxChatModel(String apiKey, String url) {
+ MiniMaxApi miniMaxApi = StrUtil.isEmpty(url) ? new MiniMaxApi(apiKey)
+ : new MiniMaxApi(url, apiKey);
+ return new MiniMaxChatModel(miniMaxApi);
+ }
+
+ /**
+ * 可参考 {@link MoonshotAutoConfiguration} 的 moonshotChatModel 方法
+ */
+ private MoonshotChatModel buildMoonshotChatModel(String apiKey, String url) {
+ MoonshotApi moonshotApi = StrUtil.isEmpty(url)? new MoonshotApi(apiKey)
+ : new MoonshotApi(url, apiKey);
+ return new MoonshotChatModel(moonshotApi);
+ }
+
/**
* 可参考 {@link YudaoAiAutoConfiguration#xingHuoChatClient(YudaoAiProperties)}
*/
@@ -454,12 +489,22 @@ public class AiModelFactoryImpl implements AiModelFactory {
* 可参考 {@link ZhiPuAiAutoConfiguration} 的 zhiPuAiEmbeddingModel 方法
*/
private ZhiPuAiEmbeddingModel buildZhiPuEmbeddingModel(String apiKey, String url, String model) {
- url = StrUtil.blankToDefault(url, ZhiPuAiConnectionProperties.DEFAULT_BASE_URL);
- ZhiPuAiApi zhiPuAiApi = new ZhiPuAiApi(url, apiKey);
+ ZhiPuAiApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiApi(apiKey)
+ : new ZhiPuAiApi(url, apiKey);
ZhiPuAiEmbeddingOptions zhiPuAiEmbeddingOptions = ZhiPuAiEmbeddingOptions.builder().model(model).build();
return new ZhiPuAiEmbeddingModel(zhiPuAiApi, MetadataMode.EMBED, zhiPuAiEmbeddingOptions);
}
+ /**
+ * 可参考 {@link MiniMaxAutoConfiguration} 的 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 QianFanAutoConfiguration} 的 qianFanEmbeddingModel 方法
*/
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/util/AiUtils.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/util/AiUtils.java
index cb968c3ffc..c3a87358cd 100644
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/util/AiUtils.java
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/util/AiUtils.java
@@ -6,6 +6,8 @@ import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
import org.springframework.ai.azure.openai.AzureOpenAiChatOptions;
import org.springframework.ai.chat.messages.*;
import org.springframework.ai.chat.prompt.ChatOptions;
+import org.springframework.ai.minimax.MiniMaxChatOptions;
+import org.springframework.ai.moonshot.MoonshotChatOptions;
import org.springframework.ai.ollama.api.OllamaOptions;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.ai.qianfan.QianFanChatOptions;
@@ -27,6 +29,10 @@ public class AiUtils {
return QianFanChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens).build();
case ZHI_PU:
return ZhiPuAiChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens).build();
+ case MINI_MAX:
+ return MiniMaxChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens).build();
+ case MOONSHOT:
+ return MoonshotChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens).build();
case OPENAI:
case DEEP_SEEK: // 复用 OpenAI 客户端
case DOU_BAO: // 复用 OpenAI 客户端
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/MiniMaxChatModelTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/MiniMaxChatModelTests.java
new file mode 100644
index 0000000000..80b60aea94
--- /dev/null
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/MiniMaxChatModelTests.java
@@ -0,0 +1,62 @@
+package cn.iocoder.yudao.framework.ai.chat;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.springframework.ai.chat.messages.Message;
+import org.springframework.ai.chat.messages.SystemMessage;
+import org.springframework.ai.chat.messages.UserMessage;
+import org.springframework.ai.chat.model.ChatResponse;
+import org.springframework.ai.chat.prompt.Prompt;
+import org.springframework.ai.minimax.MiniMaxChatModel;
+import org.springframework.ai.minimax.MiniMaxChatOptions;
+import org.springframework.ai.minimax.api.MiniMaxApi;
+import reactor.core.publisher.Flux;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * {@link MiniMaxChatModel} 的集成测试
+ *
+ * @author 芋道源码
+ */
+public class MiniMaxChatModelTests {
+
+ private final MiniMaxChatModel chatModel = new MiniMaxChatModel(
+ new MiniMaxApi("eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJHcm91cE5hbWUiOiLnjovmlofmlowiLCJVc2VyTmFtZSI6IueOi-aWh-aWjCIsIkFjY291bnQiOiIiLCJTdWJqZWN0SUQiOiIxODk3Mjg3MjQ5NDU2ODA4MzQ2IiwiUGhvbmUiOiIxNTYwMTY5MTM5OSIsIkdyb3VwSUQiOiIxODk3Mjg3MjQ5NDQ4NDE5NzM4IiwiUGFnZU5hbWUiOiIiLCJNYWlsIjoiIiwiQ3JlYXRlVGltZSI6IjIwMjUtMDMtMTEgMTI6NTI6MDIiLCJUb2tlblR5cGUiOjEsImlzcyI6Im1pbmltYXgifQ.aAuB7gWW_oA4IYhh-CF7c9MfWWxKN49B_HK-DYjXaDwwffhiG-H1571z1WQhp9QytWG-DqgLejneeSxkiq1wQIe3FsEP2wz4BmGBct31LehbJu8ehLxg_vg75Uod1nFAHbm5mZz6JSVLNIlSo87Xr3UtSzJhAXlapEkcqlA4YOzOpKrZ8l5_OJPTORTCmHWZYgJcRS-faNiH62ZnUEHUozesTFhubJHo5GfJCw_edlnmfSUocERV1BjWvenhZ9My-aYXNktcW9WaSj9l6gayV7A0Ium_PL55T9ln1PcI8gayiVUKJGJDoqNyF1AF9_aF9NOKtTnQzwNqnZdlTYH6hw"), // 密钥
+ MiniMaxChatOptions.builder()
+ .model(MiniMaxApi.ChatModel.ABAB_6_5_G_Chat.getValue()) // 模型
+ .build());
+ @Test
+ @Disabled
+ public void testCall() {
+ // 准备参数
+ List messages = new ArrayList<>();
+ messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。"));
+ messages.add(new UserMessage("1 + 1 = ?"));
+
+ // 调用
+ ChatResponse response = chatModel.call(new Prompt(messages));
+ // 打印结果
+ System.out.println(response);
+ System.out.println(response.getResult().getOutput());
+ }
+
+ @Test
+ @Disabled
+ public void testStream() {
+ // 准备参数
+ List messages = new ArrayList<>();
+ messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。"));
+ messages.add(new UserMessage("1 + 1 = ?"));
+
+ // 调用
+ Flux flux = chatModel.stream(new Prompt(messages));
+ // 打印结果
+ flux.doOnNext(response -> {
+// System.out.println(response);
+ System.out.println(response.getResult().getOutput());
+ }).then().block();
+ }
+
+}
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/MoonshotChatModelTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/MoonshotChatModelTests.java
new file mode 100644
index 0000000000..e3f644a6f7
--- /dev/null
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/MoonshotChatModelTests.java
@@ -0,0 +1,62 @@
+package cn.iocoder.yudao.framework.ai.chat;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.springframework.ai.chat.messages.Message;
+import org.springframework.ai.chat.messages.SystemMessage;
+import org.springframework.ai.chat.messages.UserMessage;
+import org.springframework.ai.chat.model.ChatResponse;
+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 java.util.ArrayList;
+import java.util.List;
+
+/**
+ * {@link org.springframework.ai.moonshot.MoonshotChatModel} 的集成测试
+ *
+ * @author 芋道源码
+ */
+public class MoonshotChatModelTests {
+
+ private final MoonshotChatModel chatModel = new MoonshotChatModel(
+ new MoonshotApi("sk-aHYYV1SARscItye5QQRRNbXij4fy65Ee7pNZlC9gsSQnUKXA"), // 密钥
+ MoonshotChatOptions.builder()
+ .model("moonshot-v1-8k") // 模型
+ .build());
+ @Test
+ @Disabled
+ public void testCall() {
+ // 准备参数
+ List messages = new ArrayList<>();
+ messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。"));
+ messages.add(new UserMessage("1 + 1 = ?"));
+
+ // 调用
+ ChatResponse response = chatModel.call(new Prompt(messages));
+ // 打印结果
+ System.out.println(response);
+ System.out.println(response.getResult().getOutput());
+ }
+
+ @Test
+ @Disabled
+ public void testStream() {
+ // 准备参数
+ List messages = new ArrayList<>();
+ messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。"));
+ messages.add(new UserMessage("1 + 1 = ?"));
+
+ // 调用
+ Flux flux = chatModel.stream(new Prompt(messages));
+ // 打印结果
+ flux.doOnNext(response -> {
+// System.out.println(response);
+ System.out.println(response.getResult().getOutput());
+ }).then().block();
+ }
+
+}
diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml
index 419fab471b..8c906e3899 100644
--- a/yudao-server/src/main/resources/application.yaml
+++ b/yudao-server/src/main/resources/application.yaml
@@ -184,6 +184,10 @@ spring:
api-key: sk-e53UqbboF8QJCscYvzJscJxJXoFcFg4iJjl1oqgE7baJETmx
dashscope: # 通义千问
api-key: sk-71800982914041848008480000000000
+ minimax: # Minimax:https://www.minimaxi.com/
+ api-key: xxxx
+ moonshot: # 月之暗灭(KIMI)
+ api-key: sk-abc
yudao:
ai: