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,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 | // |