Commit 63a8cc244d054040ad227a9b5651e0382a65d7e9

Authored by cherishsince
1 parent 0cdd3423

【修改】AI Image dall 请求返回结构优化

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,8 +32,8 @@ public class AiImageController {
32 32
33 @Operation(summary = "获取image列表", description = "dall3、midjourney") 33 @Operation(summary = "获取image列表", description = "dall3、midjourney")
34 @GetMapping("/list") 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 @Operation(summary = "dall2/dall3绘画", description = "openAi dall3是付费的!") 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 package cn.iocoder.yudao.module.ai.controller.admin.image.vo; 1 package cn.iocoder.yudao.module.ai.controller.admin.image.vo;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageParam; 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 import lombok.Data; 7 import lombok.Data;
5 import lombok.experimental.Accessors; 8 import lombok.experimental.Accessors;
6 9
@@ -15,4 +18,50 @@ import lombok.experimental.Accessors; @@ -15,4 +18,50 @@ import lombok.experimental.Accessors;
15 @Accessors(chain = true) 18 @Accessors(chain = true)
16 public class AiImageListRespVO extends PageParam { 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,6 +29,14 @@ public interface AiImageConvert {
29 * @param req 29 * @param req
30 * @return 30 * @return
31 */ 31 */
  32 + AiImageDallRespVO convertAiImageDallDrawingRespVO(AiImageDO req);
  33 +
  34 + /**
  35 + * 转换 - AiImageDallDrawingRespVO
  36 + *
  37 + * @param req
  38 + * @return
  39 + */
32 AiImageDallRespVO convertAiImageDallDrawingRespVO(AiImageDallReqVO req); 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,16 +2,10 @@ package cn.iocoder.yudao.module.ai.service.image;
2 2
3 import cn.hutool.core.util.IdUtil; 3 import cn.hutool.core.util.IdUtil;
4 import cn.hutool.core.util.StrUtil; 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 import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageModelEnum; 6 import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageModelEnum;
10 import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageStyleEnum; 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 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; 9 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
16 import cn.iocoder.yudao.framework.common.pojo.PageResult; 10 import cn.iocoder.yudao.framework.common.pojo.PageResult;
17 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 11 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
@@ -23,9 +17,17 @@ import cn.iocoder.yudao.module.ai.convert.AiImageConvert; @@ -23,9 +17,17 @@ import cn.iocoder.yudao.module.ai.convert.AiImageConvert;
23 import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; 17 import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO;
24 import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper; 18 import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper;
25 import cn.iocoder.yudao.module.ai.enums.AiImageStatusEnum; 19 import cn.iocoder.yudao.module.ai.enums.AiImageStatusEnum;
  20 +import cn.iocoder.yudao.module.infra.api.file.FileApi;
26 import jakarta.annotation.PostConstruct; 21 import jakarta.annotation.PostConstruct;
27 import lombok.AllArgsConstructor; 22 import lombok.AllArgsConstructor;
28 import lombok.extern.slf4j.Slf4j; 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 import org.springframework.ai.openai.OpenAiImageClient; 31 import org.springframework.ai.openai.OpenAiImageClient;
30 import org.springframework.ai.openai.OpenAiImageOptions; 32 import org.springframework.ai.openai.OpenAiImageOptions;
31 import org.springframework.stereotype.Service; 33 import org.springframework.stereotype.Service;
@@ -47,6 +49,7 @@ import java.util.List; @@ -47,6 +49,7 @@ import java.util.List;
47 public class AiImageServiceImpl implements AiImageService { 49 public class AiImageServiceImpl implements AiImageService {
48 50
49 private final AiImageMapper aiImageMapper; 51 private final AiImageMapper aiImageMapper;
  52 + private final FileApi fileApi;
50 private final OpenAiImageClient openAiImageClient; 53 private final OpenAiImageClient openAiImageClient;
51 private final MidjourneyWebSocketStarter midjourneyWebSocketStarter; 54 private final MidjourneyWebSocketStarter midjourneyWebSocketStarter;
52 private final MidjourneyInteractionsApi midjourneyInteractionsApi; 55 private final MidjourneyInteractionsApi midjourneyInteractionsApi;
@@ -89,8 +92,6 @@ public class AiImageServiceImpl implements AiImageService { @@ -89,8 +92,6 @@ public class AiImageServiceImpl implements AiImageService {
89 // 获取 model 92 // 获取 model
90 OpenAiImageModelEnum openAiImageModelEnum = OpenAiImageModelEnum.valueOfModel(req.getModel()); 93 OpenAiImageModelEnum openAiImageModelEnum = OpenAiImageModelEnum.valueOfModel(req.getModel());
91 OpenAiImageStyleEnum openAiImageStyleEnum = OpenAiImageStyleEnum.valueOfStyle(req.getStyle()); 94 OpenAiImageStyleEnum openAiImageStyleEnum = OpenAiImageStyleEnum.valueOfStyle(req.getStyle());
92 - // 转换 AiImageDallDrawingRespVO  
93 - AiImageDallRespVO respVO = AiImageConvert.INSTANCE.convertAiImageDallDrawingRespVO(req);  
94 try { 95 try {
95 // 转换openai 参数 96 // 转换openai 参数
96 OpenAiImageOptions openAiImageOptions = new OpenAiImageOptions(); 97 OpenAiImageOptions openAiImageOptions = new OpenAiImageOptions();
@@ -100,22 +101,21 @@ public class AiImageServiceImpl implements AiImageService { @@ -100,22 +101,21 @@ public class AiImageServiceImpl implements AiImageService {
100 ImageResponse imageResponse = openAiImageClient.call(new ImagePrompt(req.getPrompt(), openAiImageOptions)); 101 ImageResponse imageResponse = openAiImageClient.call(new ImagePrompt(req.getPrompt(), openAiImageOptions));
101 // 发送 102 // 发送
102 ImageGeneration imageGeneration = imageResponse.getResult(); 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 null, null, null); 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 } catch (AiException aiException) { 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 null, null, null); 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,7 +125,7 @@ public class AiImageServiceImpl implements AiImageService {
125 // 保存数据库 125 // 保存数据库
126 String messageId = String.valueOf(IdUtil.getSnowflakeNextId()); 126 String messageId = String.valueOf(IdUtil.getSnowflakeNextId());
127 AiImageDO aiImageDO = doSave(req.getPrompt(), null, "midjoureny", 127 AiImageDO aiImageDO = doSave(req.getPrompt(), null, "midjoureny",
128 - null, AiImageStatusEnum.SUBMIT, null, 128 + null, null, AiImageStatusEnum.SUBMIT, null,
129 messageId, null, null); 129 messageId, null, null);
130 // 提交 midjourney 任务 130 // 提交 midjourney 任务
131 Boolean imagine = midjourneyInteractionsApi.imagine(messageId, req.getPrompt()); 131 Boolean imagine = midjourneyInteractionsApi.imagine(messageId, req.getPrompt());
@@ -149,7 +149,7 @@ public class AiImageServiceImpl implements AiImageService { @@ -149,7 +149,7 @@ public class AiImageServiceImpl implements AiImageService {
149 String mjOperationName = midjourneyOperationsVO.getLabel(); 149 String mjOperationName = midjourneyOperationsVO.getLabel();
150 // 保存一个 image 任务记录 150 // 保存一个 image 任务记录
151 doSave(aiImageDO.getPrompt(), aiImageDO.getSize(), aiImageDO.getModel(), 151 doSave(aiImageDO.getPrompt(), aiImageDO.getSize(), aiImageDO.getModel(),
152 - null, AiImageStatusEnum.SUBMIT, null, 152 + null, null, AiImageStatusEnum.SUBMIT, null,
153 req.getMessageId(), req.getOperateId(), mjOperationName); 153 req.getMessageId(), req.getOperateId(), mjOperationName);
154 // 提交操作 154 // 提交操作
155 midjourneyInteractionsApi.reRoll( 155 midjourneyInteractionsApi.reRoll(
@@ -201,6 +201,7 @@ public class AiImageServiceImpl implements AiImageService { @@ -201,6 +201,7 @@ public class AiImageServiceImpl implements AiImageService {
201 private AiImageDO doSave(String prompt, 201 private AiImageDO doSave(String prompt,
202 String size, 202 String size,
203 String model, 203 String model,
  204 + String picUrl,
204 String originalPicUrl, 205 String originalPicUrl,
205 AiImageStatusEnum statusEnum, 206 AiImageStatusEnum statusEnum,
206 String errorMessage, 207 String errorMessage,
@@ -218,6 +219,7 @@ public class AiImageServiceImpl implements AiImageService { @@ -218,6 +219,7 @@ public class AiImageServiceImpl implements AiImageService {
218 // TODO @芋艿 如何上传到自己服务器 219 // TODO @芋艿 如何上传到自己服务器
219 aiImageDO.setPicUrl(null); 220 aiImageDO.setPicUrl(null);
220 aiImageDO.setStatus(statusEnum.getStatus()); 221 aiImageDO.setStatus(statusEnum.getStatus());
  222 + aiImageDO.setPicUrl(picUrl);
221 aiImageDO.setOriginalPicUrl(originalPicUrl); 223 aiImageDO.setOriginalPicUrl(originalPicUrl);
222 aiImageDO.setErrorMessage(errorMessage); 224 aiImageDO.setErrorMessage(errorMessage);
223 // 225 //