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

This commit is contained in:
YunaiV 2024-05-28 22:09:35 +08:00
parent cfeb4bdca4
commit 4932ce60d2
5 changed files with 40 additions and 14 deletions

View File

@ -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 @fanfinal 一下
private String status;
private String name;

View File

@ -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 @fanimport 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建议把 dallDrawingmidjourney 融合成一个 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要不先不要 midjourneyOperatecancelMidjourney 接口哈
@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 @fandelete-my需要校验是不是当前人哈
@Operation(summary = "删除绘画记录", description = "")
@DeleteMapping("/delete")
public CommonResult<Void> delete(@RequestParam("id") Long id) {
aiImageService.delete(id);
return success(null);
}
}

View File

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

View File

@ -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;

View File

@ -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 @fanimageMapper
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 @fan1分页然后 loginUser 通过参数传入这样 Service 无状态2另外返回 DOVO 的翻译交给 Controller3还有使用 BeanUtils 替代哈
@Override
public PageResult<AiImageListRespVO> list(AiImageListReqVO req) {
// 获取登录用户
@ -92,29 +103,33 @@ public class AiImageServiceImpl implements AiImageService {
return result;
}
// TODO @fan1返回 DOVO 的翻译交给 Controller2还有使用 BeanUtils 替代哈
@Override
public AiImageListRespVO get(Long id) {
AiImageDO aiImageDO = aiImageMapper.selectById(id);
return AiImageConvert.INSTANCE.convertAiImageListRespVO(aiImageDO);
}
// TODO @fan1loginUserId 通过 controller 传入
@Override
public AiImageDallRespVO dallDrawing(AiImageDallReqVO req) {
Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
// 保存数据库
// TODO @fan1使用 BeanUtils2使用链式调用哈
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 @fan1需要校验存在2需要校验属于我
@Override
public void delete(Long id) {
// 校验记录是否存在