mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-26 17:21:53 +08:00
【代码评审】AI:AI 绘图的逻辑
This commit is contained in:
parent
cfeb4bdca4
commit
4932ce60d2
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
// TODO @fan:convert 可以考虑去掉,使用 BeanUtils.copy 替代
|
||||
/**
|
||||
* ai image convert
|
||||
*
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
// 校验记录是否存在
|
||||
|
Loading…
Reference in New Issue
Block a user