From e118864530a7e3193f44f3cc6e7cac2df94189b7 Mon Sep 17 00:00:00 2001
From: choweli <1030848819@qq.com>
Date: Wed, 19 Mar 2025 15:31:36 +0800
Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E7=89=B9=E6=80=A7=EF=BC=9A=E6=96=B0?=
=?UTF-8?q?=E5=A2=9Ehutool-ai=E6=A8=A1=E5=9D=97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
hutool-ai/README.md | 17 +
hutool-ai/pom.xml | 54 +++
.../org/dromara/hutool/ai/AIException.java | 35 ++
.../dromara/hutool/ai/AIServiceFactory.java | 61 ++++
.../java/org/dromara/hutool/ai/AIUtil.java | 112 ++++++
.../java/org/dromara/hutool/ai/ModelName.java | 24 ++
.../java/org/dromara/hutool/ai/Models.java | 141 ++++++++
.../org/dromara/hutool/ai/core/AIConfig.java | 97 +++++
.../hutool/ai/core/AIConfigBuilder.java | 102 ++++++
.../hutool/ai/core/AIConfigRegistry.java | 29 ++
.../org/dromara/hutool/ai/core/AIService.java | 31 ++
.../hutool/ai/core/AIServiceProvider.java | 28 ++
.../dromara/hutool/ai/core/BaseAIService.java | 72 ++++
.../dromara/hutool/ai/core/BaseConfig.java | 70 ++++
.../org/dromara/hutool/ai/core/Message.java | 27 ++
.../ai/model/deepseek/DeepSeekCommon.java | 11 +
.../ai/model/deepseek/DeepSeekConfig.java | 33 ++
.../ai/model/deepseek/DeepSeekProvider.java | 24 ++
.../ai/model/deepseek/DeepSeekService.java | 37 ++
.../model/deepseek/DeepSeekServiceImpl.java | 96 +++++
.../hutool/ai/model/doubao/DoubaoCommon.java | 95 +++++
.../hutool/ai/model/doubao/DoubaoConfig.java | 33 ++
.../ai/model/doubao/DoubaoProvider.java | 23 ++
.../hutool/ai/model/doubao/DoubaoService.java | 179 +++++++++
.../ai/model/doubao/DoubaoServiceImpl.java | 341 ++++++++++++++++++
.../hutool/ai/model/grok/GrokCommon.java | 28 ++
.../hutool/ai/model/grok/GrokConfig.java | 34 ++
.../hutool/ai/model/grok/GrokProvider.java | 23 ++
.../hutool/ai/model/grok/GrokService.java | 99 +++++
.../hutool/ai/model/grok/GrokServiceImpl.java | 177 +++++++++
.../hutool/ai/model/openai/OpenaiCommon.java | 70 ++++
.../hutool/ai/model/openai/OpenaiConfig.java | 34 ++
.../ai/model/openai/OpenaiProvider.java | 24 ++
.../hutool/ai/model/openai/OpenaiService.java | 190 ++++++++++
.../ai/model/openai/OpenaiServiceImpl.java | 292 +++++++++++++++
.../org.dromara.hutool.ai.core.AIConfig | 4 +
...g.dromara.hutool.ai.core.AIServiceProvider | 4 +
.../hutool/ai/AIServiceFactoryTest.java | 25 ++
.../org/dromara/hutool/ai/AIUtilTest.java | 71 ++++
.../model/deepseek/DeepSeekServiceTest.java | 49 +++
.../ai/model/doubao/DoubaoServiceTest.java | 163 +++++++++
.../hutool/ai/model/grok/GrokServiceTest.java | 95 +++++
.../ai/model/openai/OpenaiServiceTest.java | 137 +++++++
hutool-all/pom.xml | 5 +
pom.xml | 1 +
45 files changed, 3297 insertions(+)
create mode 100644 hutool-ai/README.md
create mode 100644 hutool-ai/pom.xml
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/AIException.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/AIServiceFactory.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/AIUtil.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/ModelName.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/Models.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/core/AIConfig.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/core/AIConfigBuilder.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/core/AIConfigRegistry.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/core/AIService.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/core/AIServiceProvider.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/core/BaseAIService.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/core/BaseConfig.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/core/Message.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/model/deepseek/DeepSeekCommon.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/model/deepseek/DeepSeekConfig.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/model/deepseek/DeepSeekProvider.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/model/deepseek/DeepSeekService.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/model/deepseek/DeepSeekServiceImpl.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/model/doubao/DoubaoCommon.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/model/doubao/DoubaoConfig.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/model/doubao/DoubaoProvider.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/model/doubao/DoubaoService.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/model/doubao/DoubaoServiceImpl.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/model/grok/GrokCommon.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/model/grok/GrokConfig.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/model/grok/GrokProvider.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/model/grok/GrokService.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/model/grok/GrokServiceImpl.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/model/openai/OpenaiCommon.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/model/openai/OpenaiConfig.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/model/openai/OpenaiProvider.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/model/openai/OpenaiService.java
create mode 100644 hutool-ai/src/main/java/org/dromara/hutool/ai/model/openai/OpenaiServiceImpl.java
create mode 100644 hutool-ai/src/main/resources/META-INF/services/org.dromara.hutool.ai.core.AIConfig
create mode 100644 hutool-ai/src/main/resources/META-INF/services/org.dromara.hutool.ai.core.AIServiceProvider
create mode 100644 hutool-ai/src/test/java/org/dromara/hutool/ai/AIServiceFactoryTest.java
create mode 100644 hutool-ai/src/test/java/org/dromara/hutool/ai/AIUtilTest.java
create mode 100644 hutool-ai/src/test/java/org/dromara/hutool/ai/model/deepseek/DeepSeekServiceTest.java
create mode 100644 hutool-ai/src/test/java/org/dromara/hutool/ai/model/doubao/DoubaoServiceTest.java
create mode 100644 hutool-ai/src/test/java/org/dromara/hutool/ai/model/grok/GrokServiceTest.java
create mode 100644 hutool-ai/src/test/java/org/dromara/hutool/ai/model/openai/OpenaiServiceTest.java
diff --git a/hutool-ai/README.md b/hutool-ai/README.md
new file mode 100644
index 000000000..e78d12d28
--- /dev/null
+++ b/hutool-ai/README.md
@@ -0,0 +1,17 @@
+
+
+
+
+ 🍬Make Java Sweet Again.
+
+
+ 👉 https://hutool.cn/ 👈
+
+
+## 📚Hutool-ai 模块介绍
+
+`Hutool-ai`提供了AI大模型的封装。
+
+-------------------------------------------------------------------------------
+
+## 🛠️包含内容
\ No newline at end of file
diff --git a/hutool-ai/pom.xml b/hutool-ai/pom.xml
new file mode 100644
index 000000000..1561e6201
--- /dev/null
+++ b/hutool-ai/pom.xml
@@ -0,0 +1,54 @@
+
+
+ 4.0.0
+
+ jar
+
+
+ org.dromara.hutool
+ hutool-parent
+ 6.0.0-M21
+
+
+ hutool-ai
+ ${project.artifactId}
+ Hutool AI大模型封装
+
+
+ org.dromara.hutool.ai
+
+
+
+
+ org.dromara.hutool
+ hutool-core
+ ${project.parent.version}
+
+
+ org.dromara.hutool
+ hutool-http
+ ${project.parent.version}
+
+
+ org.dromara.hutool
+ hutool-log
+ ${project.parent.version}
+ compile
+
+
+ org.dromara.hutool
+ hutool-json
+ ${project.parent.version}
+ compile
+
+
+ org.dromara.hutool
+ hutool-swing
+ ${project.parent.version}
+ test
+
+
+
+
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/AIException.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/AIException.java
new file mode 100644
index 000000000..5dc46091c
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/AIException.java
@@ -0,0 +1,35 @@
+package org.dromara.hutool.ai;
+
+import org.dromara.hutool.core.exception.ExceptionUtil;
+import org.dromara.hutool.core.text.StrUtil;
+
+/**
+ * 异常处理类
+ */
+public class AIException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public AIException(Throwable e) {
+ super(ExceptionUtil.getMessage(e), e);
+ }
+
+ public AIException(String message) {
+ super(message);
+ }
+
+ public AIException(String messageTemplate, Object... params) {
+ super(StrUtil.format(messageTemplate, params));
+ }
+
+ public AIException(String message, Throwable throwable) {
+ super(message, throwable);
+ }
+
+ public AIException(String message, Throwable throwable, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, throwable, enableSuppression, writableStackTrace);
+ }
+
+ public AIException(Throwable throwable, String messageTemplate, Object... params) {
+ super(StrUtil.format(messageTemplate, params), throwable);
+ }
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/AIServiceFactory.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/AIServiceFactory.java
new file mode 100644
index 000000000..833f9337e
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/AIServiceFactory.java
@@ -0,0 +1,61 @@
+package org.dromara.hutool.ai;
+
+import org.dromara.hutool.ai.core.AIConfig;
+import org.dromara.hutool.ai.core.AIService;
+import org.dromara.hutool.ai.core.AIServiceProvider;
+import org.dromara.hutool.core.map.concurrent.SafeConcurrentHashMap;
+
+import java.util.Map;
+import java.util.ServiceLoader;
+
+/**
+ * 创建AIModelService的工厂类
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public class AIServiceFactory {
+
+ private static final Map providers = new SafeConcurrentHashMap<>();
+
+ // 加载所有 AIModelProvider 实现类
+ static {
+ ServiceLoader loader = ServiceLoader.load(AIServiceProvider.class);
+ for (AIServiceProvider provider : loader) {
+ providers.put(provider.getServiceName().toLowerCase(), provider);
+ }
+ }
+
+ /**
+ * 获取AI服务
+ *
+ * @param config AIConfig配置
+ * @return AI服务实例
+ * @since 6.0.0
+ */
+ public static AIService getAIService(AIConfig config) {
+ return getAIService(config, AIService.class);
+ }
+
+ /**
+ * 获取AI服务
+ *
+ * @param config AIConfig配置
+ * @param clazz AI服务类
+ * @return clazz对应的AI服务类实例
+ * @since 6.0.0
+ */
+ public static T getAIService(AIConfig config, Class clazz) {
+ AIServiceProvider provider = providers.get(config.getModelName().toLowerCase());
+ if (provider == null) {
+ throw new IllegalArgumentException("Unsupported model: " + config.getModelName());
+ }
+
+ AIService service = provider.create(config);
+ if (!clazz.isInstance(service)) {
+ throw new AIException("Model service is not of type: " + clazz.getSimpleName());
+ }
+
+ return (T) service;
+ }
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/AIUtil.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/AIUtil.java
new file mode 100644
index 000000000..73c334ca6
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/AIUtil.java
@@ -0,0 +1,112 @@
+package org.dromara.hutool.ai;
+
+import org.dromara.hutool.ai.core.AIConfig;
+import org.dromara.hutool.ai.core.AIService;
+import org.dromara.hutool.ai.core.Message;
+import org.dromara.hutool.ai.model.deepseek.DeepSeekService;
+import org.dromara.hutool.ai.model.doubao.DoubaoService;
+import org.dromara.hutool.ai.model.grok.GrokService;
+import org.dromara.hutool.ai.model.openai.OpenaiService;
+
+import java.util.List;
+
+/**
+ * AI工具类
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public class AIUtil {
+
+ /**
+ * 获取AI模型服务,每个大模型提供的功能会不一样,可以调用此方法指定不同AI服务类,调用不同的功能
+ *
+ * @param config 创建的AI服务模型的配置
+ * @param clazz AI模型服务类
+ * @return AIModelService的实现类实例
+ * @since 6.0.0
+ */
+ public static T getAIService(AIConfig config, Class clazz) {
+ return AIServiceFactory.getAIService(config, clazz);
+ }
+
+ /**
+ * 获取AI模型服务
+ *
+ * @param config 创建的AI服务模型的配置
+ * @return AIModelService 其中只有公共方法
+ * @since 6.0.0
+ */
+ public static AIService getAIService(AIConfig config) {
+ return getAIService(config, AIService.class);
+ }
+
+ /**
+ * 获取DeepSeek模型服务
+ *
+ * @param config 创建的AI服务模型的配置
+ * @return DeepSeekService
+ * @since 6.0.0
+ */
+ public static DeepSeekService getDeepSeekService(AIConfig config) {
+ return getAIService(config, DeepSeekService.class);
+ }
+
+ /**
+ * 获取Doubao模型服务
+ *
+ * @param config 创建的AI服务模型的配置
+ * @return DoubaoService
+ * @since 6.0.0
+ */
+ public static DoubaoService getDoubaoService(AIConfig config) {
+ return getAIService(config, DoubaoService.class);
+ }
+
+ /**
+ * 获取Grok模型服务
+ *
+ * @param config 创建的AI服务模型的配置
+ * @return GrokService
+ * @since 6.0.0
+ */
+ public static GrokService getGrokService(AIConfig config) {
+ return getAIService(config, GrokService.class);
+ }
+
+ /**
+ * 获取Openai模型服务
+ *
+ * @param config 创建的AI服务模型的配置
+ * @return OpenAIService
+ * @since 6.0.0
+ */
+ public static OpenaiService getOpenAIService(AIConfig config) {
+ return getAIService(config, OpenaiService.class);
+ }
+
+ /**
+ * AI大模型对话功能
+ *
+ * @param config 创建的AI服务模型的配置
+ * @param prompt 需要对话的内容
+ * @return AI模型返回的Response响应字符串
+ * @since 6.0.0
+ */
+ public static String chat(AIConfig config, String prompt) {
+ return getAIService(config).chat(prompt);
+ }
+
+ /**
+ * AI大模型对话功能
+ *
+ * @param config 创建的AI服务模型的配置
+ * @param messages 由目前为止的对话组成的消息列表,可以设置role,content。详细参考官方文档
+ * @return AI模型返回的Response响应字符串
+ * @since 6.0.0
+ */
+ public static String chat(AIConfig config, List messages) {
+ return getAIService(config).chat(messages);
+ }
+
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/ModelName.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/ModelName.java
new file mode 100644
index 000000000..4ee9ae5b1
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/ModelName.java
@@ -0,0 +1,24 @@
+package org.dromara.hutool.ai;
+
+/**
+ * 模型厂商的名称(不指具体的模型)
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public enum ModelName {
+ DEEPSEEK("deepSeek"),
+ OPENAI("openai"),
+ DOUBAO("doubao"),
+ GROK("grok");
+
+ private final String value;
+
+ ModelName(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/Models.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/Models.java
new file mode 100644
index 000000000..02db63771
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/Models.java
@@ -0,0 +1,141 @@
+package org.dromara.hutool.ai;
+
+/**
+ * 各模型厂商包含的model(指具体的模型)
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public class Models {
+
+ // DeepSeek的模型
+ public enum DeepSeek {
+ DEEPSEEK_CHAT("deepseek-chat"),
+ DEEPSEEK_REASONER("deepseek-reasoner");
+
+ private final String model;
+
+ DeepSeek(String model) {
+ this.model = model;
+ }
+
+ public String getModel() {
+ return model;
+ }
+ }
+
+ // Openai的模型
+ public enum Openai {
+ GPT_4_5_PREVIEW("gpt-4.5-preview"),
+ GPT_4O("gpt-4o"),
+ CHATGPT_4O_LATEST("chatgpt-4o-latest"),
+ GPT_4O_MINI("gpt-4o-mini"),
+ O1("o1"),
+ O1_MINI("o1-mini"),
+ O1_PREVIEW("o1-preview"),
+ O3_MINI("o3-mini"),
+ GPT_4O_REALTIME_PREVIEW("gpt-4o-realtime-preview"),
+ GPT_4O_MINI_REALTIME_PREVIEW("gpt-4o-mini-realtime-preview"),
+ GPT_4O_AUDIO_PREVIEW("gpt-4o-audio-preview"),
+ GPT_4O_MINI_AUDIO_PREVIEW("gpt-4o-mini-audio-preview"),
+ GPT_4_TURBO("gpt-4-turbo"),
+ GPT_4_TURBO_PREVIEW("gpt-4-turbo-preview"),
+ GPT_4("gpt-4"),
+ GPT_3_5_TURBO_0125("gpt-3.5-turbo-0125"),
+ GPT_3_5_TURBO("gpt-3.5-turbo"),
+ GPT_3_5_TURBO_1106("gpt-3.5-turbo-1106"),
+ GPT_3_5_TURBO_INSTRUCT("gpt-3.5-turbo-instruct"),
+ DALL_E_3("dall-e-3"),
+ DALL_E_2("dall-e-2"),
+ TTS_1("tts-1"),
+ TTS_1_HD("tts-1-hd"),
+ WHISPER_1("whisper-1"),
+ TEXT_EMBEDDING_3_LARGE("text-embedding-3-large"),
+ TEXT_EMBEDDING_3_SMALL("text-embedding-3-small"),
+ TEXT_EMBEDDING_ADA_002("text-embedding-ada-002"),
+ OMNI_MODERATION_LATEST("omni-moderation-latest"),
+ OMNI_MODERATION_2024_09_26("omni-moderation-2024-09-26"),
+ TEXT_MODERATION_LATEST("text-moderation-latest"),
+ TEXT_MODERATION_STABLE("text-moderation-stable"),
+ TEXT_MODERATION_007("text-moderation-007"),
+ BABBAGE_002("babbage-002"),
+ DAVINCI_002("davinci-002");
+
+ private final String model;
+
+ Openai(String model) {
+ this.model = model;
+ }
+
+ public String getModel() {
+ return model;
+ }
+ }
+
+ // Doubao的模型
+ public enum Doubao {
+ DOUBAO_1_5_PRO_32K("doubao-1.5-pro-32k-250115"),
+ DOUBAO_1_5_PRO_256K("doubao-1.5-pro-256k-250115"),
+ DOUBAO_1_5_LITE_32K("doubao-1.5-lite-32k-250115"),
+ DEEPSEEK_R1("deepseek-r1-250120"),
+ DEEPSEEK_R1_DISTILL_QWEN_32B("deepseek-r1-distill-qwen-32b-250120"),
+ DEEPSEEK_R1_DISTILL_QWEN_7B("deepseek-r1-distill-qwen-7b-250120"),
+ DEEPSEEK_V3("deepseek-v3-241226"),
+ DOUBAO_PRO_4K_240515("doubao-pro-4k-240515"),
+ DOUBAO_PRO_4K_CHARACTER_240728("doubao-pro-4k-character-240728"),
+ DOUBAO_PRO_4K_FUNCTIONCALL_240615("doubao-pro-4k-functioncall-240615"),
+ DOUBAO_PRO_4K_BROWSING_240524("doubao-pro-4k-browsing-240524"),
+ DOUBAO_PRO_32K_241215("doubao-pro-32k-241215"),
+ DOUBAO_PRO_32K_FUNCTIONCALL_241028("doubao-pro-32k-functioncall-241028"),
+ DOUBAO_PRO_32K_BROWSING_241115("doubao-pro-32k-browsing-241115"),
+ DOUBAO_PRO_32K_CHARACTER_241215("doubao-pro-32k-character-241215"),
+ DOUBAO_PRO_128K_240628("doubao-pro-128k-240628"),
+ DOUBAO_PRO_256K_240828("doubao-pro-256k-240828"),
+ DOUBAO_LITE_4K_240328("doubao-lite-4k-240328"),
+ DOUBAO_LITE_4K_PRETRAIN_CHARACTER_240516("doubao-lite-4k-pretrain-character-240516"),
+ DOUBAO_LITE_32K_240828("doubao-lite-32k-240828"),
+ DOUBAO_LITE_32K_CHARACTER_241015("doubao-lite-32k-character-241015"),
+ DOUBAO_LITE_128K_240828("240828"),
+ MOONSHOT_V1_8K("moonshot-v1-8k"),
+ MOONSHOT_V1_32K("moonshot-v1-32k"),
+ MOONSHOT_V1_128K("moonshot-v1-128k"),
+ CHATGLM3_130B_FC("chatglm3-130b-fc-v1.0"),
+ CHATGLM3_130_FIN("chatglm3-130-fin-v1.0-update"),
+ MISTRAL_7B("mistral-7b-instruct-v0.2"),
+ DOUBAO_1_5_VISION_PRO_32K("doubao-1.5-vision-pro-32k-250115"),
+ DOUBAO_VISION_PRO_32K("doubao-vision-pro-32k-241008"),
+ DOUBAO_VISION_LITE_32K("doubao-vision-lite-32k-241015"),
+ DOUBAO_EMBEDDING_LARGE("doubao-embedding-large-text-240915"),
+ DOUBAO_EMBEDDING_TEXT_240715("doubao-embedding-text-240715"),
+ DOUBAO_EMBEDDING_VISION("doubao-embedding-vision-241215");
+
+ private final String model;
+
+ Doubao(String model) {
+ this.model = model;
+ }
+
+ public String getModel() {
+ return model;
+ }
+ }
+
+ // Grok的模型
+ public enum Grok {
+ GROK_2_1212("grok-2-1212"),
+ GROK_2_VISION_1212("grok-2-vision-1212"),
+ GROK_BETA("grok-beta"),
+ GROK_VISION_BETA("grok-vision-beta");
+
+ private final String model;
+
+ Grok(String model) {
+ this.model = model;
+ }
+
+ public String getModel() {
+ return model;
+ }
+ }
+
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/core/AIConfig.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/core/AIConfig.java
new file mode 100644
index 000000000..0a4b2822f
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/core/AIConfig.java
@@ -0,0 +1,97 @@
+package org.dromara.hutool.ai.core;
+
+import java.util.Map;
+
+/**
+ * AI配置类
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public interface AIConfig {
+
+ /**
+ * 获取模型(厂商)名称
+ *
+ * @return 模型(厂商)名称
+ * @since 6.0.0
+ */
+ default String getModelName() {
+ return this.getClass().getSimpleName();
+ }
+
+ /**
+ * 设置apiKey
+ *
+ * @param apiKey apiKey
+ * @since 6.0.0
+ */
+ void setApiKey(String apiKey);
+
+ /**
+ * 获取apiKey
+ *
+ * @return apiKey
+ * @since 6.0.0
+ */
+ String getApiKey();
+
+ /**
+ * 设置apiUrl
+ *
+ * @param apiUrl api请求地址
+ * @since 6.0.0
+ */
+ void setApiUrl(String apiUrl);
+
+ /**
+ * 获取apiUrl
+ *
+ * @return apiUrl
+ * @since 6.0.0
+ */
+ String getApiUrl();
+
+ /**
+ * 设置model
+ *
+ * @param model model
+ * @since 6.0.0
+ */
+ void setModel(String model);
+
+ /**
+ * 返回model
+ *
+ * @return model
+ * @since 6.0.0
+ */
+ String getModel();
+
+ /**
+ * 设置动态参数
+ *
+ * @param key 参数字段
+ * @param value 参数值
+ * @since 6.0.0
+ */
+ void putAdditionalConfigByKey(String key, Object value);
+
+ /**
+ * 获取动态参数
+ *
+ * @param key 参数字段
+ * @return 参数值
+ * @since 6.0.0
+ */
+ Object getAdditionalConfigByKey(String key);
+
+ /**
+ * 获取动态参数列表
+ *
+ * @return 参数列表Map
+ * @since 6.0.0
+ */
+ Map getAdditionalConfigMap();
+
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/core/AIConfigBuilder.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/core/AIConfigBuilder.java
new file mode 100644
index 000000000..a4f19d878
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/core/AIConfigBuilder.java
@@ -0,0 +1,102 @@
+package org.dromara.hutool.ai.core;
+
+import java.lang.reflect.Constructor;
+
+/**
+ * 用于AIConfig的创建,创建同时支持链式设置参数
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public class AIConfigBuilder {
+
+ private final AIConfig config;
+
+ /**
+ * 构造
+ *
+ * @param modelName 模型厂商的名称(注意不是指具体的模型)
+ */
+ public AIConfigBuilder(String modelName) {
+ try {
+ // 获取配置类
+ Class extends AIConfig> configClass = AIConfigRegistry.getConfigClass(modelName);
+ if (configClass == null) {
+ throw new IllegalArgumentException("Unsupported model: " + modelName);
+ }
+
+ // 使用反射创建实例
+ Constructor extends AIConfig> constructor = configClass.getDeclaredConstructor();
+ config = constructor.newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to create AIConfig instance", e);
+ }
+ }
+
+ /**
+ * 设置apiKey
+ *
+ * @param apiKey apiKey
+ * @return config
+ * @since 6.0.0
+ */
+ public synchronized AIConfigBuilder setApiKey(String apiKey) {
+ if (apiKey != null) {
+ config.setApiKey(apiKey);
+ }
+ return this;
+ }
+
+ /**
+ * 设置AI模型请求API接口的地址,不设置为默认值
+ *
+ * @param apiUrl API接口地址
+ * @return config
+ * @since 6.0.0
+ */
+ public synchronized AIConfigBuilder setApiUrl(String apiUrl) {
+ if (apiUrl != null) {
+ config.setApiUrl(apiUrl);
+ }
+ return this;
+ }
+
+ /**
+ * 设置具体的model,不设置为默认值
+ *
+ * @param model 具体model的名称
+ * @return config
+ * @since 6.0.0
+ */
+ public synchronized AIConfigBuilder setModel(String model) {
+ if (model != null) {
+ config.setModel(model);
+ }
+ return this;
+ }
+
+ /**
+ * 动态设置Request请求体中的属性字段,每个模型功能支持的字段请参照对应的官方文档
+ *
+ * @param key Request中的支持的属性名
+ * @param value 设置的属性值
+ * @return config
+ * @since 6.0.0
+ */
+ public AIConfigBuilder putAdditionalConfig(String key, Object value) {
+ if (value != null) {
+ config.putAdditionalConfigByKey(key, value);
+ }
+ return this;
+ }
+
+ /**
+ * 返回config实例
+ *
+ * @return config
+ * @since 6.0.0
+ */
+ public AIConfig build() {
+ return config;
+ }
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/core/AIConfigRegistry.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/core/AIConfigRegistry.java
new file mode 100644
index 000000000..81c1d377a
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/core/AIConfigRegistry.java
@@ -0,0 +1,29 @@
+package org.dromara.hutool.ai.core;
+
+import org.dromara.hutool.core.map.concurrent.SafeConcurrentHashMap;
+
+import java.util.Map;
+import java.util.ServiceLoader;
+
+/**
+ * AIConfig实现类的加载器
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public class AIConfigRegistry {
+
+ private static final Map> configClasses = new SafeConcurrentHashMap<>();
+
+ // 加载所有 AIConfig 实现类
+ static {
+ ServiceLoader loader = ServiceLoader.load(AIConfig.class);
+ for (AIConfig config : loader) {
+ configClasses.put(config.getModelName().toLowerCase(), config.getClass());
+ }
+ }
+
+ public static Class extends AIConfig> getConfigClass(String modelName) {
+ return configClasses.get(modelName.toLowerCase());
+ }
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/core/AIService.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/core/AIService.java
new file mode 100644
index 000000000..256cefdbf
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/core/AIService.java
@@ -0,0 +1,31 @@
+package org.dromara.hutool.ai.core;
+
+import java.util.List;
+
+/**
+ * 模型公共的API功能,特有的功能在model.xx.XXService下定义
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public interface AIService {
+
+ /**
+ * 对话
+ *
+ * @param prompt user题词
+ * @return AI回答
+ * @since 6.0.0
+ */
+ String chat(String prompt);
+
+ /**
+ * 对话
+ *
+ * @param messages 由目前为止的对话组成的消息列表,可以设置role,content。详细参考官方文档
+ * @return AI回答
+ * @since 6.0.0
+ */
+ String chat(List messages);
+
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/core/AIServiceProvider.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/core/AIServiceProvider.java
new file mode 100644
index 000000000..5ff6d2f2e
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/core/AIServiceProvider.java
@@ -0,0 +1,28 @@
+package org.dromara.hutool.ai.core;
+
+/**
+ * 用于加载AI服务,每一个通过SPI创建的AI服务都要实现此接口
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public interface AIServiceProvider {
+
+ /**
+ * 获取AI服务名称
+ *
+ * @return AI服务名称
+ * @since 6.0.0
+ */
+ String getServiceName();
+
+ /**
+ * 创建AI服务实例
+ *
+ * @param config AIConfig配置
+ * @param AIService类型
+ * @return AI服务实例
+ * @since 6.0.0
+ */
+ T create(AIConfig config);
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/core/BaseAIService.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/core/BaseAIService.java
new file mode 100644
index 000000000..18d457295
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/core/BaseAIService.java
@@ -0,0 +1,72 @@
+package org.dromara.hutool.ai.core;
+
+import org.dromara.hutool.ai.AIException;
+import org.dromara.hutool.http.HttpGlobalConfig;
+import org.dromara.hutool.http.HttpUtil;
+import org.dromara.hutool.http.client.Response;
+import org.dromara.hutool.http.meta.HeaderName;
+import org.dromara.hutool.http.meta.Method;
+
+import java.util.Map;
+
+/**
+ * 基础AIService,包含基公共参数和公共方法
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public class BaseAIService {
+
+ protected final AIConfig config;
+
+ public BaseAIService(AIConfig config) {
+ this.config = config;
+ }
+
+ protected Response sendGet(String endpoint) {
+ //链式构建请求
+ try {
+ //设置超时
+ HttpGlobalConfig.setTimeout(3000);
+ return HttpUtil.createRequest(config.getApiUrl() + endpoint, Method.GET)
+ .header(HeaderName.ACCEPT, "application/json")
+ .header(HeaderName.AUTHORIZATION, "Bearer " + config.getApiKey())
+ .send();
+ } catch (AIException e) {
+ throw new AIException("Failed to send GET request: " + e.getMessage(), e);
+ }
+ }
+
+ protected Response sendPost(String endpoint, String paramJson) {
+ //链式构建请求
+ try {
+ //设置超时
+ HttpGlobalConfig.setTimeout(3000);
+ return HttpUtil.createRequest(config.getApiUrl() + endpoint, Method.POST)
+ .header(HeaderName.CONTENT_TYPE, "application/json")
+ .header(HeaderName.ACCEPT, "application/json")
+ .header(HeaderName.AUTHORIZATION, "Bearer " + config.getApiKey())
+ .body(paramJson)
+ .send();
+ } catch (AIException e) {
+ throw new AIException("Failed to send POST request:" + e.getMessage(), e);
+ }
+
+ }
+
+ protected Response sendFormData(String endpoint, Map paramMap) {
+ //链式构建请求
+ try {
+ //设置超时
+ HttpGlobalConfig.setTimeout(3000);
+ return HttpUtil.createPost(config.getApiUrl() + endpoint)
+ //form表单中有file对象会自动将文件编码为 multipart/form-data 格式。不需要设置
+// .header(HeaderName.CONTENT_TYPE, "multipart/form-data")
+ .header(HeaderName.AUTHORIZATION, "Bearer " + config.getApiKey())
+ .form(paramMap)
+ .send();
+ } catch (AIException e) {
+ throw new AIException("Failed to send POST request:" + e.getMessage(), e);
+ }
+ }
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/core/BaseConfig.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/core/BaseConfig.java
new file mode 100644
index 000000000..a5ef36deb
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/core/BaseConfig.java
@@ -0,0 +1,70 @@
+package org.dromara.hutool.ai.core;
+
+
+import org.dromara.hutool.core.map.concurrent.SafeConcurrentHashMap;
+
+import java.util.Map;
+
+/**
+ * Config基础类,定义模型配置的基本属性
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public class BaseConfig implements AIConfig {
+
+ //apiKey
+ protected volatile String apiKey;
+ //API请求地址
+ protected volatile String apiUrl;
+ //具体模型
+ protected volatile String model;
+ //动态扩展字段
+ protected Map additionalConfig = new SafeConcurrentHashMap<>();
+
+ @Override
+ public void setApiKey(String apiKey) {
+ this.apiKey = apiKey;
+ }
+
+ @Override
+ public String getApiKey() {
+ return apiKey;
+ }
+
+ @Override
+ public void setApiUrl(String apiUrl) {
+ this.apiUrl = apiUrl;
+ }
+
+ @Override
+ public String getApiUrl() {
+ return apiUrl;
+ }
+
+ @Override
+ public void setModel(String model) {
+ this.model = model;
+ }
+
+ @Override
+ public String getModel() {
+ return model;
+ }
+
+ @Override
+ public void putAdditionalConfigByKey(String key, Object value) {
+ this.additionalConfig.put(key, value);
+ }
+
+ @Override
+ public Object getAdditionalConfigByKey(String key) {
+ return additionalConfig.get(key);
+ }
+
+ @Override
+ public Map getAdditionalConfigMap() {
+ return new SafeConcurrentHashMap<>(additionalConfig);
+ }
+
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/core/Message.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/core/Message.java
new file mode 100644
index 000000000..b5dce74a1
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/core/Message.java
@@ -0,0 +1,27 @@
+package org.dromara.hutool.ai.core;
+
+/**
+ * 公共Message类
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public class Message {
+ //角色 注意:如果设置系统消息,请放在messages列表的第一位
+ private final String role;
+ //内容
+ private final Object content;
+
+ public Message(String role, Object content) {
+ this.role = role;
+ this.content = content;
+ }
+
+ public String getRole() {
+ return role;
+ }
+
+ public Object getContent() {
+ return content;
+ }
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/model/deepseek/DeepSeekCommon.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/model/deepseek/DeepSeekCommon.java
new file mode 100644
index 000000000..a3aaee27e
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/model/deepseek/DeepSeekCommon.java
@@ -0,0 +1,11 @@
+package org.dromara.hutool.ai.model.deepseek;
+
+/**
+ * deepSeek公共类
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public class DeepSeekCommon {
+
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/model/deepseek/DeepSeekConfig.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/model/deepseek/DeepSeekConfig.java
new file mode 100644
index 000000000..66a15aed1
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/model/deepseek/DeepSeekConfig.java
@@ -0,0 +1,33 @@
+package org.dromara.hutool.ai.model.deepseek;
+
+import org.dromara.hutool.ai.Models;
+import org.dromara.hutool.ai.core.BaseConfig;
+
+/**
+ * DeepSeek配置类,初始化API接口地址,设置默认的模型
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public class DeepSeekConfig extends BaseConfig {
+
+ private final String API_URL = "https://api.deepseek.com";
+
+ private final String DEFAULT_MODEL = Models.DeepSeek.DEEPSEEK_CHAT.getModel();
+
+ public DeepSeekConfig() {
+ setApiUrl(API_URL);
+ setModel(DEFAULT_MODEL);
+ }
+
+ public DeepSeekConfig(String apiKey) {
+ this();
+ setApiKey(apiKey);
+ }
+
+ @Override
+ public String getModelName() {
+ return "deepSeek";
+ }
+
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/model/deepseek/DeepSeekProvider.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/model/deepseek/DeepSeekProvider.java
new file mode 100644
index 000000000..126790f4e
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/model/deepseek/DeepSeekProvider.java
@@ -0,0 +1,24 @@
+package org.dromara.hutool.ai.model.deepseek;
+
+
+import org.dromara.hutool.ai.core.AIConfig;
+import org.dromara.hutool.ai.core.AIServiceProvider;
+
+/**
+ * 创建DeepSeek服务实现类
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public class DeepSeekProvider implements AIServiceProvider {
+
+ @Override
+ public String getServiceName() {
+ return "deepSeek";
+ }
+
+ @Override
+ public DeepSeekService create(AIConfig config) {
+ return new DeepSeekServiceImpl(config);
+ }
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/model/deepseek/DeepSeekService.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/model/deepseek/DeepSeekService.java
new file mode 100644
index 000000000..da893e266
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/model/deepseek/DeepSeekService.java
@@ -0,0 +1,37 @@
+package org.dromara.hutool.ai.model.deepseek;
+
+import org.dromara.hutool.ai.core.AIService;
+
+/**
+ * deepSeek支持的扩展接口
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public interface DeepSeekService extends AIService {
+
+ /**
+ * 模型beta功能
+ *
+ * @param prompt 题词
+ * @return AI的回答
+ * @since 6.0.0
+ */
+ String beta(String prompt);
+
+ /**
+ * 列出所有模型列表
+ *
+ * @return model列表
+ * @since 6.0.0
+ */
+ String models();
+
+ /**
+ * 查询余额
+ *
+ * @return 余额
+ * @since 6.0.0
+ */
+ String balance();
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/model/deepseek/DeepSeekServiceImpl.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/model/deepseek/DeepSeekServiceImpl.java
new file mode 100644
index 000000000..d01ee33e3
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/model/deepseek/DeepSeekServiceImpl.java
@@ -0,0 +1,96 @@
+package org.dromara.hutool.ai.model.deepseek;
+
+import org.dromara.hutool.ai.core.AIConfig;
+import org.dromara.hutool.ai.core.BaseAIService;
+import org.dromara.hutool.ai.core.Message;
+import org.dromara.hutool.http.client.Response;
+import org.dromara.hutool.json.JSONUtil;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * DeepSeek服务,AI具体功能的实现
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public class DeepSeekServiceImpl extends BaseAIService implements DeepSeekService {
+
+ //对话补全
+ private final String CHAT_ENDPOINT = "/chat/completions";
+ //FIM补全(beta)
+ private final String BETA_ENDPOINT = "/beta/completions";
+ //列出模型
+ private final String MODELS_ENDPOINT = "/models";
+ //余额查询
+ private final String BALANCE_ENDPOINT = "/user/balance";
+
+ public DeepSeekServiceImpl(AIConfig config) {
+ //初始化DeepSeek客户端
+ super(config);
+ }
+
+ @Override
+ public String chat(String prompt) {
+ // 定义消息结构
+ List messages = new ArrayList<>();
+ messages.add(new Message("system", "You are a helpful assistant"));
+ messages.add(new Message("user", prompt));
+ return chat(messages);
+ }
+
+ @Override
+ public String chat(List messages) {
+ String paramJson = buildChatRequestBody(messages);
+ Response response = sendPost(CHAT_ENDPOINT, paramJson);
+ return response.bodyStr();
+ }
+
+ @Override
+ public String beta(String prompt) {
+ String paramJson = buildBetaRequestBody(prompt);
+ Response response = sendPost(BETA_ENDPOINT, paramJson);
+ return response.bodyStr();
+ }
+
+ @Override
+ public String models() {
+ Response response = sendGet(MODELS_ENDPOINT);
+ return response.bodyStr();
+ }
+
+ @Override
+ public String balance() {
+ Response response = sendGet(BALANCE_ENDPOINT);
+ return response.bodyStr();
+ }
+
+ // 构建chat请求体
+ private String buildChatRequestBody(List messages) {
+ //使用JSON工具
+ Map paramMap = new HashMap<>();
+ paramMap.put("model", config.getModel());
+ paramMap.put("messages", messages);
+ //合并其他参数
+ paramMap.putAll(config.getAdditionalConfigMap());
+
+ return JSONUtil.toJsonStr(paramMap);
+ }
+
+ // 构建beta请求体
+ private String buildBetaRequestBody(String prompt) {
+ // 定义消息结构
+ //使用JSON工具
+ Map paramMap = new HashMap<>();
+ paramMap.put("model", config.getModel());
+ paramMap.put("prompt", prompt);
+// //合并其他参数
+ paramMap.putAll(config.getAdditionalConfigMap());
+
+ return JSONUtil.toJsonStr(paramMap);
+ }
+
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/model/doubao/DoubaoCommon.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/model/doubao/DoubaoCommon.java
new file mode 100644
index 000000000..fe471a44f
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/model/doubao/DoubaoCommon.java
@@ -0,0 +1,95 @@
+package org.dromara.hutool.ai.model.doubao;
+
+/**
+ * doubao公共类
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public class DoubaoCommon {
+
+ //doubao上下文缓存参数
+ public enum DoubaoContext {
+
+ SESSION("session"),
+ COMMON_PREFIX("common_prefix");
+
+ private final String mode;
+
+ DoubaoContext(String mode) {
+ this.mode = mode;
+ }
+
+ public String getMode() {
+ return mode;
+ }
+ }
+
+ //豆包视觉参数
+ public enum DoubaoVision {
+
+ AUTO("auto"),
+ LOW("low"),
+ HIGH("high");
+
+ private final String detail;
+
+ DoubaoVision(String detail) {
+ this.detail = detail;
+ }
+
+ public String getDetail() {
+ return detail;
+ }
+ }
+
+ //doubao视频生成参数
+ public enum DoubaoVideo {
+
+ //宽高比例
+ RATIO_16_9("--rt", "16:9"),//[1280, 720]
+ RATIO_4_3("--rt", "4:3"),//[960, 720]
+ RATIO_1_1("--rt", "1:1"),//[720, 720]
+ RATIO_3_4("--rt", "3:4"),//[720, 960]
+ RATIO_9_16("--rt", "9:16"),//[720, 1280]
+ RATIO_21_9("--rt", "21:9"),//[1280, 544]
+
+ //生成视频时长
+ DURATION_5("--dur", 5),//文生视频,图生视频
+ DURATION_10("--dur", 10),//文生视频
+
+ //帧率,即一秒时间内视频画面数量
+ FPS_5("--fps", 24),
+
+ //视频分辨率
+ RESOLUTION_5("--rs", "720p"),
+
+ //生成视频是否包含水印
+ WATERMARK_TRUE("--wm", true),
+ WATERMARK_FALSE("--wm", false);
+
+ private final String type;
+ private final Object value;
+
+ DoubaoVideo(String type, Object value) {
+ this.type = type;
+ this.value = value;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public Object getValue() {
+ if (value instanceof String) {
+ return (String) value;
+ } else if (value instanceof Integer) {
+ return (Integer) value;
+ } else if (value instanceof Boolean) {
+ return (Boolean) value;
+ }
+ return value;
+ }
+
+ }
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/model/doubao/DoubaoConfig.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/model/doubao/DoubaoConfig.java
new file mode 100644
index 000000000..ee3786696
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/model/doubao/DoubaoConfig.java
@@ -0,0 +1,33 @@
+package org.dromara.hutool.ai.model.doubao;
+
+import org.dromara.hutool.ai.Models;
+import org.dromara.hutool.ai.core.BaseConfig;
+
+/**
+ * Doubao配置类,初始化API接口地址,设置默认的模型
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public class DoubaoConfig extends BaseConfig {
+
+ private final String API_URL = "https://ark.cn-beijing.volces.com/api/v3";
+
+ private final String DEFAULT_MODEL = Models.Doubao.DOUBAO_1_5_LITE_32K.getModel();
+
+ public DoubaoConfig() {
+ setApiUrl(API_URL);
+ setModel(DEFAULT_MODEL);
+ }
+
+ public DoubaoConfig(String apiKey) {
+ this();
+ setApiKey(apiKey);
+ }
+
+ @Override
+ public String getModelName() {
+ return "doubao";
+ }
+
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/model/doubao/DoubaoProvider.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/model/doubao/DoubaoProvider.java
new file mode 100644
index 000000000..050fde6ca
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/model/doubao/DoubaoProvider.java
@@ -0,0 +1,23 @@
+package org.dromara.hutool.ai.model.doubao;
+
+import org.dromara.hutool.ai.core.AIConfig;
+import org.dromara.hutool.ai.core.AIServiceProvider;
+
+/**
+ * 创建Doubap服务实现类
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public class DoubaoProvider implements AIServiceProvider {
+
+ @Override
+ public String getServiceName() {
+ return "doubao";
+ }
+
+ @Override
+ public DoubaoService create(AIConfig config) {
+ return new DoubaoServiceImpl(config);
+ }
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/model/doubao/DoubaoService.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/model/doubao/DoubaoService.java
new file mode 100644
index 000000000..8f5b36959
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/model/doubao/DoubaoService.java
@@ -0,0 +1,179 @@
+package org.dromara.hutool.ai.model.doubao;
+
+import org.dromara.hutool.ai.core.AIService;
+import org.dromara.hutool.ai.core.Message;
+
+import java.util.List;
+
+/**
+ * doubao支持的扩展接口
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public interface DoubaoService extends AIService {
+
+ /**
+ * 图像理解:模型会依据传入的图片信息以及问题,给出回复。
+ *
+ * @param prompt 提问
+ * @param images 图片列表/或者图片Base64编码图片列表(URI形式)
+ * @param detail 手动设置图片的质量,取值范围high、low、auto,默认为auto
+ * @return AI回答
+ * @since 6.0.0
+ */
+ String chatVision(String prompt, List images, String detail);
+
+ /**
+ * 图像理解:模型会依据传入的图片信息以及问题,给出回复。
+ *
+ * @param prompt 提问
+ * @param images 传入的图片列表地址/或者图片Base64编码图片列表(URI形式)
+ * @return AI回答
+ * @since 6.0.0
+ */
+ default String chatVision(String prompt, List images) {
+ return chatVision(prompt, images, DoubaoCommon.DoubaoVision.AUTO.getDetail());
+ }
+
+ /**
+ * 创建视频生成任务
+ * 注意:调用该方法时,配置config中的model为您创建的推理接入点(Endpoint)ID。详细参考官方文档
+ *
+ * @param text 文本提示词
+ * @param image 图片/或者图片Base64编码图片(URI形式)
+ * @param videoParams 视频参数列表
+ * @return 生成任务id
+ * @since 6.0.0
+ */
+ String videoTasks(String text, String image, List videoParams);
+
+ /**
+ * 创建视频生成任务
+ * 注意:调用该方法时,配置config中的model为您创建的推理接入点(Endpoint)ID。详细参考官方文档
+ *
+ * @param text 文本提示词
+ * @param image 图片/或者图片Base64编码图片(URI形式)
+ * @return 生成任务id
+ * @since 6.0.0
+ */
+ default String videoTasks(String text, String image) {
+ return videoTasks(text, image, null);
+ }
+
+ /**
+ * 查询视频生成任务信息
+ *
+ * @param taskId 通过创建生成视频任务返回的生成任务id
+ * @return 生成任务信息
+ * @since 6.0.0
+ */
+ String getVideoTasksInfo(String taskId);
+
+ /**
+ * 文本向量化
+ *
+ * @param input 需要向量化的内容列表,支持中文、英文
+ * @return 处理后的向量信息
+ * @since 6.0.0
+ */
+ String embeddingText(String[] input);
+
+ /**
+ * 图文向量化:仅支持单一文本、单张图片或文本与图片的组合输入(即一段文本 + 一张图片),暂不支持批量文本 / 图片的同时处理
+ *
+ * @param text 需要向量化的内容
+ * @param image 需要向量化的图片地址/或者图片Base64编码图片(URI形式)
+ * @return 处理后的向量信息
+ * @since 6.0.0
+ */
+ String embeddingVision(String text, String image);
+
+ /**
+ * 应用(Bot) config中model设置为您创建的应用ID
+ *
+ * @param messages 由对话组成的消息列表。如系统人设,背景信息等,用户自定义的信息
+ * @return AI回答
+ * @since 6.0.0
+ */
+ String botsChat(List messages);
+
+ /**
+ * 分词:可以将文本转换为模型可理解的 token id,并返回文本的 tokens 数量、token id、 token 在原始文本中的偏移量等信息
+ *
+ * @param text 需要分词的内容列表
+ * @return 分词结果
+ * @since 6.0.0
+ */
+ String tokenization(String[] text);
+
+ /**
+ * 批量推理 Chat
+ * 注意:调用该方法时,配置config中的model为您创建的批量推理接入点(Endpoint)ID。详细参考官方文档
+ * 该方法不支持流式
+ *
+ * @param prompt chat内容
+ * @return AI回答
+ * @since 6.0.0
+ */
+ String batchChat(String prompt);
+
+ /**
+ * 批量推理 Chat
+ * 注意:调用该方法时,配置config中的model为您创建的批量推理接入点(Endpoint)ID。详细参考官方文档
+ * 该方法不支持流式
+ *
+ * @param messages 由对话组成的消息列表。如系统人设,背景信息等,用户自定义的信息
+ * @return AI回答
+ * @since 6.0.0
+ */
+ String batchChat(List messages);
+
+ /**
+ * 创建上下文缓存: 创建上下文缓存,获得缓存 id字段后,在上下文缓存对话 API中使用。
+ * 注意:调用该方法时,配置config中的model为您创建的推理接入点(Endpoint)ID,
+ * 推理接入点中使用的模型需要在模型管理中开启缓存功能。详细参考官方文档
+ *
+ * @param messages 由对话组成的消息列表。如系统人设,背景信息等,用户自定义的信息
+ * @param mode 上下文缓存的类型,详细参考官方文档 默认为session
+ * @return 返回的缓存id
+ * @since 6.0.0
+ */
+ String createContext(List messages, String mode);
+
+ /**
+ * 创建上下文缓存: 创建上下文缓存,获得缓存 id字段后,在上下文缓存对话 API中使用。
+ * 注意:调用该方法时,配置config中的model为您创建的推理接入点(Endpoint)ID,
+ * 推理接入点中使用的模型需要在模型管理中开启缓存功能。详细参考官方文档
+ *
+ * @param messages 由对话组成的消息列表。如系统人设,背景信息等,用户自定义的信息
+ * @return 返回的缓存id
+ * @since 6.0.0
+ */
+ default String createContext(List messages) {
+ return createContext(messages, DoubaoCommon.DoubaoContext.SESSION.getMode());
+ }
+
+ /**
+ * 上下文缓存对话: 向大模型发起带上下文缓存的请求
+ * 注意:配置config中的model可以为您创建的推理接入点(Endpoint)ID,也可以是支持chat的model
+ *
+ * @param prompt 对话的内容题词
+ * @param contextId 创建上下文缓存后获取的缓存id
+ * @return AI的回答
+ * @since 6.0.0
+ */
+ String chatContext(String prompt, String contextId);
+
+ /**
+ * 上下文缓存对话: 向大模型发起带上下文缓存的请求
+ * 注意:配置config中的model可以为您创建的推理接入点(Endpoint)ID,也可以是支持chat的model
+ *
+ * @param messages 对话的信息 不支持最后一个元素的role设置为assistant。如使用session 缓存(mode设置为session)传入最新一轮对话的信息,无需传入历史信息
+ * @param contextId 创建上下文缓存后获取的缓存id
+ * @return AI的回答
+ * @since 6.0.0
+ */
+ String chatContext(List messages, String contextId);
+
+}
diff --git a/hutool-ai/src/main/java/org/dromara/hutool/ai/model/doubao/DoubaoServiceImpl.java b/hutool-ai/src/main/java/org/dromara/hutool/ai/model/doubao/DoubaoServiceImpl.java
new file mode 100644
index 000000000..5a897becb
--- /dev/null
+++ b/hutool-ai/src/main/java/org/dromara/hutool/ai/model/doubao/DoubaoServiceImpl.java
@@ -0,0 +1,341 @@
+package org.dromara.hutool.ai.model.doubao;
+
+import org.dromara.hutool.ai.core.AIConfig;
+import org.dromara.hutool.ai.core.BaseAIService;
+import org.dromara.hutool.ai.core.Message;
+import org.dromara.hutool.core.text.StrUtil;
+import org.dromara.hutool.http.client.Response;
+import org.dromara.hutool.json.JSONUtil;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Doubao服务,AI具体功能的实现
+ *
+ * @author elichow
+ * @since 6.0.0
+ */
+public class DoubaoServiceImpl extends BaseAIService implements DoubaoService {
+
+ //对话
+ private final String CHAT_ENDPOINT = "/chat/completions";
+ //文本向量化
+ private final String EMBEDDING_TEXT = "/embeddings";
+ //图文向量化
+ private final String EMBEDDING_VISION = "/embeddings/multimodal";
+ //应用bots
+ private final String BOTS_CHAT = "/bots/chat/completions";
+ //分词
+ private final String TOKENIZATION = "/tokenization";
+ //批量推理chat
+ private final String BATCH_CHAT = "/batch/chat/completions";
+ //创建上下文缓存
+ private final String CREATE_CONTEXT = "/context/create";
+ //上下文缓存对话
+ private final String CHAT_CONTEXT = "/context/chat/completions";
+ //创建视频生成任务
+ private final String CREATE_VIDEO = "/contents/generations/tasks";
+
+ public DoubaoServiceImpl(AIConfig config) {
+ //初始化doubao客户端
+ super(config);
+ }
+
+ @Override
+ public String chat(String prompt) {
+ // 定义消息结构
+ List messages = new ArrayList<>();
+ messages.add(new Message("system", "You are a helpful assistant"));
+ messages.add(new Message("user", prompt));
+ return chat(messages);
+ }
+
+ @Override
+ public String chat(List messages) {
+ String paramJson = buildChatRequestBody(messages);
+ Response response = sendPost(CHAT_ENDPOINT, paramJson);
+ return response.bodyStr();
+ }
+
+ @Override
+ public String chatVision(String prompt, List images, String detail) {
+ String paramJson = buildChatVisionRequestBody(prompt, images, detail);
+ Response response = sendPost(CHAT_ENDPOINT, paramJson);
+ return response.bodyStr();
+ }
+
+ @Override
+ public String videoTasks(String text, String image, List videoParams) {
+ String paramJson = buildGenerationsTasksRequestBody(text, image, videoParams);
+ Response response = sendPost(CREATE_VIDEO, paramJson);
+ return response.bodyStr();
+ }
+
+ @Override
+ public String getVideoTasksInfo(String taskId) {
+ Response response = sendGet(CREATE_VIDEO + "/" + taskId);
+ return response.bodyStr();
+ }
+
+
+ @Override
+ public String embeddingText(String[] input) {
+ String paramJson = buildEmbeddingTextRequestBody(input);
+ Response response = sendPost(EMBEDDING_TEXT, paramJson);
+ return response.bodyStr();
+ }
+
+ @Override
+ public String embeddingVision(String text, String image) {
+ String paramJson = buildEmbeddingVisionRequestBody(text, image);
+ Response response = sendPost(EMBEDDING_VISION, paramJson);
+ return response.bodyStr();
+ }
+
+ @Override
+ public String botsChat(List messages) {
+ String paramJson = buildBotsChatRequestBody(messages);
+ System.out.println(paramJson);
+ Response response = sendPost(BOTS_CHAT, paramJson);
+ return response.bodyStr();
+ }
+
+ @Override
+ public String tokenization(String[] text) {
+ String paramJson = buildTokenizationRequestBody(text);
+ Response response = sendPost(TOKENIZATION, paramJson);
+ return response.bodyStr();
+ }
+
+ @Override
+ public String batchChat(String prompt) {
+ // 定义消息结构
+ List messages = new ArrayList<>();
+ messages.add(new Message("system", "You are a helpful assistant"));
+ messages.add(new Message("user", prompt));
+ return batchChat(messages);
+ }
+
+ @Override
+ public String batchChat(List messages) {
+ String paramJson = buildBatchChatRequestBody(messages);
+ System.out.println(paramJson);
+ Response response = sendPost(BATCH_CHAT, paramJson);
+ return response.bodyStr();
+ }
+
+ @Override
+ public String createContext(List messages, String mode) {
+ String paramJson = buildCreateContextRequest(messages, mode);
+ System.out.println(paramJson);
+ Response response = sendPost(CREATE_CONTEXT, paramJson);
+ return response.bodyStr();
+ }
+
+ @Override
+ public String chatContext(String prompt, String contextId) {
+ // 定义消息结构
+ List messages = new ArrayList<>();
+ messages.add(new Message("user", prompt));
+ return chatContext(messages, contextId);
+ }
+
+ @Override
+ public String chatContext(List messages, String contextId) {
+ String paramJson = buildChatContentRequestBody(messages, contextId);
+ Response response = sendPost(CHAT_CONTEXT, paramJson);
+ return response.bodyStr();
+ }
+
+ // 构建chat请求体
+ private String buildChatRequestBody(List messages) {
+ //使用JSON工具
+ Map paramMap = new HashMap<>();
+ paramMap.put("model", config.getModel());
+ paramMap.put("messages", messages);
+ //合并其他参数
+ paramMap.putAll(config.getAdditionalConfigMap());
+
+ return JSONUtil.toJsonStr(paramMap);
+ }
+
+ //构建chatVision请求体
+ private String buildChatVisionRequestBody(String prompt, List images, String detail) {
+ // 定义消息结构
+ List messages = new ArrayList<>();
+ List