Commit 99d477ac0a4196eaa37cf5a6f6cfe12a862359be
1 parent
0311c77e
【增加】图片绘画增加 绘画失败状态,并保存绘画错误信息,同时可以将错误信息返回给前端
Showing
4 changed files
with
73 additions
and
9 deletions
yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatDrawingStatusEnum.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.ai.enums; | ||
| 2 | + | ||
| 3 | +import lombok.AllArgsConstructor; | ||
| 4 | +import lombok.Getter; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * ai绘画状态 | ||
| 8 | + * | ||
| 9 | + * @author fansili | ||
| 10 | + * @time 2024/4/28 17:05 | ||
| 11 | + * @since 1.0 | ||
| 12 | + */ | ||
| 13 | +@AllArgsConstructor | ||
| 14 | +@Getter | ||
| 15 | +public enum AiChatDrawingStatusEnum { | ||
| 16 | + | ||
| 17 | + COMPLETE("complete", "完成"), | ||
| 18 | + FAIL("fail", "失败"), | ||
| 19 | + | ||
| 20 | + ; | ||
| 21 | + | ||
| 22 | + private String status; | ||
| 23 | + | ||
| 24 | + private String name; | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + public static AiChatDrawingStatusEnum valueOfStatus(String status) { | ||
| 28 | + for (AiChatDrawingStatusEnum itemEnum : AiChatDrawingStatusEnum.values()) { | ||
| 29 | + if (itemEnum.getStatus().equals(status)) { | ||
| 30 | + return itemEnum; | ||
| 31 | + } | ||
| 32 | + } | ||
| 33 | + throw new IllegalArgumentException("Invalid MessageType value: " + status); | ||
| 34 | + } | ||
| 35 | +} |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiImageDO.java
| @@ -41,5 +41,8 @@ public class AiImageDO extends BaseDO { | @@ -41,5 +41,8 @@ public class AiImageDO extends BaseDO { | ||
| 41 | @Schema(description = "绘画图片地址") | 41 | @Schema(description = "绘画图片地址") |
| 42 | private String drawingImageUrl; | 42 | private String drawingImageUrl; |
| 43 | 43 | ||
| 44 | + @Schema(description = "绘画错误信息") | ||
| 45 | + private String drawingError; | ||
| 46 | + | ||
| 44 | } | 47 | } |
| 45 | 48 |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java
| 1 | package cn.iocoder.yudao.module.ai.service.impl; | 1 | package cn.iocoder.yudao.module.ai.service.impl; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.framework.ai.image.Image; | 3 | +import cn.iocoder.yudao.framework.ai.exception.AiException; |
| 4 | import cn.iocoder.yudao.framework.ai.image.ImageGeneration; | 4 | import cn.iocoder.yudao.framework.ai.image.ImageGeneration; |
| 5 | import cn.iocoder.yudao.framework.ai.image.ImagePrompt; | 5 | import cn.iocoder.yudao.framework.ai.image.ImagePrompt; |
| 6 | import cn.iocoder.yudao.framework.ai.image.ImageResponse; | 6 | import cn.iocoder.yudao.framework.ai.image.ImageResponse; |
| 7 | import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageClient; | 7 | import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageClient; |
| 8 | import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageModelEnum; | 8 | import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageModelEnum; |
| 9 | import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageOptions; | 9 | import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageOptions; |
| 10 | +import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageStyleEnum; | ||
| 10 | import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; | 11 | import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; |
| 11 | import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; | 12 | import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; |
| 12 | import cn.iocoder.yudao.module.ai.dal.dataobject.AiImageDO; | 13 | import cn.iocoder.yudao.module.ai.dal.dataobject.AiImageDO; |
| 14 | +import cn.iocoder.yudao.module.ai.enums.AiChatDrawingStatusEnum; | ||
| 13 | import cn.iocoder.yudao.module.ai.mapper.AiImageMapper; | 15 | import cn.iocoder.yudao.module.ai.mapper.AiImageMapper; |
| 14 | import cn.iocoder.yudao.module.ai.service.AiImageService; | 16 | import cn.iocoder.yudao.module.ai.service.AiImageService; |
| 15 | import cn.iocoder.yudao.module.ai.vo.AiImageDallDrawingReq; | 17 | import cn.iocoder.yudao.module.ai.vo.AiImageDallDrawingReq; |
| @@ -39,25 +41,43 @@ public class AiImageServiceImpl implements AiImageService { | @@ -39,25 +41,43 @@ public class AiImageServiceImpl implements AiImageService { | ||
| 39 | public void dallDrawing(AiImageDallDrawingReq req, Utf8SseEmitter sseEmitter) { | 41 | public void dallDrawing(AiImageDallDrawingReq req, Utf8SseEmitter sseEmitter) { |
| 40 | // 获取 model | 42 | // 获取 model |
| 41 | OpenAiImageModelEnum openAiImageModelEnum = OpenAiImageModelEnum.valueOfModel(req.getModal()); | 43 | OpenAiImageModelEnum openAiImageModelEnum = OpenAiImageModelEnum.valueOfModel(req.getModal()); |
| 44 | + OpenAiImageStyleEnum openAiImageStyleEnum = OpenAiImageStyleEnum.valueOfStyle(req.getStyle()); | ||
| 42 | // | 45 | // |
| 43 | OpenAiImageOptions openAiImageOptions = new OpenAiImageOptions(); | 46 | OpenAiImageOptions openAiImageOptions = new OpenAiImageOptions(); |
| 44 | openAiImageOptions.setModel(openAiImageModelEnum); | 47 | openAiImageOptions.setModel(openAiImageModelEnum); |
| 45 | - ImageResponse imageResponse = openAiImageClient.call(new ImagePrompt(req.getPrompt(), openAiImageOptions)); | ||
| 46 | - // 发送 | ||
| 47 | - ImageGeneration imageGeneration = imageResponse.getResult(); | 48 | + openAiImageOptions.setStyle(openAiImageStyleEnum); |
| 49 | + openAiImageOptions.setSize(req.getSize()); | ||
| 50 | + ImageResponse imageResponse; | ||
| 48 | try { | 51 | try { |
| 49 | - sseEmitter.send(imageGeneration, MediaType.APPLICATION_JSON); | 52 | + imageResponse = openAiImageClient.call(new ImagePrompt(req.getPrompt(), openAiImageOptions)); |
| 53 | + // 发送 | ||
| 54 | + ImageGeneration imageGeneration = imageResponse.getResult(); | ||
| 55 | + // 发送信息 | ||
| 56 | + sendSseEmitter(sseEmitter, imageGeneration); | ||
| 57 | + // 保存数据库 | ||
| 58 | + doSave(req, imageGeneration.getOutput().getUrl(), AiChatDrawingStatusEnum.COMPLETE, null); | ||
| 59 | + } catch (AiException aiException) { | ||
| 60 | + // 保存数据库 | ||
| 61 | + doSave(req, null, AiChatDrawingStatusEnum.FAIL, aiException.getMessage()); | ||
| 62 | + // 发送错误信息 | ||
| 63 | + sendSseEmitter(sseEmitter, aiException.getMessage()); | ||
| 64 | + } | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + private static void sendSseEmitter(Utf8SseEmitter sseEmitter, Object object) { | ||
| 68 | + try { | ||
| 69 | + sseEmitter.send(object, MediaType.APPLICATION_JSON); | ||
| 50 | } catch (IOException e) { | 70 | } catch (IOException e) { |
| 51 | throw new RuntimeException(e); | 71 | throw new RuntimeException(e); |
| 52 | } finally { | 72 | } finally { |
| 53 | // 发送 complete | 73 | // 发送 complete |
| 54 | sseEmitter.complete(); | 74 | sseEmitter.complete(); |
| 55 | } | 75 | } |
| 56 | - Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); | ||
| 57 | - // | 76 | + } |
| 77 | + | ||
| 78 | + private void doSave(AiImageDallDrawingReq req, String imageUrl, AiChatDrawingStatusEnum drawingStatusEnum, String drawingError) { | ||
| 58 | // 保存数据库 | 79 | // 保存数据库 |
| 59 | - Image output = imageGeneration.getOutput(); | ||
| 60 | - String imageUrl = output.getUrl(); | 80 | + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); |
| 61 | AiImageDO aiImageDO = new AiImageDO(); | 81 | AiImageDO aiImageDO = new AiImageDO(); |
| 62 | aiImageDO.setId(null); | 82 | aiImageDO.setId(null); |
| 63 | aiImageDO.setPrompt(req.getPrompt()); | 83 | aiImageDO.setPrompt(req.getPrompt()); |
| @@ -65,6 +85,8 @@ public class AiImageServiceImpl implements AiImageService { | @@ -65,6 +85,8 @@ public class AiImageServiceImpl implements AiImageService { | ||
| 65 | aiImageDO.setModal(req.getModal()); | 85 | aiImageDO.setModal(req.getModal()); |
| 66 | aiImageDO.setUserId(loginUserId); | 86 | aiImageDO.setUserId(loginUserId); |
| 67 | aiImageDO.setDrawingImageUrl(imageUrl); | 87 | aiImageDO.setDrawingImageUrl(imageUrl); |
| 88 | + aiImageDO.setDrawingStatus(drawingStatusEnum.getStatus()); | ||
| 89 | + aiImageDO.setDrawingError(drawingError); | ||
| 68 | aiImageMapper.insert(aiImageDO); | 90 | aiImageMapper.insert(aiImageDO); |
| 69 | } | 91 | } |
| 70 | } | 92 | } |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageDallDrawingReq.java
| @@ -24,6 +24,10 @@ public class AiImageDallDrawingReq { | @@ -24,6 +24,10 @@ public class AiImageDallDrawingReq { | ||
| 24 | @NotNull(message = "模型不能为空") | 24 | @NotNull(message = "模型不能为空") |
| 25 | private String modal; | 25 | private String modal; |
| 26 | 26 | ||
| 27 | + @Schema(description = "图像生成的风格。可为vivid(生动)或natural(自然)") | ||
| 28 | + @NotNull(message = "图像生成的风格,不能为空!") | ||
| 29 | + private String style; | ||
| 30 | + | ||
| 27 | @Schema(description = "生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。") | 31 | @Schema(description = "生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。") |
| 28 | @NotNull(message = "size不能为空!") | 32 | @NotNull(message = "size不能为空!") |
| 29 | private String size; | 33 | private String size; |