Browse Source

【代码评审】AI:AI 绘图的逻辑

YunaiV 1 year ago
parent
commit
4932ce60d2

+ 2 - 0
yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageStatusEnum.java

@@ -14,6 +14,7 @@ import lombok.Getter;
 @Getter
 public enum AiImageStatusEnum {
 
+    // TODO @fan:改成 10 生成中;20 成功;30 失败;其它可以去掉噢
     SUBMIT("submit", "提交任务"),
     WAITING("waiting", "等待"),
     IN_PROGRESS("in_progress", "进行中"),
@@ -22,6 +23,7 @@ public enum AiImageStatusEnum {
 
     ;
 
+    // TODO @fan:final 一下
     private String status;
 
     private String name;

+ 12 - 0
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java

@@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.*;
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 
 // TODO @芋艿:整理接口定义
+// TODO @fan:参考 AiChatMessageController 改下 swagger 注解、注释
 /**
  * ai作图
  *
@@ -28,20 +29,28 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 @AllArgsConstructor
 public class AiImageController {
 
+    // TODO @fan:使用 @Resource 注入哈;然后 aiImageService => imageService;
     private final AiImageService aiImageService;
 
+    // TODO @fan:分页列表,建议是 getImagePage,包括接口 path 也建议改下哈;
+    // TODO @fan:@ModelAttribute 不需要哈;
+    // TODO @fan:这个要不搞成 my-page?因为是我的哈
     @Operation(summary = "获取image列表", description = "dall3、midjourney")
     @GetMapping("/list")
     public CommonResult<PageResult<AiImageListRespVO>> list(@Validated @ModelAttribute AiImageListReqVO req) {
+        // TODO @fan:import static,这样只要 success() 就行啦
         return CommonResult.success(aiImageService.list(req));
     }
 
+    // TODO @fan:搞成 get-my?
+    // TODO @fan:方法名改下哈。
     @Operation(summary = "获取image信息", description = "获取image信息")
     @GetMapping("/get")
     public CommonResult<AiImageListRespVO> get(@RequestParam("id") Long id) {
         return CommonResult.success(aiImageService.get(id));
     }
 
+    // TODO @fan:建议把 dallDrawing、midjourney 融合成一个 draw 接口,异步绘制;然后返回一个 id 给前端;前端通过 get 接口轮询,直到获取到生成成功
     @Operation(summary = "dall2/dall3绘画", description = "openAi dall3是付费的!")
     @PostMapping("/dall")
     public AiImageDallRespVO dallDrawing(@Validated @RequestBody AiImageDallReqVO req) {
@@ -62,6 +71,7 @@ public class AiImageController {
         return success(null);
     }
 
+    // TODO @fan:要不先不要 midjourneyOperate、cancelMidjourney 接口哈
     @Operation(summary = "取消 midjourney 绘画", description = "取消 midjourney 绘画")
     @PostMapping("/cancel-midjourney")
     public CommonResult<Void> cancelMidjourney(@RequestParam("id") Long id) {
@@ -69,10 +79,12 @@ public class AiImageController {
         return success(null);
     }
 
+    // TODO @fan:delete-my?需要校验是不是当前人哈
     @Operation(summary = "删除绘画记录", description = "")
     @DeleteMapping("/delete")
     public CommonResult<Void> delete(@RequestParam("id") Long id) {
         aiImageService.delete(id);
         return success(null);
     }
+
 }

+ 1 - 0
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java

@@ -11,6 +11,7 @@ import org.mapstruct.factory.Mappers;
 
 import java.util.List;
 
+// TODO @fan:convert 可以考虑去掉,使用 BeanUtils.copy 替代
 /**
  * ai image convert
  *

+ 2 - 0
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java

@@ -29,6 +29,8 @@ public class AiImageDO extends BaseDO {
     @Schema(description = "提示词")
     private String prompt;
 
+    // TODO @fan:要加一个平台字段;platform;因为一个平台,会有多种 model 模型;
+
     @Schema(description = "模型 dall2/dall3、MJ、NIJI")
     private String model;
 

+ 23 - 14
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java

@@ -39,6 +39,7 @@ import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
+// TODO @fan:注释优化下哈
 /**
  * ai 作图
  *
@@ -51,14 +52,23 @@ import java.util.concurrent.TimeUnit;
 @Slf4j
 public class AiImageServiceImpl implements AiImageService {
 
+    // TODO @fan:使用 @Resource 注入
+
+    // TODO @fan:imageMapper
     private final AiImageMapper aiImageMapper;
+
     private final FileApi fileApi;
+
     private final OpenAiImageClient openAiImageClient;
+
     private final MidjourneyWebSocketStarter midjourneyWebSocketStarter;
+
     private final MidjourneyInteractionsApi midjourneyInteractionsApi;
+
     private static ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(
             3, 5, 1, TimeUnit.HOURS, new LinkedBlockingQueue<>(32));
 
+    // TODO @fan:接 mj proxy
     @PostConstruct
     public void startMidjourney() {
         log.info("midjourney web socket starter...");
@@ -75,6 +85,7 @@ public class AiImageServiceImpl implements AiImageService {
         });
     }
 
+    // TODO @fan:1)分页,然后 loginUser 通过参数传入,这样 Service 无状态;2)另外,返回 DO;VO 的翻译,交给 Controller;3:还有,使用 BeanUtils 替代哈
     @Override
     public PageResult<AiImageListRespVO> list(AiImageListReqVO req) {
         // 获取登录用户
@@ -92,29 +103,33 @@ public class AiImageServiceImpl implements AiImageService {
         return result;
     }
 
+    // TODO @fan:1)返回 DO;VO 的翻译,交给 Controller;2)还有,使用 BeanUtils 替代哈
     @Override
     public AiImageListRespVO get(Long id) {
         AiImageDO aiImageDO = aiImageMapper.selectById(id);
         return AiImageConvert.INSTANCE.convertAiImageListRespVO(aiImageDO);
     }
 
+    // TODO @fan:1)loginUserId 通过 controller 传入;
     @Override
     public AiImageDallRespVO dallDrawing(AiImageDallReqVO req) {
         Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
         // 保存数据库
+        // TODO @fan:1)使用 BeanUtils;2)使用链式调用哈;
         AiImageDO aiImageDO = AiImageConvert.INSTANCE.convertAiImageDO(req);
         aiImageDO.setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus());
         aiImageDO.setUserId(loginUserId);
         aiImageMapper.insert(aiImageDO);
         // 异步执行
+        // TODO @fan:使用 @Async 去调用哈;
         EXECUTOR.execute(() -> {
             try {
-
                 // 获取 model
                 OpenAiImageModelEnum openAiImageModelEnum = OpenAiImageModelEnum.valueOfModel(req.getModel());
                 OpenAiImageStyleEnum openAiImageStyleEnum = OpenAiImageStyleEnum.valueOfStyle(req.getStyle());
 
                 // 转换openai 参数
+                // TODO @fan:需要考虑,不同平台,参数不同;
                 OpenAiImageOptions openAiImageOptions = new OpenAiImageOptions();
                 openAiImageOptions.setModel(openAiImageModelEnum.getModel());
                 openAiImageOptions.setStyle(openAiImageStyleEnum.getStyle());
@@ -125,23 +140,16 @@ public class AiImageServiceImpl implements AiImageService {
                 // 图片保存到服务器
                 String filePath = fileApi.createFile(HttpUtil.downloadBytes(imageGeneration.getOutput().getUrl()));
                 // 更新数据库
-                aiImageMapper.updateById(
-                        new AiImageDO()
-                                .setId(aiImageDO.getId())
-                                .setStatus(AiImageStatusEnum.COMPLETE.getStatus())
-                                .setPicUrl(filePath)
-                                .setOriginalPicUrl(imageGeneration.getOutput().getUrl())
+                aiImageMapper.updateById(new AiImageDO().setId(aiImageDO.getId()).setStatus(AiImageStatusEnum.COMPLETE.getStatus())
+                        .setPicUrl(filePath).setOriginalPicUrl(imageGeneration.getOutput().getUrl())
                 );
             } catch (AiException aiException) {
-                // 更新错误信息
-                aiImageMapper.updateById(
-                        new AiImageDO()
-                                .setId(aiImageDO.getId())
-                                .setStatus(AiImageStatusEnum.FAIL.getStatus())
-                                .setErrorMessage(aiException.getMessage())
-                );
+                // TODO @fan:错误日志,也打印下哈;因为 aiException.getMessage() 比较精简;
+                aiImageMapper.updateById(new AiImageDO().setId(aiImageDO.getId()).setStatus(AiImageStatusEnum.FAIL.getStatus())
+                        .setErrorMessage(aiException.getMessage()));
             }
         });
+        // TODO @fan:返回 id 就可以啦
         // 转换 AiImageDallDrawingRespVO
         return AiImageConvert.INSTANCE.convertAiImageDallDrawingRespVO(aiImageDO);
     }
@@ -188,6 +196,7 @@ public class AiImageServiceImpl implements AiImageService {
         );
     }
 
+    // TODO @fan:1)需要校验存在;2)需要校验属于我;
     @Override
     public void delete(Long id) {
         // 校验记录是否存在