mirror of
				https://github.com/YunaiV/ruoyi-vue-pro.git
				synced 2025-10-31 10:37:41 +08:00 
			
		
		
		
	【新增】AI:API 模型管理
This commit is contained in:
		| @ -11,10 +11,15 @@ public interface ErrorCodeConstants { | |||||||
|  |  | ||||||
|     // ========== API 密钥 1-040-000-000 ========== |     // ========== API 密钥 1-040-000-000 ========== | ||||||
|     ErrorCode API_KEY_NOT_EXISTS = new ErrorCode(1_040_000_000, "AI API 密钥不存在"); |     ErrorCode API_KEY_NOT_EXISTS = new ErrorCode(1_040_000_000, "AI API 密钥不存在"); | ||||||
|  |     ErrorCode API_KEY_DISABLE = new ErrorCode(1_040_000_001, "AI API 密钥已禁用!"); | ||||||
|  |  | ||||||
|     // chat |     // ========== API 聊天模型 1-040-001-000 ========== | ||||||
|  |  | ||||||
|     ErrorCode AI_MODULE_NOT_SUPPORTED = new ErrorCode(1_022_000_000, "AI 模型暂不支持!"); |     ErrorCode CHAT_MODAL_NOT_EXIST = new ErrorCode(1_040_001_000, "AI 模型不存在!"); | ||||||
|  |     ErrorCode CHAT_MODAL_DISABLE = new ErrorCode(1_040_001_001, "AI 模型({})已禁用!"); | ||||||
|  |  | ||||||
|  |     //    ErrorCode AI_MODAL_CONFIG_PARAMS_INCORRECT = new ErrorCode(1_022_000_081, "AI 模型 config 参数不正确! {} "); | ||||||
|  | //    ErrorCode AI_MODAL_PLATFORM_PARAMS_INCORRECT = new ErrorCode(1_022_000_083, "AI 平台参数不正确! {} "); | ||||||
|  |  | ||||||
|     // conversation |     // conversation | ||||||
|  |  | ||||||
| @ -31,12 +36,5 @@ public interface ErrorCodeConstants { | |||||||
|     ErrorCode AI_CHAT_ROLE_NOT_EXIST = new ErrorCode(1_022_000_060, "AI 角色不存在!"); |     ErrorCode AI_CHAT_ROLE_NOT_EXIST = new ErrorCode(1_022_000_060, "AI 角色不存在!"); | ||||||
|     ErrorCode AI_CHAT_ROLE_NOT_PUBLIC = new ErrorCode(1_022_000_060, "AI 角色未公开!"); |     ErrorCode AI_CHAT_ROLE_NOT_PUBLIC = new ErrorCode(1_022_000_060, "AI 角色未公开!"); | ||||||
|  |  | ||||||
|     // modal |  | ||||||
|  |  | ||||||
|     ErrorCode AI_MODAL_NOT_EXIST = new ErrorCode(1_022_000_080, "AI 模型不存在!"); |  | ||||||
|     ErrorCode AI_MODAL_CONFIG_PARAMS_INCORRECT = new ErrorCode(1_022_000_081, "AI 模型 config 参数不正确! {} "); |  | ||||||
|     ErrorCode AI_MODAL_PLATFORM_PARAMS_INCORRECT = new ErrorCode(1_022_000_083, "AI 平台参数不正确! {} "); |  | ||||||
|     ErrorCode AI_MODAL_DISABLE_NOT_USED = new ErrorCode(1_022_000_084, "AI 模型禁用不能使用!"); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -29,14 +29,14 @@ public class AiApiKeyController { | |||||||
|     private AiApiKeyService apiKeyService; |     private AiApiKeyService apiKeyService; | ||||||
|  |  | ||||||
|     @PostMapping("/create") |     @PostMapping("/create") | ||||||
|     @Operation(summary = "创建AI API 密钥") |     @Operation(summary = "创建 API 密钥") | ||||||
|     @PreAuthorize("@ss.hasPermission('ai:api-key:create')") |     @PreAuthorize("@ss.hasPermission('ai:api-key:create')") | ||||||
|     public CommonResult<Long> createApiKey(@Valid @RequestBody AiApiKeySaveReqVO createReqVO) { |     public CommonResult<Long> createApiKey(@Valid @RequestBody AiApiKeySaveReqVO createReqVO) { | ||||||
|         return success(apiKeyService.createApiKey(createReqVO)); |         return success(apiKeyService.createApiKey(createReqVO)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @PutMapping("/update") |     @PutMapping("/update") | ||||||
|     @Operation(summary = "更新AI API 密钥") |     @Operation(summary = "更新 API 密钥") | ||||||
|     @PreAuthorize("@ss.hasPermission('ai:api-key:update')") |     @PreAuthorize("@ss.hasPermission('ai:api-key:update')") | ||||||
|     public CommonResult<Boolean> updateApiKey(@Valid @RequestBody AiApiKeySaveReqVO updateReqVO) { |     public CommonResult<Boolean> updateApiKey(@Valid @RequestBody AiApiKeySaveReqVO updateReqVO) { | ||||||
|         apiKeyService.updateApiKey(updateReqVO); |         apiKeyService.updateApiKey(updateReqVO); | ||||||
| @ -44,7 +44,7 @@ public class AiApiKeyController { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @DeleteMapping("/delete") |     @DeleteMapping("/delete") | ||||||
|     @Operation(summary = "删除AI API 密钥") |     @Operation(summary = "删除 API 密钥") | ||||||
|     @Parameter(name = "id", description = "编号", required = true) |     @Parameter(name = "id", description = "编号", required = true) | ||||||
|     @PreAuthorize("@ss.hasPermission('ai:api-key:delete')") |     @PreAuthorize("@ss.hasPermission('ai:api-key:delete')") | ||||||
|     public CommonResult<Boolean> deleteApiKey(@RequestParam("id") Long id) { |     public CommonResult<Boolean> deleteApiKey(@RequestParam("id") Long id) { | ||||||
| @ -53,7 +53,7 @@ public class AiApiKeyController { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @GetMapping("/get") |     @GetMapping("/get") | ||||||
|     @Operation(summary = "获得AI API 密钥") |     @Operation(summary = "获得 API 密钥") | ||||||
|     @Parameter(name = "id", description = "编号", required = true, example = "1024") |     @Parameter(name = "id", description = "编号", required = true, example = "1024") | ||||||
|     @PreAuthorize("@ss.hasPermission('ai:api-key:query')") |     @PreAuthorize("@ss.hasPermission('ai:api-key:query')") | ||||||
|     public CommonResult<AiApiKeyRespVO> getApiKey(@RequestParam("id") Long id) { |     public CommonResult<AiApiKeyRespVO> getApiKey(@RequestParam("id") Long id) { | ||||||
| @ -62,7 +62,7 @@ public class AiApiKeyController { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @GetMapping("/page") |     @GetMapping("/page") | ||||||
|     @Operation(summary = "获得AI API 密钥分页") |     @Operation(summary = "获得 API 密钥分页") | ||||||
|     @PreAuthorize("@ss.hasPermission('ai:api-key:query')") |     @PreAuthorize("@ss.hasPermission('ai:api-key:query')") | ||||||
|     public CommonResult<PageResult<AiApiKeyRespVO>> getApiKeyPage(@Valid AiApiKeyPageReqVO pageReqVO) { |     public CommonResult<PageResult<AiApiKeyRespVO>> getApiKeyPage(@Valid AiApiKeyPageReqVO pageReqVO) { | ||||||
|         PageResult<AiApiKeyDO> pageResult = apiKeyService.getApiKeyPage(pageReqVO); |         PageResult<AiApiKeyDO> pageResult = apiKeyService.getApiKeyPage(pageReqVO); | ||||||
|  | |||||||
| @ -2,60 +2,71 @@ package cn.iocoder.yudao.module.ai.controller.admin.model; | |||||||
|  |  | ||||||
| import cn.iocoder.yudao.framework.common.pojo.CommonResult; | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||||
| import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelAddReqVO; | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||||||
| import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelListReqVO; | import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelPageReqVO; | ||||||
| import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelListRespVO; | import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelRespVO; | ||||||
| import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelUpdateReqVO; | import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelSaveReqVO; | ||||||
| import cn.iocoder.yudao.module.ai.service.AiChatModelService; | import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; | ||||||
|  | import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; | ||||||
| import io.swagger.v3.oas.annotations.Operation; | import io.swagger.v3.oas.annotations.Operation; | ||||||
|  | import io.swagger.v3.oas.annotations.Parameter; | ||||||
| import io.swagger.v3.oas.annotations.tags.Tag; | import io.swagger.v3.oas.annotations.tags.Tag; | ||||||
| import lombok.AllArgsConstructor; | import jakarta.annotation.Resource; | ||||||
| import lombok.extern.slf4j.Slf4j; | import jakarta.validation.Valid; | ||||||
|  | import org.springframework.security.access.prepost.PreAuthorize; | ||||||
| import org.springframework.validation.annotation.Validated; | import org.springframework.validation.annotation.Validated; | ||||||
| import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||||
|  |  | ||||||
| // TODO @fan:调整下接口;相关 vo 的命名等等;modal => model | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||||||
|  |  | ||||||
| /** | @Tag(name = "管理后台 - AI 聊天模型") | ||||||
|  * ai 模型 |  | ||||||
|  * |  | ||||||
|  * @author fansili |  | ||||||
|  * @time 2024/4/24 19:42 |  | ||||||
|  * @since 1.0 |  | ||||||
|  */ |  | ||||||
| @Tag(name = "A6-AI模型") |  | ||||||
| @RestController | @RestController | ||||||
| @RequestMapping("/ai/chat/model") | @RequestMapping("/ai/chat-model") | ||||||
| @Slf4j | @Validated | ||||||
| @AllArgsConstructor |  | ||||||
| public class AiChatModelController { | public class AiChatModelController { | ||||||
|  |  | ||||||
|     private final AiChatModelService aiChatModelService; |     @Resource | ||||||
|  |     private AiChatModelService chatModelService; | ||||||
|  |  | ||||||
|     @Operation(summary = "ai模型 - 模型列表") |     @PostMapping("/create") | ||||||
|     @GetMapping("/list") |     @Operation(summary = "创建聊天模型") | ||||||
|     public PageResult<AiChatModelListRespVO> list(@ModelAttribute AiChatModelListReqVO req) { |     @PreAuthorize("@ss.hasPermission('ai:chat-model:create')") | ||||||
|         return aiChatModelService.list(req); |     public CommonResult<Long> createChatModel(@Valid @RequestBody AiChatModelSaveReqVO createReqVO) { | ||||||
|  |         return success(chatModelService.createChatModel(createReqVO)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Operation(summary = "ai模型 - 添加") |     @PutMapping("/update") | ||||||
|     @PutMapping("/add") |     @Operation(summary = "更新聊天模型") | ||||||
|     public CommonResult<Void> add(@RequestBody @Validated AiChatModelAddReqVO req) { |     @PreAuthorize("@ss.hasPermission('ai:chat-model:update')") | ||||||
|         aiChatModelService.add(req); |     public CommonResult<Boolean> updateChatModel(@Valid @RequestBody AiChatModelSaveReqVO updateReqVO) { | ||||||
|         return CommonResult.success(null); |         chatModelService.updateChatModel(updateReqVO); | ||||||
|  |         return success(true); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Operation(summary = "ai模型 - 修改") |  | ||||||
|     @PostMapping("/update") |  | ||||||
|     public CommonResult<Void> update(@RequestBody @Validated AiChatModelUpdateReqVO req) { |  | ||||||
|         aiChatModelService.update(req); |  | ||||||
|         return CommonResult.success(null); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Operation(summary = "ai模型 - 删除") |  | ||||||
|     @DeleteMapping("/delete") |     @DeleteMapping("/delete") | ||||||
|     public CommonResult<Void> delete(@RequestParam("id") Long id) { |     @Operation(summary = "删除聊天模型") | ||||||
|         aiChatModelService.delete(id); |     @Parameter(name = "id", description = "编号", required = true) | ||||||
|         return CommonResult.success(null); |     @PreAuthorize("@ss.hasPermission('ai:chat-model:delete')") | ||||||
|  |     public CommonResult<Boolean> deleteChatModel(@RequestParam("id") Long id) { | ||||||
|  |         chatModelService.deleteChatModel(id); | ||||||
|  |         return success(true); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @GetMapping("/get") | ||||||
|  |     @Operation(summary = "获得聊天模型") | ||||||
|  |     @Parameter(name = "id", description = "编号", required = true, example = "1024") | ||||||
|  |     @PreAuthorize("@ss.hasPermission('ai:chat-model:query')") | ||||||
|  |     public CommonResult<AiChatModelRespVO> getChatModel(@RequestParam("id") Long id) { | ||||||
|  |         AiChatModelDO chatModel = chatModelService.getChatModel(id); | ||||||
|  |         return success(BeanUtils.toBean(chatModel, AiChatModelRespVO.class)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @GetMapping("/page") | ||||||
|  |     @Operation(summary = "获得聊天模型分页") | ||||||
|  |     @PreAuthorize("@ss.hasPermission('ai:chat-model:query')") | ||||||
|  |     public CommonResult<PageResult<AiChatModelRespVO>> getChatModelPage(@Valid AiChatModelPageReqVO pageReqVO) { | ||||||
|  |         PageResult<AiChatModelDO> pageResult = chatModelService.getChatModelPage(pageReqVO); | ||||||
|  |         return success(BeanUtils.toBean(pageResult, AiChatModelRespVO.class)); | ||||||
|  |     } | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -6,26 +6,20 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.*; | |||||||
| import cn.iocoder.yudao.module.ai.service.AiChatRoleService; | import cn.iocoder.yudao.module.ai.service.AiChatRoleService; | ||||||
| import io.swagger.v3.oas.annotations.Operation; | import io.swagger.v3.oas.annotations.Operation; | ||||||
| import io.swagger.v3.oas.annotations.tags.Tag; | import io.swagger.v3.oas.annotations.tags.Tag; | ||||||
|  | import jakarta.annotation.Resource; | ||||||
| import lombok.AllArgsConstructor; | import lombok.AllArgsConstructor; | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
| import org.springframework.validation.annotation.Validated; | import org.springframework.validation.annotation.Validated; | ||||||
| import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||||
|  |  | ||||||
| // TODO @fan:调整下接口;相关 vo 的命名等等;modal => model | @Tag(name = "管理后台 - AI 聊天角色") | ||||||
| /** |  | ||||||
|  * ai chat 角色 |  | ||||||
|  * |  | ||||||
|  * @fansili |  | ||||||
|  * @since v1.0 |  | ||||||
|  */ |  | ||||||
| @Tag(name = "A4-chat角色") |  | ||||||
| @RestController | @RestController | ||||||
| @RequestMapping("/ai/chat/role") | @RequestMapping("/ai/chat-role") | ||||||
| @Slf4j | @Validated | ||||||
| @AllArgsConstructor |  | ||||||
| public class AiChatRoleController { | public class AiChatRoleController { | ||||||
|  |  | ||||||
|     private final AiChatRoleService chatRoleService; |     @Resource | ||||||
|  |     private AiChatRoleService chatRoleService; | ||||||
|  |  | ||||||
|     @Operation(summary = "chat角色 - 角色列表") |     @Operation(summary = "chat角色 - 角色列表") | ||||||
|     @GetMapping("/list") |     @GetMapping("/list") | ||||||
| @ -60,4 +54,9 @@ public class AiChatRoleController { | |||||||
|         chatRoleService.delete(id); |         chatRoleService.delete(id); | ||||||
|         return CommonResult.success(null); |         return CommonResult.success(null); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // ========== 角色管理 ========== | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,22 @@ | |||||||
|  | package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel; | ||||||
|  |  | ||||||
|  | import lombok.*; | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  | import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||||||
|  |  | ||||||
|  | @Schema(description = "管理后台 - API 聊天模型分页 Request VO") | ||||||
|  | @Data | ||||||
|  | @EqualsAndHashCode(callSuper = true) | ||||||
|  | @ToString(callSuper = true) | ||||||
|  | public class AiChatModelPageReqVO extends PageParam { | ||||||
|  |  | ||||||
|  |     @Schema(description = "模型名字", example = "张三") | ||||||
|  |     private String name; | ||||||
|  |  | ||||||
|  |     @Schema(description = "模型标识", example = "gpt-3.5-turbo-0125") | ||||||
|  |     private String model; | ||||||
|  |  | ||||||
|  |     @Schema(description = "模型平台", example = "OpenAI") | ||||||
|  |     private String platform; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,45 @@ | |||||||
|  | package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel; | ||||||
|  |  | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | import java.time.LocalDateTime; | ||||||
|  |  | ||||||
|  | @Schema(description = "管理后台 - AI 聊天模型 Response VO") | ||||||
|  | @Data | ||||||
|  | public class AiChatModelRespVO { | ||||||
|  |  | ||||||
|  |     @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2630") | ||||||
|  |     private Long id; | ||||||
|  |  | ||||||
|  |     @Schema(description = "API 秘钥编号", example = "22042") | ||||||
|  |     private Long keyId; | ||||||
|  |  | ||||||
|  |     @Schema(description = "模型名字", example = "张三") | ||||||
|  |     private String name; | ||||||
|  |  | ||||||
|  |     @Schema(description = "模型标识", example = "gpt-3.5-turbo-0125") | ||||||
|  |     private String model; | ||||||
|  |  | ||||||
|  |     @Schema(description = "模型平台", example = "OpenAI") | ||||||
|  |     private String platform; | ||||||
|  |  | ||||||
|  |     @Schema(description = "排序", example = "1") | ||||||
|  |     private Integer sort; | ||||||
|  |  | ||||||
|  |     @Schema(description = "状态", example = "2") | ||||||
|  |     private Integer status; | ||||||
|  |  | ||||||
|  |     @Schema(description = "温度参数", example = "1") | ||||||
|  |     private Double temperature; | ||||||
|  |  | ||||||
|  |     @Schema(description = "单条回复的最大 Token 数量", example = "4096") | ||||||
|  |     private Integer maxTokens; | ||||||
|  |  | ||||||
|  |     @Schema(description = "上下文的最大 Message 数量", example = "8192") | ||||||
|  |     private Integer maxContexts; | ||||||
|  |  | ||||||
|  |     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||||||
|  |     private LocalDateTime createTime; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,50 @@ | |||||||
|  | package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||||||
|  | import cn.iocoder.yudao.framework.common.validation.InEnum; | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  | import lombok.*; | ||||||
|  | import jakarta.validation.constraints.*; | ||||||
|  |  | ||||||
|  | @Schema(description = "管理后台 - API 聊天模型新增/修改 Request VO") | ||||||
|  | @Data | ||||||
|  | public class AiChatModelSaveReqVO { | ||||||
|  |  | ||||||
|  |     @Schema(description = "编号", example = "2630") | ||||||
|  |     private Long id; | ||||||
|  |  | ||||||
|  |     @Schema(description = "API 秘钥编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22042") | ||||||
|  |     @NotNull(message = "API 秘钥编号不能为空") | ||||||
|  |     private Long keyId; | ||||||
|  |  | ||||||
|  |     @Schema(description = "模型名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") | ||||||
|  |     @NotEmpty(message = "模型名字不能为空") | ||||||
|  |     private String name; | ||||||
|  |  | ||||||
|  |     @Schema(description = "模型标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "gpt-3.5-turbo-0125") | ||||||
|  |     @NotEmpty(message = "模型标识不能为空") | ||||||
|  |     private String model; | ||||||
|  |  | ||||||
|  |     @Schema(description = "模型平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI") | ||||||
|  |     @NotEmpty(message = "模型平台不能为空") | ||||||
|  |     private String platform; | ||||||
|  |  | ||||||
|  |     @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||||
|  |     @NotNull(message = "排序不能为空") | ||||||
|  |     private Integer sort; | ||||||
|  |  | ||||||
|  |     @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||||
|  |     @InEnum(CommonStatusEnum.class) | ||||||
|  |     @NotNull(message = "状态不能为空") | ||||||
|  |     private Integer status; | ||||||
|  |  | ||||||
|  |     @Schema(description = "温度参数", example = "1") | ||||||
|  |     private Double temperature; | ||||||
|  |  | ||||||
|  |     @Schema(description = "单条回复的最大 Token 数量", example = "4096") | ||||||
|  |     private Integer maxTokens; | ||||||
|  |  | ||||||
|  |     @Schema(description = "上下文的最大 Message 数量", example = "8192") | ||||||
|  |     private Integer maxContexts; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -1,50 +0,0 @@ | |||||||
| package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; |  | ||||||
|  |  | ||||||
| import io.swagger.v3.oas.annotations.media.Schema; |  | ||||||
| import jakarta.validation.constraints.Size; |  | ||||||
| import lombok.Data; |  | ||||||
| import lombok.experimental.Accessors; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * modal list |  | ||||||
|  * |  | ||||||
|  * @author fansili |  | ||||||
|  * @time 2024/4/24 19:56 |  | ||||||
|  * @since 1.0 |  | ||||||
|  */ |  | ||||||
| @Data |  | ||||||
| @Accessors(chain = true) |  | ||||||
| public class AiChatModalRespVO { |  | ||||||
|  |  | ||||||
|     @Schema(description = "编号") |  | ||||||
|     private Long id; |  | ||||||
|  |  | ||||||
|     @Schema(description = "API 秘钥编号") |  | ||||||
|     private Long keyId; |  | ||||||
|  |  | ||||||
|     @Schema(description = "模型名字") |  | ||||||
|     private String name; |  | ||||||
|  |  | ||||||
|     @Schema(description = "模型类型(qianwen、yiyan、xinghuo、openai)") |  | ||||||
|     private String model; |  | ||||||
|  |  | ||||||
|     @Size(max = 32, message = "模型平台最大32个字符") |  | ||||||
|     private String platform; |  | ||||||
|  |  | ||||||
|     @Schema(description = "排序") |  | ||||||
|     private Integer sort; |  | ||||||
|  |  | ||||||
|     @Schema(description = "状态") |  | ||||||
|     private Integer status; |  | ||||||
|  |  | ||||||
|     // ========== 会话配置 ========== |  | ||||||
|  |  | ||||||
|     @Schema(description = "温度参数") |  | ||||||
|     private Integer temperature; |  | ||||||
|  |  | ||||||
|     @Schema(description = "单条回复的最大 Token 数量") |  | ||||||
|     private Integer maxTokens; |  | ||||||
|  |  | ||||||
|     @Schema(description = "上下文的最大 Message 数量") |  | ||||||
|     private Integer maxContexts; |  | ||||||
| } |  | ||||||
| @ -1,63 +0,0 @@ | |||||||
| package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; |  | ||||||
|  |  | ||||||
| import io.swagger.v3.oas.annotations.media.Schema; |  | ||||||
| import jakarta.validation.constraints.NotNull; |  | ||||||
| import jakarta.validation.constraints.Size; |  | ||||||
| import lombok.Data; |  | ||||||
| import lombok.experimental.Accessors; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * ai chat modal |  | ||||||
|  * |  | ||||||
|  * @author fansili |  | ||||||
|  * @time 2024/4/24 19:47 |  | ||||||
|  * @since 1.0 |  | ||||||
|  */ |  | ||||||
| @Data |  | ||||||
| @Accessors(chain = true) |  | ||||||
| public class AiChatModalUpdateReqVO { |  | ||||||
|  |  | ||||||
|     @Schema(description = "编号") |  | ||||||
|     @Size(max = 32, message = "编号最大32个字符") |  | ||||||
|     @NotNull(message = "编号不能为空") |  | ||||||
|     private Long id; |  | ||||||
|  |  | ||||||
|     @Schema(description = "API 秘钥编号") |  | ||||||
|     @Size(max = 32, message = "API 秘钥编号最大32个字符") |  | ||||||
|     @NotNull(message = "API 秘钥编号不能为空!") |  | ||||||
|     private Long keyId; |  | ||||||
|  |  | ||||||
|     @Schema(description = "模型名字") |  | ||||||
|     @Size(max = 60, message = "模型名字最大60个字符") |  | ||||||
|     @NotNull(message = "模型名字不能为空!") |  | ||||||
|     private String name; |  | ||||||
|  |  | ||||||
|     @Schema(description = "模型类型(qianwen、yiyan、xinghuo、openai)") |  | ||||||
|     @Size(max = 32, message = "模型类型最大32个字符") |  | ||||||
|     @NotNull(message = "model模型不能为空!") |  | ||||||
|     private String model; |  | ||||||
|  |  | ||||||
|     @Size(max = 32, message = "模型平台最大32个字符") |  | ||||||
|     @Schema(description = "模型平台 参考 AiPlatformEnum") |  | ||||||
|     @NotNull(message = "平台不能为空!") |  | ||||||
|     private String platform; |  | ||||||
|  |  | ||||||
|     @Schema(description = "排序") |  | ||||||
|     @NotNull(message = "sort排序不能为空!") |  | ||||||
|     private Integer sort; |  | ||||||
|  |  | ||||||
|     @Schema(description = "状态") |  | ||||||
|     @NotNull(message = "状态不能为空!") |  | ||||||
|     private Integer status; |  | ||||||
|  |  | ||||||
|     // ========== 会话配置 ========== |  | ||||||
|  |  | ||||||
|     @Schema(description = "温度参数") |  | ||||||
|     private Integer temperature; |  | ||||||
|  |  | ||||||
|     @Schema(description = "单条回复的最大 Token 数量") |  | ||||||
|     private Integer maxTokens; |  | ||||||
|  |  | ||||||
|     @Schema(description = "上下文的最大 Message 数量") |  | ||||||
|     private Integer maxContexts; |  | ||||||
| } |  | ||||||
| @ -1,53 +0,0 @@ | |||||||
| package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; |  | ||||||
|  |  | ||||||
| import io.swagger.v3.oas.annotations.media.Schema; |  | ||||||
| import jakarta.validation.constraints.NotNull; |  | ||||||
| import jakarta.validation.constraints.Size; |  | ||||||
| import lombok.Data; |  | ||||||
| import lombok.experimental.Accessors; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * ai chat modal |  | ||||||
|  * |  | ||||||
|  * @author fansili |  | ||||||
|  * @time 2024/4/24 19:47 |  | ||||||
|  * @since 1.0 |  | ||||||
|  */ |  | ||||||
| @Data |  | ||||||
| @Accessors(chain = true) |  | ||||||
| public class AiChatModelAddReqVO { |  | ||||||
|  |  | ||||||
|     @Schema(description = "API 秘钥编号") |  | ||||||
|     @NotNull(message = "API 秘钥编号不能为空!") |  | ||||||
|     private Long keyId; |  | ||||||
|  |  | ||||||
|     @Schema(description = "模型名字") |  | ||||||
|     @Size(max = 60, message = "模型名字最大60个字符") |  | ||||||
|     @NotNull(message = "模型名字不能为空!") |  | ||||||
|     private String name; |  | ||||||
|  |  | ||||||
|     @Schema(description = "模型类型(qianwen、yiyan、xinghuo、openai)") |  | ||||||
|     @Size(max = 32, message = "模型类型最大32个字符") |  | ||||||
|     @NotNull(message = "model模型不能为空!") |  | ||||||
|     private String model; |  | ||||||
|  |  | ||||||
|     @Size(max = 32, message = "模型平台最大32个字符") |  | ||||||
|     @Schema(description = "模型平台 参考 AiPlatformEnum") |  | ||||||
|     @NotNull(message = "平台不能为空!") |  | ||||||
|     private String platform; |  | ||||||
|  |  | ||||||
|     @Schema(description = "排序") |  | ||||||
|     @NotNull(message = "sort排序不能为空!") |  | ||||||
|     private Integer sort; |  | ||||||
|  |  | ||||||
|     // ========== 会话配置 ========== |  | ||||||
|  |  | ||||||
|     @Schema(description = "温度参数") |  | ||||||
|     private Integer temperature; |  | ||||||
|  |  | ||||||
|     @Schema(description = "单条回复的最大 Token 数量") |  | ||||||
|     private Integer maxTokens; |  | ||||||
|  |  | ||||||
|     @Schema(description = "上下文的最大 Message 数量") |  | ||||||
|     private Integer maxContexts; |  | ||||||
| } |  | ||||||
| @ -1,22 +0,0 @@ | |||||||
| package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; |  | ||||||
|  |  | ||||||
| import cn.iocoder.yudao.framework.common.pojo.PageParam; |  | ||||||
| import io.swagger.v3.oas.annotations.media.Schema; |  | ||||||
| import lombok.Data; |  | ||||||
| import lombok.experimental.Accessors; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * modal list |  | ||||||
|  * |  | ||||||
|  * @author fansili |  | ||||||
|  * @time 2024/4/24 19:56 |  | ||||||
|  * @since 1.0 |  | ||||||
|  */ |  | ||||||
| @Data |  | ||||||
| @Accessors(chain = true) |  | ||||||
| public class AiChatModelListReqVO extends PageParam { |  | ||||||
|  |  | ||||||
|     @Schema(description = "名字搜搜") |  | ||||||
|     private String search; |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @ -1,50 +0,0 @@ | |||||||
| package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; |  | ||||||
|  |  | ||||||
| import io.swagger.v3.oas.annotations.media.Schema; |  | ||||||
| import lombok.Data; |  | ||||||
| import lombok.experimental.Accessors; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * modal list |  | ||||||
|  * |  | ||||||
|  * @author fansili |  | ||||||
|  * @time 2024/4/24 19:56 |  | ||||||
|  * @since 1.0 |  | ||||||
|  */ |  | ||||||
| @Data |  | ||||||
| @Accessors(chain = true) |  | ||||||
| public class AiChatModelListRespVO { |  | ||||||
|  |  | ||||||
|     @Schema(description = "编号") |  | ||||||
|     private Long id; |  | ||||||
|  |  | ||||||
|     @Schema(description = "API 秘钥编号") |  | ||||||
|     private Long keyId; |  | ||||||
|  |  | ||||||
|     @Schema(description = "模型名称") |  | ||||||
|     private String name; |  | ||||||
|  |  | ||||||
|     @Schema(description = "模型标志") |  | ||||||
|     private String model; |  | ||||||
|  |  | ||||||
|     @Schema(description = "平台") |  | ||||||
|     private String platform; |  | ||||||
|  |  | ||||||
|     @Schema(description = "排序值") |  | ||||||
|     private Integer sort; |  | ||||||
|  |  | ||||||
|     @Schema(description = "状态") |  | ||||||
|     private Integer status; |  | ||||||
|  |  | ||||||
|     // ========== 会话配置 ========== |  | ||||||
|  |  | ||||||
|     @Schema(description = "温度参数") |  | ||||||
|     private Double temperature; |  | ||||||
|  |  | ||||||
|     @Schema(description = "单条回复的最大 Token 数量") |  | ||||||
|     private Integer maxTokens; |  | ||||||
|  |  | ||||||
|     @Schema(description = "上下文的最大 Message 数量") |  | ||||||
|     private Integer maxContexts; |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @ -1,57 +0,0 @@ | |||||||
| package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; |  | ||||||
|  |  | ||||||
| import io.swagger.v3.oas.annotations.media.Schema; |  | ||||||
| import jakarta.validation.constraints.NotNull; |  | ||||||
| import jakarta.validation.constraints.Size; |  | ||||||
| import lombok.Data; |  | ||||||
| import lombok.experimental.Accessors; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * ai chat modal |  | ||||||
|  * |  | ||||||
|  * @author fansili |  | ||||||
|  * @time 2024/4/24 19:47 |  | ||||||
|  * @since 1.0 |  | ||||||
|  */ |  | ||||||
| @Data |  | ||||||
| @Accessors(chain = true) |  | ||||||
| public class AiChatModelUpdateReqVO { |  | ||||||
|  |  | ||||||
|     @Schema(description = "编号") |  | ||||||
|     @NotNull(message = "编号不能为空") |  | ||||||
|     private Long id; |  | ||||||
|  |  | ||||||
|     @Schema(description = "API 秘钥编号") |  | ||||||
|     @NotNull(message = "API 秘钥编号不能为空!") |  | ||||||
|     private Long keyId; |  | ||||||
|  |  | ||||||
|     @Schema(description = "模型名字") |  | ||||||
|     @Size(max = 60, message = "模型名字最大60个字符") |  | ||||||
|     @NotNull(message = "模型名字不能为空!") |  | ||||||
|     private String name; |  | ||||||
|  |  | ||||||
|     @Schema(description = "模型类型(qianwen、yiyan、xinghuo、openai)") |  | ||||||
|     @Size(max = 32, message = "模型类型最大32个字符") |  | ||||||
|     @NotNull(message = "model模型不能为空!") |  | ||||||
|     private String model; |  | ||||||
|  |  | ||||||
|     @Size(max = 32, message = "模型平台最大32个字符") |  | ||||||
|     @Schema(description = "模型平台 参考 AiPlatformEnum") |  | ||||||
|     @NotNull(message = "平台不能为空!") |  | ||||||
|     private String platform; |  | ||||||
|  |  | ||||||
|     @Schema(description = "排序") |  | ||||||
|     @NotNull(message = "sort排序不能为空!") |  | ||||||
|     private Integer sort; |  | ||||||
|  |  | ||||||
|     // ========== 会话配置 ========== |  | ||||||
|  |  | ||||||
|     @Schema(description = "温度参数") |  | ||||||
|     private Integer temperature; |  | ||||||
|  |  | ||||||
|     @Schema(description = "单条回复的最大 Token 数量") |  | ||||||
|     private Integer maxTokens; |  | ||||||
|  |  | ||||||
|     @Schema(description = "上下文的最大 Message 数量") |  | ||||||
|     private Integer maxContexts; |  | ||||||
| } |  | ||||||
| @ -19,14 +19,6 @@ public interface AiChatMessageConvert { | |||||||
|  |  | ||||||
|     AiChatMessageConvert INSTANCE = Mappers.getMapper(AiChatMessageConvert.class); |     AiChatMessageConvert INSTANCE = Mappers.getMapper(AiChatMessageConvert.class); | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 转换 ChatMessageListRes |  | ||||||
|      * |  | ||||||
|      * @param list |  | ||||||
|      * @return |  | ||||||
|      */ |  | ||||||
|     List<AiChatMessageRespVO> convert(List<AiChatMessageDO> list); |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 转换 AiChatMessageRespVO |      * 转换 AiChatMessageRespVO | ||||||
|      * |      * | ||||||
|  | |||||||
| @ -1,57 +0,0 @@ | |||||||
| package cn.iocoder.yudao.module.ai.convert; |  | ||||||
|  |  | ||||||
| import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRespVO; |  | ||||||
| import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelAddReqVO; |  | ||||||
| import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelListRespVO; |  | ||||||
| import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelUpdateReqVO; |  | ||||||
| import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; |  | ||||||
| import org.mapstruct.Mapper; |  | ||||||
| import org.mapstruct.factory.Mappers; |  | ||||||
|  |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * 聊天 modal |  | ||||||
|  * |  | ||||||
|  * @author fansili |  | ||||||
|  * @time 2024/4/18 16:39 |  | ||||||
|  * @since 1.0 |  | ||||||
|  */ |  | ||||||
| @Mapper |  | ||||||
| public interface AiChatModelConvert { |  | ||||||
|  |  | ||||||
|     AiChatModelConvert INSTANCE = Mappers.getMapper(AiChatModelConvert.class); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 转换 - AiChatModalListRes |  | ||||||
|      * |  | ||||||
|      * @param list |  | ||||||
|      * @return |  | ||||||
|      */ |  | ||||||
|     List<AiChatModelListRespVO> convertAiChatModalListRes(List<AiChatModelDO> list); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 转换 - AiChatModalDO |  | ||||||
|      * |  | ||||||
|      * @param req |  | ||||||
|      * @return |  | ||||||
|      */ |  | ||||||
|     AiChatModelDO convertAiChatModalDO(AiChatModelAddReqVO req); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 转换 - AiChatModalDO |  | ||||||
|      * |  | ||||||
|      * @param req |  | ||||||
|      * @return |  | ||||||
|      */ |  | ||||||
|     AiChatModelDO convertAiChatModalDO(AiChatModelUpdateReqVO req); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 转换 - AiChatModalRes |  | ||||||
|      * |  | ||||||
|      * @param aiChatModalDO |  | ||||||
|      * @return |  | ||||||
|      */ |  | ||||||
|     AiChatModalRespVO convertAiChatModalRes(AiChatModelDO aiChatModalDO); |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @ -5,21 +5,19 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam; | |||||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||||
| import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||||||
| import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||||||
|  | import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelPageReqVO; | ||||||
| import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; | import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; | ||||||
| import org.apache.ibatis.annotations.Mapper; | import org.apache.ibatis.annotations.Mapper; | ||||||
| import org.springframework.stereotype.Repository; |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * chat modal |  * API 聊天模型 Mapper | ||||||
|  * |  * | ||||||
|  * @author fansili |  * @author fansili | ||||||
|  * @time 2024/4/24 19:41 |  | ||||||
|  * @since 1.0 |  | ||||||
|  */ |  */ | ||||||
| @Repository |  | ||||||
| @Mapper | @Mapper | ||||||
| public interface AiChatModelMapper extends BaseMapperX<AiChatModelDO> { | public interface AiChatModelMapper extends BaseMapperX<AiChatModelDO> { | ||||||
|  |  | ||||||
|  |     // TODO 芋艿:要搞一下 | ||||||
|     /** |     /** | ||||||
|      * 查询 - 第一个modal |      * 查询 - 第一个modal | ||||||
|      * |      * | ||||||
| @ -36,5 +34,12 @@ public interface AiChatModelMapper extends BaseMapperX<AiChatModelDO> { | |||||||
|         return pageResult.getList().get(0); |         return pageResult.getList().get(0); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     default PageResult<AiChatModelDO> selectPage(AiChatModelPageReqVO reqVO) { | ||||||
|  |         return selectPage(reqVO, new LambdaQueryWrapperX<AiChatModelDO>() | ||||||
|  |                 .likeIfPresent(AiChatModelDO::getName, reqVO.getName()) | ||||||
|  |                 .eqIfPresent(AiChatModelDO::getModel, reqVO.getModel()) | ||||||
|  |                 .eqIfPresent(AiChatModelDO::getPlatform, reqVO.getPlatform()) | ||||||
|  |                 .orderByDesc(AiChatModelDO::getId)); | ||||||
|  |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,67 +0,0 @@ | |||||||
| package cn.iocoder.yudao.module.ai.service; |  | ||||||
|  |  | ||||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; |  | ||||||
| import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.*; |  | ||||||
| import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * ai modal |  | ||||||
|  * |  | ||||||
|  * @author fansili |  | ||||||
|  * @time 2024/4/24 19:42 |  | ||||||
|  * @since 1.0 |  | ||||||
|  */ |  | ||||||
| public interface AiChatModelService { |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * ai modal - 列表 |  | ||||||
|      * |  | ||||||
|      * @param req |  | ||||||
|      * @return |  | ||||||
|      */ |  | ||||||
|     PageResult<AiChatModelListRespVO> list(AiChatModelListReqVO req); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * ai modal - 添加 |  | ||||||
|      * |  | ||||||
|      * @param req |  | ||||||
|      */ |  | ||||||
|     void add(AiChatModelAddReqVO req); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * ai modal - 更新 |  | ||||||
|      * |  | ||||||
|      * @param req |  | ||||||
|      */ |  | ||||||
|     void update(AiChatModelUpdateReqVO req); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * ai modal - 删除 |  | ||||||
|      * |  | ||||||
|      * @param id |  | ||||||
|      */ |  | ||||||
|     void delete(Long id); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 获取 - 获取 modal |  | ||||||
|      * |  | ||||||
|      * @param modalId |  | ||||||
|      * @return |  | ||||||
|      */ |  | ||||||
|     AiChatModalRespVO getChatModalOfValidate(Long modalId); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 校验 - 是否存在 |  | ||||||
|      * |  | ||||||
|      * @param id |  | ||||||
|      * @return |  | ||||||
|      */ |  | ||||||
|     AiChatModelDO validateExists(Long id); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 校验 - 校验是否可用 |  | ||||||
|      * |  | ||||||
|      * @param chatModal |  | ||||||
|      */ |  | ||||||
|     void validateAvailable(AiChatModalRespVO chatModal); |  | ||||||
| } |  | ||||||
| @ -72,4 +72,5 @@ public interface AiChatRoleService { | |||||||
|      * @param aiChatRoleDO |      * @param aiChatRoleDO | ||||||
|      */ |      */ | ||||||
|     void validateIsPublic(AiChatRoleDO aiChatRoleDO); |     void validateIsPublic(AiChatRoleDO aiChatRoleDO); | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,127 +0,0 @@ | |||||||
| package cn.iocoder.yudao.module.ai.service.impl; |  | ||||||
|  |  | ||||||
| import cn.hutool.core.util.StrUtil; |  | ||||||
| import cn.hutool.extra.validation.ValidationUtil; |  | ||||||
| import cn.iocoder.yudao.framework.ai.AiPlatformEnum; |  | ||||||
| import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |  | ||||||
| import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; |  | ||||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; |  | ||||||
| import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |  | ||||||
| import cn.iocoder.yudao.module.ai.ErrorCodeConstants; |  | ||||||
| import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.*; |  | ||||||
| import cn.iocoder.yudao.module.ai.convert.AiChatModelConvert; |  | ||||||
| import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; |  | ||||||
| import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModelMapper; |  | ||||||
| import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalConfigVO; |  | ||||||
| import cn.iocoder.yudao.module.ai.service.AiChatModelService; |  | ||||||
| import jakarta.validation.ConstraintViolation; |  | ||||||
| import lombok.AllArgsConstructor; |  | ||||||
| import lombok.extern.slf4j.Slf4j; |  | ||||||
| import org.springframework.stereotype.Service; |  | ||||||
|  |  | ||||||
| import java.util.List; |  | ||||||
| import java.util.Set; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * ai 模型 |  | ||||||
|  * |  | ||||||
|  * @author fansili |  | ||||||
|  * @time 2024/4/24 19:42 |  | ||||||
|  * @since 1.0 |  | ||||||
|  */ |  | ||||||
| @AllArgsConstructor |  | ||||||
| @Service |  | ||||||
| @Slf4j |  | ||||||
| public class AiChatModalServiceImpl implements AiChatModelService { |  | ||||||
|  |  | ||||||
|     private final AiChatModelMapper aiChatModelMapper; |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public PageResult<AiChatModelListRespVO> list(AiChatModelListReqVO req) { |  | ||||||
|         LambdaQueryWrapperX<AiChatModelDO> queryWrapperX = new LambdaQueryWrapperX<>(); |  | ||||||
|         // 查询的都是未禁用的模型 |  | ||||||
|         queryWrapperX.eq(AiChatModelDO::getStatus, CommonStatusEnum.ENABLE.getStatus()); |  | ||||||
|         // search |  | ||||||
|         if (!StrUtil.isBlank(req.getSearch())) { |  | ||||||
|             queryWrapperX.like(AiChatModelDO::getName, req.getSearch().trim()); |  | ||||||
|         } |  | ||||||
|         // 默认排序 |  | ||||||
|         queryWrapperX.orderByAsc(AiChatModelDO::getSort); |  | ||||||
|         // 查询 |  | ||||||
|         PageResult<AiChatModelDO> aiChatModalDOPageResult = aiChatModelMapper.selectPage(req, queryWrapperX); |  | ||||||
|         // 转换 res |  | ||||||
|         List<AiChatModelListRespVO> resList = AiChatModelConvert.INSTANCE.convertAiChatModalListRes(aiChatModalDOPageResult.getList()); |  | ||||||
|         return new PageResult<>(resList, aiChatModalDOPageResult.getTotal()); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public void add(AiChatModelAddReqVO req) { |  | ||||||
|         // 校验 platform、type |  | ||||||
|         validatePlatform(req.getPlatform()); |  | ||||||
|         // 转换 do |  | ||||||
|         AiChatModelDO insertChatModalDO = AiChatModelConvert.INSTANCE.convertAiChatModalDO(req); |  | ||||||
|         // 设置默认属性 |  | ||||||
|         insertChatModalDO.setStatus(CommonStatusEnum.ENABLE.getStatus()); |  | ||||||
|         // 保存数据库 |  | ||||||
|         aiChatModelMapper.insert(insertChatModalDO); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public void update(AiChatModelUpdateReqVO req) { |  | ||||||
|         // 校验 platform |  | ||||||
|         validatePlatform(req.getPlatform()); |  | ||||||
|         // 校验模型是否存在 |  | ||||||
|         validateExists(req.getId()); |  | ||||||
|         // 转换 updateChatModalDO |  | ||||||
|         AiChatModelDO updateChatModalDO = AiChatModelConvert.INSTANCE.convertAiChatModalDO(req); |  | ||||||
|         updateChatModalDO.setId(req.getId()); |  | ||||||
|         // 更新数据库 |  | ||||||
|         aiChatModelMapper.updateById(updateChatModalDO); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public void delete(Long id) { |  | ||||||
|         // 检查 modal 是否存在 |  | ||||||
|         validateExists(id); |  | ||||||
|         // 删除 delete |  | ||||||
|         aiChatModelMapper.deleteById(id); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public AiChatModalRespVO getChatModalOfValidate(Long modalId) { |  | ||||||
|         // 检查 modal 是否存在 |  | ||||||
|         AiChatModelDO aiChatModalDO = validateExists(modalId); |  | ||||||
|         return AiChatModelConvert.INSTANCE.convertAiChatModalRes(aiChatModalDO); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public void validateAvailable(AiChatModalRespVO chatModal) { |  | ||||||
|         // 对话模型是否可用 |  | ||||||
|         if (!CommonStatusEnum.ENABLE.getStatus().equals(chatModal.getStatus())) { |  | ||||||
|             throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_DISABLE_NOT_USED); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public AiChatModelDO validateExists(Long id) { |  | ||||||
|         AiChatModelDO aiChatModalDO = aiChatModelMapper.selectById(id); |  | ||||||
|         if (aiChatModalDO == null) { |  | ||||||
|             throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_NOT_EXIST); |  | ||||||
|         } |  | ||||||
|         return aiChatModalDO; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private void validatePlatform(String platform) { |  | ||||||
|         try { |  | ||||||
|             AiPlatformEnum.valueOfPlatform(platform); |  | ||||||
|         } catch (IllegalArgumentException e) { |  | ||||||
|             throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_PLATFORM_PARAMS_INCORRECT, e.getMessage()); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private void validateModalConfig(AiChatModalConfigVO aiChatModalConfigVO) { |  | ||||||
|         Set<ConstraintViolation<AiChatModalConfigVO>> validate = ValidationUtil.validate(aiChatModalConfigVO); |  | ||||||
|         for (ConstraintViolation<AiChatModalConfigVO> constraintViolation : validate) { |  | ||||||
|             throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_CONFIG_PARAMS_INCORRECT, constraintViolation.getMessage()); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -12,7 +12,7 @@ import cn.iocoder.yudao.module.ai.convert.AiChatRoleConvert; | |||||||
| import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; | import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; | ||||||
| import cn.iocoder.yudao.module.ai.dal.mysql.AiChatRoleMapper; | import cn.iocoder.yudao.module.ai.dal.mysql.AiChatRoleMapper; | ||||||
| import cn.iocoder.yudao.module.ai.enums.AiChatRoleCategoryEnum; | import cn.iocoder.yudao.module.ai.enums.AiChatRoleCategoryEnum; | ||||||
| import cn.iocoder.yudao.module.ai.service.AiChatModelService; | import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; | ||||||
| import cn.iocoder.yudao.module.ai.service.AiChatRoleService; | import cn.iocoder.yudao.module.ai.service.AiChatRoleService; | ||||||
| import lombok.AllArgsConstructor; | import lombok.AllArgsConstructor; | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
| @ -57,8 +57,8 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { | |||||||
|     public void add(AiChatRoleAddReqVO req) { |     public void add(AiChatRoleAddReqVO req) { | ||||||
|         // 转换enum,并校验enum |         // 转换enum,并校验enum | ||||||
|         AiChatRoleCategoryEnum.valueOfCategory(req.getCategory()); |         AiChatRoleCategoryEnum.valueOfCategory(req.getCategory()); | ||||||
|         // 校验模型是否存在 |         // 校验模型是否存在 TODO | ||||||
|         aiChatModalService.validateExists(req.getModelId()); | //        aiChatModalService.validateExists(req.getModelId()); | ||||||
|         // 转换do |         // 转换do | ||||||
|         AiChatRoleDO insertAiChatRoleDO = AiChatRoleConvert.INSTANCE.convertAiChatRoleDO(req); |         AiChatRoleDO insertAiChatRoleDO = AiChatRoleConvert.INSTANCE.convertAiChatRoleDO(req); | ||||||
|         insertAiChatRoleDO.setUserId(SecurityFrameworkUtils.getLoginUserId()); |         insertAiChatRoleDO.setUserId(SecurityFrameworkUtils.getLoginUserId()); | ||||||
| @ -73,8 +73,8 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { | |||||||
|         validateExists(req.getId()); |         validateExists(req.getId()); | ||||||
|         // 转换enum,并校验enum |         // 转换enum,并校验enum | ||||||
|         AiChatRoleCategoryEnum.valueOfCategory(req.getCategory()); |         AiChatRoleCategoryEnum.valueOfCategory(req.getCategory()); | ||||||
|         // 校验模型是否存在 |         // 校验模型是否存在 TODO | ||||||
|         aiChatModalService.validateExists(req.getModelId()); | //        aiChatModalService.validateExists(req.getModelId()); | ||||||
|         // 转换do |         // 转换do | ||||||
|         AiChatRoleDO updateChatRole = AiChatRoleConvert.INSTANCE.convertAiChatRoleDO(req); |         AiChatRoleDO updateChatRole = AiChatRoleConvert.INSTANCE.convertAiChatRoleDO(req); | ||||||
|         updateChatRole.setId(req.getId()); |         updateChatRole.setId(req.getId()); | ||||||
|  | |||||||
| @ -12,14 +12,14 @@ import cn.iocoder.yudao.module.ai.config.AiChatClientFactory; | |||||||
| import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; | import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; | ||||||
| import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; | import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; | ||||||
| import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; | import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; | ||||||
| import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRespVO; |  | ||||||
| import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert; | import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert; | ||||||
| import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; | import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; | ||||||
|  | import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; | ||||||
| import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; | import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; | ||||||
| import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; | import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; | ||||||
| import cn.iocoder.yudao.module.ai.dal.mysql.AiChatMessageMapper; | import cn.iocoder.yudao.module.ai.dal.mysql.AiChatMessageMapper; | ||||||
| import cn.iocoder.yudao.module.ai.service.AiChatConversationService; | import cn.iocoder.yudao.module.ai.service.AiChatConversationService; | ||||||
| import cn.iocoder.yudao.module.ai.service.AiChatModelService; | import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; | ||||||
| import cn.iocoder.yudao.module.ai.service.AiChatRoleService; | import cn.iocoder.yudao.module.ai.service.AiChatRoleService; | ||||||
| import cn.iocoder.yudao.module.ai.service.AiChatService; | import cn.iocoder.yudao.module.ai.service.AiChatService; | ||||||
| import lombok.AllArgsConstructor; | import lombok.AllArgsConstructor; | ||||||
| @ -57,9 +57,7 @@ public class AiChatServiceImpl implements AiChatService { | |||||||
|         // 查询对话 |         // 查询对话 | ||||||
|         AiChatConversationRespVO conversation = chatConversationService.getConversationOfValidate(req.getConversationId()); |         AiChatConversationRespVO conversation = chatConversationService.getConversationOfValidate(req.getConversationId()); | ||||||
|         // 获取对话模型 |         // 获取对话模型 | ||||||
|         AiChatModalRespVO chatModal = aiChatModalService.getChatModalOfValidate(conversation.getModelId()); |         AiChatModelDO chatModel = aiChatModalService.validateChatModel(conversation.getModelId()); | ||||||
|         // 对话模型是否可用 |  | ||||||
|         aiChatModalService.validateAvailable(chatModal); |  | ||||||
|         // 获取角色信息 |         // 获取角色信息 | ||||||
|         AiChatRoleDO aiChatRoleDO = null; |         AiChatRoleDO aiChatRoleDO = null; | ||||||
|         if (conversation.getRoleId() != null) { |         if (conversation.getRoleId() != null) { | ||||||
| @ -68,10 +66,10 @@ public class AiChatServiceImpl implements AiChatService { | |||||||
|         // 校验角色是否公开 |         // 校验角色是否公开 | ||||||
|         aiChatRoleService.validateIsPublic(aiChatRoleDO); |         aiChatRoleService.validateIsPublic(aiChatRoleDO); | ||||||
|         // 获取 client 类型 |         // 获取 client 类型 | ||||||
|         AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(chatModal.getPlatform()); |         AiPlatformEnum platformEnum = AiPlatformEnum.validatePlatform(chatModel.getPlatform()); | ||||||
|         // 保存 chat message |         // 保存 chat message | ||||||
|         insertChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(), |         insertChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(), | ||||||
|                 chatModal.getModel(), chatModal.getId(), req.getContent(), |                 chatModel.getModel(), chatModel.getId(), req.getContent(), | ||||||
|                 null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); |                 null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); | ||||||
|         String content = null; |         String content = null; | ||||||
|         int tokens = 0; |         int tokens = 0; | ||||||
| @ -93,7 +91,7 @@ public class AiChatServiceImpl implements AiChatService { | |||||||
|         } finally { |         } finally { | ||||||
|             // 保存 chat message |             // 保存 chat message | ||||||
|             insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), |             insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), | ||||||
|                     chatModal.getModel(), chatModal.getId(), content, |                     chatModel.getModel(), chatModel.getId(), content, | ||||||
|                     tokens, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); |                     tokens, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); | ||||||
|         } |         } | ||||||
|         return new AiChatMessageRespVO().setContent(content); |         return new AiChatMessageRespVO().setContent(content); | ||||||
| @ -128,9 +126,7 @@ public class AiChatServiceImpl implements AiChatService { | |||||||
|         // 查询对话 |         // 查询对话 | ||||||
|         AiChatConversationRespVO conversation = chatConversationService.getConversationOfValidate(req.getConversationId()); |         AiChatConversationRespVO conversation = chatConversationService.getConversationOfValidate(req.getConversationId()); | ||||||
|         // 获取对话模型 |         // 获取对话模型 | ||||||
|         AiChatModalRespVO chatModal = aiChatModalService.getChatModalOfValidate(conversation.getModelId()); |         AiChatModelDO chatModel = aiChatModalService.validateChatModel(conversation.getModelId()); | ||||||
|         // 对话模型是否可用 |  | ||||||
|         aiChatModalService.validateAvailable(chatModal); |  | ||||||
|         // 获取角色信息 |         // 获取角色信息 | ||||||
|         AiChatRoleDO aiChatRoleDO = null; |         AiChatRoleDO aiChatRoleDO = null; | ||||||
|         if (conversation.getRoleId() != null) { |         if (conversation.getRoleId() != null) { | ||||||
| @ -145,10 +141,10 @@ public class AiChatServiceImpl implements AiChatService { | |||||||
| //        req.setTemperature(req.getTemperature()); | //        req.setTemperature(req.getTemperature()); | ||||||
|         // 保存 chat message |         // 保存 chat message | ||||||
|         insertChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(), |         insertChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(), | ||||||
|                 chatModal.getModel(), chatModal.getId(), req.getContent(), |                 chatModel.getModel(), chatModel.getId(), req.getContent(), | ||||||
|                 null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); |                 null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); | ||||||
|         // 获取 client 类型 |         // 获取 client 类型 | ||||||
|         AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(chatModal.getPlatform()); |         AiPlatformEnum platformEnum = AiPlatformEnum.validatePlatform(chatModel.getPlatform()); | ||||||
|         StreamingChatClient streamingChatClient = aiChatClientFactory.getStreamingChatClient(platformEnum); |         StreamingChatClient streamingChatClient = aiChatClientFactory.getStreamingChatClient(platformEnum); | ||||||
|         Flux<ChatResponse> streamResponse = streamingChatClient.stream(prompt); |         Flux<ChatResponse> streamResponse = streamingChatClient.stream(prompt); | ||||||
|         // 转换 flex AiChatMessageRespVO |         // 转换 flex AiChatMessageRespVO | ||||||
| @ -167,7 +163,7 @@ public class AiChatServiceImpl implements AiChatService { | |||||||
|                 log.info("发送完成!"); |                 log.info("发送完成!"); | ||||||
|                 // 保存 chat message |                 // 保存 chat message | ||||||
|                 insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), |                 insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), | ||||||
|                         chatModal.getModel(), chatModal.getId(), contentBuffer.toString(), |                         chatModel.getModel(), chatModel.getId(), contentBuffer.toString(), | ||||||
|                         tokens.get(), conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); |                         tokens.get(), conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); | ||||||
|             } |             } | ||||||
|         }).doOnError(new Consumer<Throwable>() { |         }).doOnError(new Consumer<Throwable>() { | ||||||
| @ -176,7 +172,7 @@ public class AiChatServiceImpl implements AiChatService { | |||||||
|                 log.error("发送错误 {}!", throwable.getMessage()); |                 log.error("发送错误 {}!", throwable.getMessage()); | ||||||
|                 // 保存 chat message |                 // 保存 chat message | ||||||
|                 insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), |                 insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), | ||||||
|                         chatModal.getModel(), chatModal.getId(), throwable.getMessage(), |                         chatModel.getModel(), chatModel.getId(), throwable.getMessage(), | ||||||
|                         tokens.get(), conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); |                         tokens.get(), conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|  | |||||||
| @ -14,7 +14,7 @@ import jakarta.validation.Valid; | |||||||
| public interface AiApiKeyService { | public interface AiApiKeyService { | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 创建AI API 密钥 |      * 创建 API 密钥 | ||||||
|      * |      * | ||||||
|      * @param createReqVO 创建信息 |      * @param createReqVO 创建信息 | ||||||
|      * @return 编号 |      * @return 编号 | ||||||
| @ -22,32 +22,40 @@ public interface AiApiKeyService { | |||||||
|     Long createApiKey(@Valid AiApiKeySaveReqVO createReqVO); |     Long createApiKey(@Valid AiApiKeySaveReqVO createReqVO); | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 更新AI API 密钥 |      * 更新 API 密钥 | ||||||
|      * |      * | ||||||
|      * @param updateReqVO 更新信息 |      * @param updateReqVO 更新信息 | ||||||
|      */ |      */ | ||||||
|     void updateApiKey(@Valid AiApiKeySaveReqVO updateReqVO); |     void updateApiKey(@Valid AiApiKeySaveReqVO updateReqVO); | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 删除AI API 密钥 |      * 删除 API 密钥 | ||||||
|      * |      * | ||||||
|      * @param id 编号 |      * @param id 编号 | ||||||
|      */ |      */ | ||||||
|     void deleteApiKey(Long id); |     void deleteApiKey(Long id); | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 获得AI API 密钥 |      * 获得 API 密钥 | ||||||
|      * |      * | ||||||
|      * @param id 编号 |      * @param id 编号 | ||||||
|      * @return AI API 密钥 |      * @return API 密钥 | ||||||
|      */ |      */ | ||||||
|     AiApiKeyDO getApiKey(Long id); |     AiApiKeyDO getApiKey(Long id); | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 获得AI API 密钥分页 |      * 校验 API 密钥 | ||||||
|  |      * | ||||||
|  |      * @param id 比那好 | ||||||
|  |      * @return API 密钥 | ||||||
|  |      */ | ||||||
|  |     AiApiKeyDO validateApiKey(Long id); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获得 API 密钥分页 | ||||||
|      * |      * | ||||||
|      * @param pageReqVO 分页查询 |      * @param pageReqVO 分页查询 | ||||||
|      * @return AI API 密钥分页 |      * @return API 密钥分页 | ||||||
|      */ |      */ | ||||||
|     PageResult<AiApiKeyDO> getApiKeyPage(AiApiKeyPageReqVO pageReqVO); |     PageResult<AiApiKeyDO> getApiKeyPage(AiApiKeyPageReqVO pageReqVO); | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| package cn.iocoder.yudao.module.ai.service.model; | package cn.iocoder.yudao.module.ai.service.model; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||||
| import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||||||
| import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageReqVO; | import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageReqVO; | ||||||
| @ -11,7 +12,7 @@ import org.springframework.stereotype.Service; | |||||||
| import org.springframework.validation.annotation.Validated; | import org.springframework.validation.annotation.Validated; | ||||||
|  |  | ||||||
| import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||||||
| import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.API_KEY_NOT_EXISTS; | import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.*; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * AI API 密钥 Service 实现类 |  * AI API 密钥 Service 实现类 | ||||||
| @ -51,10 +52,12 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { | |||||||
|         apiKeyMapper.deleteById(id); |         apiKeyMapper.deleteById(id); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void validateApiKeyExists(Long id) { |     private AiApiKeyDO validateApiKeyExists(Long id) { | ||||||
|         if (apiKeyMapper.selectById(id) == null) { |         AiApiKeyDO apiKey = apiKeyMapper.selectById(id); | ||||||
|  |         if (apiKey == null) { | ||||||
|             throw exception(API_KEY_NOT_EXISTS); |             throw exception(API_KEY_NOT_EXISTS); | ||||||
|         } |         } | ||||||
|  |         return apiKey; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
| @ -62,6 +65,15 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { | |||||||
|         return apiKeyMapper.selectById(id); |         return apiKeyMapper.selectById(id); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public AiApiKeyDO validateApiKey(Long id) { | ||||||
|  |         AiApiKeyDO apiKey = validateApiKeyExists(id); | ||||||
|  |         if (CommonStatusEnum.isDisable(apiKey.getStatus())) { | ||||||
|  |             throw exception(API_KEY_DISABLE); | ||||||
|  |         } | ||||||
|  |         return apiKey; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public PageResult<AiApiKeyDO> getApiKeyPage(AiApiKeyPageReqVO pageReqVO) { |     public PageResult<AiApiKeyDO> getApiKeyPage(AiApiKeyPageReqVO pageReqVO) { | ||||||
|         return apiKeyMapper.selectPage(pageReqVO); |         return apiKeyMapper.selectPage(pageReqVO); | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| package cn.iocoder.yudao.module.ai.service.impl; | package cn.iocoder.yudao.module.ai.service.model; | ||||||
| 
 | 
 | ||||||
| import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; | import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; | ||||||
| import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; | import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; | ||||||
| @ -7,7 +7,6 @@ import cn.iocoder.yudao.module.ai.ErrorCodeConstants; | |||||||
| import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateReqVO; | import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateReqVO; | ||||||
| import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; | import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; | ||||||
| import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateReqVO; | import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateReqVO; | ||||||
| import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRespVO; |  | ||||||
| import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleRespVO; | import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleRespVO; | ||||||
| import cn.iocoder.yudao.module.ai.convert.AiChatConversationConvert; | import cn.iocoder.yudao.module.ai.convert.AiChatConversationConvert; | ||||||
| import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; | import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; | ||||||
| @ -15,7 +14,6 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; | |||||||
| import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; | import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; | ||||||
| import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModelMapper; | import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModelMapper; | ||||||
| import cn.iocoder.yudao.module.ai.service.AiChatConversationService; | import cn.iocoder.yudao.module.ai.service.AiChatConversationService; | ||||||
| import cn.iocoder.yudao.module.ai.service.AiChatModelService; |  | ||||||
| import cn.iocoder.yudao.module.ai.service.AiChatRoleService; | import cn.iocoder.yudao.module.ai.service.AiChatRoleService; | ||||||
| import lombok.AllArgsConstructor; | import lombok.AllArgsConstructor; | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
| @ -87,9 +85,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService | |||||||
|         // 校验对话是否存在 |         // 校验对话是否存在 | ||||||
|         validateExists(updateReqVO.getId()); |         validateExists(updateReqVO.getId()); | ||||||
|         // 获取模型信息并验证 |         // 获取模型信息并验证 | ||||||
|         AiChatModalRespVO chatModal = aiChatModalService.getChatModalOfValidate(updateReqVO.getModelId()); |         aiChatModalService.validateChatModel(updateReqVO.getModelId()); | ||||||
|         // 校验modal是否可用 |  | ||||||
|         aiChatModalService.validateAvailable(chatModal); |  | ||||||
|         // 更新对话信息 |         // 更新对话信息 | ||||||
|         AiChatConversationDO updateAiChatConversationDO |         AiChatConversationDO updateAiChatConversationDO | ||||||
|                 = AiChatConversationConvert.INSTANCE.convertAiChatConversationDO(updateReqVO); |                 = AiChatConversationConvert.INSTANCE.convertAiChatConversationDO(updateReqVO); | ||||||
| @ -0,0 +1,63 @@ | |||||||
|  | package cn.iocoder.yudao.module.ai.service.model; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||||
|  | import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelPageReqVO; | ||||||
|  | import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelSaveReqVO; | ||||||
|  | import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; | ||||||
|  | import jakarta.validation.Valid; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * AI 聊天模型 Service 接口 | ||||||
|  |  * | ||||||
|  |  * @author fansili | ||||||
|  |  * @since 2024/4/24 19:42 | ||||||
|  |  */ | ||||||
|  | public interface AiChatModelService { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 创建聊天模型 | ||||||
|  |      * | ||||||
|  |      * @param createReqVO 创建信息 | ||||||
|  |      * @return 编号 | ||||||
|  |      */ | ||||||
|  |     Long createChatModel(@Valid AiChatModelSaveReqVO createReqVO); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 更新聊天模型 | ||||||
|  |      * | ||||||
|  |      * @param updateReqVO 更新信息 | ||||||
|  |      */ | ||||||
|  |     void updateChatModel(@Valid AiChatModelSaveReqVO updateReqVO); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 删除聊天模型 | ||||||
|  |      * | ||||||
|  |      * @param id 编号 | ||||||
|  |      */ | ||||||
|  |     void deleteChatModel(Long id); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获得聊天模型 | ||||||
|  |      * | ||||||
|  |      * @param id 编号 | ||||||
|  |      * @return API 聊天模型 | ||||||
|  |      */ | ||||||
|  |     AiChatModelDO getChatModel(Long id); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获得聊天模型分页 | ||||||
|  |      * | ||||||
|  |      * @param pageReqVO 分页查询 | ||||||
|  |      * @return API 聊天模型分页 | ||||||
|  |      */ | ||||||
|  |     PageResult<AiChatModelDO> getChatModelPage(AiChatModelPageReqVO pageReqVO); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 校验聊天模型 | ||||||
|  |      * | ||||||
|  |      * @param id 编号 | ||||||
|  |      * @return 聊天模型 | ||||||
|  |      */ | ||||||
|  |     AiChatModelDO validateChatModel(Long id); | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,92 @@ | |||||||
|  | package cn.iocoder.yudao.module.ai.service.model; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.ai.AiPlatformEnum; | ||||||
|  | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||||||
|  | import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||||
|  | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||||||
|  | import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelPageReqVO; | ||||||
|  | import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelSaveReqVO; | ||||||
|  | import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; | ||||||
|  | import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModelMapper; | ||||||
|  | import jakarta.annotation.Resource; | ||||||
|  | import org.springframework.stereotype.Service; | ||||||
|  | import org.springframework.validation.annotation.Validated; | ||||||
|  |  | ||||||
|  | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||||||
|  | import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.*; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * AI 聊天模型 Service 实现类 | ||||||
|  |  * | ||||||
|  |  * @author fansili | ||||||
|  |  */ | ||||||
|  | @Service | ||||||
|  | @Validated | ||||||
|  | public class AiChatModelServiceImpl implements AiChatModelService { | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private AiApiKeyService apiKeyService; | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private AiChatModelMapper chatModelMapper; | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public Long createChatModel(AiChatModelSaveReqVO createReqVO) { | ||||||
|  |         // 1. 校验 | ||||||
|  |         AiPlatformEnum.validatePlatform(createReqVO.getPlatform()); | ||||||
|  |         apiKeyService.validateApiKey(createReqVO.getKeyId()); | ||||||
|  |  | ||||||
|  |         // 2. 插入 | ||||||
|  |         AiChatModelDO chatModel = BeanUtils.toBean(createReqVO, AiChatModelDO.class); | ||||||
|  |         chatModelMapper.insert(chatModel); | ||||||
|  |         return chatModel.getId(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void updateChatModel(AiChatModelSaveReqVO updateReqVO) { | ||||||
|  |         // 1. 校验 | ||||||
|  |         validateChatModelExists(updateReqVO.getId()); | ||||||
|  |         AiPlatformEnum.validatePlatform(updateReqVO.getPlatform()); | ||||||
|  |         apiKeyService.validateApiKey(updateReqVO.getKeyId()); | ||||||
|  |  | ||||||
|  |         // 2. 更新 | ||||||
|  |         AiChatModelDO updateObj = BeanUtils.toBean(updateReqVO, AiChatModelDO.class); | ||||||
|  |         chatModelMapper.updateById(updateObj); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void deleteChatModel(Long id) { | ||||||
|  |         // 校验存在 | ||||||
|  |         validateChatModelExists(id); | ||||||
|  |         // 删除 | ||||||
|  |         chatModelMapper.deleteById(id); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private AiChatModelDO validateChatModelExists(Long id) { | ||||||
|  |         AiChatModelDO model = chatModelMapper.selectById(id); | ||||||
|  |         if (chatModelMapper.selectById(id) == null) { | ||||||
|  |             throw exception(CHAT_MODAL_NOT_EXIST); | ||||||
|  |         } | ||||||
|  |         return model; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public AiChatModelDO getChatModel(Long id) { | ||||||
|  |         return chatModelMapper.selectById(id); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public PageResult<AiChatModelDO> getChatModelPage(AiChatModelPageReqVO pageReqVO) { | ||||||
|  |         return chatModelMapper.selectPage(pageReqVO); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public AiChatModelDO validateChatModel(Long id) { | ||||||
|  |         AiChatModelDO model = validateChatModelExists(id); | ||||||
|  |         if (CommonStatusEnum.isDisable(model.getStatus())) { | ||||||
|  |             throw exception(CHAT_MODAL_DISABLE); | ||||||
|  |         } | ||||||
|  |         return model; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -41,7 +41,7 @@ public enum AiPlatformEnum { | |||||||
|             AiPlatformEnum.MIDJOURNEY |             AiPlatformEnum.MIDJOURNEY | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     public static AiPlatformEnum valueOfPlatform(String platform) { |     public static AiPlatformEnum validatePlatform(String platform) { | ||||||
|         for (AiPlatformEnum itemEnum : AiPlatformEnum.values()) { |         for (AiPlatformEnum itemEnum : AiPlatformEnum.values()) { | ||||||
|             if (itemEnum.getPlatform().equals(platform)) { |             if (itemEnum.getPlatform().equals(platform)) { | ||||||
|                 return itemEnum; |                 return itemEnum; | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV