From 56e8707e387736294cf431425e978fdc2575bd3a Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 31 May 2024 17:05:28 +0800 Subject: [PATCH] 【增加】Midjourney Proxy 回调通知 --- yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyReqVO.java | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyVO.java | 46 ---------------------------------------------- yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java | 8 ++++---- yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java | 3 +++ yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java | 11 ++++++++++- yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java | 9 +++++++++ yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java | 71 +++++++++++++++++++++++++++++++++++++---------------------------------- 7 files changed, 112 insertions(+), 85 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyReqVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyVO.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyReqVO.java new file mode 100644 index 0000000..3cc92c7 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyReqVO.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.ai.client.vo; + +import cn.iocoder.yudao.module.ai.client.enums.MidjourneyTaskActionEnum; +import cn.iocoder.yudao.module.ai.client.enums.MidjourneyTaskStatusEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * @author fansili + * @time 2024/5/31 10:37 + * @since 1.0 + */ +@Data +public class MidjourneyNotifyReqVO { + + @Schema(description = "job id") + private String id; + + @Schema(description = "任务类型") + private MidjourneyTaskActionEnum action; + @Schema(description = "任务状态") + private MidjourneyTaskStatusEnum status = MidjourneyTaskStatusEnum.NOT_START; + + @Schema(description = "提示词") + private String prompt; + @Schema(description = "提示词-英文") + private String promptEn; + + @Schema(description = "任务描述") + private String description; + @Schema(description = "自定义参数") + private String state; + + @Schema(description = "提交时间") + private Long submitTime; + @Schema(description = "开始执行时间") + private Long startTime; + @Schema(description = "结束时间") + private Long finishTime; + + @Schema(description = "图片url") + private String imageUrl; + + @Schema(description = "任务进度") + private String progress; + @Schema(description = "失败原因") + private String failReason; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyVO.java deleted file mode 100644 index c2a9343..0000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyVO.java +++ /dev/null @@ -1,46 +0,0 @@ -package cn.iocoder.yudao.module.ai.client.vo; - -import cn.iocoder.yudao.module.ai.client.enums.MidjourneyTaskActionEnum; -import cn.iocoder.yudao.module.ai.client.enums.MidjourneyTaskStatusEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * @author fansili - * @time 2024/5/31 10:37 - * @since 1.0 - */ -@Data -public class MidjourneyNotifyVO { - - @Schema(description = "任务类型") - private MidjourneyTaskActionEnum action; - @Schema(description = "任务状态") - private MidjourneyTaskStatusEnum status = MidjourneyTaskStatusEnum.NOT_START; - - @Schema(description = "提示词") - private String prompt; - @Schema(description = "提示词-英文") - private String promptEn; - - @Schema(description = "任务描述") - private String description; - @Schema(description = "自定义参数") - private String state; - - @Schema(description = "提交时间") - private Long submitTime; - @Schema(description = "开始执行时间") - private Long startTime; - @Schema(description = "结束时间") - private Long finishTime; - - @Schema(description = "图片url") - private String imageUrl; - - @Schema(description = "任务进度") - private String progress; - @Schema(description = "失败原因") - private String failReason; - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index bef20fe..1ffe4f1 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.ai.controller.admin.image; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.ai.client.vo.MidjourneyNotifyReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageListReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyImagineReqVO; @@ -13,7 +14,6 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -74,9 +74,9 @@ public class AiImageController { return success(aiImageService.deleteIdMy(id, getLoginUserId())); } - @Operation(summary = "删除【我的】绘画记录") + @Operation(summary = "midjourney proxy - 回调通知") @RequestMapping("/midjourney-notify") - public CommonResult midjourneyNotify(HttpServletRequest request) { - return success(true); + public CommonResult midjourneyNotify(MidjourneyNotifyReqVO notifyReqVO) { + return success(aiImageService.midjourneyNotify(getLoginUserId(), notifyReqVO)); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java index 259215c..0f6282a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java @@ -28,6 +28,9 @@ public class AiImageDO extends BaseDO { @Schema(description = "用户编号") private Long userId; + @Schema(description = "midjourney proxy 关联的 job id") + private String jobId; + @Schema(description = "提示词") private String prompt; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java index f60668d..af37a29 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java @@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import org.apache.ibatis.annotations.Mapper; -import org.springframework.stereotype.Repository; /** * AI 绘图 Mapper @@ -26,4 +25,14 @@ public interface AiImageMapper extends BaseMapperX { return; } + /** + * 查询 - 根据 job id + * + * @param id + * @return + */ + default AiImageDO selectByJobId(String id) { + return this.selectOne(new LambdaQueryWrapperX().eq(AiImageDO::getJobId, id)); + } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java index b07ba7d..05ad0ed 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.ai.service.image; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.ai.client.vo.MidjourneyNotifyReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageListReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyImagineReqVO; @@ -65,4 +66,12 @@ public interface AiImageService { */ Boolean deleteIdMy(Long id, Long loginUserId); + /** + * midjourney proxy - 回调通知 + * + * @param loginUserId + * @param notifyReqVO + * @return + */ + Boolean midjourneyNotify(Long loginUserId, MidjourneyNotifyReqVO notifyReqVO); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index bef3b60..1688704 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.ai.service.image; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageModelEnum; @@ -14,9 +16,14 @@ import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.client.MidjourneyProxyClient; import cn.iocoder.yudao.module.ai.client.enums.MidjourneyModelEnum; import cn.iocoder.yudao.module.ai.client.enums.MidjourneySubmitCodeEnum; +import cn.iocoder.yudao.module.ai.client.enums.MidjourneyTaskStatusEnum; import cn.iocoder.yudao.module.ai.client.vo.MidjourneyImagineReqVO; +import cn.iocoder.yudao.module.ai.client.vo.MidjourneyNotifyReqVO; import cn.iocoder.yudao.module.ai.client.vo.MidjourneySubmitRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageListReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyImagineReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyOperateReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper; import cn.iocoder.yudao.module.ai.enums.AiImagePublicStatusEnum; @@ -36,15 +43,9 @@ import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -// TODO @fan:注释优化下哈 - /** * AI 绘画(接入 dall2/dall3、midjourney) * @@ -56,9 +57,6 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU @Slf4j public class AiImageServiceImpl implements AiImageService { - // TODO @fan:使用 @Resource 注入 - - // TODO @fan:imageMapper @Resource private AiImageMapper imageMapper; @Resource @@ -173,19 +171,16 @@ public class AiImageServiceImpl implements AiImageService { // 4、保存任务 id (状态码: 1(提交成功), 21(已存在), 22(排队中), other(错误)) String updateStatus = null; String errorMessage = null; - Map drawResponse = new HashMap<>(); if (!MidjourneySubmitCodeEnum.SUCCESS_CODES.contains(submitRespVO.getCode())) { updateStatus = AiImageStatusEnum.FAIL.getStatus(); errorMessage = submitRespVO.getDescription(); - } else { - drawResponse.put("jobId", submitRespVO.getResult()); } imageMapper.updateById(new AiImageDO() .setId(aiImageDO.getId()) .setStatus(updateStatus) .setErrorMessage(errorMessage) - .setDrawResponse(drawResponse) + .setJobId(submitRespVO.getResult()) ); return aiImageDO.getId(); } @@ -228,28 +223,36 @@ public class AiImageServiceImpl implements AiImageService { return imageMapper.deleteById(id) > 0; } - private void validateMessageId(String mjMessageId, String messageId) { - if (!mjMessageId.equals(messageId)) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MIDJOURNEY_MESSAGE_ID_INCORRECT); + @Override + public Boolean midjourneyNotify(Long loginUserId, MidjourneyNotifyReqVO notifyReqVO) { + // 1、根据 job id 查询关联的 image + AiImageDO image = imageMapper.selectByJobId(notifyReqVO.getId()); + if (image == null) { + log.warn("midjourneyNotify 回调的 jobId 不存在! jobId: {}", notifyReqVO.getId()); + return false; } - } - - private AiImageMidjourneyOperationsVO validateMidjourneyOperationsExists(List midjourneyOperations, String operateId) { - for (AiImageMidjourneyOperationsVO midjourneyOperation : midjourneyOperations) { - if (midjourneyOperation.getCustom_id().equals(operateId)) { - return midjourneyOperation; - } + // + String imageStatus = null; + if (MidjourneyTaskStatusEnum.SUCCESS == notifyReqVO.getStatus()) { + imageStatus = AiImageStatusEnum.COMPLETE.getStatus(); + } else if (MidjourneyTaskStatusEnum.FAILURE == notifyReqVO.getStatus()) { + imageStatus = AiImageStatusEnum.FAIL.getStatus(); } - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MIDJOURNEY_OPERATION_NOT_EXISTS); - } - - - private List getMidjourneyOperations(AiImageDO aiImageDO) { -// if (StrUtil.isBlank(aiImageDO.getMjOperations())) { -// return Collections.emptyList(); -// } -// return JsonUtils.parseArray(aiImageDO.getMjOperations(), AiImageMidjourneyOperationsVO.class); - return null; + // 2、上传图片 + String filePath = null; + if (!StrUtil.isBlank(notifyReqVO.getImageUrl())) { + filePath = fileApi.createFile(HttpUtil.downloadBytes(notifyReqVO.getImageUrl())); + } + // 2、更新 image 状态 + imageMapper.updateById( + new AiImageDO() + .setId(image.getId()) + .setStatus(imageStatus) + .setPicUrl(filePath) + .setOriginalPicUrl(notifyReqVO.getImageUrl()) + .setDrawResponse(BeanUtil.beanToMap(notifyReqVO)) + ); + return true; } private AiImageDO validateExists(Long id) { -- libgit2 0.21.4