Commit 63a8cc244d054040ad227a9b5651e0382a65d7e9
1 parent
0cdd3423
【修改】AI Image dall 请求返回结构优化
Showing
4 changed files
with
83 additions
and
24 deletions
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java
| ... | ... | @@ -32,8 +32,8 @@ public class AiImageController { |
| 32 | 32 | |
| 33 | 33 | @Operation(summary = "获取image列表", description = "dall3、midjourney") |
| 34 | 34 | @GetMapping("/list") |
| 35 | - public PageResult<AiImageListRespVO> list(@Validated @RequestBody AiImageListReqVO req) { | |
| 36 | - return aiImageService.list(req); | |
| 35 | + public CommonResult<PageResult<AiImageListRespVO>> list(@Validated @ModelAttribute AiImageListReqVO req) { | |
| 36 | + return CommonResult.success(aiImageService.list(req)); | |
| 37 | 37 | } |
| 38 | 38 | |
| 39 | 39 | @Operation(summary = "dall2/dall3绘画", description = "openAi dall3是付费的!") | ... | ... |
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 com.baomidou.mybatisplus.annotation.IdType; | |
| 5 | +import com.baomidou.mybatisplus.annotation.TableId; | |
| 6 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | 7 | import lombok.Data; |
| 5 | 8 | import lombok.experimental.Accessors; |
| 6 | 9 | |
| ... | ... | @@ -15,4 +18,50 @@ import lombok.experimental.Accessors; |
| 15 | 18 | @Accessors(chain = true) |
| 16 | 19 | public class AiImageListRespVO extends PageParam { |
| 17 | 20 | |
| 21 | + private Long id; | |
| 22 | + | |
| 23 | + @Schema(description = "用户id") | |
| 24 | + private Long userId; | |
| 25 | + | |
| 26 | + @Schema(description = "提示词") | |
| 27 | + private String prompt; | |
| 28 | + | |
| 29 | + @Schema(description = "模型 dall2/dall3、MJ、NIJI") | |
| 30 | + private String model; | |
| 31 | + | |
| 32 | + @Schema(description = "生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。") | |
| 33 | + private String size; | |
| 34 | + | |
| 35 | + @Schema(description = "风格") | |
| 36 | + private String style; | |
| 37 | + | |
| 38 | + @Schema(description = "图片地址(自己服务器)") | |
| 39 | + private String picUrl; | |
| 40 | + | |
| 41 | + @Schema(description = "绘画状态:提交、排队、绘画中、绘画完成、绘画失败") | |
| 42 | + private String status; | |
| 43 | + | |
| 44 | + @Schema(description = "绘画图片地址(绘画好的服务器)") | |
| 45 | + private String originalPicUrl; | |
| 46 | + | |
| 47 | + @Schema(description = "绘画错误信息") | |
| 48 | + private String errorMessage; | |
| 49 | + | |
| 50 | + @Schema(description = "是否发布") | |
| 51 | + private String publicStatus; | |
| 52 | + | |
| 53 | + // ============ mj 需要字段 | |
| 54 | + | |
| 55 | + @Schema(description = "用户操作的Nonce编号(MJ返回)") | |
| 56 | + private String mjNonceId; | |
| 57 | + | |
| 58 | + @Schema(description = "用户操作的操作编号(MJ返回)") | |
| 59 | + private String mjOperationId; | |
| 60 | + | |
| 61 | + @Schema(description = "用户操作的操作名字(MJ返回)") | |
| 62 | + private String mjOperationName; | |
| 63 | + | |
| 64 | + @Schema(description = "mj图片生产成功保存的 components json 数组") | |
| 65 | + private String mjOperations; | |
| 66 | + | |
| 18 | 67 | } | ... | ... |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java
| ... | ... | @@ -29,6 +29,14 @@ public interface AiImageConvert { |
| 29 | 29 | * @param req |
| 30 | 30 | * @return |
| 31 | 31 | */ |
| 32 | + AiImageDallRespVO convertAiImageDallDrawingRespVO(AiImageDO req); | |
| 33 | + | |
| 34 | + /** | |
| 35 | + * 转换 - AiImageDallDrawingRespVO | |
| 36 | + * | |
| 37 | + * @param req | |
| 38 | + * @return | |
| 39 | + */ | |
| 32 | 40 | AiImageDallRespVO convertAiImageDallDrawingRespVO(AiImageDallReqVO req); |
| 33 | 41 | |
| 34 | 42 | /** | ... | ... |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java
| ... | ... | @@ -2,16 +2,10 @@ package cn.iocoder.yudao.module.ai.service.image; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.util.IdUtil; |
| 4 | 4 | import cn.hutool.core.util.StrUtil; |
| 5 | -import cn.iocoder.yudao.framework.ai.core.exception.AiException; | |
| 6 | -import org.springframework.ai.image.ImageGeneration; | |
| 7 | -import org.springframework.ai.image.ImagePrompt; | |
| 8 | -import org.springframework.ai.image.ImageResponse; | |
| 5 | +import cn.hutool.http.HttpUtil; | |
| 9 | 6 | import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageModelEnum; |
| 10 | 7 | import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageStyleEnum; |
| 11 | -import org.springframework.ai.models.midjourney.api.MidjourneyInteractionsApi; | |
| 12 | -import org.springframework.ai.models.midjourney.api.req.ReRollReq; | |
| 13 | -import org.springframework.ai.models.midjourney.webSocket.MidjourneyWebSocketStarter; | |
| 14 | -import org.springframework.ai.models.midjourney.webSocket.WssNotify; | |
| 8 | +import cn.iocoder.yudao.framework.ai.core.exception.AiException; | |
| 15 | 9 | import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; |
| 16 | 10 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 17 | 11 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| ... | ... | @@ -23,9 +17,17 @@ import cn.iocoder.yudao.module.ai.convert.AiImageConvert; |
| 23 | 17 | import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; |
| 24 | 18 | import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper; |
| 25 | 19 | import cn.iocoder.yudao.module.ai.enums.AiImageStatusEnum; |
| 20 | +import cn.iocoder.yudao.module.infra.api.file.FileApi; | |
| 26 | 21 | import jakarta.annotation.PostConstruct; |
| 27 | 22 | import lombok.AllArgsConstructor; |
| 28 | 23 | import lombok.extern.slf4j.Slf4j; |
| 24 | +import org.springframework.ai.image.ImageGeneration; | |
| 25 | +import org.springframework.ai.image.ImagePrompt; | |
| 26 | +import org.springframework.ai.image.ImageResponse; | |
| 27 | +import org.springframework.ai.models.midjourney.api.MidjourneyInteractionsApi; | |
| 28 | +import org.springframework.ai.models.midjourney.api.req.ReRollReq; | |
| 29 | +import org.springframework.ai.models.midjourney.webSocket.MidjourneyWebSocketStarter; | |
| 30 | +import org.springframework.ai.models.midjourney.webSocket.WssNotify; | |
| 29 | 31 | import org.springframework.ai.openai.OpenAiImageClient; |
| 30 | 32 | import org.springframework.ai.openai.OpenAiImageOptions; |
| 31 | 33 | import org.springframework.stereotype.Service; |
| ... | ... | @@ -47,6 +49,7 @@ import java.util.List; |
| 47 | 49 | public class AiImageServiceImpl implements AiImageService { |
| 48 | 50 | |
| 49 | 51 | private final AiImageMapper aiImageMapper; |
| 52 | + private final FileApi fileApi; | |
| 50 | 53 | private final OpenAiImageClient openAiImageClient; |
| 51 | 54 | private final MidjourneyWebSocketStarter midjourneyWebSocketStarter; |
| 52 | 55 | private final MidjourneyInteractionsApi midjourneyInteractionsApi; |
| ... | ... | @@ -89,8 +92,6 @@ public class AiImageServiceImpl implements AiImageService { |
| 89 | 92 | // 获取 model |
| 90 | 93 | OpenAiImageModelEnum openAiImageModelEnum = OpenAiImageModelEnum.valueOfModel(req.getModel()); |
| 91 | 94 | OpenAiImageStyleEnum openAiImageStyleEnum = OpenAiImageStyleEnum.valueOfStyle(req.getStyle()); |
| 92 | - // 转换 AiImageDallDrawingRespVO | |
| 93 | - AiImageDallRespVO respVO = AiImageConvert.INSTANCE.convertAiImageDallDrawingRespVO(req); | |
| 94 | 95 | try { |
| 95 | 96 | // 转换openai 参数 |
| 96 | 97 | OpenAiImageOptions openAiImageOptions = new OpenAiImageOptions(); |
| ... | ... | @@ -100,22 +101,21 @@ public class AiImageServiceImpl implements AiImageService { |
| 100 | 101 | ImageResponse imageResponse = openAiImageClient.call(new ImagePrompt(req.getPrompt(), openAiImageOptions)); |
| 101 | 102 | // 发送 |
| 102 | 103 | ImageGeneration imageGeneration = imageResponse.getResult(); |
| 104 | + // 图片保存到服务器 | |
| 105 | + String filePath = fileApi.createFile(HttpUtil.downloadBytes(imageGeneration.getOutput().getUrl())); | |
| 103 | 106 | // 保存数据库 |
| 104 | - doSave(req.getPrompt(), req.getSize(), req.getModel(), | |
| 105 | - imageGeneration.getOutput().getUrl(), AiImageStatusEnum.COMPLETE, null, | |
| 107 | + AiImageDO aiImageDO = doSave(req.getPrompt(), req.getSize(), req.getModel(), | |
| 108 | + filePath, imageGeneration.getOutput().getUrl(), AiImageStatusEnum.COMPLETE, null, | |
| 106 | 109 | null, null, null); |
| 107 | - // 返回 flex | |
| 108 | - respVO.setOriginalPicUrl(imageGeneration.getOutput().getUrl()); | |
| 109 | - respVO.setBase64(imageGeneration.getOutput().getB64Json()); | |
| 110 | - return respVO; | |
| 110 | + // 转换 AiImageDallDrawingRespVO | |
| 111 | + return AiImageConvert.INSTANCE.convertAiImageDallDrawingRespVO(aiImageDO); | |
| 111 | 112 | } catch (AiException aiException) { |
| 112 | 113 | // 保存数据库 |
| 113 | - doSave(req.getPrompt(), req.getSize(), req.getModel(), | |
| 114 | - null, AiImageStatusEnum.FAIL, aiException.getMessage(), | |
| 114 | + AiImageDO aiImageDO = doSave(req.getPrompt(), req.getSize(), req.getModel(), | |
| 115 | + null, null, AiImageStatusEnum.FAIL, aiException.getMessage(), | |
| 115 | 116 | null, null, null); |
| 116 | 117 | // 发送错误信息 |
| 117 | - respVO.setErrorMessage(aiException.getMessage()); | |
| 118 | - return respVO; | |
| 118 | + return AiImageConvert.INSTANCE.convertAiImageDallDrawingRespVO(aiImageDO); | |
| 119 | 119 | } |
| 120 | 120 | } |
| 121 | 121 | |
| ... | ... | @@ -125,7 +125,7 @@ public class AiImageServiceImpl implements AiImageService { |
| 125 | 125 | // 保存数据库 |
| 126 | 126 | String messageId = String.valueOf(IdUtil.getSnowflakeNextId()); |
| 127 | 127 | AiImageDO aiImageDO = doSave(req.getPrompt(), null, "midjoureny", |
| 128 | - null, AiImageStatusEnum.SUBMIT, null, | |
| 128 | + null, null, AiImageStatusEnum.SUBMIT, null, | |
| 129 | 129 | messageId, null, null); |
| 130 | 130 | // 提交 midjourney 任务 |
| 131 | 131 | Boolean imagine = midjourneyInteractionsApi.imagine(messageId, req.getPrompt()); |
| ... | ... | @@ -149,7 +149,7 @@ public class AiImageServiceImpl implements AiImageService { |
| 149 | 149 | String mjOperationName = midjourneyOperationsVO.getLabel(); |
| 150 | 150 | // 保存一个 image 任务记录 |
| 151 | 151 | doSave(aiImageDO.getPrompt(), aiImageDO.getSize(), aiImageDO.getModel(), |
| 152 | - null, AiImageStatusEnum.SUBMIT, null, | |
| 152 | + null, null, AiImageStatusEnum.SUBMIT, null, | |
| 153 | 153 | req.getMessageId(), req.getOperateId(), mjOperationName); |
| 154 | 154 | // 提交操作 |
| 155 | 155 | midjourneyInteractionsApi.reRoll( |
| ... | ... | @@ -201,6 +201,7 @@ public class AiImageServiceImpl implements AiImageService { |
| 201 | 201 | private AiImageDO doSave(String prompt, |
| 202 | 202 | String size, |
| 203 | 203 | String model, |
| 204 | + String picUrl, | |
| 204 | 205 | String originalPicUrl, |
| 205 | 206 | AiImageStatusEnum statusEnum, |
| 206 | 207 | String errorMessage, |
| ... | ... | @@ -218,6 +219,7 @@ public class AiImageServiceImpl implements AiImageService { |
| 218 | 219 | // TODO @芋艿 如何上传到自己服务器 |
| 219 | 220 | aiImageDO.setPicUrl(null); |
| 220 | 221 | aiImageDO.setStatus(statusEnum.getStatus()); |
| 222 | + aiImageDO.setPicUrl(picUrl); | |
| 221 | 223 | aiImageDO.setOriginalPicUrl(originalPicUrl); |
| 222 | 224 | aiImageDO.setErrorMessage(errorMessage); |
| 223 | 225 | // | ... | ... |