Commit e8cf40a82a0db2b136fd481971b719415442dfd3
1 parent
16a47bde
【增加】1、mj components 相关操作任务提交 2、增加ai image 列表查询
Showing
12 changed files
with
240 additions
and
57 deletions
yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java
| ... | ... | @@ -14,29 +14,26 @@ public interface ErrorCodeConstants { |
| 14 | 14 | // chat |
| 15 | 15 | |
| 16 | 16 | ErrorCode AI_MODULE_NOT_SUPPORTED = new ErrorCode(1_022_000_000, "AI 模型暂不支持!"); |
| 17 | - ErrorCode AI_CHAT_ROLE_NOT_EXISTENT = new ErrorCode(1_022_000_001, "AI Role 不存在!");; | |
| 18 | 17 | |
| 19 | 18 | // conversation |
| 20 | 19 | |
| 21 | 20 | ErrorCode AI_CONVERSATION_NOT_EXISTS = new ErrorCode(1_022_000_002, "AI 对话不存在!");; |
| 22 | - ErrorCode AI_CHAT_CONTINUE_CONVERSATION_ID_NOT_NULL = new ErrorCode(1_022_000_002, "chat 继续对话,对话 id 不能为空!");; | |
| 23 | - ErrorCode AI_CHAT_CONTINUE_NOT_EXIST = new ErrorCode(1_022_000_020, "chat 对话不存在!"); | |
| 24 | - ErrorCode AI_CHAT_CONVERSATION_NOT_YOURS = new ErrorCode(1_022_000_021, "这条 chat 对话不是你的!"); | |
| 25 | 21 | |
| 26 | 22 | // midjourney |
| 27 | 23 | |
| 28 | 24 | ErrorCode AI_MIDJOURNEY_IMAGINE_FAIL = new ErrorCode(1_022_000_040, "midjourney imagine 操作失败!"); |
| 25 | + ErrorCode AI_MIDJOURNEY_OPERATION_NOT_EXISTS = new ErrorCode(1_022_000_040, "midjourney 操作不存在!"); | |
| 26 | + ErrorCode AI_MIDJOURNEY_MESSAGE_ID_INCORRECT = new ErrorCode(1_022_000_040, "midjourney message id 不正确!"); | |
| 29 | 27 | |
| 30 | 28 | // role |
| 31 | 29 | |
| 32 | - ErrorCode AI_CHAT_ROLE_NOT_EXIST = new ErrorCode(1_022_000_060, "chatRole 不存在!"); | |
| 30 | + ErrorCode AI_CHAT_ROLE_NOT_EXIST = new ErrorCode(1_022_000_060, "AI 角色不存在!"); | |
| 33 | 31 | ErrorCode AI_CHAT_ROLE_NOT_PUBLIC = new ErrorCode(1_022_000_060, "AI 角色未公开!"); |
| 34 | 32 | |
| 35 | 33 | // modal |
| 36 | 34 | |
| 37 | 35 | ErrorCode AI_MODAL_NOT_EXIST = new ErrorCode(1_022_000_080, "AI 模型不存在!"); |
| 38 | 36 | ErrorCode AI_MODAL_CONFIG_PARAMS_INCORRECT = new ErrorCode(1_022_000_081, "AI 模型 config 参数不正确! {} "); |
| 39 | - ErrorCode AI_MODAL_NOT_SUPPORTED_MODAL = new ErrorCode(1_022_000_082, "AI 模型不支持的 modal! {} "); | |
| 40 | 37 | ErrorCode AI_MODAL_PLATFORM_PARAMS_INCORRECT = new ErrorCode(1_022_000_083, "AI 平台参数不正确! {} "); |
| 41 | 38 | ErrorCode AI_MODAL_DISABLE_NOT_USED = new ErrorCode(1_022_000_084, "AI 模型禁用不能使用!"); |
| 42 | 39 | ... | ... |
yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatDrawingStatusEnum.java renamed to yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageDrawingStatusEnum.java
| ... | ... | @@ -12,7 +12,7 @@ import lombok.Getter; |
| 12 | 12 | */ |
| 13 | 13 | @AllArgsConstructor |
| 14 | 14 | @Getter |
| 15 | -public enum AiChatDrawingStatusEnum { | |
| 15 | +public enum AiImageDrawingStatusEnum { | |
| 16 | 16 | |
| 17 | 17 | SUBMIT("submit", "提交任务"), |
| 18 | 18 | WAITING("waiting", "等待"), |
| ... | ... | @@ -27,8 +27,8 @@ public enum AiChatDrawingStatusEnum { |
| 27 | 27 | private String name; |
| 28 | 28 | |
| 29 | 29 | |
| 30 | - public static AiChatDrawingStatusEnum valueOfStatus(String status) { | |
| 31 | - for (AiChatDrawingStatusEnum itemEnum : AiChatDrawingStatusEnum.values()) { | |
| 30 | + public static AiImageDrawingStatusEnum valueOfStatus(String status) { | |
| 31 | + for (AiImageDrawingStatusEnum itemEnum : AiImageDrawingStatusEnum.values()) { | |
| 32 | 32 | if (itemEnum.getStatus().equals(status)) { |
| 33 | 33 | return itemEnum; |
| 34 | 34 | } | ... | ... |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java
| 1 | 1 | package cn.iocoder.yudao.module.ai.controller.admin.image; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReqVO; | |
| 5 | -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingRespVO; | |
| 6 | -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReqVO; | |
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 5 | +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; | |
| 7 | 6 | import cn.iocoder.yudao.module.ai.service.AiImageService; |
| 8 | 7 | import io.swagger.v3.oas.annotations.Operation; |
| 9 | 8 | import io.swagger.v3.oas.annotations.tags.Tag; |
| ... | ... | @@ -31,6 +30,12 @@ public class AiImageController { |
| 31 | 30 | |
| 32 | 31 | private final AiImageService aiImageService; |
| 33 | 32 | |
| 33 | + @Operation(summary = "获取image列表", description = "dall3、midjourney") | |
| 34 | + @GetMapping("/list") | |
| 35 | + public PageResult<AiImageListRespVO> list(@Validated @RequestBody AiImageListReqVO req) { | |
| 36 | + return aiImageService.list(req); | |
| 37 | + } | |
| 38 | + | |
| 34 | 39 | @Operation(summary = "dall2/dall3绘画", description = "openAi dall3是付费的!") |
| 35 | 40 | @PostMapping("/dallDrawing") |
| 36 | 41 | public AiImageDallDrawingRespVO dallDrawing(@Validated @RequestBody AiImageDallDrawingReqVO req) { |
| ... | ... | @@ -46,13 +51,8 @@ public class AiImageController { |
| 46 | 51 | |
| 47 | 52 | @Operation(summary = "midjourney绘画操作", description = "一般有选择图片、放大、换一批...") |
| 48 | 53 | @PostMapping("/midjourney-operate") |
| 49 | - public CommonResult<Void> midjourneyOperate(@Validated @RequestBody AiImageMidjourneyReqVO req) { | |
| 50 | - return success(null); | |
| 51 | - } | |
| 52 | - | |
| 53 | - @Operation(summary = "获取midjourney绘画列表", description = "获取 Midjourney 绘画列表") | |
| 54 | - @GetMapping("/get-midjourney-list") | |
| 55 | - public CommonResult<Void> getMidjourneyList(@Validated @RequestBody AiImageMidjourneyReqVO req) { | |
| 54 | + public CommonResult<Void> midjourneyOperate(@Validated @RequestBody AiImageMidjourneyOperateReqVO req) { | |
| 55 | + aiImageService.midjourneyOperate(req); | |
| 56 | 56 | return success(null); |
| 57 | 57 | } |
| 58 | 58 | ... | ... |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyListRespVO.java renamed to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListReqVO.java
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyListReqVO.java renamed to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java
| 1 | 1 | package cn.iocoder.yudao.module.ai.controller.admin.image.vo; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 4 | -import io.swagger.v3.oas.annotations.media.Schema; | |
| 5 | 4 | import lombok.Data; |
| 6 | 5 | import lombok.experimental.Accessors; |
| 7 | 6 | |
| ... | ... | @@ -14,6 +13,6 @@ import lombok.experimental.Accessors; |
| 14 | 13 | */ |
| 15 | 14 | @Data |
| 16 | 15 | @Accessors(chain = true) |
| 17 | -public class AiImageMidjourneyListReqVO extends PageParam { | |
| 16 | +public class AiImageListRespVO extends PageParam { | |
| 18 | 17 | |
| 19 | 18 | } | ... | ... |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyOperateReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.ai.controller.admin.image.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import jakarta.validation.constraints.NotNull; | |
| 5 | +import lombok.Data; | |
| 6 | +import lombok.experimental.Accessors; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * midjourney req | |
| 10 | + * | |
| 11 | + * @author fansili | |
| 12 | + * @time 2024/4/28 17:42 | |
| 13 | + * @since 1.0 | |
| 14 | + */ | |
| 15 | +@Data | |
| 16 | +@Accessors(chain = true) | |
| 17 | +public class AiImageMidjourneyOperateReqVO { | |
| 18 | + | |
| 19 | + | |
| 20 | + @NotNull(message = "图片编号不能为空") | |
| 21 | + @Schema(description = "编号") | |
| 22 | + private String id; | |
| 23 | + | |
| 24 | + @NotNull(message = "消息编号不能为空") | |
| 25 | + @Schema(description = "消息编号") | |
| 26 | + private String messageId; | |
| 27 | + | |
| 28 | + @NotNull(message = "操作编号不能为空") | |
| 29 | + @Schema(description = "操作编号") | |
| 30 | + private String operateId; | |
| 31 | +} | ... | ... |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyOperationsVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.ai.controller.admin.image.vo; | |
| 2 | + | |
| 3 | +import lombok.Data; | |
| 4 | +import lombok.experimental.Accessors; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * mj 保存 components 记录 | |
| 8 | + * | |
| 9 | + * "components": [ | |
| 10 | + * { | |
| 11 | + * "custom_id": "MJ::JOB::upsample::1::5d32f4e8-8d2f-4bef-82d8-bf517e3c3660", | |
| 12 | + * "style": 2, | |
| 13 | + * "label": "U1", | |
| 14 | + * "type": 2 | |
| 15 | + * }, | |
| 16 | + * ] | |
| 17 | + * | |
| 18 | + * @author fansili | |
| 19 | + * @time 2024/5/8 14:44 | |
| 20 | + * @since 1.0 | |
| 21 | + */ | |
| 22 | +@Data | |
| 23 | +@Accessors(chain = true) | |
| 24 | +public class AiImageMidjourneyOperationsVO { | |
| 25 | + | |
| 26 | + private String custom_id; | |
| 27 | + private String style; | |
| 28 | + private String label; | |
| 29 | + private String type; | |
| 30 | +} | ... | ... |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java
| ... | ... | @@ -2,9 +2,13 @@ package cn.iocoder.yudao.module.ai.convert; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReqVO; |
| 4 | 4 | import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingRespVO; |
| 5 | +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageListRespVO; | |
| 6 | +import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; | |
| 5 | 7 | import org.mapstruct.Mapper; |
| 6 | 8 | import org.mapstruct.factory.Mappers; |
| 7 | 9 | |
| 10 | +import java.util.List; | |
| 11 | + | |
| 8 | 12 | /** |
| 9 | 13 | * ai image convert |
| 10 | 14 | * |
| ... | ... | @@ -24,4 +28,12 @@ public interface AiImageConvert { |
| 24 | 28 | * @return |
| 25 | 29 | */ |
| 26 | 30 | AiImageDallDrawingRespVO convertAiImageDallDrawingRespVO(AiImageDallDrawingReqVO req); |
| 31 | + | |
| 32 | + /** | |
| 33 | + * 转换 - AiImageListRespVO | |
| 34 | + * | |
| 35 | + * @param list | |
| 36 | + * @return | |
| 37 | + */ | |
| 38 | + List<AiImageListRespVO> convertAiImageListRespVO(List<AiImageDO> list); | |
| 27 | 39 | } | ... | ... |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java
| ... | ... | @@ -29,20 +29,37 @@ public class AiImageDO extends BaseDO { |
| 29 | 29 | @Schema(description = "提示词") |
| 30 | 30 | private String prompt; |
| 31 | 31 | |
| 32 | - @Schema(description = "模型") | |
| 32 | + @Schema(description = "模型 dall2/dall3、MJ、NIJI") | |
| 33 | 33 | private String modal; |
| 34 | 34 | |
| 35 | 35 | @Schema(description = "生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。") |
| 36 | 36 | private String size; |
| 37 | 37 | |
| 38 | + @Schema(description = "图片地址(自己服务器)") | |
| 39 | + private String imageUrl; | |
| 40 | + | |
| 38 | 41 | @Schema(description = "绘画状态:提交、排队、绘画中、绘画完成、绘画失败") |
| 39 | 42 | private String drawingStatus; |
| 40 | 43 | |
| 41 | - @Schema(description = "绘画图片地址") | |
| 44 | + @Schema(description = "绘画图片地址(绘画好的服务器)") | |
| 42 | 45 | private String drawingImageUrl; |
| 43 | 46 | |
| 44 | 47 | @Schema(description = "绘画错误信息") |
| 45 | - private String drawingError; | |
| 48 | + private String drawingErrorMessage; | |
| 49 | + | |
| 50 | + // ============ mj 需要字段 | |
| 51 | + | |
| 52 | + @Schema(description = "用户操作的消息编号(MJ返回)") | |
| 53 | + private String mjMessageId; | |
| 54 | + | |
| 55 | + @Schema(description = "用户操作的操作编号(MJ返回)") | |
| 56 | + private String mjOperationId; | |
| 57 | + | |
| 58 | + @Schema(description = "用户操作的操作名字(MJ返回)") | |
| 59 | + private String mjOperationName; | |
| 60 | + | |
| 61 | + @Schema(description = "mj图片生产成功保存的 components json 数组") | |
| 62 | + private String mjOperations; | |
| 46 | 63 | |
| 47 | 64 | } |
| 48 | 65 | ... | ... |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java
| 1 | 1 | package cn.iocoder.yudao.module.ai.service; |
| 2 | 2 | |
| 3 | -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReqVO; | |
| 4 | -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingRespVO; | |
| 5 | -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReqVO; | |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 4 | +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; | |
| 5 | + | |
| 6 | +import java.util.List; | |
| 6 | 7 | |
| 7 | 8 | /** |
| 8 | 9 | * ai 作图 |
| ... | ... | @@ -14,6 +15,14 @@ import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReq |
| 14 | 15 | public interface AiImageService { |
| 15 | 16 | |
| 16 | 17 | /** |
| 18 | + * ai绘画 - 列表 | |
| 19 | + * | |
| 20 | + * @param req | |
| 21 | + * @return | |
| 22 | + */ | |
| 23 | + PageResult<AiImageListRespVO> list(AiImageListReqVO req); | |
| 24 | + | |
| 25 | + /** | |
| 17 | 26 | * ai绘画 - dall2/dall3 绘画 |
| 18 | 27 | * |
| 19 | 28 | * @param req |
| ... | ... | @@ -27,4 +36,12 @@ public interface AiImageService { |
| 27 | 36 | * @return |
| 28 | 37 | */ |
| 29 | 38 | void midjourney(AiImageMidjourneyReqVO req); |
| 39 | + | |
| 40 | + /** | |
| 41 | + * midjourney 操作(u1、u2、放大、换一批...) | |
| 42 | + * | |
| 43 | + * @param req | |
| 44 | + */ | |
| 45 | + void midjourneyOperate(AiImageMidjourneyOperateReqVO req); | |
| 46 | + | |
| 30 | 47 | } | ... | ... |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.ai.service.impl; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.util.StrUtil; | |
| 3 | 4 | import cn.iocoder.yudao.framework.ai.exception.AiException; |
| 4 | 5 | import cn.iocoder.yudao.framework.ai.image.ImageGeneration; |
| 5 | 6 | import cn.iocoder.yudao.framework.ai.image.ImagePrompt; |
| ... | ... | @@ -9,18 +10,20 @@ import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageOptions; |
| 9 | 10 | import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageModelEnum; |
| 10 | 11 | import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageStyleEnum; |
| 11 | 12 | import cn.iocoder.yudao.framework.ai.midjourney.api.MidjourneyInteractionsApi; |
| 13 | +import cn.iocoder.yudao.framework.ai.midjourney.api.req.ReRollReq; | |
| 12 | 14 | import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyWebSocketStarter; |
| 13 | 15 | import cn.iocoder.yudao.framework.ai.midjourney.webSocket.WssNotify; |
| 14 | 16 | import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; |
| 17 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 18 | +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | |
| 19 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 15 | 20 | import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; |
| 16 | 21 | import cn.iocoder.yudao.module.ai.ErrorCodeConstants; |
| 17 | -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReqVO; | |
| 18 | -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingRespVO; | |
| 19 | -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReqVO; | |
| 22 | +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; | |
| 20 | 23 | import cn.iocoder.yudao.module.ai.convert.AiImageConvert; |
| 21 | 24 | import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; |
| 22 | 25 | import cn.iocoder.yudao.module.ai.dal.mysql.AiImageMapper; |
| 23 | -import cn.iocoder.yudao.module.ai.enums.AiChatDrawingStatusEnum; | |
| 26 | +import cn.iocoder.yudao.module.ai.enums.AiImageDrawingStatusEnum; | |
| 24 | 27 | import cn.iocoder.yudao.module.ai.service.AiImageService; |
| 25 | 28 | import jakarta.annotation.PostConstruct; |
| 26 | 29 | import lombok.AllArgsConstructor; |
| ... | ... | @@ -28,6 +31,9 @@ import lombok.extern.slf4j.Slf4j; |
| 28 | 31 | import org.springframework.stereotype.Service; |
| 29 | 32 | import org.springframework.transaction.annotation.Transactional; |
| 30 | 33 | |
| 34 | +import java.util.Collections; | |
| 35 | +import java.util.List; | |
| 36 | + | |
| 31 | 37 | /** |
| 32 | 38 | * ai 作图 |
| 33 | 39 | * |
| ... | ... | @@ -62,6 +68,23 @@ public class AiImageServiceImpl implements AiImageService { |
| 62 | 68 | } |
| 63 | 69 | |
| 64 | 70 | @Override |
| 71 | + public PageResult<AiImageListRespVO> list(AiImageListReqVO req) { | |
| 72 | + // 获取登录用户 | |
| 73 | + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); | |
| 74 | + // 查询当前用户下所有的绘画记录 | |
| 75 | + PageResult<AiImageDO> pageResult = aiImageMapper.selectPage(req, | |
| 76 | + new LambdaQueryWrapperX<AiImageDO>() | |
| 77 | + .eq(AiImageDO::getUserId, loginUserId) | |
| 78 | + .orderByDesc(AiImageDO::getId) | |
| 79 | + ); | |
| 80 | + // 转换 PageResult<AiImageListRespVO> 返回 | |
| 81 | + PageResult<AiImageListRespVO> result = new PageResult<>(); | |
| 82 | + result.setTotal(pageResult.getTotal()); | |
| 83 | + result.setList(AiImageConvert.INSTANCE.convertAiImageListRespVO(pageResult.getList())); | |
| 84 | + return result; | |
| 85 | + } | |
| 86 | + | |
| 87 | + @Override | |
| 65 | 88 | public AiImageDallDrawingRespVO dallDrawing(AiImageDallDrawingReqVO req) { |
| 66 | 89 | // 获取 model |
| 67 | 90 | OpenAiImageModelEnum openAiImageModelEnum = OpenAiImageModelEnum.valueOfModel(req.getModal()); |
| ... | ... | @@ -79,7 +102,8 @@ public class AiImageServiceImpl implements AiImageService { |
| 79 | 102 | ImageGeneration imageGeneration = imageResponse.getResult(); |
| 80 | 103 | // 保存数据库 |
| 81 | 104 | doSave(req.getPrompt(), req.getSize(), req.getModal(), |
| 82 | - imageGeneration.getOutput().getUrl(), AiChatDrawingStatusEnum.COMPLETE, null); | |
| 105 | + imageGeneration.getOutput().getUrl(), AiImageDrawingStatusEnum.COMPLETE, null, | |
| 106 | + null, null, null); | |
| 83 | 107 | // 返回 flex |
| 84 | 108 | respVO.setUrl(imageGeneration.getOutput().getUrl()); |
| 85 | 109 | respVO.setBase64(imageGeneration.getOutput().getB64Json()); |
| ... | ... | @@ -87,7 +111,8 @@ public class AiImageServiceImpl implements AiImageService { |
| 87 | 111 | } catch (AiException aiException) { |
| 88 | 112 | // 保存数据库 |
| 89 | 113 | doSave(req.getPrompt(), req.getSize(), req.getModal(), |
| 90 | - null, AiChatDrawingStatusEnum.FAIL, aiException.getMessage()); | |
| 114 | + null, AiImageDrawingStatusEnum.FAIL, aiException.getMessage(), | |
| 115 | + null, null, null); | |
| 91 | 116 | // 发送错误信息 |
| 92 | 117 | respVO.setErrorMessage(aiException.getMessage()); |
| 93 | 118 | return respVO; |
| ... | ... | @@ -99,7 +124,8 @@ public class AiImageServiceImpl implements AiImageService { |
| 99 | 124 | public void midjourney(AiImageMidjourneyReqVO req) { |
| 100 | 125 | // 保存数据库 |
| 101 | 126 | AiImageDO aiImageDO = doSave(req.getPrompt(), null, "midjoureny", |
| 102 | - null, AiChatDrawingStatusEnum.SUBMIT, null); | |
| 127 | + null, AiImageDrawingStatusEnum.SUBMIT, null, | |
| 128 | + null, null, null); | |
| 103 | 129 | // 提交 midjourney 任务 |
| 104 | 130 | Boolean imagine = midjourneyInteractionsApi.imagine(aiImageDO.getId(), req.getPrompt()); |
| 105 | 131 | if (!imagine) { |
| ... | ... | @@ -107,23 +133,71 @@ public class AiImageServiceImpl implements AiImageService { |
| 107 | 133 | } |
| 108 | 134 | } |
| 109 | 135 | |
| 110 | -// private static void sendSseEmitter(Utf8SseEmitter sseEmitter, Object object) { | |
| 111 | -// try { | |
| 112 | -// sseEmitter.send(object, MediaType.APPLICATION_JSON); | |
| 113 | -// } catch (IOException e) { | |
| 114 | -// throw new RuntimeException(e); | |
| 115 | -// } finally { | |
| 116 | -// // 发送 complete | |
| 117 | -// sseEmitter.complete(); | |
| 118 | -// } | |
| 119 | -// } | |
| 136 | + @Transactional(rollbackFor = Exception.class) | |
| 137 | + @Override | |
| 138 | + public void midjourneyOperate(AiImageMidjourneyOperateReqVO req) { | |
| 139 | + // 校验是否存在 | |
| 140 | + AiImageDO aiImageDO = validateExists(req); | |
| 141 | + // 获取 midjourneyOperations | |
| 142 | + List<AiImageMidjourneyOperationsVO> midjourneyOperations = getMidjourneyOperations(aiImageDO); | |
| 143 | + // 校验 OperateId 是否存在 | |
| 144 | + AiImageMidjourneyOperationsVO midjourneyOperationsVO = validateMidjourneyOperationsExists(midjourneyOperations, req.getOperateId()); | |
| 145 | + // 校验 messageId | |
| 146 | + validateMessageId(aiImageDO.getMjMessageId(), req.getMessageId()); | |
| 147 | + // 获取 mjOperationName | |
| 148 | + String mjOperationName = midjourneyOperationsVO.getLabel(); | |
| 149 | + // 保存一个 image 任务记录 | |
| 150 | + doSave(aiImageDO.getPrompt(), aiImageDO.getSize(), aiImageDO.getModal(), | |
| 151 | + null, AiImageDrawingStatusEnum.SUBMIT, null, | |
| 152 | + req.getMessageId(), req.getOperateId(), mjOperationName); | |
| 153 | + // 提交操作 | |
| 154 | + midjourneyInteractionsApi.reRoll( | |
| 155 | + new ReRollReq() | |
| 156 | + .setCustomId(req.getOperateId()) | |
| 157 | + .setMessageId(req.getMessageId()) | |
| 158 | + ); | |
| 159 | + } | |
| 160 | + | |
| 161 | + private void validateMessageId(String mjMessageId, String messageId) { | |
| 162 | + if (!mjMessageId.equals(messageId)) { | |
| 163 | + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MIDJOURNEY_MESSAGE_ID_INCORRECT); | |
| 164 | + } | |
| 165 | + } | |
| 166 | + | |
| 167 | + private AiImageMidjourneyOperationsVO validateMidjourneyOperationsExists(List<AiImageMidjourneyOperationsVO> midjourneyOperations, String operateId) { | |
| 168 | + for (AiImageMidjourneyOperationsVO midjourneyOperation : midjourneyOperations) { | |
| 169 | + if (midjourneyOperation.getCustom_id().equals(operateId)) { | |
| 170 | + return midjourneyOperation; | |
| 171 | + } | |
| 172 | + } | |
| 173 | + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MIDJOURNEY_OPERATION_NOT_EXISTS); | |
| 174 | + } | |
| 175 | + | |
| 176 | + | |
| 177 | + private List<AiImageMidjourneyOperationsVO> getMidjourneyOperations(AiImageDO aiImageDO) { | |
| 178 | + if (StrUtil.isBlank(aiImageDO.getMjOperations())) { | |
| 179 | + return Collections.emptyList(); | |
| 180 | + } | |
| 181 | + return JsonUtils.parseArray(aiImageDO.getMjOperations(), AiImageMidjourneyOperationsVO.class); | |
| 182 | + } | |
| 183 | + | |
| 184 | + private AiImageDO validateExists(AiImageMidjourneyOperateReqVO req) { | |
| 185 | + AiImageDO aiImageDO = aiImageMapper.selectById(req.getId()); | |
| 186 | + if (aiImageDO == null) { | |
| 187 | + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MIDJOURNEY_IMAGINE_FAIL); | |
| 188 | + } | |
| 189 | + return aiImageDO; | |
| 190 | + } | |
| 120 | 191 | |
| 121 | 192 | private AiImageDO doSave(String prompt, |
| 122 | - String size, | |
| 123 | - String model, | |
| 124 | - String imageUrl, | |
| 125 | - AiChatDrawingStatusEnum drawingStatusEnum, | |
| 126 | - String drawingError) { | |
| 193 | + String size, | |
| 194 | + String model, | |
| 195 | + String drawingImageUrl, | |
| 196 | + AiImageDrawingStatusEnum drawingStatusEnum, | |
| 197 | + String drawingErrorMessage, | |
| 198 | + String mjMessageId, | |
| 199 | + String mjOperationId, | |
| 200 | + String mjOperationName) { | |
| 127 | 201 | // 保存数据库 |
| 128 | 202 | Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); |
| 129 | 203 | AiImageDO aiImageDO = new AiImageDO(); |
| ... | ... | @@ -132,9 +206,15 @@ public class AiImageServiceImpl implements AiImageService { |
| 132 | 206 | aiImageDO.setSize(size); |
| 133 | 207 | aiImageDO.setModal(model); |
| 134 | 208 | aiImageDO.setUserId(loginUserId); |
| 135 | - aiImageDO.setDrawingImageUrl(imageUrl); | |
| 209 | + // TODO @芋艿 如何上传到自己服务器 | |
| 210 | + aiImageDO.setImageUrl(null); | |
| 136 | 211 | aiImageDO.setDrawingStatus(drawingStatusEnum.getStatus()); |
| 137 | - aiImageDO.setDrawingError(drawingError); | |
| 212 | + aiImageDO.setDrawingImageUrl(drawingImageUrl); | |
| 213 | + aiImageDO.setDrawingErrorMessage(drawingErrorMessage); | |
| 214 | + // | |
| 215 | + aiImageDO.setMjMessageId(mjMessageId); | |
| 216 | + aiImageDO.setMjOperationId(mjOperationId); | |
| 217 | + aiImageDO.setMjOperationName(mjOperationName); | |
| 138 | 218 | aiImageMapper.insert(aiImageDO); |
| 139 | 219 | return aiImageDO; |
| 140 | 220 | } | ... | ... |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java
| ... | ... | @@ -6,7 +6,7 @@ import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyMessage; |
| 6 | 6 | import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyGennerateStatusEnum; |
| 7 | 7 | import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyMessageHandler; |
| 8 | 8 | import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; |
| 9 | -import cn.iocoder.yudao.module.ai.enums.AiChatDrawingStatusEnum; | |
| 9 | +import cn.iocoder.yudao.module.ai.enums.AiImageDrawingStatusEnum; | |
| 10 | 10 | import cn.iocoder.yudao.module.ai.dal.mysql.AiImageMapper; |
| 11 | 11 | import com.alibaba.fastjson2.JSON; |
| 12 | 12 | import lombok.AllArgsConstructor; |
| ... | ... | @@ -53,14 +53,14 @@ public class YuDaoMidjourneyMessageHandler implements MidjourneyMessageHandler { |
| 53 | 53 | imageUrl = midjourneyMessage.getAttachments().get(0).getUrl(); |
| 54 | 54 | } |
| 55 | 55 | // 转换状态 |
| 56 | - AiChatDrawingStatusEnum drawingStatusEnum = null; | |
| 56 | + AiImageDrawingStatusEnum drawingStatusEnum = null; | |
| 57 | 57 | String generateStatus = midjourneyMessage.getGenerateStatus(); |
| 58 | 58 | if (MidjourneyGennerateStatusEnum.COMPLETED.getStatus().equals(generateStatus)) { |
| 59 | - drawingStatusEnum = AiChatDrawingStatusEnum.COMPLETE; | |
| 59 | + drawingStatusEnum = AiImageDrawingStatusEnum.COMPLETE; | |
| 60 | 60 | } else if (MidjourneyGennerateStatusEnum.IN_PROGRESS.getStatus().equals(generateStatus)) { |
| 61 | - drawingStatusEnum = AiChatDrawingStatusEnum.IN_PROGRESS; | |
| 61 | + drawingStatusEnum = AiImageDrawingStatusEnum.IN_PROGRESS; | |
| 62 | 62 | } else if (MidjourneyGennerateStatusEnum.WAITING.getStatus().equals(generateStatus)) { |
| 63 | - drawingStatusEnum = AiChatDrawingStatusEnum.WAITING; | |
| 63 | + drawingStatusEnum = AiImageDrawingStatusEnum.WAITING; | |
| 64 | 64 | } |
| 65 | 65 | aiImageMapper.updateById( |
| 66 | 66 | new AiImageDO() | ... | ... |