Commit 89d079349c987eaa1065883433cd0e2ab6fc5bfe
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 | } |