Commit 89d079349c987eaa1065883433cd0e2ab6fc5bfe

Authored by YunaiV
1 parent 3f460dc6

【代码重构】AI:“聊天模型”重构为“模型”,支持 type 模型类型

Showing 36 changed files with 617 additions and 554 deletions
yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java
@@ -12,31 +12,25 @@ public interface ErrorCodeConstants { @@ -12,31 +12,25 @@ public interface ErrorCodeConstants {
12 // ========== API 密钥 1-040-000-000 ========== 12 // ========== API 密钥 1-040-000-000 ==========
13 ErrorCode API_KEY_NOT_EXISTS = new ErrorCode(1_040_000_000, "API 密钥不存在"); 13 ErrorCode API_KEY_NOT_EXISTS = new ErrorCode(1_040_000_000, "API 密钥不存在");
14 ErrorCode API_KEY_DISABLE = new ErrorCode(1_040_000_001, "API 密钥已禁用!"); 14 ErrorCode API_KEY_DISABLE = new ErrorCode(1_040_000_001, "API 密钥已禁用!");
15 - ErrorCode API_KEY_MIDJOURNEY_NOT_FOUND = new ErrorCode(1_040_000_900, "Midjourney 模型不存在");  
16 - ErrorCode API_KEY_SUNO_NOT_FOUND = new ErrorCode(1_040_000_901, "Suno 模型不存在");  
17 - ErrorCode API_KEY_IMAGE_NODE_FOUND = new ErrorCode(1_040_000_902, "平台({}) 图片模型未配置");  
18 15
19 - // ========== API 聊天模型 1-040-001-000 ==========  
20 - ErrorCode CHAT_MODEL_NOT_EXISTS = new ErrorCode(1_040_001_000, "模型不存在!");  
21 - ErrorCode CHAT_MODEL_DISABLE = new ErrorCode(1_040_001_001, "模型({})已禁用!");  
22 - ErrorCode CHAT_MODEL_DEFAULT_NOT_EXISTS = new ErrorCode(1_040_001_002, "操作失败,找不到默认聊天模型"); 16 + // ========== API 模型 1-040-001-000 ==========
  17 + ErrorCode MODEL_NOT_EXISTS = new ErrorCode(1_040_001_000, "模型不存在!");
  18 + ErrorCode MODEL_DISABLE = new ErrorCode(1_040_001_001, "模型({})已禁用!");
  19 + ErrorCode MODEL_DEFAULT_NOT_EXISTS = new ErrorCode(1_040_001_002, "操作失败,找不到默认模型");
23 20
24 // ========== API 聊天角色 1-040-002-000 ========== 21 // ========== API 聊天角色 1-040-002-000 ==========
25 ErrorCode CHAT_ROLE_NOT_EXISTS = new ErrorCode(1_040_002_000, "聊天角色不存在"); 22 ErrorCode CHAT_ROLE_NOT_EXISTS = new ErrorCode(1_040_002_000, "聊天角色不存在");
26 ErrorCode CHAT_ROLE_DISABLE = new ErrorCode(1_040_001_001, "聊天角色({})已禁用!"); 23 ErrorCode CHAT_ROLE_DISABLE = new ErrorCode(1_040_001_001, "聊天角色({})已禁用!");
27 24
28 // ========== API 聊天会话 1-040-003-000 ========== 25 // ========== API 聊天会话 1-040-003-000 ==========
29 -  
30 ErrorCode CHAT_CONVERSATION_NOT_EXISTS = new ErrorCode(1_040_003_000, "对话不存在!"); 26 ErrorCode CHAT_CONVERSATION_NOT_EXISTS = new ErrorCode(1_040_003_000, "对话不存在!");
31 ErrorCode CHAT_CONVERSATION_MODEL_ERROR = new ErrorCode(1_040_003_001, "操作失败,该聊天模型的配置不完整"); 27 ErrorCode CHAT_CONVERSATION_MODEL_ERROR = new ErrorCode(1_040_003_001, "操作失败,该聊天模型的配置不完整");
32 28
33 // ========== API 聊天消息 1-040-004-000 ========== 29 // ========== API 聊天消息 1-040-004-000 ==========
34 -  
35 ErrorCode CHAT_MESSAGE_NOT_EXIST = new ErrorCode(1_040_004_000, "消息不存在!"); 30 ErrorCode CHAT_MESSAGE_NOT_EXIST = new ErrorCode(1_040_004_000, "消息不存在!");
36 ErrorCode CHAT_STREAM_ERROR = new ErrorCode(1_040_004_001, "对话生成异常!"); 31 ErrorCode CHAT_STREAM_ERROR = new ErrorCode(1_040_004_001, "对话生成异常!");
37 32
38 // ========== API 绘画 1-040-005-000 ========== 33 // ========== API 绘画 1-040-005-000 ==========
39 -  
40 ErrorCode IMAGE_NOT_EXISTS = new ErrorCode(1_022_005_000, "图片不存在!"); 34 ErrorCode IMAGE_NOT_EXISTS = new ErrorCode(1_022_005_000, "图片不存在!");
41 ErrorCode IMAGE_MIDJOURNEY_SUBMIT_FAIL = new ErrorCode(1_022_005_001, "Midjourney 提交失败!原因:{}"); 35 ErrorCode IMAGE_MIDJOURNEY_SUBMIT_FAIL = new ErrorCode(1_022_005_001, "Midjourney 提交失败!原因:{}");
42 ErrorCode IMAGE_CUSTOM_ID_NOT_EXISTS = new ErrorCode(1_022_005_002, "Midjourney 按钮 customId 不存在! {}"); 36 ErrorCode IMAGE_CUSTOM_ID_NOT_EXISTS = new ErrorCode(1_022_005_002, "Midjourney 按钮 customId 不存在! {}");
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java
1 package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation; 1 package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation;
2 2
3 -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; 3 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
4 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; 4 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
5 import com.fhs.core.trans.anno.Trans; 5 import com.fhs.core.trans.anno.Trans;
6 import com.fhs.core.trans.constant.TransType; 6 import com.fhs.core.trans.constant.TransType;
@@ -31,7 +31,7 @@ public class AiChatConversationRespVO implements VO { @@ -31,7 +31,7 @@ public class AiChatConversationRespVO implements VO {
31 private Long roleId; 31 private Long roleId;
32 32
33 @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 33 @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
34 - @Trans(type = TransType.SIMPLE, target = AiChatModelDO.class, fields = "name", ref = "modelName") 34 + @Trans(type = TransType.SIMPLE, target = AiModelDO.class, fields = "name", ref = "modelName")
35 private Long modelId; 35 private Long modelId;
36 36
37 @Schema(description = "模型标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "ERNIE-Bot-turbo-0922") 37 @Schema(description = "模型标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "ERNIE-Bot-turbo-0922")
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDrawReqVO.java
@@ -14,18 +14,15 @@ import java.util.Map; @@ -14,18 +14,15 @@ import java.util.Map;
14 @Data 14 @Data
15 public class AiImageDrawReqVO { 15 public class AiImageDrawReqVO {
16 16
17 - @Schema(description = "模型平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI")  
18 - private String platform; // 参见 AiPlatformEnum 枚举 17 + @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  18 + @NotNull(message = "模型编号不能为空")
  19 + private Long modelId;
19 20
20 @Schema(description = "提示词", requiredMode = Schema.RequiredMode.REQUIRED, example = "画一个长城") 21 @Schema(description = "提示词", requiredMode = Schema.RequiredMode.REQUIRED, example = "画一个长城")
21 @NotEmpty(message = "提示词不能为空") 22 @NotEmpty(message = "提示词不能为空")
22 @Size(max = 1200, message = "提示词最大 1200") 23 @Size(max = 1200, message = "提示词最大 1200")
23 private String prompt; 24 private String prompt;
24 25
25 - @Schema(description = "模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "stable-diffusion-v1-6")  
26 - @NotEmpty(message = "模型不能为空")  
27 - private String model;  
28 -  
29 /** 26 /**
30 * 1. dall-e-2 模型:256x256、512x512、1024x1024 27 * 1. dall-e-2 模型:256x256、512x512、1024x1024
31 * 2. dall-e-3 模型:1024x1024, 1792x1024, 或 1024x1792 28 * 2. dall-e-3 模型:1024x1024, 1792x1024, 或 1024x1792
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiApiKeyController.java
@@ -6,9 +6,8 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -6,9 +6,8 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageReqVO; 6 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageReqVO;
7 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyRespVO; 7 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyRespVO;
8 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveReqVO; 8 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveReqVO;
9 -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelRespVO; 9 +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiModelRespVO;
10 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; 10 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO;
11 -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO;  
12 import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; 11 import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService;
13 import io.swagger.v3.oas.annotations.Operation; 12 import io.swagger.v3.oas.annotations.Operation;
14 import io.swagger.v3.oas.annotations.Parameter; 13 import io.swagger.v3.oas.annotations.Parameter;
@@ -76,9 +75,9 @@ public class AiApiKeyController { @@ -76,9 +75,9 @@ public class AiApiKeyController {
76 75
77 @GetMapping("/simple-list") 76 @GetMapping("/simple-list")
78 @Operation(summary = "获得 API 密钥分页列表") 77 @Operation(summary = "获得 API 密钥分页列表")
79 - public CommonResult<List<AiChatModelRespVO>> getApiKeySimpleList() { 78 + public CommonResult<List<AiModelRespVO>> getApiKeySimpleList() {
80 List<AiApiKeyDO> list = apiKeyService.getApiKeyList(); 79 List<AiApiKeyDO> list = apiKeyService.getApiKeyList();
81 - return success(convertList(list, key -> new AiChatModelRespVO().setId(key.getId()).setName(key.getName()))); 80 + return success(convertList(list, key -> new AiModelRespVO().setId(key.getId()).setName(key.getName())));
82 } 81 }
83 82
84 } 83 }
85 \ No newline at end of file 84 \ No newline at end of file
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java deleted
1 -package cn.iocoder.yudao.module.ai.controller.admin.model;  
2 -  
3 -import cn.iocoder.yudao.framework.common.pojo.CommonResult;  
4 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
5 -import cn.iocoder.yudao.framework.common.util.object.BeanUtils;  
6 -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelPageReqVO;  
7 -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelRespVO;  
8 -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelSaveReqVO;  
9 -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO;  
10 -import cn.iocoder.yudao.module.ai.service.model.AiChatModelService;  
11 -import io.swagger.v3.oas.annotations.Operation;  
12 -import io.swagger.v3.oas.annotations.Parameter;  
13 -import io.swagger.v3.oas.annotations.tags.Tag;  
14 -import jakarta.annotation.Resource;  
15 -import jakarta.validation.Valid;  
16 -import org.springframework.security.access.prepost.PreAuthorize;  
17 -import org.springframework.validation.annotation.Validated;  
18 -import org.springframework.web.bind.annotation.*;  
19 -  
20 -import java.util.List;  
21 -  
22 -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;  
23 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;  
24 -  
25 -@Tag(name = "管理后台 - AI 聊天模型")  
26 -@RestController  
27 -@RequestMapping("/ai/chat-model")  
28 -@Validated  
29 -public class AiChatModelController {  
30 -  
31 - @Resource  
32 - private AiChatModelService chatModelService;  
33 -  
34 - @PostMapping("/create")  
35 - @Operation(summary = "创建聊天模型")  
36 - @PreAuthorize("@ss.hasPermission('ai:chat-model:create')")  
37 - public CommonResult<Long> createChatModel(@Valid @RequestBody AiChatModelSaveReqVO createReqVO) {  
38 - return success(chatModelService.createChatModel(createReqVO));  
39 - }  
40 -  
41 - @PutMapping("/update")  
42 - @Operation(summary = "更新聊天模型")  
43 - @PreAuthorize("@ss.hasPermission('ai:chat-model:update')")  
44 - public CommonResult<Boolean> updateChatModel(@Valid @RequestBody AiChatModelSaveReqVO updateReqVO) {  
45 - chatModelService.updateChatModel(updateReqVO);  
46 - return success(true);  
47 - }  
48 -  
49 - @DeleteMapping("/delete")  
50 - @Operation(summary = "删除聊天模型")  
51 - @Parameter(name = "id", description = "编号", required = true)  
52 - @PreAuthorize("@ss.hasPermission('ai:chat-model:delete')")  
53 - public CommonResult<Boolean> deleteChatModel(@RequestParam("id") Long id) {  
54 - chatModelService.deleteChatModel(id);  
55 - return success(true);  
56 - }  
57 -  
58 - @GetMapping("/get")  
59 - @Operation(summary = "获得聊天模型")  
60 - @Parameter(name = "id", description = "编号", required = true, example = "1024")  
61 - @PreAuthorize("@ss.hasPermission('ai:chat-model:query')")  
62 - public CommonResult<AiChatModelRespVO> getChatModel(@RequestParam("id") Long id) {  
63 - AiChatModelDO chatModel = chatModelService.getChatModel(id);  
64 - return success(BeanUtils.toBean(chatModel, AiChatModelRespVO.class));  
65 - }  
66 -  
67 - @GetMapping("/page")  
68 - @Operation(summary = "获得聊天模型分页")  
69 - @PreAuthorize("@ss.hasPermission('ai:chat-model:query')")  
70 - public CommonResult<PageResult<AiChatModelRespVO>> getChatModelPage(@Valid AiChatModelPageReqVO pageReqVO) {  
71 - PageResult<AiChatModelDO> pageResult = chatModelService.getChatModelPage(pageReqVO);  
72 - return success(BeanUtils.toBean(pageResult, AiChatModelRespVO.class));  
73 - }  
74 -  
75 - @GetMapping("/simple-list")  
76 - @Operation(summary = "获得聊天模型列表")  
77 - @Parameter(name = "status", description = "状态", required = true, example = "1")  
78 - public CommonResult<List<AiChatModelRespVO>> getChatModelSimpleList(@RequestParam("status") Integer status) {  
79 - List<AiChatModelDO> list = chatModelService.getChatModelListByStatus(status);  
80 - return success(convertList(list, model -> new AiChatModelRespVO().setId(model.getId())  
81 - .setName(model.getName()).setModel(model.getModel())));  
82 - }  
83 -  
84 -}  
85 \ No newline at end of file 0 \ No newline at end of file
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiModelController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.ai.controller.admin.model;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  4 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  7 +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiModelPageReqVO;
  8 +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiModelRespVO;
  9 +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiModelSaveReqVO;
  10 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
  11 +import cn.iocoder.yudao.module.ai.service.model.AiModelService;
  12 +import io.swagger.v3.oas.annotations.Operation;
  13 +import io.swagger.v3.oas.annotations.Parameter;
  14 +import io.swagger.v3.oas.annotations.tags.Tag;
  15 +import jakarta.annotation.Resource;
  16 +import jakarta.validation.Valid;
  17 +import org.springframework.security.access.prepost.PreAuthorize;
  18 +import org.springframework.validation.annotation.Validated;
  19 +import org.springframework.web.bind.annotation.*;
  20 +
  21 +import java.util.List;
  22 +
  23 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  24 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
  25 +
  26 +@Tag(name = "管理后台 - AI 模型")
  27 +@RestController
  28 +@RequestMapping("/ai/model")
  29 +@Validated
  30 +public class AiModelController {
  31 +
  32 + @Resource
  33 + private AiModelService modelService;
  34 +
  35 + @PostMapping("/create")
  36 + @Operation(summary = "创建模型")
  37 + @PreAuthorize("@ss.hasPermission('ai:model:create')")
  38 + public CommonResult<Long> createModel(@Valid @RequestBody AiModelSaveReqVO createReqVO) {
  39 + return success(modelService.createModel(createReqVO));
  40 + }
  41 +
  42 + @PutMapping("/update")
  43 + @Operation(summary = "更新模型")
  44 + @PreAuthorize("@ss.hasPermission('ai:model:update')")
  45 + public CommonResult<Boolean> updateModel(@Valid @RequestBody AiModelSaveReqVO updateReqVO) {
  46 + modelService.updateModel(updateReqVO);
  47 + return success(true);
  48 + }
  49 +
  50 + @DeleteMapping("/delete")
  51 + @Operation(summary = "删除模型")
  52 + @Parameter(name = "id", description = "编号", required = true)
  53 + @PreAuthorize("@ss.hasPermission('ai:model:delete')")
  54 + public CommonResult<Boolean> deleteModel(@RequestParam("id") Long id) {
  55 + modelService.deleteModel(id);
  56 + return success(true);
  57 + }
  58 +
  59 + @GetMapping("/get")
  60 + @Operation(summary = "获得模型")
  61 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  62 + @PreAuthorize("@ss.hasPermission('ai:model:query')")
  63 + public CommonResult<AiModelRespVO> getModel(@RequestParam("id") Long id) {
  64 + AiModelDO model = modelService.getModel(id);
  65 + return success(BeanUtils.toBean(model, AiModelRespVO.class));
  66 + }
  67 +
  68 + @GetMapping("/page")
  69 + @Operation(summary = "获得模型分页")
  70 + @PreAuthorize("@ss.hasPermission('ai:model:query')")
  71 + public CommonResult<PageResult<AiModelRespVO>> getModelPage(@Valid AiModelPageReqVO pageReqVO) {
  72 + PageResult<AiModelDO> pageResult = modelService.getModelPage(pageReqVO);
  73 + return success(BeanUtils.toBean(pageResult, AiModelRespVO.class));
  74 + }
  75 +
  76 + @GetMapping("/simple-list")
  77 + @Operation(summary = "获得模型列表")
  78 + @Parameter(name = "type", description = "类型", required = true, example = "1")
  79 + @Parameter(name = "platform", description = "平台", example = "midjourney")
  80 + public CommonResult<List<AiModelRespVO>> getModelSimpleList(
  81 + @RequestParam("type") Integer type,
  82 + @RequestParam(value = "platform", required = false) String platform) {
  83 + List<AiModelDO> list = modelService.getModelListByStatusAndType(
  84 + CommonStatusEnum.ENABLE.getStatus(), type, platform);
  85 + return success(convertList(list, model -> new AiModelRespVO().setId(model.getId())
  86 + .setName(model.getName()).setModel(model.getModel()).setPlatform(model.getPlatform())));
  87 + }
  88 +
  89 +}
0 \ No newline at end of file 90 \ No newline at end of file
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java
1 package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole; 1 package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole;
2 2
3 -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; 3 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
4 import com.fhs.core.trans.anno.Trans; 4 import com.fhs.core.trans.anno.Trans;
5 import com.fhs.core.trans.constant.TransType; 5 import com.fhs.core.trans.constant.TransType;
6 import com.fhs.core.trans.vo.VO; 6 import com.fhs.core.trans.vo.VO;
@@ -20,7 +20,7 @@ public class AiChatRoleRespVO implements VO { @@ -20,7 +20,7 @@ public class AiChatRoleRespVO implements VO {
20 private Long userId; 20 private Long userId;
21 21
22 @Schema(description = "模型编号", example = "17640") 22 @Schema(description = "模型编号", example = "17640")
23 - @Trans(type = TransType.SIMPLE, target = AiChatModelDO.class, fields = {"name", "model"}, refs = {"modelName", "model"}) 23 + @Trans(type = TransType.SIMPLE, target = AiModelDO.class, fields = {"name", "model"}, refs = {"modelName", "model"})
24 private Long modelId; 24 private Long modelId;
25 @Schema(description = "模型名字", example = "张三") 25 @Schema(description = "模型名字", example = "张三")
26 private String modelName; 26 private String modelName;
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatModel/AiChatModelPageReqVO.java renamed to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiModelPageReqVO.java
1 -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel; 1 +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model;
2 2
3 import lombok.*; 3 import lombok.*;
4 import io.swagger.v3.oas.annotations.media.Schema; 4 import io.swagger.v3.oas.annotations.media.Schema;
5 import cn.iocoder.yudao.framework.common.pojo.PageParam; 5 import cn.iocoder.yudao.framework.common.pojo.PageParam;
6 6
7 -@Schema(description = "管理后台 - API 聊天模型分页 Request VO") 7 +@Schema(description = "管理后台 - API 模型分页 Request VO")
8 @Data 8 @Data
9 -public class AiChatModelPageReqVO extends PageParam { 9 +public class AiModelPageReqVO extends PageParam {
10 10
11 @Schema(description = "模型名字", example = "张三") 11 @Schema(description = "模型名字", example = "张三")
12 private String name; 12 private String name;
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatModel/AiChatModelRespVO.java renamed to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiModelRespVO.java
1 -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel; 1 +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model;
2 2
3 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
4 import lombok.Data; 4 import lombok.Data;
5 5
6 import java.time.LocalDateTime; 6 import java.time.LocalDateTime;
7 7
8 -@Schema(description = "管理后台 - AI 聊天模型 Response VO") 8 +@Schema(description = "管理后台 - AI 模型 Response VO")
9 @Data 9 @Data
10 -public class AiChatModelRespVO { 10 +public class AiModelRespVO {
11 11
12 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2630") 12 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2630")
13 private Long id; 13 private Long id;
@@ -24,6 +24,9 @@ public class AiChatModelRespVO { @@ -24,6 +24,9 @@ public class AiChatModelRespVO {
24 @Schema(description = "模型平台", example = "OpenAI") 24 @Schema(description = "模型平台", example = "OpenAI")
25 private String platform; 25 private String platform;
26 26
  27 + @Schema(description = "模型类型", example = "1")
  28 + private Integer type;
  29 +
27 @Schema(description = "排序", example = "1") 30 @Schema(description = "排序", example = "1")
28 private Integer sort; 31 private Integer sort;
29 32
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatModel/AiChatModelSaveReqVO.java renamed to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiModelSaveReqVO.java
1 -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel; 1 +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model;
2 2
  3 +import cn.iocoder.yudao.framework.ai.core.enums.AiModelTypeEnum;
  4 +import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;
3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 import cn.iocoder.yudao.framework.common.validation.InEnum; 6 import cn.iocoder.yudao.framework.common.validation.InEnum;
5 import io.swagger.v3.oas.annotations.media.Schema; 7 import io.swagger.v3.oas.annotations.media.Schema;
6 -import lombok.*;  
7 -import jakarta.validation.constraints.*; 8 +import jakarta.validation.constraints.NotEmpty;
  9 +import jakarta.validation.constraints.NotNull;
  10 +import lombok.Data;
8 11
9 -@Schema(description = "管理后台 - API 聊天模型新增/修改 Request VO") 12 +@Schema(description = "管理后台 - API 模型新增/修改 Request VO")
10 @Data 13 @Data
11 -public class AiChatModelSaveReqVO { 14 +public class AiModelSaveReqVO {
12 15
13 @Schema(description = "编号", example = "2630") 16 @Schema(description = "编号", example = "2630")
14 private Long id; 17 private Long id;
@@ -27,8 +30,14 @@ public class AiChatModelSaveReqVO { @@ -27,8 +30,14 @@ public class AiChatModelSaveReqVO {
27 30
28 @Schema(description = "模型平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI") 31 @Schema(description = "模型平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI")
29 @NotEmpty(message = "模型平台不能为空") 32 @NotEmpty(message = "模型平台不能为空")
  33 + @InEnum(AiPlatformEnum.class)
30 private String platform; 34 private String platform;
31 35
  36 + @Schema(description = "模型类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  37 + @NotNull(message = "模型类型不能为空")
  38 + @InEnum(AiModelTypeEnum.class)
  39 + private Integer type;
  40 +
32 @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 41 @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
33 @NotNull(message = "排序不能为空") 42 @NotNull(message = "排序不能为空")
34 private Integer sort; 43 private Integer sort;
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.chat; @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.chat;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO; 4 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO;
5 -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; 5 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
6 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; 6 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
7 import com.baomidou.mybatisplus.annotation.KeySequence; 7 import com.baomidou.mybatisplus.annotation.KeySequence;
8 import com.baomidou.mybatisplus.annotation.TableId; 8 import com.baomidou.mybatisplus.annotation.TableId;
@@ -76,13 +76,13 @@ public class AiChatConversationDO extends BaseDO { @@ -76,13 +76,13 @@ public class AiChatConversationDO extends BaseDO {
76 /** 76 /**
77 * 模型编号 77 * 模型编号
78 * 78 *
79 - * 关联 {@link AiChatModelDO#getId()} 字段 79 + * 关联 {@link AiModelDO#getId()} 字段
80 */ 80 */
81 private Long modelId; 81 private Long modelId;
82 /** 82 /**
83 * 模型标志 83 * 模型标志
84 * 84 *
85 - * 冗余 {@link AiChatModelDO#getModel()} 字段 85 + * 冗余 {@link AiModelDO#getModel()} 字段
86 */ 86 */
87 private String model; 87 private String model;
88 88
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.chat; @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.chat;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO; 4 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO;
5 -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; 5 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
6 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; 6 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
7 import com.baomidou.mybatisplus.annotation.KeySequence; 7 import com.baomidou.mybatisplus.annotation.KeySequence;
8 import com.baomidou.mybatisplus.annotation.TableField; 8 import com.baomidou.mybatisplus.annotation.TableField;
@@ -83,13 +83,13 @@ public class AiChatMessageDO extends BaseDO { @@ -83,13 +83,13 @@ public class AiChatMessageDO extends BaseDO {
83 /** 83 /**
84 * 模型标志 84 * 模型标志
85 * 85 *
86 - * 冗余 {@link AiChatModelDO#getModel()} 86 + * 冗余 {@link AiModelDO#getModel()}
87 */ 87 */
88 private String model; 88 private String model;
89 /** 89 /**
90 * 模型编号 90 * 模型编号
91 * 91 *
92 - * 关联 {@link AiChatModelDO#getId()} 字段 92 + * 关联 {@link AiModelDO#getId()} 字段
93 */ 93 */
94 private Long modelId; 94 private Long modelId;
95 95
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.image; @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.image;
2 2
3 import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi; 3 import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi;
4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
5 -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; 5 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
6 import cn.iocoder.yudao.module.ai.enums.image.AiImageStatusEnum; 6 import cn.iocoder.yudao.module.ai.enums.image.AiImageStatusEnum;
7 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; 7 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
8 import com.baomidou.mybatisplus.annotation.KeySequence; 8 import com.baomidou.mybatisplus.annotation.KeySequence;
@@ -52,11 +52,16 @@ public class AiImageDO extends BaseDO { @@ -52,11 +52,16 @@ public class AiImageDO extends BaseDO {
52 * 枚举 {@link cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum} 52 * 枚举 {@link cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum}
53 */ 53 */
54 private String platform; 54 private String platform;
55 - // TODO @芋艿:modelId?  
56 /** 55 /**
57 - * 模型 56 + * 模型编号
58 * 57 *
59 - * 冗余 {@link AiChatModelDO#getModel()} 58 + * 关联 {@link AiModelDO#getId()}
  59 + */
  60 + private Long modelId;
  61 + /**
  62 + * 模型标识
  63 + *
  64 + * 冗余 {@link AiModelDO#getModel()}
60 */ 65 */
61 private String model; 66 private String model;
62 67
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeDO.java
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge; @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge;
2 2
3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
5 -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; 5 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
6 import com.baomidou.mybatisplus.annotation.KeySequence; 6 import com.baomidou.mybatisplus.annotation.KeySequence;
7 import com.baomidou.mybatisplus.annotation.TableId; 7 import com.baomidou.mybatisplus.annotation.TableId;
8 import com.baomidou.mybatisplus.annotation.TableName; 8 import com.baomidou.mybatisplus.annotation.TableName;
@@ -35,13 +35,13 @@ public class AiKnowledgeDO extends BaseDO { @@ -35,13 +35,13 @@ public class AiKnowledgeDO extends BaseDO {
35 /** 35 /**
36 * 向量模型编号 36 * 向量模型编号
37 * 37 *
38 - * 关联 {@link AiChatModelDO#getId()} 38 + * 关联 {@link AiModelDO#getId()}
39 */ 39 */
40 private Long embeddingModelId; 40 private Long embeddingModelId;
41 /** 41 /**
42 * 模型标识 42 * 模型标识
43 * 43 *
44 - * 冗余 {@link AiChatModelDO#getModel()} 44 + * 冗余 {@link AiModelDO#getModel()}
45 */ 45 */
46 private String embeddingModel; 46 private String embeddingModel;
47 47
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/mindmap/AiMindMapDO.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.mindmap; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.mindmap;
2 2
3 import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; 3 import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;
4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  5 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
5 import com.baomidou.mybatisplus.annotation.KeySequence; 6 import com.baomidou.mybatisplus.annotation.KeySequence;
6 import com.baomidou.mybatisplus.annotation.TableId; 7 import com.baomidou.mybatisplus.annotation.TableId;
7 import com.baomidou.mybatisplus.annotation.TableName; 8 import com.baomidou.mybatisplus.annotation.TableName;
@@ -36,7 +37,12 @@ public class AiMindMapDO extends BaseDO { @@ -36,7 +37,12 @@ public class AiMindMapDO extends BaseDO {
36 * 枚举 {@link AiPlatformEnum} 37 * 枚举 {@link AiPlatformEnum}
37 */ 38 */
38 private String platform; 39 private String platform;
39 - // TODO @芋艿:modelId? 40 + /**
  41 + * 模型编号
  42 + *
  43 + * 关联 {@link AiModelDO#getId()}
  44 + */
  45 + private Long modelId;
40 /** 46 /**
41 * 模型 47 * 模型
42 */ 48 */
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java
@@ -58,7 +58,7 @@ public class AiChatRoleDO extends BaseDO { @@ -58,7 +58,7 @@ public class AiChatRoleDO extends BaseDO {
58 /** 58 /**
59 * 模型编号 59 * 模型编号
60 * 60 *
61 - * 关联 {@link AiChatModelDO#getId()} 字段 61 + * 关联 {@link AiModelDO#getId()} 字段
62 */ 62 */
63 private Long modelId; 63 private Long modelId;
64 64
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModelDO.java renamed to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiModelDO.java
1 package cn.iocoder.yudao.module.ai.dal.dataobject.model; 1 package cn.iocoder.yudao.module.ai.dal.dataobject.model;
2 2
  3 +import cn.iocoder.yudao.framework.ai.core.enums.AiModelTypeEnum;
3 import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; 4 import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;
4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 6 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
@@ -8,23 +9,22 @@ import com.baomidou.mybatisplus.annotation.TableId; @@ -8,23 +9,22 @@ import com.baomidou.mybatisplus.annotation.TableId;
8 import com.baomidou.mybatisplus.annotation.TableName; 9 import com.baomidou.mybatisplus.annotation.TableName;
9 import lombok.*; 10 import lombok.*;
10 11
11 -// TODO @芋艿,需要改造,增加 type  
12 /** 12 /**
13 - * AI 聊天模型 DO 13 + * AI 模型 DO
14 * 14 *
15 - * 默认聊天模型:{@link #status} 为开启,并且 {@link #sort} 排序第一 15 + * 默认模型:{@link #status} 为开启,并且 {@link #sort} 排序第一
16 * 16 *
17 * @author fansili 17 * @author fansili
18 * @since 2024/4/24 19:39 18 * @since 2024/4/24 19:39
19 */ 19 */
20 -@TableName("ai_chat_model")  
21 -@KeySequence("ai_chat_model_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 20 +@TableName("ai_model")
  21 +@KeySequence("ai_model_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
22 @Data 22 @Data
23 @EqualsAndHashCode(callSuper = true) 23 @EqualsAndHashCode(callSuper = true)
24 @Builder 24 @Builder
25 @NoArgsConstructor 25 @NoArgsConstructor
26 @AllArgsConstructor 26 @AllArgsConstructor
27 -public class AiChatModelDO extends BaseDO { 27 +public class AiModelDO extends BaseDO {
28 28
29 /** 29 /**
30 * 编号 30 * 编号
@@ -51,6 +51,12 @@ public class AiChatModelDO extends BaseDO { @@ -51,6 +51,12 @@ public class AiChatModelDO extends BaseDO {
51 * 枚举 {@link AiPlatformEnum} 51 * 枚举 {@link AiPlatformEnum}
52 */ 52 */
53 private String platform; 53 private String platform;
  54 + /**
  55 + * 类型
  56 + *
  57 + * 枚举 {@link AiModelTypeEnum}
  58 + */
  59 + private Integer type;
54 60
55 /** 61 /**
56 * 排序值 62 * 排序值
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/write/AiWriteDO.java
@@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.write; @@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.write;
2 2
3 import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; 3 import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;
4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  5 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
  6 +import cn.iocoder.yudao.module.ai.enums.DictTypeConstants;
5 import cn.iocoder.yudao.module.ai.enums.write.AiWriteTypeEnum; 7 import cn.iocoder.yudao.module.ai.enums.write.AiWriteTypeEnum;
6 import com.baomidou.mybatisplus.annotation.KeySequence; 8 import com.baomidou.mybatisplus.annotation.KeySequence;
7 import com.baomidou.mybatisplus.annotation.TableId; 9 import com.baomidou.mybatisplus.annotation.TableId;
@@ -44,7 +46,12 @@ public class AiWriteDO extends BaseDO { @@ -44,7 +46,12 @@ public class AiWriteDO extends BaseDO {
44 * 枚举 {@link AiPlatformEnum} 46 * 枚举 {@link AiPlatformEnum}
45 */ 47 */
46 private String platform; 48 private String platform;
47 - // TODO @芋艿:modelId? 49 + /**
  50 + * 模型编号
  51 + *
  52 + * 关联 {@link AiModelDO#getId()}
  53 + */
  54 + private Long modelId;
48 /** 55 /**
49 * 模型 56 * 模型
50 */ 57 */
@@ -67,25 +74,25 @@ public class AiWriteDO extends BaseDO { @@ -67,25 +74,25 @@ public class AiWriteDO extends BaseDO {
67 /** 74 /**
68 * 长度提示词 75 * 长度提示词
69 * 76 *
70 - * 字典:{@link cn.iocoder.yudao.module.ai.enums.DictTypeConstants#AI_WRITE_LENGTH} 77 + * 字典:{@link DictTypeConstants#AI_WRITE_LENGTH}
71 */ 78 */
72 private Integer length; 79 private Integer length;
73 /** 80 /**
74 * 格式提示词 81 * 格式提示词
75 * 82 *
76 - * 字典:{@link cn.iocoder.yudao.module.ai.enums.DictTypeConstants#AI_WRITE_FORMAT} 83 + * 字典:{@link DictTypeConstants#AI_WRITE_FORMAT}
77 */ 84 */
78 private Integer format; 85 private Integer format;
79 /** 86 /**
80 * 语气提示词 87 * 语气提示词
81 * 88 *
82 - * 字典:{@link cn.iocoder.yudao.module.ai.enums.DictTypeConstants#AI_WRITE_TONE} 89 + * 字典:{@link DictTypeConstants#AI_WRITE_TONE}
83 */ 90 */
84 private Integer tone; 91 private Integer tone;
85 /** 92 /**
86 * 语言提示词 93 * 语言提示词
87 * 94 *
88 - * 字典:{@link cn.iocoder.yudao.module.ai.enums.DictTypeConstants#AI_WRITE_LANGUAGE} 95 + * 字典:{@link DictTypeConstants#AI_WRITE_LANGUAGE}
89 */ 96 */
90 private Integer language; 97 private Integer language;
91 98
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiChatMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.ai.dal.mysql.model;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  6 +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
  7 +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiModelPageReqVO;
  8 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
  9 +import org.apache.ibatis.annotations.Mapper;
  10 +
  11 +import javax.annotation.Nullable;
  12 +import java.util.List;
  13 +
  14 +/**
  15 + * API 模型 Mapper
  16 + *
  17 + * @author fansili
  18 + */
  19 +@Mapper
  20 +public interface AiChatMapper extends BaseMapperX<AiModelDO> {
  21 +
  22 + default AiModelDO selectFirstByStatus(Integer type, Integer status) {
  23 + return selectOne(new QueryWrapperX<AiModelDO>()
  24 + .eq("type", type)
  25 + .eq("status", status)
  26 + .limitN(1)
  27 + .orderByAsc("sort"));
  28 + }
  29 +
  30 + default PageResult<AiModelDO> selectPage(AiModelPageReqVO reqVO) {
  31 + return selectPage(reqVO, new LambdaQueryWrapperX<AiModelDO>()
  32 + .likeIfPresent(AiModelDO::getName, reqVO.getName())
  33 + .eqIfPresent(AiModelDO::getModel, reqVO.getModel())
  34 + .eqIfPresent(AiModelDO::getPlatform, reqVO.getPlatform())
  35 + .orderByAsc(AiModelDO::getSort));
  36 + }
  37 +
  38 + default List<AiModelDO> selectListByStatusAndType(Integer status, Integer type,
  39 + @Nullable String platform) {
  40 + return selectList(new LambdaQueryWrapperX<AiModelDO>()
  41 + .eq(AiModelDO::getStatus, status)
  42 + .eq(AiModelDO::getType, type)
  43 + .eqIfPresent(AiModelDO::getPlatform, platform)
  44 + .orderByAsc(AiModelDO::getSort));
  45 + }
  46 +
  47 +}
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiChatModelMapper.java deleted
1 -package cn.iocoder.yudao.module.ai.dal.mysql.model;  
2 -  
3 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
4 -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;  
5 -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;  
6 -import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;  
7 -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelPageReqVO;  
8 -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO;  
9 -import org.apache.ibatis.annotations.Mapper;  
10 -  
11 -import java.util.Collection;  
12 -import java.util.List;  
13 -  
14 -/**  
15 - * API 聊天模型 Mapper  
16 - *  
17 - * @author fansili  
18 - */  
19 -@Mapper  
20 -public interface AiChatModelMapper extends BaseMapperX<AiChatModelDO> {  
21 -  
22 - default AiChatModelDO selectFirstByStatus(Integer status) {  
23 - return selectOne(new QueryWrapperX<AiChatModelDO>()  
24 - .eq("status", status)  
25 - .limitN(1)  
26 - .orderByAsc("sort"));  
27 - }  
28 -  
29 - default PageResult<AiChatModelDO> selectPage(AiChatModelPageReqVO reqVO) {  
30 - return selectPage(reqVO, new LambdaQueryWrapperX<AiChatModelDO>()  
31 - .likeIfPresent(AiChatModelDO::getName, reqVO.getName())  
32 - .eqIfPresent(AiChatModelDO::getModel, reqVO.getModel())  
33 - .eqIfPresent(AiChatModelDO::getPlatform, reqVO.getPlatform())  
34 - .orderByAsc(AiChatModelDO::getSort));  
35 - }  
36 -  
37 - default List<AiChatModelDO> selectList(Integer status) {  
38 - return selectList(new LambdaQueryWrapperX<AiChatModelDO>()  
39 - .eq(AiChatModelDO::getStatus, status)  
40 - .orderByAsc(AiChatModelDO::getSort));  
41 - }  
42 -  
43 -}  
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java
@@ -4,17 +4,18 @@ import cn.hutool.core.collection.CollUtil; @@ -4,17 +4,18 @@ import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.lang.Assert; 4 import cn.hutool.core.lang.Assert;
5 import cn.hutool.core.util.ObjUtil; 5 import cn.hutool.core.util.ObjUtil;
6 import cn.hutool.core.util.ObjectUtil; 6 import cn.hutool.core.util.ObjectUtil;
  7 +import cn.iocoder.yudao.framework.ai.core.enums.AiModelTypeEnum;
7 import cn.iocoder.yudao.framework.common.pojo.PageResult; 8 import cn.iocoder.yudao.framework.common.pojo.PageResult;
8 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 9 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
9 import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateMyReqVO; 10 import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateMyReqVO;
10 import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO; 11 import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO;
11 import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateMyReqVO; 12 import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateMyReqVO;
12 import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; 13 import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO;
13 -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; 14 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
14 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; 15 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
15 import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatConversationMapper; 16 import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatConversationMapper;
16 import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeService; 17 import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeService;
17 -import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; 18 +import cn.iocoder.yudao.module.ai.service.model.AiModelService;
18 import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; 19 import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService;
19 import jakarta.annotation.Resource; 20 import jakarta.annotation.Resource;
20 import lombok.extern.slf4j.Slf4j; 21 import lombok.extern.slf4j.Slf4j;
@@ -44,7 +45,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService @@ -44,7 +45,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService
44 private AiChatConversationMapper chatConversationMapper; 45 private AiChatConversationMapper chatConversationMapper;
45 46
46 @Resource 47 @Resource
47 - private AiChatModelService chatModalService; 48 + private AiModelService chatModalService;
48 @Resource 49 @Resource
49 private AiChatRoleService chatRoleService; 50 private AiChatRoleService chatRoleService;
50 @Resource 51 @Resource
@@ -54,9 +55,9 @@ public class AiChatConversationServiceImpl implements AiChatConversationService @@ -54,9 +55,9 @@ public class AiChatConversationServiceImpl implements AiChatConversationService
54 public Long createChatConversationMy(AiChatConversationCreateMyReqVO createReqVO, Long userId) { 55 public Long createChatConversationMy(AiChatConversationCreateMyReqVO createReqVO, Long userId) {
55 // 1.1 获得 AiChatRoleDO 聊天角色 56 // 1.1 获得 AiChatRoleDO 聊天角色
56 AiChatRoleDO role = createReqVO.getRoleId() != null ? chatRoleService.validateChatRole(createReqVO.getRoleId()) : null; 57 AiChatRoleDO role = createReqVO.getRoleId() != null ? chatRoleService.validateChatRole(createReqVO.getRoleId()) : null;
57 - // 1.2 获得 AiChatModelDO 聊天模型  
58 - AiChatModelDO model = role != null && role.getModelId() != null ? chatModalService.validateChatModel(role.getModelId())  
59 - : chatModalService.getRequiredDefaultChatModel(); 58 + // 1.2 获得 AiModelDO 聊天模型
  59 + AiModelDO model = role != null && role.getModelId() != null ? chatModalService.validateModel(role.getModelId())
  60 + : chatModalService.getRequiredDefaultModel(AiModelTypeEnum.CHAT.getType());
60 Assert.notNull(model, "必须找到默认模型"); 61 Assert.notNull(model, "必须找到默认模型");
61 validateChatModel(model); 62 validateChatModel(model);
62 63
@@ -86,9 +87,9 @@ public class AiChatConversationServiceImpl implements AiChatConversationService @@ -86,9 +87,9 @@ public class AiChatConversationServiceImpl implements AiChatConversationService
86 throw exception(CHAT_CONVERSATION_NOT_EXISTS); 87 throw exception(CHAT_CONVERSATION_NOT_EXISTS);
87 } 88 }
88 // 1.2 校验模型是否存在(修改模型的情况) 89 // 1.2 校验模型是否存在(修改模型的情况)
89 - AiChatModelDO model = null; 90 + AiModelDO model = null;
90 if (updateReqVO.getModelId() != null) { 91 if (updateReqVO.getModelId() != null) {
91 - model = chatModalService.validateChatModel(updateReqVO.getModelId()); 92 + model = chatModalService.validateModel(updateReqVO.getModelId());
92 } 93 }
93 94
94 // 1.3 校验知识库是否存在 95 // 1.3 校验知识库是否存在
@@ -139,7 +140,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService @@ -139,7 +140,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService
139 chatConversationMapper.deleteById(id); 140 chatConversationMapper.deleteById(id);
140 } 141 }
141 142
142 - private void validateChatModel(AiChatModelDO model) { 143 + private void validateChatModel(AiModelDO model) {
143 if (ObjectUtil.isAllNotEmpty(model.getTemperature(), model.getMaxTokens(), model.getMaxContexts())) { 144 if (ObjectUtil.isAllNotEmpty(model.getTemperature(), model.getMaxTokens(), model.getMaxContexts())) {
144 return; 145 return;
145 } 146 }
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java
@@ -15,13 +15,12 @@ import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessage @@ -15,13 +15,12 @@ import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessage
15 import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; 15 import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO;
16 import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; 16 import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO;
17 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO; 17 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO;
18 -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; 18 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
19 import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatMessageMapper; 19 import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatMessageMapper;
20 import cn.iocoder.yudao.module.ai.enums.AiChatRoleEnum; 20 import cn.iocoder.yudao.module.ai.enums.AiChatRoleEnum;
21 import cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants; 21 import cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants;
22 import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeSegmentService; 22 import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeSegmentService;
23 -import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService;  
24 -import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; 23 +import cn.iocoder.yudao.module.ai.service.model.AiModelService;
25 import jakarta.annotation.Resource; 24 import jakarta.annotation.Resource;
26 import lombok.extern.slf4j.Slf4j; 25 import lombok.extern.slf4j.Slf4j;
27 import org.springframework.ai.chat.messages.Message; 26 import org.springframework.ai.chat.messages.Message;
@@ -63,9 +62,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { @@ -63,9 +62,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
63 @Resource 62 @Resource
64 private AiChatConversationService chatConversationService; 63 private AiChatConversationService chatConversationService;
65 @Resource 64 @Resource
66 - private AiChatModelService chatModalService;  
67 - @Resource  
68 - private AiApiKeyService apiKeyService; 65 + private AiModelService modalService;
69 @Resource 66 @Resource
70 private AiKnowledgeSegmentService knowledgeSegmentService; 67 private AiKnowledgeSegmentService knowledgeSegmentService;
71 68
@@ -78,8 +75,8 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { @@ -78,8 +75,8 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
78 } 75 }
79 List<AiChatMessageDO> historyMessages = chatMessageMapper.selectListByConversationId(conversation.getId()); 76 List<AiChatMessageDO> historyMessages = chatMessageMapper.selectListByConversationId(conversation.getId());
80 // 1.2 校验模型 77 // 1.2 校验模型
81 - AiChatModelDO model = chatModalService.validateChatModel(conversation.getModelId());  
82 - ChatModel chatModel = apiKeyService.getChatModel(model.getKeyId()); 78 + AiModelDO model = modalService.validateModel(conversation.getModelId());
  79 + ChatModel chatModel = modalService.getChatModel(model.getKeyId());
83 80
84 // 2. 插入 user 发送消息 81 // 2. 插入 user 发送消息
85 AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model, 82 AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model,
@@ -112,8 +109,8 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { @@ -112,8 +109,8 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
112 } 109 }
113 List<AiChatMessageDO> historyMessages = chatMessageMapper.selectListByConversationId(conversation.getId()); 110 List<AiChatMessageDO> historyMessages = chatMessageMapper.selectListByConversationId(conversation.getId());
114 // 1.2 校验模型 111 // 1.2 校验模型
115 - AiChatModelDO model = chatModalService.validateChatModel(conversation.getModelId());  
116 - StreamingChatModel chatModel = apiKeyService.getChatModel(model.getKeyId()); 112 + AiModelDO model = modalService.validateModel(conversation.getModelId());
  113 + StreamingChatModel chatModel = modalService.getChatModel(model.getKeyId());
117 114
118 // 2. 插入 user 发送消息 115 // 2. 插入 user 发送消息
119 AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model, 116 AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model,
@@ -161,8 +158,8 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { @@ -161,8 +158,8 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
161 return null; 158 return null;
162 } 159 }
163 160
164 - private Prompt buildPrompt(AiChatConversationDO conversation, List<AiChatMessageDO> messages,List<AiKnowledgeSegmentDO> segmentList,  
165 - AiChatModelDO model, AiChatMessageSendReqVO sendReqVO) { 161 + private Prompt buildPrompt(AiChatConversationDO conversation, List<AiChatMessageDO> messages, List<AiKnowledgeSegmentDO> segmentList,
  162 + AiModelDO model, AiChatMessageSendReqVO sendReqVO) {
166 // 1. 构建 Prompt Message 列表 163 // 1. 构建 Prompt Message 列表
167 List<Message> chatMessages = new ArrayList<>(); 164 List<Message> chatMessages = new ArrayList<>();
168 165
@@ -232,7 +229,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { @@ -232,7 +229,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
232 } 229 }
233 230
234 private AiChatMessageDO createChatMessage(Long conversationId, Long replyId, 231 private AiChatMessageDO createChatMessage(Long conversationId, Long replyId,
235 - AiChatModelDO model, Long userId, Long roleId, 232 + AiModelDO model, Long userId, Long roleId,
236 MessageType messageType, String content, Boolean useContext) { 233 MessageType messageType, String content, Boolean useContext) {
237 AiChatMessageDO message = new AiChatMessageDO().setConversationId(conversationId).setReplyId(replyId) 234 AiChatMessageDO message = new AiChatMessageDO().setConversationId(conversationId).setReplyId(replyId)
238 .setModel(model.getModel()).setModelId(model.getId()).setUserId(userId).setRoleId(roleId) 235 .setModel(model.getModel()).setModelId(model.getId()).setUserId(userId).setRoleId(roleId)
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java
@@ -12,13 +12,17 @@ import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; @@ -12,13 +12,17 @@ import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;
12 import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi; 12 import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi;
13 import cn.iocoder.yudao.framework.common.pojo.PageResult; 13 import cn.iocoder.yudao.framework.common.pojo.PageResult;
14 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 14 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
15 -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; 15 +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDrawReqVO;
  16 +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImagePageReqVO;
  17 +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImagePublicPageReqVO;
  18 +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageUpdateReqVO;
16 import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyActionReqVO; 19 import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyActionReqVO;
17 import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyImagineReqVO; 20 import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyImagineReqVO;
18 import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; 21 import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO;
  22 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
19 import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper; 23 import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper;
20 import cn.iocoder.yudao.module.ai.enums.image.AiImageStatusEnum; 24 import cn.iocoder.yudao.module.ai.enums.image.AiImageStatusEnum;
21 -import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; 25 +import cn.iocoder.yudao.module.ai.service.model.AiModelService;
22 import cn.iocoder.yudao.module.infra.api.file.FileApi; 26 import cn.iocoder.yudao.module.infra.api.file.FileApi;
23 import com.alibaba.cloud.ai.dashscope.image.DashScopeImageOptions; 27 import com.alibaba.cloud.ai.dashscope.image.DashScopeImageOptions;
24 import jakarta.annotation.Resource; 28 import jakarta.annotation.Resource;
@@ -55,13 +59,13 @@ import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.*; @@ -55,13 +59,13 @@ import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.*;
55 public class AiImageServiceImpl implements AiImageService { 59 public class AiImageServiceImpl implements AiImageService {
56 60
57 @Resource 61 @Resource
58 - private AiImageMapper imageMapper; 62 + private AiModelService modelService;
59 63
60 @Resource 64 @Resource
61 - private FileApi fileApi; 65 + private AiImageMapper imageMapper;
62 66
63 @Resource 67 @Resource
64 - private AiApiKeyService apiKeyService; 68 + private FileApi fileApi;
65 69
66 @Override 70 @Override
67 public PageResult<AiImageDO> getImagePageMy(Long userId, AiImagePageReqVO pageReqVO) { 71 public PageResult<AiImageDO> getImagePageMy(Long userId, AiImagePageReqVO pageReqVO) {
@@ -88,23 +92,31 @@ public class AiImageServiceImpl implements AiImageService { @@ -88,23 +92,31 @@ public class AiImageServiceImpl implements AiImageService {
88 92
89 @Override 93 @Override
90 public Long drawImage(Long userId, AiImageDrawReqVO drawReqVO) { 94 public Long drawImage(Long userId, AiImageDrawReqVO drawReqVO) {
91 - // 1. 保存数据库  
92 - AiImageDO image = BeanUtils.toBean(drawReqVO, AiImageDO.class).setUserId(userId).setPublicStatus(false)  
93 - .setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus()); 95 + // 1. 校验模型
  96 + AiModelDO model = modelService.validateModel(drawReqVO.getModelId());
  97 +
  98 + // 2. 保存数据库
  99 + AiImageDO image = BeanUtils.toBean(drawReqVO, AiImageDO.class).setUserId(userId)
  100 + .setPlatform(model.getPlatform()).setModelId(model.getId()).setModel(model.getModel())
  101 + .setPublicStatus(false).setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus());
94 imageMapper.insert(image); 102 imageMapper.insert(image);
95 - // 2. 异步绘制,后续前端通过返回的 id 进行轮询结果  
96 - getSelf().executeDrawImage(image, drawReqVO); 103 +
  104 + // 3. 异步绘制,后续前端通过返回的 id 进行轮询结果
  105 + getSelf().executeDrawImage(image, drawReqVO, model);
97 return image.getId(); 106 return image.getId();
98 } 107 }
99 108
100 @Async 109 @Async
101 - public void executeDrawImage(AiImageDO image, AiImageDrawReqVO req) { 110 + public void executeDrawImage(AiImageDO image, AiImageDrawReqVO reqVO, AiModelDO model) {
102 try { 111 try {
103 // 1.1 构建请求 112 // 1.1 构建请求
104 - ImageOptions request = buildImageOptions(req); 113 + ImageOptions request = buildImageOptions(reqVO, model);
105 // 1.2 执行请求 114 // 1.2 执行请求
106 - ImageModel imageModel = apiKeyService.getImageModel(AiPlatformEnum.validatePlatform(req.getPlatform()));  
107 - ImageResponse response = imageModel.call(new ImagePrompt(req.getPrompt(), request)); 115 + ImageModel imageModel = modelService.getImageModel(model.getId());
  116 + ImageResponse response = imageModel.call(new ImagePrompt(reqVO.getPrompt(), request));
  117 + if (response.getResult() == null) {
  118 + throw new IllegalArgumentException("生成结果为空");
  119 + }
108 120
109 // 2. 上传到文件服务 121 // 2. 上传到文件服务
110 String b64Json = response.getResult().getOutput().getB64Json(); 122 String b64Json = response.getResult().getOutput().getB64Json();
@@ -116,25 +128,25 @@ public class AiImageServiceImpl implements AiImageService { @@ -116,25 +128,25 @@ public class AiImageServiceImpl implements AiImageService {
116 imageMapper.updateById(new AiImageDO().setId(image.getId()).setStatus(AiImageStatusEnum.SUCCESS.getStatus()) 128 imageMapper.updateById(new AiImageDO().setId(image.getId()).setStatus(AiImageStatusEnum.SUCCESS.getStatus())
117 .setPicUrl(filePath).setFinishTime(LocalDateTime.now())); 129 .setPicUrl(filePath).setFinishTime(LocalDateTime.now()));
118 } catch (Exception ex) { 130 } catch (Exception ex) {
119 - log.error("[doDall][image({}) 生成异常]", image, ex); 131 + log.error("[executeDrawImage][image({}) 生成异常]", image, ex);
120 imageMapper.updateById(new AiImageDO().setId(image.getId()) 132 imageMapper.updateById(new AiImageDO().setId(image.getId())
121 .setStatus(AiImageStatusEnum.FAIL.getStatus()) 133 .setStatus(AiImageStatusEnum.FAIL.getStatus())
122 .setErrorMessage(ex.getMessage()).setFinishTime(LocalDateTime.now())); 134 .setErrorMessage(ex.getMessage()).setFinishTime(LocalDateTime.now()));
123 } 135 }
124 } 136 }
125 137
126 - private static ImageOptions buildImageOptions(AiImageDrawReqVO draw) {  
127 - if (ObjUtil.equal(draw.getPlatform(), AiPlatformEnum.OPENAI.getPlatform())) { 138 + private static ImageOptions buildImageOptions(AiImageDrawReqVO draw, AiModelDO model) {
  139 + if (ObjUtil.equal(model.getPlatform(), AiPlatformEnum.OPENAI.getPlatform())) {
128 // https://platform.openai.com/docs/api-reference/images/create 140 // https://platform.openai.com/docs/api-reference/images/create
129 - return OpenAiImageOptions.builder().withModel(draw.getModel()) 141 + return OpenAiImageOptions.builder().withModel(model.getModel())
130 .withHeight(draw.getHeight()).withWidth(draw.getWidth()) 142 .withHeight(draw.getHeight()).withWidth(draw.getWidth())
131 .withStyle(MapUtil.getStr(draw.getOptions(), "style")) // 风格 143 .withStyle(MapUtil.getStr(draw.getOptions(), "style")) // 风格
132 .withResponseFormat("b64_json") 144 .withResponseFormat("b64_json")
133 .build(); 145 .build();
134 - } else if (ObjUtil.equal(draw.getPlatform(), AiPlatformEnum.STABLE_DIFFUSION.getPlatform())) { 146 + } else if (ObjUtil.equal(model.getPlatform(), AiPlatformEnum.STABLE_DIFFUSION.getPlatform())) {
135 // https://platform.stability.ai/docs/api-reference#tag/SDXL-and-SD1.6/operation/textToImage 147 // https://platform.stability.ai/docs/api-reference#tag/SDXL-and-SD1.6/operation/textToImage
136 // https://platform.stability.ai/docs/api-reference#tag/Text-to-Image/operation/textToImage 148 // https://platform.stability.ai/docs/api-reference#tag/Text-to-Image/operation/textToImage
137 - return StabilityAiImageOptions.builder().model(draw.getModel()) 149 + return StabilityAiImageOptions.builder().model(model.getModel())
138 .height(draw.getHeight()).width(draw.getWidth()) 150 .height(draw.getHeight()).width(draw.getWidth())
139 .seed(Long.valueOf(draw.getOptions().get("seed"))) 151 .seed(Long.valueOf(draw.getOptions().get("seed")))
140 .cfgScale(Float.valueOf(draw.getOptions().get("scale"))) 152 .cfgScale(Float.valueOf(draw.getOptions().get("scale")))
@@ -143,22 +155,22 @@ public class AiImageServiceImpl implements AiImageService { @@ -143,22 +155,22 @@ public class AiImageServiceImpl implements AiImageService {
143 .stylePreset(String.valueOf(draw.getOptions().get("stylePreset"))) 155 .stylePreset(String.valueOf(draw.getOptions().get("stylePreset")))
144 .clipGuidancePreset(String.valueOf(draw.getOptions().get("clipGuidancePreset"))) 156 .clipGuidancePreset(String.valueOf(draw.getOptions().get("clipGuidancePreset")))
145 .build(); 157 .build();
146 - } else if (ObjUtil.equal(draw.getPlatform(), AiPlatformEnum.TONG_YI.getPlatform())) { 158 + } else if (ObjUtil.equal(model.getPlatform(), AiPlatformEnum.TONG_YI.getPlatform())) {
147 return DashScopeImageOptions.builder() 159 return DashScopeImageOptions.builder()
148 - .withModel(draw.getModel()).withN(1) 160 + .withModel(model.getModel()).withN(1)
149 .withHeight(draw.getHeight()).withWidth(draw.getWidth()) 161 .withHeight(draw.getHeight()).withWidth(draw.getWidth())
150 .build(); 162 .build();
151 - } else if (ObjUtil.equal(draw.getPlatform(), AiPlatformEnum.YI_YAN.getPlatform())) { 163 + } else if (ObjUtil.equal(model.getPlatform(), AiPlatformEnum.YI_YAN.getPlatform())) {
152 return QianFanImageOptions.builder() 164 return QianFanImageOptions.builder()
153 - .model(draw.getModel()).N(1) 165 + .model(model.getModel()).N(1)
154 .height(draw.getHeight()).width(draw.getWidth()) 166 .height(draw.getHeight()).width(draw.getWidth())
155 .build(); 167 .build();
156 - } else if (ObjUtil.equal(draw.getPlatform(), AiPlatformEnum.ZHI_PU.getPlatform())) { 168 + } else if (ObjUtil.equal(model.getPlatform(), AiPlatformEnum.ZHI_PU.getPlatform())) {
157 return ZhiPuAiImageOptions.builder() 169 return ZhiPuAiImageOptions.builder()
158 - .model(draw.getModel()) 170 + .model(model.getModel())
159 .build(); 171 .build();
160 } 172 }
161 - throw new IllegalArgumentException("不支持的 AI 平台:" + draw.getPlatform()); 173 + throw new IllegalArgumentException("不支持的 AI 平台:" + model.getPlatform());
162 } 174 }
163 175
164 @Override 176 @Override
@@ -206,7 +218,7 @@ public class AiImageServiceImpl implements AiImageService { @@ -206,7 +218,7 @@ public class AiImageServiceImpl implements AiImageService {
206 @Override 218 @Override
207 @Transactional(rollbackFor = Exception.class) 219 @Transactional(rollbackFor = Exception.class)
208 public Long midjourneyImagine(Long userId, AiMidjourneyImagineReqVO reqVO) { 220 public Long midjourneyImagine(Long userId, AiMidjourneyImagineReqVO reqVO) {
209 - MidjourneyApi midjourneyApi = apiKeyService.getMidjourneyApi(); 221 + MidjourneyApi midjourneyApi = modelService.getMidjourneyApi();
210 // 1. 保存数据库 222 // 1. 保存数据库
211 AiImageDO image = BeanUtils.toBean(reqVO, AiImageDO.class).setUserId(userId).setPublicStatus(false) 223 AiImageDO image = BeanUtils.toBean(reqVO, AiImageDO.class).setUserId(userId).setPublicStatus(false)
212 .setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus()) 224 .setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus())
@@ -237,7 +249,7 @@ public class AiImageServiceImpl implements AiImageService { @@ -237,7 +249,7 @@ public class AiImageServiceImpl implements AiImageService {
237 249
238 @Override 250 @Override
239 public Integer midjourneySync() { 251 public Integer midjourneySync() {
240 - MidjourneyApi midjourneyApi = apiKeyService.getMidjourneyApi(); 252 + MidjourneyApi midjourneyApi = modelService.getMidjourneyApi();
241 // 1.1 获取 Midjourney 平台,状态在 “进行中” 的 image 253 // 1.1 获取 Midjourney 平台,状态在 “进行中” 的 image
242 List<AiImageDO> imageList = imageMapper.selectListByStatusAndPlatform( 254 List<AiImageDO> imageList = imageMapper.selectListByStatusAndPlatform(
243 AiImageStatusEnum.IN_PROGRESS.getStatus(), AiPlatformEnum.MIDJOURNEY.getPlatform()); 255 AiImageStatusEnum.IN_PROGRESS.getStatus(), AiPlatformEnum.MIDJOURNEY.getPlatform());
@@ -308,7 +320,7 @@ public class AiImageServiceImpl implements AiImageService { @@ -308,7 +320,7 @@ public class AiImageServiceImpl implements AiImageService {
308 320
309 @Override 321 @Override
310 public Long midjourneyAction(Long userId, AiMidjourneyActionReqVO reqVO) { 322 public Long midjourneyAction(Long userId, AiMidjourneyActionReqVO reqVO) {
311 - MidjourneyApi midjourneyApi = apiKeyService.getMidjourneyApi(); 323 + MidjourneyApi midjourneyApi = modelService.getMidjourneyApi();
312 // 1.1 检查 image 324 // 1.1 检查 image
313 AiImageDO image = validateImageExists(reqVO.getId()); 325 AiImageDO image = validateImageExists(reqVO.getId());
314 if (ObjUtil.notEqual(userId, image.getUserId())) { 326 if (ObjUtil.notEqual(userId, image.getUserId())) {
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeSegmentServiceImpl.java
@@ -7,14 +7,17 @@ import cn.hutool.core.util.StrUtil; @@ -7,14 +7,17 @@ import cn.hutool.core.util.StrUtil;
7 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 7 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
8 import cn.iocoder.yudao.framework.common.pojo.PageResult; 8 import cn.iocoder.yudao.framework.common.pojo.PageResult;
9 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 9 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
10 -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.*; 10 +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentPageReqVO;
  11 +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentProcessRespVO;
  12 +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentSaveReqVO;
  13 +import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentUpdateStatusReqVO;
11 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO; 14 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO;
12 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO; 15 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO;
13 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO; 16 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO;
14 import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeSegmentMapper; 17 import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeSegmentMapper;
15 -import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService;  
16 import cn.iocoder.yudao.module.ai.service.knowledge.bo.AiKnowledgeSegmentSearchReqBO; 18 import cn.iocoder.yudao.module.ai.service.knowledge.bo.AiKnowledgeSegmentSearchReqBO;
17 import cn.iocoder.yudao.module.ai.service.knowledge.bo.AiKnowledgeSegmentSearchRespBO; 19 import cn.iocoder.yudao.module.ai.service.knowledge.bo.AiKnowledgeSegmentSearchRespBO;
  20 +import cn.iocoder.yudao.module.ai.service.model.AiModelService;
18 import jakarta.annotation.Resource; 21 import jakarta.annotation.Resource;
19 import lombok.extern.slf4j.Slf4j; 22 import lombok.extern.slf4j.Slf4j;
20 import org.springframework.ai.document.Document; 23 import org.springframework.ai.document.Document;
@@ -33,8 +36,8 @@ import java.util.Objects; @@ -33,8 +36,8 @@ import java.util.Objects;
33 36
34 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 37 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
35 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; 38 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
36 -import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.KNOWLEDGE_SEGMENT_NOT_EXISTS;  
37 import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.KNOWLEDGE_SEGMENT_CONTENT_TOO_LONG; 39 import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.KNOWLEDGE_SEGMENT_CONTENT_TOO_LONG;
  40 +import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.KNOWLEDGE_SEGMENT_NOT_EXISTS;
38 41
39 /** 42 /**
40 * AI 知识库分片 Service 实现类 43 * AI 知识库分片 Service 实现类
@@ -58,7 +61,7 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService @@ -58,7 +61,7 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService
58 @Lazy // 延迟加载,避免循环依赖 61 @Lazy // 延迟加载,避免循环依赖
59 private AiKnowledgeDocumentService knowledgeDocumentService; 62 private AiKnowledgeDocumentService knowledgeDocumentService;
60 @Resource 63 @Resource
61 - private AiApiKeyService apiKeyService; 64 + private AiModelService modelService;
62 65
63 @Resource 66 @Resource
64 private TokenCountEstimator tokenCountEstimator; 67 private TokenCountEstimator tokenCountEstimator;
@@ -180,7 +183,7 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService @@ -180,7 +183,7 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService
180 AiKnowledgeDO knowledge = knowledgeService.validateKnowledgeExists(reqBO.getKnowledgeId()); 183 AiKnowledgeDO knowledge = knowledgeService.validateKnowledgeExists(reqBO.getKnowledgeId());
181 184
182 // 2.1 向量检索 185 // 2.1 向量检索
183 - VectorStore vectorStore = apiKeyService.getOrCreateVectorStoreByModelId(knowledge.getEmbeddingModelId()); 186 + VectorStore vectorStore = getVectorStoreById(knowledge);
184 List<Document> documents = vectorStore.similaritySearch(SearchRequest.builder() 187 List<Document> documents = vectorStore.similaritySearch(SearchRequest.builder()
185 .query(reqBO.getContent()) 188 .query(reqBO.getContent())
186 .topK(ObjUtil.defaultIfNull(reqBO.getTopK(), knowledge.getTopK())) 189 .topK(ObjUtil.defaultIfNull(reqBO.getTopK(), knowledge.getTopK()))
@@ -251,11 +254,12 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService @@ -251,11 +254,12 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService
251 } 254 }
252 255
253 private VectorStore getVectorStoreById(AiKnowledgeDO knowledge) { 256 private VectorStore getVectorStoreById(AiKnowledgeDO knowledge) {
254 - return apiKeyService.getOrCreateVectorStoreByModelId(knowledge.getEmbeddingModelId()); 257 + return modelService.getOrCreateVectorStore(knowledge.getEmbeddingModelId());
255 } 258 }
256 259
257 private VectorStore getVectorStoreById(Long knowledgeId) { 260 private VectorStore getVectorStoreById(Long knowledgeId) {
258 - return getVectorStoreById(knowledgeService.validateKnowledgeExists(knowledgeId)); 261 + AiKnowledgeDO knowledge = knowledgeService.validateKnowledgeExists(knowledgeId);
  262 + return getVectorStoreById(knowledge);
259 } 263 }
260 264
261 private static List<Document> splitContentByToken(String content, Integer segmentMaxTokens) { 265 private static List<Document> splitContentByToken(String content, Integer segmentMaxTokens) {
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeServiceImpl.java
@@ -5,9 +5,9 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -5,9 +5,9 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
5 import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgePageReqVO; 5 import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgePageReqVO;
6 import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeSaveReqVO; 6 import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeSaveReqVO;
7 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO; 7 import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO;
8 -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; 8 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
9 import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeMapper; 9 import cn.iocoder.yudao.module.ai.dal.mysql.knowledge.AiKnowledgeMapper;
10 -import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; 10 +import cn.iocoder.yudao.module.ai.service.model.AiModelService;
11 import jakarta.annotation.Resource; 11 import jakarta.annotation.Resource;
12 import lombok.extern.slf4j.Slf4j; 12 import lombok.extern.slf4j.Slf4j;
13 import org.springframework.stereotype.Service; 13 import org.springframework.stereotype.Service;
@@ -28,12 +28,12 @@ public class AiKnowledgeServiceImpl implements AiKnowledgeService { @@ -28,12 +28,12 @@ public class AiKnowledgeServiceImpl implements AiKnowledgeService {
28 private AiKnowledgeMapper knowledgeMapper; 28 private AiKnowledgeMapper knowledgeMapper;
29 29
30 @Resource 30 @Resource
31 - private AiChatModelService chatModelService; 31 + private AiModelService chatModelService;
32 32
33 @Override 33 @Override
34 public Long createKnowledge(AiKnowledgeSaveReqVO createReqVO) { 34 public Long createKnowledge(AiKnowledgeSaveReqVO createReqVO) {
35 // 1. 校验模型配置 35 // 1. 校验模型配置
36 - AiChatModelDO model = chatModelService.validateChatModel(createReqVO.getEmbeddingModelId()); 36 + AiModelDO model = chatModelService.validateModel(createReqVO.getEmbeddingModelId());
37 37
38 // 2. 插入知识库 38 // 2. 插入知识库
39 AiKnowledgeDO knowledge = BeanUtils.toBean(createReqVO, AiKnowledgeDO.class) 39 AiKnowledgeDO knowledge = BeanUtils.toBean(createReqVO, AiKnowledgeDO.class)
@@ -47,7 +47,7 @@ public class AiKnowledgeServiceImpl implements AiKnowledgeService { @@ -47,7 +47,7 @@ public class AiKnowledgeServiceImpl implements AiKnowledgeService {
47 // 1.1 校验知识库存在 47 // 1.1 校验知识库存在
48 validateKnowledgeExists(updateReqVO.getId()); 48 validateKnowledgeExists(updateReqVO.getId());
49 // 1.2 校验模型配置 49 // 1.2 校验模型配置
50 - AiChatModelDO model = chatModelService.validateChatModel(updateReqVO.getEmbeddingModelId()); 50 + AiModelDO model = chatModelService.validateModel(updateReqVO.getEmbeddingModelId());
51 51
52 // 2. 更新知识库 52 // 2. 更新知识库
53 AiKnowledgeDO updateObj = BeanUtils.toBean(updateReqVO, AiKnowledgeDO.class) 53 AiKnowledgeDO updateObj = BeanUtils.toBean(updateReqVO, AiKnowledgeDO.class)
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/mindmap/AiMindMapServiceImpl.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.ai.service.mindmap; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.ai.service.mindmap;
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.lang.Assert; 4 import cn.hutool.core.lang.Assert;
5 import cn.hutool.core.util.StrUtil; 5 import cn.hutool.core.util.StrUtil;
  6 +import cn.iocoder.yudao.framework.ai.core.enums.AiModelTypeEnum;
6 import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; 7 import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;
7 import cn.iocoder.yudao.framework.ai.core.util.AiUtils; 8 import cn.iocoder.yudao.framework.ai.core.util.AiUtils;
8 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 9 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
@@ -12,14 +13,13 @@ import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; @@ -12,14 +13,13 @@ import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
12 import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapGenerateReqVO; 13 import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapGenerateReqVO;
13 import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapPageReqVO; 14 import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapPageReqVO;
14 import cn.iocoder.yudao.module.ai.dal.dataobject.mindmap.AiMindMapDO; 15 import cn.iocoder.yudao.module.ai.dal.dataobject.mindmap.AiMindMapDO;
15 -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO;  
16 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; 16 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
  17 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
17 import cn.iocoder.yudao.module.ai.dal.mysql.mindmap.AiMindMapMapper; 18 import cn.iocoder.yudao.module.ai.dal.mysql.mindmap.AiMindMapMapper;
18 import cn.iocoder.yudao.module.ai.enums.AiChatRoleEnum; 19 import cn.iocoder.yudao.module.ai.enums.AiChatRoleEnum;
19 import cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants; 20 import cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants;
20 -import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService;  
21 -import cn.iocoder.yudao.module.ai.service.model.AiChatModelService;  
22 import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; 21 import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService;
  22 +import cn.iocoder.yudao.module.ai.service.model.AiModelService;
23 import jakarta.annotation.Resource; 23 import jakarta.annotation.Resource;
24 import lombok.extern.slf4j.Slf4j; 24 import lombok.extern.slf4j.Slf4j;
25 import org.springframework.ai.chat.messages.Message; 25 import org.springframework.ai.chat.messages.Message;
@@ -50,9 +50,7 @@ import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.MIND_MAP_NOT_E @@ -50,9 +50,7 @@ import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.MIND_MAP_NOT_E
50 public class AiMindMapServiceImpl implements AiMindMapService { 50 public class AiMindMapServiceImpl implements AiMindMapService {
51 51
52 @Resource 52 @Resource
53 - private AiApiKeyService apiKeyService;  
54 - @Resource  
55 - private AiChatModelService chatModalService; 53 + private AiModelService modalService;
56 @Resource 54 @Resource
57 private AiChatRoleService chatRoleService; 55 private AiChatRoleService chatRoleService;
58 56
@@ -65,17 +63,17 @@ public class AiMindMapServiceImpl implements AiMindMapService { @@ -65,17 +63,17 @@ public class AiMindMapServiceImpl implements AiMindMapService {
65 AiChatRoleDO role = CollUtil.getFirst( 63 AiChatRoleDO role = CollUtil.getFirst(
66 chatRoleService.getChatRoleListByName(AiChatRoleEnum.AI_MIND_MAP_ROLE.getName())); 64 chatRoleService.getChatRoleListByName(AiChatRoleEnum.AI_MIND_MAP_ROLE.getName()));
67 // 1.1 获取导图执行模型 65 // 1.1 获取导图执行模型
68 - AiChatModelDO model = getModel(role); 66 + AiModelDO model = getModel(role);
69 // 1.2 获取角色设定消息 67 // 1.2 获取角色设定消息
70 String systemMessage = role != null && StrUtil.isNotBlank(role.getSystemMessage()) 68 String systemMessage = role != null && StrUtil.isNotBlank(role.getSystemMessage())
71 ? role.getSystemMessage() : AiChatRoleEnum.AI_MIND_MAP_ROLE.getSystemMessage(); 69 ? role.getSystemMessage() : AiChatRoleEnum.AI_MIND_MAP_ROLE.getSystemMessage();
72 // 1.3 校验平台 70 // 1.3 校验平台
73 AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); 71 AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform());
74 - ChatModel chatModel = apiKeyService.getChatModel(model.getKeyId()); 72 + ChatModel chatModel = modalService.getChatModel(model.getId());
75 73
76 // 2. 插入思维导图信息 74 // 2. 插入思维导图信息
77 - AiMindMapDO mindMapDO = BeanUtils.toBean(generateReqVO, AiMindMapDO.class,  
78 - mindMap -> mindMap.setUserId(userId).setModel(model.getModel()).setPlatform(platform.getPlatform())); 75 + AiMindMapDO mindMapDO = BeanUtils.toBean(generateReqVO, AiMindMapDO.class, mindMap -> mindMap.setUserId(userId)
  76 + .setPlatform(platform.getPlatform()).setModelId(model.getId()).setModel(model.getModel()));
79 mindMapMapper.insert(mindMapDO); 77 mindMapMapper.insert(mindMapDO);
80 78
81 // 3.1 构建 Prompt,并进行调用 79 // 3.1 构建 Prompt,并进行调用
@@ -103,7 +101,7 @@ public class AiMindMapServiceImpl implements AiMindMapService { @@ -103,7 +101,7 @@ public class AiMindMapServiceImpl implements AiMindMapService {
103 101
104 } 102 }
105 103
106 - private Prompt buildPrompt(AiMindMapGenerateReqVO generateReqVO, AiChatModelDO model, String systemMessage) { 104 + private Prompt buildPrompt(AiMindMapGenerateReqVO generateReqVO, AiModelDO model, String systemMessage) {
107 // 1. 构建 message 列表 105 // 1. 构建 message 列表
108 List<Message> chatMessages = buildMessages(generateReqVO, systemMessage); 106 List<Message> chatMessages = buildMessages(generateReqVO, systemMessage);
109 // 2. 构建 options 对象 107 // 2. 构建 options 对象
@@ -123,13 +121,13 @@ public class AiMindMapServiceImpl implements AiMindMapService { @@ -123,13 +121,13 @@ public class AiMindMapServiceImpl implements AiMindMapService {
123 return chatMessages; 121 return chatMessages;
124 } 122 }
125 123
126 - private AiChatModelDO getModel(AiChatRoleDO role) {  
127 - AiChatModelDO model = null; 124 + private AiModelDO getModel(AiChatRoleDO role) {
  125 + AiModelDO model = null;
128 if (role != null && role.getModelId() != null) { 126 if (role != null && role.getModelId() != null) {
129 - model = chatModalService.getChatModel(role.getModelId()); 127 + model = modalService.getModel(role.getModelId());
130 } 128 }
131 if (model == null) { 129 if (model == null) {
132 - model = chatModalService.getRequiredDefaultChatModel(); 130 + model = modalService.getRequiredDefaultModel(AiModelTypeEnum.CHAT.getType());
133 } 131 }
134 Assert.notNull(model, "[AI] 获取不到模型"); 132 Assert.notNull(model, "[AI] 获取不到模型");
135 return model; 133 return model;
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java
1 package cn.iocoder.yudao.module.ai.service.model; 1 package cn.iocoder.yudao.module.ai.service.model;
2 2
3 -import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;  
4 -import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi;  
5 -import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi;  
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageReqVO; 4 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageReqVO;
8 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveReqVO; 5 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveReqVO;
9 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; 6 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO;
10 import jakarta.validation.Valid; 7 import jakarta.validation.Valid;
11 -import org.springframework.ai.chat.model.ChatModel;  
12 -import org.springframework.ai.image.ImageModel;  
13 -import org.springframework.ai.vectorstore.VectorStore;  
14 8
15 import java.util.List; 9 import java.util.List;
16 10
@@ -74,50 +68,13 @@ public interface AiApiKeyService { @@ -74,50 +68,13 @@ public interface AiApiKeyService {
74 */ 68 */
75 List<AiApiKeyDO> getApiKeyList(); 69 List<AiApiKeyDO> getApiKeyList();
76 70
77 - // ========== 与 spring-ai 集成 ==========  
78 -  
79 - /**  
80 - * 获得 ChatModel 对象  
81 - *  
82 - * @param id 编号  
83 - * @return ChatModel 对象  
84 - */  
85 - ChatModel getChatModel(Long id);  
86 -  
87 /** 71 /**
88 - * 获得 ImageModel 对象  
89 - *  
90 - * TODO 可优化点:目前默认获取 platform 对应的第一个开启的配置用于绘画;后续可以支持配置选择 72 + * 获得默认的 API 密钥
91 * 73 *
92 * @param platform 平台 74 * @param platform 平台
93 - * @return ImageModel 对象  
94 - */  
95 - ImageModel getImageModel(AiPlatformEnum platform);  
96 -  
97 - /**  
98 - * 获得 MidjourneyApi 对象  
99 - *  
100 - * TODO 可优化点:目前默认获取 Midjourney 对应的第一个开启的配置用于绘画;后续可以支持配置选择  
101 - *  
102 - * @return MidjourneyApi 对象  
103 - */  
104 - MidjourneyApi getMidjourneyApi();  
105 -  
106 - /**  
107 - * 获得 SunoApi 对象  
108 - *  
109 - * TODO 可优化点:目前默认获取 Suno 对应的第一个开启的配置用于音乐;后续可以支持配置选择  
110 - *  
111 - * @return SunoApi 对象  
112 - */  
113 - SunoApi getSunoApi();  
114 -  
115 - /**  
116 - * 获得 VectorStore 对象  
117 - *  
118 - * @param modelId 编号  
119 - * @return VectorStore 对象 75 + * @param status 状态
  76 + * @return API 密钥
120 */ 77 */
121 - VectorStore getOrCreateVectorStoreByModelId(Long modelId); 78 + AiApiKeyDO getRequiredDefaultApiKey(String platform, Integer status);
122 79
123 } 80 }
124 \ No newline at end of file 81 \ No newline at end of file
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java
1 package cn.iocoder.yudao.module.ai.service.model; 1 package cn.iocoder.yudao.module.ai.service.model;
2 2
3 -import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;  
4 -import cn.iocoder.yudao.framework.ai.core.factory.AiModelFactory;  
5 -import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi;  
6 -import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi;  
7 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
8 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
9 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
10 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageReqVO; 6 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageReqVO;
11 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveReqVO; 7 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveReqVO;
12 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; 8 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO;
13 -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO;  
14 import cn.iocoder.yudao.module.ai.dal.mysql.model.AiApiKeyMapper; 9 import cn.iocoder.yudao.module.ai.dal.mysql.model.AiApiKeyMapper;
15 import jakarta.annotation.Resource; 10 import jakarta.annotation.Resource;
16 -import org.springframework.ai.chat.model.ChatModel;  
17 -import org.springframework.ai.embedding.EmbeddingModel;  
18 -import org.springframework.ai.image.ImageModel;  
19 -import org.springframework.ai.vectorstore.SimpleVectorStore;  
20 -import org.springframework.ai.vectorstore.VectorStore;  
21 -import org.springframework.context.annotation.Lazy;  
22 import org.springframework.stereotype.Service; 11 import org.springframework.stereotype.Service;
23 import org.springframework.validation.annotation.Validated; 12 import org.springframework.validation.annotation.Validated;
24 13
25 import java.util.List; 14 import java.util.List;
26 15
27 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 16 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
28 -import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.*; 17 +import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.API_KEY_DISABLE;
  18 +import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.API_KEY_NOT_EXISTS;
29 19
30 /** 20 /**
31 * AI API 密钥 Service 实现类 21 * AI API 密钥 Service 实现类
@@ -39,14 +29,6 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { @@ -39,14 +29,6 @@ public class AiApiKeyServiceImpl implements AiApiKeyService {
39 @Resource 29 @Resource
40 private AiApiKeyMapper apiKeyMapper; 30 private AiApiKeyMapper apiKeyMapper;
41 31
42 - // TODO @芋艿:后续要不要改?  
43 - @Resource  
44 - @Lazy // 延迟加载,解决渲染依赖  
45 - private AiChatModelService chatModelService;  
46 -  
47 - @Resource  
48 - private AiModelFactory modelFactory;  
49 -  
50 @Override 32 @Override
51 public Long createApiKey(AiApiKeySaveReqVO createReqVO) { 33 public Long createApiKey(AiApiKeySaveReqVO createReqVO) {
52 // 插入 34 // 插入
@@ -105,57 +87,13 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { @@ -105,57 +87,13 @@ public class AiApiKeyServiceImpl implements AiApiKeyService {
105 return apiKeyMapper.selectList(); 87 return apiKeyMapper.selectList();
106 } 88 }
107 89
108 - // ========== 与 spring-ai 集成 ==========  
109 -  
110 - @Override  
111 - public ChatModel getChatModel(Long id) {  
112 - AiApiKeyDO apiKey = validateApiKey(id);  
113 - AiPlatformEnum platform = AiPlatformEnum.validatePlatform(apiKey.getPlatform());  
114 - return modelFactory.getOrCreateChatModel(platform, apiKey.getApiKey(), apiKey.getUrl());  
115 - }  
116 -  
117 - @Override  
118 - public ImageModel getImageModel(AiPlatformEnum platform) {  
119 - AiApiKeyDO apiKey = apiKeyMapper.selectFirstByPlatformAndStatus(platform.getPlatform(), CommonStatusEnum.ENABLE.getStatus());  
120 - if (apiKey == null) {  
121 - throw exception(API_KEY_IMAGE_NODE_FOUND, platform.getName());  
122 - }  
123 - return modelFactory.getOrCreateImageModel(platform, apiKey.getApiKey(), apiKey.getUrl());  
124 - }  
125 -  
126 @Override 90 @Override
127 - public MidjourneyApi getMidjourneyApi() {  
128 - AiApiKeyDO apiKey = apiKeyMapper.selectFirstByPlatformAndStatus(  
129 - AiPlatformEnum.MIDJOURNEY.getPlatform(), CommonStatusEnum.ENABLE.getStatus()); 91 + public AiApiKeyDO getRequiredDefaultApiKey(String platform, Integer status) {
  92 + AiApiKeyDO apiKey = apiKeyMapper.selectFirstByPlatformAndStatus(platform, status);
130 if (apiKey == null) { 93 if (apiKey == null) {
131 - throw exception(API_KEY_MIDJOURNEY_NOT_FOUND);  
132 - }  
133 - return modelFactory.getOrCreateMidjourneyApi(apiKey.getApiKey(), apiKey.getUrl());  
134 - }  
135 -  
136 - @Override  
137 - public SunoApi getSunoApi() {  
138 - AiApiKeyDO apiKey = apiKeyMapper.selectFirstByPlatformAndStatus(  
139 - AiPlatformEnum.SUNO.getPlatform(), CommonStatusEnum.ENABLE.getStatus());  
140 - if (apiKey == null) {  
141 - throw exception(API_KEY_SUNO_NOT_FOUND); 94 + throw exception(API_KEY_NOT_EXISTS);
142 } 95 }
143 - return modelFactory.getOrCreateSunoApi(apiKey.getApiKey(), apiKey.getUrl());  
144 - }  
145 -  
146 - @Override  
147 - public VectorStore getOrCreateVectorStoreByModelId(Long modelId) {  
148 - // 获取模型 + 密钥  
149 - AiChatModelDO chatModel = chatModelService.validateChatModel(modelId);  
150 - AiApiKeyDO apiKey = validateApiKey(chatModel.getKeyId());  
151 - AiPlatformEnum platform = AiPlatformEnum.validatePlatform(apiKey.getPlatform());  
152 -  
153 - // 创建或获取 EmbeddingModel 对象  
154 - EmbeddingModel embeddingModel = modelFactory.getOrCreateEmbeddingModel(platform, apiKey.getApiKey(),  
155 - apiKey.getUrl(), chatModel.getModel());  
156 -  
157 - // 创建或获取 VectorStore 对象  
158 - return modelFactory.getOrCreateVectorStore(SimpleVectorStore.class, embeddingModel); 96 + return apiKey;
159 } 97 }
160 98
161 } 99 }
162 \ No newline at end of file 100 \ No newline at end of file
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelService.java deleted
1 -package cn.iocoder.yudao.module.ai.service.model;  
2 -  
3 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
4 -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelPageReqVO;  
5 -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelSaveReqVO;  
6 -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO;  
7 -import jakarta.validation.Valid;  
8 -  
9 -import java.util.Collection;  
10 -import java.util.List;  
11 -  
12 -import java.util.Set;  
13 -  
14 -/**  
15 - * AI 聊天模型 Service 接口  
16 - *  
17 - * @author fansili  
18 - * @since 2024/4/24 19:42  
19 - */  
20 -public interface AiChatModelService {  
21 -  
22 - /**  
23 - * 创建聊天模型  
24 - *  
25 - * @param createReqVO 创建信息  
26 - * @return 编号  
27 - */  
28 - Long createChatModel(@Valid AiChatModelSaveReqVO createReqVO);  
29 -  
30 - /**  
31 - * 更新聊天模型  
32 - *  
33 - * @param updateReqVO 更新信息  
34 - */  
35 - void updateChatModel(@Valid AiChatModelSaveReqVO updateReqVO);  
36 -  
37 - /**  
38 - * 删除聊天模型  
39 - *  
40 - * @param id 编号  
41 - */  
42 - void deleteChatModel(Long id);  
43 -  
44 - /**  
45 - * 获得聊天模型  
46 - *  
47 - * @param id 编号  
48 - * @return 聊天模型  
49 - */  
50 - AiChatModelDO getChatModel(Long id);  
51 -  
52 - /**  
53 - * 获得默认的聊天模型  
54 - *  
55 - * 如果获取不到,则抛出 {@link cn.iocoder.yudao.framework.common.exception.ServiceException} 业务异常  
56 - *  
57 - * @return 聊天模型  
58 - */  
59 - AiChatModelDO getRequiredDefaultChatModel();  
60 -  
61 - /**  
62 - * 获得聊天模型分页  
63 - *  
64 - * @param pageReqVO 分页查询  
65 - * @return 聊天模型分页  
66 - */  
67 - PageResult<AiChatModelDO> getChatModelPage(AiChatModelPageReqVO pageReqVO);  
68 -  
69 - /**  
70 - * 校验聊天模型  
71 - *  
72 - * @param id 编号  
73 - * @return 聊天模型  
74 - */  
75 - AiChatModelDO validateChatModel(Long id);  
76 -  
77 - /**  
78 - * 获得聊天模型列表  
79 - *  
80 - * @param status 状态  
81 - * @return 聊天模型列表  
82 - */  
83 - List<AiChatModelDO> getChatModelListByStatus(Integer status);  
84 -  
85 - /**  
86 - * 获得聊天模型列表  
87 - *  
88 - * @param ids 编号数组  
89 - * @return 模型列表  
90 - */  
91 - List<AiChatModelDO> getChatModelList(Collection<Long> ids);  
92 -}  
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java
1 package cn.iocoder.yudao.module.ai.service.model; 1 package cn.iocoder.yudao.module.ai.service.model;
2 2
3 import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; 3 import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;
  4 +import cn.iocoder.yudao.framework.ai.core.factory.AiModelFactory;
  5 +import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi;
  6 +import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi;
4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 7 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 8 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 9 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
7 -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelPageReqVO;  
8 -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelSaveReqVO;  
9 -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO;  
10 -import cn.iocoder.yudao.module.ai.dal.mysql.model.AiChatModelMapper; 10 +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiModelPageReqVO;
  11 +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiModelSaveReqVO;
  12 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO;
  13 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
  14 +import cn.iocoder.yudao.module.ai.dal.mysql.model.AiChatMapper;
11 import jakarta.annotation.Resource; 15 import jakarta.annotation.Resource;
  16 +import org.springframework.ai.chat.model.ChatModel;
  17 +import org.springframework.ai.embedding.EmbeddingModel;
  18 +import org.springframework.ai.image.ImageModel;
  19 +import org.springframework.ai.vectorstore.SimpleVectorStore;
  20 +import org.springframework.ai.vectorstore.VectorStore;
12 import org.springframework.stereotype.Service; 21 import org.springframework.stereotype.Service;
13 import org.springframework.validation.annotation.Validated; 22 import org.springframework.validation.annotation.Validated;
14 23
15 -import java.util.Collection;  
16 import java.util.List; 24 import java.util.List;
17 25
18 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 26 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
19 import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.*; 27 import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.*;
20 28
21 /** 29 /**
22 - * AI 聊天模型 Service 实现类 30 + * AI 模型 Service 实现类
23 * 31 *
24 * @author fansili 32 * @author fansili
25 */ 33 */
26 @Service 34 @Service
27 @Validated 35 @Validated
28 -public class AiChatModelServiceImpl implements AiChatModelService { 36 +public class AiChatModelServiceImpl implements AiModelService {
29 37
30 @Resource 38 @Resource
31 private AiApiKeyService apiKeyService; 39 private AiApiKeyService apiKeyService;
32 40
33 @Resource 41 @Resource
34 - private AiChatModelMapper chatModelMapper; 42 + private AiChatMapper modelMapper;
  43 +
  44 + @Resource
  45 + private AiModelFactory modelFactory;
35 46
36 @Override 47 @Override
37 - public Long createChatModel(AiChatModelSaveReqVO createReqVO) { 48 + public Long createModel(AiModelSaveReqVO createReqVO) {
38 // 1. 校验 49 // 1. 校验
39 AiPlatformEnum.validatePlatform(createReqVO.getPlatform()); 50 AiPlatformEnum.validatePlatform(createReqVO.getPlatform());
40 apiKeyService.validateApiKey(createReqVO.getKeyId()); 51 apiKeyService.validateApiKey(createReqVO.getKeyId());
41 52
42 // 2. 插入 53 // 2. 插入
43 - AiChatModelDO chatModel = BeanUtils.toBean(createReqVO, AiChatModelDO.class);  
44 - chatModelMapper.insert(chatModel);  
45 - return chatModel.getId(); 54 + AiModelDO model = BeanUtils.toBean(createReqVO, AiModelDO.class);
  55 + modelMapper.insert(model);
  56 + return model.getId();
46 } 57 }
47 58
48 @Override 59 @Override
49 - public void updateChatModel(AiChatModelSaveReqVO updateReqVO) { 60 + public void updateModel(AiModelSaveReqVO updateReqVO) {
50 // 1. 校验 61 // 1. 校验
51 - validateChatModelExists(updateReqVO.getId()); 62 + validateModelExists(updateReqVO.getId());
52 AiPlatformEnum.validatePlatform(updateReqVO.getPlatform()); 63 AiPlatformEnum.validatePlatform(updateReqVO.getPlatform());
53 apiKeyService.validateApiKey(updateReqVO.getKeyId()); 64 apiKeyService.validateApiKey(updateReqVO.getKeyId());
54 65
55 // 2. 更新 66 // 2. 更新
56 - AiChatModelDO updateObj = BeanUtils.toBean(updateReqVO, AiChatModelDO.class);  
57 - chatModelMapper.updateById(updateObj); 67 + AiModelDO updateObj = BeanUtils.toBean(updateReqVO, AiModelDO.class);
  68 + modelMapper.updateById(updateObj);
58 } 69 }
59 70
60 @Override 71 @Override
61 - public void deleteChatModel(Long id) { 72 + public void deleteModel(Long id) {
62 // 校验存在 73 // 校验存在
63 - validateChatModelExists(id); 74 + validateModelExists(id);
64 // 删除 75 // 删除
65 - chatModelMapper.deleteById(id); 76 + modelMapper.deleteById(id);
66 } 77 }
67 78
68 - private AiChatModelDO validateChatModelExists(Long id) {  
69 - AiChatModelDO model = chatModelMapper.selectById(id);  
70 - if (chatModelMapper.selectById(id) == null) {  
71 - throw exception(CHAT_MODEL_NOT_EXISTS); 79 + private AiModelDO validateModelExists(Long id) {
  80 + AiModelDO model = modelMapper.selectById(id);
  81 + if (modelMapper.selectById(id) == null) {
  82 + throw exception(MODEL_NOT_EXISTS);
72 } 83 }
73 return model; 84 return model;
74 } 85 }
75 86
76 @Override 87 @Override
77 - public AiChatModelDO getChatModel(Long id) {  
78 - return chatModelMapper.selectById(id); 88 + public AiModelDO getModel(Long id) {
  89 + return modelMapper.selectById(id);
79 } 90 }
80 91
81 @Override 92 @Override
82 - public AiChatModelDO getRequiredDefaultChatModel() {  
83 - AiChatModelDO model = chatModelMapper.selectFirstByStatus(CommonStatusEnum.ENABLE.getStatus()); 93 + public AiModelDO getRequiredDefaultModel(Integer type) {
  94 + AiModelDO model = modelMapper.selectFirstByStatus(type, CommonStatusEnum.ENABLE.getStatus());
84 if (model == null) { 95 if (model == null) {
85 - throw exception(CHAT_MODEL_DEFAULT_NOT_EXISTS); 96 + throw exception(MODEL_DEFAULT_NOT_EXISTS);
86 } 97 }
87 return model; 98 return model;
88 } 99 }
89 100
90 @Override 101 @Override
91 - public PageResult<AiChatModelDO> getChatModelPage(AiChatModelPageReqVO pageReqVO) {  
92 - return chatModelMapper.selectPage(pageReqVO); 102 + public PageResult<AiModelDO> getModelPage(AiModelPageReqVO pageReqVO) {
  103 + return modelMapper.selectPage(pageReqVO);
93 } 104 }
94 105
95 @Override 106 @Override
96 - public AiChatModelDO validateChatModel(Long id) {  
97 - AiChatModelDO model = validateChatModelExists(id); 107 + public AiModelDO validateModel(Long id) {
  108 + AiModelDO model = validateModelExists(id);
98 if (CommonStatusEnum.isDisable(model.getStatus())) { 109 if (CommonStatusEnum.isDisable(model.getStatus())) {
99 - throw exception(CHAT_MODEL_DISABLE); 110 + throw exception(MODEL_DISABLE);
100 } 111 }
101 return model; 112 return model;
102 } 113 }
103 114
104 @Override 115 @Override
105 - public List<AiChatModelDO> getChatModelListByStatus(Integer status) {  
106 - return chatModelMapper.selectList(status); 116 + public List<AiModelDO> getModelListByStatusAndType(Integer status, Integer type,
  117 + String platform) {
  118 + return modelMapper.selectListByStatusAndType(status, type, platform);
  119 + }
  120 +
  121 + // ========== 与 Spring AI 集成 ==========
  122 +
  123 + @Override
  124 + public ChatModel getChatModel(Long id) {
  125 + AiModelDO model = validateModel(id);
  126 + AiApiKeyDO apiKey = apiKeyService.validateApiKey(model.getKeyId());
  127 + AiPlatformEnum platform = AiPlatformEnum.validatePlatform(apiKey.getPlatform());
  128 + return modelFactory.getOrCreateChatModel(platform, apiKey.getApiKey(), apiKey.getUrl());
  129 + }
  130 +
  131 + @Override
  132 + public ImageModel getImageModel(Long id) {
  133 + AiModelDO model = validateModel(id);
  134 + AiApiKeyDO apiKey = apiKeyService.validateApiKey(model.getKeyId());
  135 + AiPlatformEnum platform = AiPlatformEnum.validatePlatform(apiKey.getPlatform());
  136 + return modelFactory.getOrCreateImageModel(platform, apiKey.getApiKey(), apiKey.getUrl());
  137 + }
  138 +
  139 + @Override
  140 + public MidjourneyApi getMidjourneyApi() {
  141 + AiApiKeyDO apiKey = apiKeyService.getRequiredDefaultApiKey(
  142 + AiPlatformEnum.MIDJOURNEY.getPlatform(), CommonStatusEnum.ENABLE.getStatus());
  143 + return modelFactory.getOrCreateMidjourneyApi(apiKey.getApiKey(), apiKey.getUrl());
  144 + }
  145 +
  146 + @Override
  147 + public SunoApi getSunoApi() {
  148 + AiApiKeyDO apiKey = apiKeyService.getRequiredDefaultApiKey(
  149 + AiPlatformEnum.SUNO.getPlatform(), CommonStatusEnum.ENABLE.getStatus());
  150 + return modelFactory.getOrCreateSunoApi(apiKey.getApiKey(), apiKey.getUrl());
107 } 151 }
108 152
109 @Override 153 @Override
110 - public List<AiChatModelDO> getChatModelList(Collection<Long> ids) {  
111 - return chatModelMapper.selectBatchIds(ids); 154 + public VectorStore getOrCreateVectorStore(Long id) {
  155 + // 获取模型 + 密钥
  156 + AiModelDO model = validateModel(id);
  157 + AiApiKeyDO apiKey = apiKeyService.validateApiKey(model.getKeyId());
  158 + AiPlatformEnum platform = AiPlatformEnum.validatePlatform(apiKey.getPlatform());
  159 +
  160 + // 创建或获取 EmbeddingModel 对象
  161 + EmbeddingModel embeddingModel = modelFactory.getOrCreateEmbeddingModel(
  162 + platform, apiKey.getApiKey(), apiKey.getUrl(), model.getModel());
  163 +
  164 + // 创建或获取 VectorStore 对象
  165 + return modelFactory.getOrCreateVectorStore(SimpleVectorStore.class, embeddingModel);
112 } 166 }
113 167
114 } 168 }
115 \ No newline at end of file 169 \ No newline at end of file
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiModelService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.ai.service.model;
  2 +
  3 +import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi;
  4 +import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiModelPageReqVO;
  7 +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiModelSaveReqVO;
  8 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
  9 +import jakarta.validation.Valid;
  10 +import org.springframework.ai.chat.model.ChatModel;
  11 +import org.springframework.ai.image.ImageModel;
  12 +import org.springframework.ai.vectorstore.VectorStore;
  13 +
  14 +import javax.annotation.Nullable;
  15 +import java.util.List;
  16 +
  17 +/**
  18 + * AI 模型 Service 接口
  19 + *
  20 + * @author fansili
  21 + * @since 2024/4/24 19:42
  22 + */
  23 +public interface AiModelService {
  24 +
  25 + /**
  26 + * 创建模型
  27 + *
  28 + * @param createReqVO 创建信息
  29 + * @return 编号
  30 + */
  31 + Long createModel(@Valid AiModelSaveReqVO createReqVO);
  32 +
  33 + /**
  34 + * 更新模型
  35 + *
  36 + * @param updateReqVO 更新信息
  37 + */
  38 + void updateModel(@Valid AiModelSaveReqVO updateReqVO);
  39 +
  40 + /**
  41 + * 删除模型
  42 + *
  43 + * @param id 编号
  44 + */
  45 + void deleteModel(Long id);
  46 +
  47 + /**
  48 + * 获得模型
  49 + *
  50 + * @param id 编号
  51 + * @return 模型
  52 + */
  53 + AiModelDO getModel(Long id);
  54 +
  55 + /**
  56 + * 获得默认的模型
  57 + *
  58 + * 如果获取不到,则抛出 {@link cn.iocoder.yudao.framework.common.exception.ServiceException} 业务异常
  59 + *
  60 + * @return 模型
  61 + */
  62 + AiModelDO getRequiredDefaultModel(Integer type);
  63 +
  64 + /**
  65 + * 获得模型分页
  66 + *
  67 + * @param pageReqVO 分页查询
  68 + * @return 模型分页
  69 + */
  70 + PageResult<AiModelDO> getModelPage(AiModelPageReqVO pageReqVO);
  71 +
  72 + /**
  73 + * 校验模型是否可使用
  74 + *
  75 + * @param id 编号
  76 + * @return 模型
  77 + */
  78 + AiModelDO validateModel(Long id);
  79 +
  80 + /**
  81 + * 获得模型列表
  82 + *
  83 + * @param status 状态
  84 + * @param type 类型
  85 + * @param platform 平台,允许空
  86 + * @return 模型列表
  87 + */
  88 + List<AiModelDO> getModelListByStatusAndType(Integer status, Integer type,
  89 + @Nullable String platform);
  90 +
  91 + // ========== 与 Spring AI 集成 ==========
  92 +
  93 + /**
  94 + * 获得 ChatModel 对象
  95 + *
  96 + * @param id 编号
  97 + * @return ChatModel 对象
  98 + */
  99 + ChatModel getChatModel(Long id);
  100 +
  101 + /**
  102 + * 获得 ImageModel 对象
  103 + *
  104 + * @param id 编号
  105 + * @return ImageModel 对象
  106 + */
  107 + ImageModel getImageModel(Long id);
  108 +
  109 + /**
  110 + * 获得 MidjourneyApi 对象
  111 + *
  112 + * @return MidjourneyApi 对象
  113 + */
  114 + MidjourneyApi getMidjourneyApi();
  115 +
  116 + /**
  117 + * 获得 SunoApi 对象
  118 + *
  119 + * @return SunoApi 对象
  120 + */
  121 + SunoApi getSunoApi();
  122 +
  123 + /**
  124 + * 获得 VectorStore 对象
  125 + *
  126 + * @param id 编号
  127 + * @return VectorStore 对象
  128 + */
  129 + VectorStore getOrCreateVectorStore(Long id);
  130 +
  131 +}
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/AiMusicServiceImpl.java
@@ -16,7 +16,7 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.music.AiMusicDO; @@ -16,7 +16,7 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.music.AiMusicDO;
16 import cn.iocoder.yudao.module.ai.dal.mysql.music.AiMusicMapper; 16 import cn.iocoder.yudao.module.ai.dal.mysql.music.AiMusicMapper;
17 import cn.iocoder.yudao.module.ai.enums.music.AiMusicGenerateModeEnum; 17 import cn.iocoder.yudao.module.ai.enums.music.AiMusicGenerateModeEnum;
18 import cn.iocoder.yudao.module.ai.enums.music.AiMusicStatusEnum; 18 import cn.iocoder.yudao.module.ai.enums.music.AiMusicStatusEnum;
19 -import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; 19 +import cn.iocoder.yudao.module.ai.service.model.AiModelService;
20 import cn.iocoder.yudao.module.infra.api.file.FileApi; 20 import cn.iocoder.yudao.module.infra.api.file.FileApi;
21 import jakarta.annotation.Resource; 21 import jakarta.annotation.Resource;
22 import lombok.extern.slf4j.Slf4j; 22 import lombok.extern.slf4j.Slf4j;
@@ -41,7 +41,7 @@ import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.MUSIC_NOT_EXIS @@ -41,7 +41,7 @@ import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.MUSIC_NOT_EXIS
41 public class AiMusicServiceImpl implements AiMusicService { 41 public class AiMusicServiceImpl implements AiMusicService {
42 42
43 @Resource 43 @Resource
44 - private AiApiKeyService apiKeyService; 44 + private AiModelService modelService;
45 45
46 @Resource 46 @Resource
47 private AiMusicMapper musicMapper; 47 private AiMusicMapper musicMapper;
@@ -53,7 +53,7 @@ public class AiMusicServiceImpl implements AiMusicService { @@ -53,7 +53,7 @@ public class AiMusicServiceImpl implements AiMusicService {
53 @Transactional(rollbackFor = Exception.class) 53 @Transactional(rollbackFor = Exception.class)
54 public List<Long> generateMusic(Long userId, AiSunoGenerateReqVO reqVO) { 54 public List<Long> generateMusic(Long userId, AiSunoGenerateReqVO reqVO) {
55 // 1. 调用 Suno 生成音乐 55 // 1. 调用 Suno 生成音乐
56 - SunoApi sunoApi = apiKeyService.getSunoApi(); 56 + SunoApi sunoApi = modelService.getSunoApi();
57 List<SunoApi.MusicData> musicDataList; 57 List<SunoApi.MusicData> musicDataList;
58 if (Objects.equals(AiMusicGenerateModeEnum.DESCRIPTION.getMode(), reqVO.getGenerateMode())) { 58 if (Objects.equals(AiMusicGenerateModeEnum.DESCRIPTION.getMode(), reqVO.getGenerateMode())) {
59 // 1.1 描述模式 59 // 1.1 描述模式
@@ -88,7 +88,7 @@ public class AiMusicServiceImpl implements AiMusicService { @@ -88,7 +88,7 @@ public class AiMusicServiceImpl implements AiMusicService {
88 log.info("[syncMusic][Suno 开始同步, 共 ({}) 个任务]", streamingTask.size()); 88 log.info("[syncMusic][Suno 开始同步, 共 ({}) 个任务]", streamingTask.size());
89 89
90 // GET 请求,为避免参数过长,分批次处理 90 // GET 请求,为避免参数过长,分批次处理
91 - SunoApi sunoApi = apiKeyService.getSunoApi(); 91 + SunoApi sunoApi = modelService.getSunoApi();
92 CollUtil.split(streamingTask, 36).forEach(chunkList -> { 92 CollUtil.split(streamingTask, 36).forEach(chunkList -> {
93 Map<String, Long> taskIdMap = convertMap(chunkList, AiMusicDO::getTaskId, AiMusicDO::getId); 93 Map<String, Long> taskIdMap = convertMap(chunkList, AiMusicDO::getTaskId, AiMusicDO::getId);
94 List<SunoApi.MusicData> musicTaskList = sunoApi.getMusicList(new ArrayList<>(taskIdMap.keySet())); 94 List<SunoApi.MusicData> musicTaskList = sunoApi.getMusicList(new ArrayList<>(taskIdMap.keySet()));
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/write/AiWriteServiceImpl.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.ai.service.write; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.ai.service.write;
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.lang.Assert; 4 import cn.hutool.core.lang.Assert;
5 import cn.hutool.core.util.StrUtil; 5 import cn.hutool.core.util.StrUtil;
  6 +import cn.iocoder.yudao.framework.ai.core.enums.AiModelTypeEnum;
6 import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; 7 import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;
7 import cn.iocoder.yudao.framework.ai.core.util.AiUtils; 8 import cn.iocoder.yudao.framework.ai.core.util.AiUtils;
8 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 9 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
@@ -11,17 +12,16 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -11,17 +12,16 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
11 import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; 12 import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
12 import cn.iocoder.yudao.module.ai.controller.admin.write.vo.AiWriteGenerateReqVO; 13 import cn.iocoder.yudao.module.ai.controller.admin.write.vo.AiWriteGenerateReqVO;
13 import cn.iocoder.yudao.module.ai.controller.admin.write.vo.AiWritePageReqVO; 14 import cn.iocoder.yudao.module.ai.controller.admin.write.vo.AiWritePageReqVO;
14 -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO;  
15 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; 15 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
  16 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
16 import cn.iocoder.yudao.module.ai.dal.dataobject.write.AiWriteDO; 17 import cn.iocoder.yudao.module.ai.dal.dataobject.write.AiWriteDO;
17 import cn.iocoder.yudao.module.ai.dal.mysql.write.AiWriteMapper; 18 import cn.iocoder.yudao.module.ai.dal.mysql.write.AiWriteMapper;
18 import cn.iocoder.yudao.module.ai.enums.AiChatRoleEnum; 19 import cn.iocoder.yudao.module.ai.enums.AiChatRoleEnum;
19 import cn.iocoder.yudao.module.ai.enums.DictTypeConstants; 20 import cn.iocoder.yudao.module.ai.enums.DictTypeConstants;
20 import cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants; 21 import cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants;
21 import cn.iocoder.yudao.module.ai.enums.write.AiWriteTypeEnum; 22 import cn.iocoder.yudao.module.ai.enums.write.AiWriteTypeEnum;
22 -import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService;  
23 -import cn.iocoder.yudao.module.ai.service.model.AiChatModelService;  
24 import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; 23 import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService;
  24 +import cn.iocoder.yudao.module.ai.service.model.AiModelService;
25 import cn.iocoder.yudao.module.system.api.dict.DictDataApi; 25 import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
26 import jakarta.annotation.Resource; 26 import jakarta.annotation.Resource;
27 import lombok.extern.slf4j.Slf4j; 27 import lombok.extern.slf4j.Slf4j;
@@ -54,17 +54,15 @@ import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.WRITE_NOT_EXIS @@ -54,17 +54,15 @@ import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.WRITE_NOT_EXIS
54 public class AiWriteServiceImpl implements AiWriteService { 54 public class AiWriteServiceImpl implements AiWriteService {
55 55
56 @Resource 56 @Resource
57 - private AiApiKeyService apiKeyService;  
58 - @Resource  
59 - private AiChatModelService chatModalService; 57 + private AiModelService chatModalService;
60 @Resource 58 @Resource
61 private AiChatRoleService chatRoleService; 59 private AiChatRoleService chatRoleService;
62 60
63 @Resource 61 @Resource
64 - private DictDataApi dictDataApi; 62 + private AiWriteMapper writeMapper;
65 63
66 @Resource 64 @Resource
67 - private AiWriteMapper writeMapper; 65 + private DictDataApi dictDataApi;
68 66
69 @Override 67 @Override
70 public Flux<CommonResult<String>> generateWriteContent(AiWriteGenerateReqVO generateReqVO, Long userId) { 68 public Flux<CommonResult<String>> generateWriteContent(AiWriteGenerateReqVO generateReqVO, Long userId) {
@@ -72,17 +70,17 @@ public class AiWriteServiceImpl implements AiWriteService { @@ -72,17 +70,17 @@ public class AiWriteServiceImpl implements AiWriteService {
72 AiChatRoleDO writeRole = CollUtil.getFirst( 70 AiChatRoleDO writeRole = CollUtil.getFirst(
73 chatRoleService.getChatRoleListByName(AiChatRoleEnum.AI_WRITE_ROLE.getName())); 71 chatRoleService.getChatRoleListByName(AiChatRoleEnum.AI_WRITE_ROLE.getName()));
74 // 1.1 获取写作执行模型 72 // 1.1 获取写作执行模型
75 - AiChatModelDO model = getModel(writeRole); 73 + AiModelDO model = getModel(writeRole);
76 // 1.2 获取角色设定消息 74 // 1.2 获取角色设定消息
77 String systemMessage = Objects.nonNull(writeRole) && StrUtil.isNotBlank(writeRole.getSystemMessage()) 75 String systemMessage = Objects.nonNull(writeRole) && StrUtil.isNotBlank(writeRole.getSystemMessage())
78 ? writeRole.getSystemMessage() : AiChatRoleEnum.AI_WRITE_ROLE.getSystemMessage(); 76 ? writeRole.getSystemMessage() : AiChatRoleEnum.AI_WRITE_ROLE.getSystemMessage();
79 // 1.3 校验平台 77 // 1.3 校验平台
80 AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); 78 AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform());
81 - StreamingChatModel chatModel = apiKeyService.getChatModel(model.getKeyId()); 79 + StreamingChatModel chatModel = chatModalService.getChatModel(model.getKeyId());
82 80
83 // 2. 插入写作信息 81 // 2. 插入写作信息
84 - AiWriteDO writeDO = BeanUtils.toBean(generateReqVO, AiWriteDO.class,  
85 - write -> write.setUserId(userId).setPlatform(platform.getPlatform()).setModel(model.getModel())); 82 + AiWriteDO writeDO = BeanUtils.toBean(generateReqVO, AiWriteDO.class, write -> write.setUserId(userId)
  83 + .setPlatform(platform.getPlatform()).setModelId(model.getId()).setModel(model.getModel()));
86 writeMapper.insert(writeDO); 84 writeMapper.insert(writeDO);
87 85
88 // 3.1 构建 Prompt,并进行调用 86 // 3.1 构建 Prompt,并进行调用
@@ -109,19 +107,19 @@ public class AiWriteServiceImpl implements AiWriteService { @@ -109,19 +107,19 @@ public class AiWriteServiceImpl implements AiWriteService {
109 }).onErrorResume(error -> Flux.just(error(ErrorCodeConstants.WRITE_STREAM_ERROR))); 107 }).onErrorResume(error -> Flux.just(error(ErrorCodeConstants.WRITE_STREAM_ERROR)));
110 } 108 }
111 109
112 - private AiChatModelDO getModel(AiChatRoleDO writeRole) {  
113 - AiChatModelDO model = null; 110 + private AiModelDO getModel(AiChatRoleDO writeRole) {
  111 + AiModelDO model = null;
114 if (Objects.nonNull(writeRole) && Objects.nonNull(writeRole.getModelId())) { 112 if (Objects.nonNull(writeRole) && Objects.nonNull(writeRole.getModelId())) {
115 - model = chatModalService.getChatModel(writeRole.getModelId()); 113 + model = chatModalService.getModel(writeRole.getModelId());
116 } 114 }
117 if (model == null) { 115 if (model == null) {
118 - model = chatModalService.getRequiredDefaultChatModel(); 116 + model = chatModalService.getRequiredDefaultModel(AiModelTypeEnum.CHAT.getType());
119 } 117 }
120 Assert.notNull(model, "[AI] 获取不到模型"); 118 Assert.notNull(model, "[AI] 获取不到模型");
121 return model; 119 return model;
122 } 120 }
123 121
124 - private Prompt buildPrompt(AiWriteGenerateReqVO generateReqVO, AiChatModelDO model, String systemMessage) { 122 + private Prompt buildPrompt(AiWriteGenerateReqVO generateReqVO, AiModelDO model, String systemMessage) {
125 // 1. 构建 message 列表 123 // 1. 构建 message 列表
126 List<Message> chatMessages = buildMessages(generateReqVO, systemMessage); 124 List<Message> chatMessages = buildMessages(generateReqVO, systemMessage);
127 // 2. 构建 options 对象 125 // 2. 构建 options 对象
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiModelTypeEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ai.core.enums;
  2 +
  3 +import cn.iocoder.yudao.framework.common.core.ArrayValuable;
  4 +import lombok.Getter;
  5 +import lombok.RequiredArgsConstructor;
  6 +
  7 +import java.util.Arrays;
  8 +
  9 +/**
  10 + * AI 模型类型的枚举
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +@Getter
  15 +@RequiredArgsConstructor
  16 +public enum AiModelTypeEnum implements ArrayValuable<Integer> {
  17 +
  18 + CHAT(1, "对话"),
  19 + IMAGE(2, "图片"),
  20 + VOICE(3, "语音"),
  21 + VIDEO(4, "视频"),
  22 + EMBEDDING(5, "向量"),
  23 + RERANK(6, "重排序");
  24 +
  25 + /**
  26 + * 类型
  27 + */
  28 + private final Integer type;
  29 + /**
  30 + * 类型名
  31 + */
  32 + private final String name;
  33 +
  34 + public static final Integer[] ARRAYS = Arrays.stream(values()).map(AiModelTypeEnum::getType).toArray(Integer[]::new);
  35 +
  36 + @Override
  37 + public Integer[] array() {
  38 + return ARRAYS;
  39 + }
  40 +
  41 +}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java
1 package cn.iocoder.yudao.framework.ai.core.enums; 1 package cn.iocoder.yudao.framework.ai.core.enums;
2 2
  3 +import cn.iocoder.yudao.framework.common.core.ArrayValuable;
3 import lombok.AllArgsConstructor; 4 import lombok.AllArgsConstructor;
4 import lombok.Getter; 5 import lombok.Getter;
5 6
  7 +import java.util.Arrays;
  8 +
6 /** 9 /**
7 * AI 模型平台 10 * AI 模型平台
8 * 11 *
@@ -10,7 +13,7 @@ import lombok.Getter; @@ -10,7 +13,7 @@ import lombok.Getter;
10 */ 13 */
11 @Getter 14 @Getter
12 @AllArgsConstructor 15 @AllArgsConstructor
13 -public enum AiPlatformEnum { 16 +public enum AiPlatformEnum implements ArrayValuable<String> {
14 17
15 // ========== 国内平台 ========== 18 // ========== 国内平台 ==========
16 19
@@ -44,6 +47,8 @@ public enum AiPlatformEnum { @@ -44,6 +47,8 @@ public enum AiPlatformEnum {
44 */ 47 */
45 private final String name; 48 private final String name;
46 49
  50 + public static final String[] ARRAYS = Arrays.stream(values()).map(AiPlatformEnum::getPlatform).toArray(String[]::new);
  51 +
47 public static AiPlatformEnum validatePlatform(String platform) { 52 public static AiPlatformEnum validatePlatform(String platform) {
48 for (AiPlatformEnum platformEnum : AiPlatformEnum.values()) { 53 for (AiPlatformEnum platformEnum : AiPlatformEnum.values()) {
49 if (platformEnum.getPlatform().equals(platform)) { 54 if (platformEnum.getPlatform().equals(platform)) {
@@ -53,4 +58,9 @@ public enum AiPlatformEnum { @@ -53,4 +58,9 @@ public enum AiPlatformEnum {
53 throw new IllegalArgumentException("非法平台: " + platform); 58 throw new IllegalArgumentException("非法平台: " + platform);
54 } 59 }
55 60
  61 + @Override
  62 + public String[] array() {
  63 + return ARRAYS;
  64 + }
  65 +
56 } 66 }
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java
@@ -456,25 +456,4 @@ public class AiModelFactoryImpl implements AiModelFactory { @@ -456,25 +456,4 @@ public class AiModelFactoryImpl implements AiModelFactory {
456 return vectorStore; 456 return vectorStore;
457 } 457 }
458 458
459 - /**  
460 - * 创建向量存储文件  
461 - *  
462 - * @param embeddingModel 嵌入模型  
463 - * @return 向量存储文件  
464 - */  
465 - private File createVectorStoreFile(EmbeddingModel embeddingModel) {  
466 - // 获取简单类名  
467 - String simpleClassName = embeddingModel.getClass().getSimpleName();  
468 - // 获取用户主目录  
469 - String userHome = FileUtil.getUserHomePath();  
470 - // 创建vector_store目录  
471 - File vectorStoreDir = new File(userHome, "vector_store");  
472 - if (!vectorStoreDir.exists()) {  
473 - vectorStoreDir.mkdirs();  
474 - }  
475 -  
476 - // 创建文件  
477 - return new File(vectorStoreDir, "simple_" + simpleClassName + ".json");  
478 - }  
479 -  
480 } 459 }