diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml
index 32ff741f9..cfd9ee9f8 100644
--- a/yudao-dependencies/pom.xml
+++ b/yudao-dependencies/pom.xml
@@ -75,7 +75,6 @@
1.6.6-beta2
2.12.2
4.6.0
- 2.2.9
0.8.0
diff --git a/yudao-module-ai/pom.xml b/yudao-module-ai/pom.xml
index 04244f21e..f2ce4fe30 100644
--- a/yudao-module-ai/pom.xml
+++ b/yudao-module-ai/pom.xml
@@ -2,28 +2,26 @@
- 4.0.0
cn.iocoder.boot
yudao
${revision}
- pom
- yudao-module-ai
-
+ 4.0.0
yudao-module-ai-api
yudao-module-ai-biz
yudao-spring-boot-starter-ai
+ pom
+ yudao-module-ai
-
- 17
- 17
- UTF-8
-
-
-
-
+ ${project.artifactId}
+
+ ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维脑图等功能。
+ 目前已接入各种模型,不限于:
+ 国内:通义千问、文心一言、讯飞星火
+ 国外:OpenAI、Ollama、Midjourney、StableDiffusion、Suno
+
\ No newline at end of file
diff --git a/yudao-module-ai/yudao-module-ai-api/pom.xml b/yudao-module-ai/yudao-module-ai-api/pom.xml
index ce9c41527..41fe56efc 100644
--- a/yudao-module-ai/yudao-module-ai-api/pom.xml
+++ b/yudao-module-ai/yudao-module-ai-api/pom.xml
@@ -2,32 +2,26 @@
- 4.0.0
cn.iocoder.boot
yudao-module-ai
${revision}
-
+ 4.0.0
yudao-module-ai-api
+ jar
-
- 17
- 17
- UTF-8
-
+ ${project.artifactId}
+
+ ai 模块 API,暴露给其它模块调用
+
-
cn.iocoder.boot
yudao-common
-
-
- org.projectlombok
- lombok
-
+
org.springframework.boot
diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java
index 5a3e290a3..183079d0c 100644
--- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java
+++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java
@@ -12,6 +12,9 @@ public interface ErrorCodeConstants {
// ========== API 密钥 1-040-000-000 ==========
ErrorCode API_KEY_NOT_EXISTS = new ErrorCode(1_040_000_000, "API 密钥不存在");
ErrorCode API_KEY_DISABLE = new ErrorCode(1_040_000_001, "API 密钥已禁用!");
+ ErrorCode API_KEY_MIDJOURNEY_NOT_FOUND = new ErrorCode(1_040_000_900, "Midjourney 模型不存在");
+ ErrorCode API_KEY_SUNO_NOT_FOUND = new ErrorCode(1_040_000_901, "Suno 模型不存在");
+ ErrorCode API_KEY_IMAGE_NODE_FOUND = new ErrorCode(1_040_000_902, "平台({}) 图片模型未配置");
// ========== API 聊天模型 1-040-001-000 ==========
ErrorCode CHAT_MODEL_NOT_EXISTS = new ErrorCode(1_040_001_000, "模型不存在!");
diff --git a/yudao-module-ai/yudao-module-ai-biz/pom.xml b/yudao-module-ai/yudao-module-ai-biz/pom.xml
index 3eb23d57f..f0c73246d 100644
--- a/yudao-module-ai/yudao-module-ai-biz/pom.xml
+++ b/yudao-module-ai/yudao-module-ai-biz/pom.xml
@@ -2,21 +2,21 @@
- 4.0.0
cn.iocoder.boot
yudao-module-ai
${revision}
-
+ 4.0.0
yudao-module-ai-biz
-
- 8
- 8
- UTF-8
-
-
+ ${project.artifactId}
+
+ ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维脑图等功能。
+ 目前已接入各种模型,不限于:
+ 国内:通义千问、文心一言、讯飞星火
+ 国外:OpenAI、Ollama、Midjourney、StableDiffusion、Suno
+
@@ -24,44 +24,36 @@
yudao-module-ai-api
${revision}
+
+
cn.iocoder.boot
yudao-spring-boot-starter-ai
${revision}
-
-
- cn.iocoder.boot
- yudao-common
-
+
+
cn.iocoder.boot
yudao-spring-boot-starter-security
+
+
cn.iocoder.boot
yudao-spring-boot-starter-mybatis
-
-
- cn.iocoder.boot
- yudao-spring-boot-starter-test
-
+
+
cn.iocoder.boot
yudao-spring-boot-starter-job
+
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-test
+
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
-
- 17
- 17
-
-
-
-
\ No newline at end of file
diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePageReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePageReqVO.java
index 57dea8fbc..bdf329c61 100644
--- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePageReqVO.java
+++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePageReqVO.java
@@ -13,8 +13,6 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@Schema(description = "管理后台 - AI 绘画分页 Request VO")
@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
public class AiImagePageReqVO extends PageParam {
@Schema(description = "用户编号", example = "28987")
diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyImagineReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyImagineReqVO.java
index 5f9d12445..b90882639 100644
--- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyImagineReqVO.java
+++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyImagineReqVO.java
@@ -5,8 +5,6 @@ import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
-import java.util.List;
-
@Schema(description = "管理后台 - AI 绘画生成(Midjourney) Request VO")
@Data
public class AiMidjourneyImagineReqVO {
@@ -31,7 +29,7 @@ public class AiMidjourneyImagineReqVO {
@NotEmpty(message = "版本号不能为空")
private String version;
- @Schema(description = "参考图")
+ @Schema(description = "参考图", example = "https://www.iocoder.cn/x.png")
private String referImageUrl;
}
diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyPageReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyPageReqVO.java
index 021e0f80c..063696244 100644
--- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyPageReqVO.java
+++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyPageReqVO.java
@@ -11,8 +11,6 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@Schema(description = "管理后台 - AI API 密钥分页 Request VO")
@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
public class AiApiKeyPageReqVO extends PageParam {
@Schema(description = "名称", example = "文心一言")
diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatModel/AiChatModelPageReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatModel/AiChatModelPageReqVO.java
index 0971522eb..ce2f83b4b 100644
--- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatModel/AiChatModelPageReqVO.java
+++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatModel/AiChatModelPageReqVO.java
@@ -6,8 +6,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam;
@Schema(description = "管理后台 - API 聊天模型分页 Request VO")
@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
public class AiChatModelPageReqVO extends PageParam {
@Schema(description = "模型名字", example = "张三")
diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRolePageReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRolePageReqVO.java
index 237c83463..0a9d08de5 100644
--- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRolePageReqVO.java
+++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRolePageReqVO.java
@@ -6,8 +6,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam;
@Schema(description = "管理后台 - AI 聊天角色分页 Request VO")
@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
public class AiChatRolePageReqVO extends PageParam {
@Schema(description = "角色名称", example = "李四")
diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicPageReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicPageReqVO.java
index f68e25702..678edae3d 100644
--- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicPageReqVO.java
+++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicPageReqVO.java
@@ -16,8 +16,6 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@Schema(description = "管理后台 - AI 音乐分页 Request VO")
@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
public class AiMusicPageReqVO extends PageParam {
@Schema(description = "用户编号", example = "12212")
diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java
index 6f5e9ac67..948d75c68 100644
--- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java
+++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java
@@ -35,7 +35,6 @@ import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -192,10 +191,8 @@ public class AiImageServiceImpl implements AiImageService {
imageMapper.insert(image);
// 2. 调用 Midjourney Proxy 提交任务
- List base64Array = new ArrayList<>(8);
- if (StrUtil.isNotBlank(reqVO.getReferImageUrl())) {
- base64Array.add("data:image/jpeg;base64,".concat(Base64.encode(HttpUtil.downloadBytes(reqVO.getReferImageUrl()))));
- }
+ List base64Array = StrUtil.isBlank(reqVO.getReferImageUrl()) ? null :
+ Collections.singletonList("data:image/jpeg;base64,".concat(Base64.encode(HttpUtil.downloadBytes(reqVO.getReferImageUrl()))));
MidjourneyApi.ImagineRequest imagineRequest = new MidjourneyApi.ImagineRequest(
base64Array, reqVO.getPrompt(),null,
MidjourneyApi.ImagineRequest.buildState(reqVO.getWidth(),
diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java
index f68527e93..1ef235068 100644
--- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java
+++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java
@@ -108,7 +108,7 @@ public class AiApiKeyServiceImpl implements AiApiKeyService {
public ImageModel getImageClient(AiPlatformEnum platform) {
AiApiKeyDO apiKey = apiKeyMapper.selectFirstByPlatformAndStatus(platform.getName(), CommonStatusEnum.ENABLE.getStatus());
if (apiKey == null) {
- return null;
+ throw exception(API_KEY_IMAGE_NODE_FOUND, platform.getName());
}
return clientFactory.getOrCreateImageClient(platform, apiKey.getApiKey(), apiKey.getUrl());
}
@@ -117,9 +117,8 @@ public class AiApiKeyServiceImpl implements AiApiKeyService {
public MidjourneyApi getMidjourneyApi() {
AiApiKeyDO apiKey = apiKeyMapper.selectFirstByPlatformAndStatus(
AiPlatformEnum.MIDJOURNEY.getPlatform(), CommonStatusEnum.ENABLE.getStatus());
- // todo @芋艿 这些地方直接抛异常会好点,不然调用到的地方都需要做判断
if (apiKey == null) {
- return null;
+ throw exception(API_KEY_MIDJOURNEY_NOT_FOUND);
}
return clientFactory.getOrCreateMidjourneyApi(apiKey.getApiKey(), apiKey.getUrl());
}
@@ -129,7 +128,7 @@ public class AiApiKeyServiceImpl implements AiApiKeyService {
AiApiKeyDO apiKey = apiKeyMapper.selectFirstByPlatformAndStatus(
AiPlatformEnum.SUNO.getPlatform(), CommonStatusEnum.ENABLE.getStatus());
if (apiKey == null) {
- return null;
+ throw exception(API_KEY_SUNO_NOT_FOUND);
}
return clientFactory.getOrCreateSunoApi(apiKey.getApiKey(), apiKey.getUrl());
}
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 c83a6669e..fff4dc052 100644
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml
@@ -8,8 +8,9 @@
${revision}
4.0.0
-
yudao-spring-boot-starter-ai
+ jar
+
${project.artifactId}
AI 大模型拓展,接入国内外大模型
@@ -58,6 +59,7 @@
2.14.0
+
junit
junit
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/package-info.java
deleted file mode 100644
index f0149323c..000000000
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/package-info.java
+++ /dev/null
@@ -1,10 +0,0 @@
-/**
- * model 包,接入各种大模型,对标 https://github.com/spring-projects/spring-ai/tree/main/models
- *
- * 1. yiyan 包:【百度】文心一言
- * 2. tongyi 包:【阿里】通义千问,对标 spring-cloud-alibaba 提供的 ai 包 TODO 芋艿:未来直接使用它
- * 3. xinghuo 包:【讯飞】星火,自己实现
- * 4. midjourney 包:Midjourney,接入 https://github.com/novicezk/midjourney-proxy 实现
- * 5. suno 包:TODO 芋艿:
- */
-package cn.iocoder.yudao.framework.ai.core.model;
\ No newline at end of file
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/package-info.java
deleted file mode 100644
index b728517d0..000000000
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 芋道 AI Starter,整体参考 spring-ai 拓展
- */
-package cn.iocoder.yudao.framework.ai.core;
\ No newline at end of file
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java
index a132fdfc5..60e492ed7 100644
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java
@@ -6,10 +6,8 @@
* 包路径:
* 1. chat、parser、model、parser 包:https://github.com/spring-projects/spring-ai/tree/main/spring-ai-core 拷贝
* 2. models 包:对标 https://github.com/spring-projects/spring-ai/tree/main/models 拷贝
- * 2.1 tongyi 包:【阿里】通义千问,对标 spring-cloud-alibaba 提供的 ai 包
- * 2.2 yiyan 包:【百度】文心一言,自己实现
- * 2.3 xinghuo 包:【讯飞】星火,自己实现
- * 2.4 openai 包:【OpenAI】ChatGPT,拷贝 spring-ai 提供的 models/openai 包
- * 2.5 midjourney 包:Midjourney,参考 https://github.com/novicezk/midjourney-proxy 实现
+ * 2.1 xinghuo 包:【讯飞】星火,自己实现
+ * 2.2 midjourney 包:Midjourney API,对接 https://github.com/novicezk/midjourney-proxy 实现
+ * 2.3 suno 包:Suno API,对接 https://github.com/gcui-art/suno-api 实现
*/
package cn.iocoder.yudao.framework.ai;
\ No newline at end of file