From 7f75464e578f4f4e24af12db69b90e1413458e81 Mon Sep 17 00:00:00 2001 From: xueqingkun Date: Tue, 1 Apr 2025 15:37:37 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0comfyuo=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 10 ++ .../hub/config/ExceptionHandlerConfig.java | 63 ++++++++ .../hub/config/MyMetaObjectHandler.java | 26 ++++ .../service/hub/config/MybatisPlusConfig.java | 43 ++++++ .../ai/service/hub/config/SecurityConfig.java | 10 ++ .../hub/constant/ComfyuiParamTypeEnum.java | 87 +++++++++++ .../hub/constant/ResultStatusEnum.java | 55 +++++++ .../hub/controller/ComfyUIController.java | 48 ++++++ .../ai/service/hub/domain/ComfyuiPrompt.java | 58 ++++++++ .../hub/domain/ComfyuiPromptParam.java | 59 ++++++++ .../hub/dto/comfyui/ImageUploadDTO.java | 14 ++ .../service/hub/dto/comfyui/PromptRunDTO.java | 19 +++ .../hub/dto/comfyui/ResourceViewDTO.java | 22 +++ .../hub/exception/BusinessException.java | 76 ++++++++++ .../hub/mapper/ComfyuiPromptMapper.java | 18 +++ .../hub/mapper/ComfyuiPromptParamMapper.java | 18 +++ .../hub/service/ComfyUIApiService.java | 32 ++++ .../service/ComfyUIPromptParamService.java | 37 +++++ .../hub/service/ComfyUIPromptService.java | 21 +++ .../service/hub/service/ComfyUIService.java | 20 +++ .../service/impl/ComfyUIApiServiceImpl.java | 105 ++++++++++++++ .../impl/ComfyUIPromptParamServiceImpl.java | 76 ++++++++++ .../impl/ComfyUIPromptServiceImpl.java | 28 ++++ .../hub/service/impl/ComfyUIServiceImpl.java | 137 ++++++++++++++++++ .../service/impl/HeygemApiServiceImpl.java | 8 +- .../hub/vo/comfyui/RunPromptReqVo.java | 20 +++ .../hub/vo/comfyui/TaskResultResVo.java | 17 +++ src/main/resources/application.yml | 9 +- .../resources/mapper/ComfyuiPromptMapper.xml | 20 +++ .../mapper/ComfyuiPromptParamMapper.xml | 22 +++ .../ai/service/hub/ComfyUIApiServiceTest.java | 60 ++++++++ 31 files changed, 1233 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/supervision/ai/service/hub/config/ExceptionHandlerConfig.java create mode 100644 src/main/java/com/supervision/ai/service/hub/config/MyMetaObjectHandler.java create mode 100644 src/main/java/com/supervision/ai/service/hub/config/MybatisPlusConfig.java create mode 100644 src/main/java/com/supervision/ai/service/hub/constant/ComfyuiParamTypeEnum.java create mode 100644 src/main/java/com/supervision/ai/service/hub/constant/ResultStatusEnum.java create mode 100644 src/main/java/com/supervision/ai/service/hub/controller/ComfyUIController.java create mode 100644 src/main/java/com/supervision/ai/service/hub/domain/ComfyuiPrompt.java create mode 100644 src/main/java/com/supervision/ai/service/hub/domain/ComfyuiPromptParam.java create mode 100644 src/main/java/com/supervision/ai/service/hub/dto/comfyui/ImageUploadDTO.java create mode 100644 src/main/java/com/supervision/ai/service/hub/dto/comfyui/PromptRunDTO.java create mode 100644 src/main/java/com/supervision/ai/service/hub/dto/comfyui/ResourceViewDTO.java create mode 100644 src/main/java/com/supervision/ai/service/hub/exception/BusinessException.java create mode 100644 src/main/java/com/supervision/ai/service/hub/mapper/ComfyuiPromptMapper.java create mode 100644 src/main/java/com/supervision/ai/service/hub/mapper/ComfyuiPromptParamMapper.java create mode 100644 src/main/java/com/supervision/ai/service/hub/service/ComfyUIApiService.java create mode 100644 src/main/java/com/supervision/ai/service/hub/service/ComfyUIPromptParamService.java create mode 100644 src/main/java/com/supervision/ai/service/hub/service/ComfyUIPromptService.java create mode 100644 src/main/java/com/supervision/ai/service/hub/service/ComfyUIService.java create mode 100644 src/main/java/com/supervision/ai/service/hub/service/impl/ComfyUIApiServiceImpl.java create mode 100644 src/main/java/com/supervision/ai/service/hub/service/impl/ComfyUIPromptParamServiceImpl.java create mode 100644 src/main/java/com/supervision/ai/service/hub/service/impl/ComfyUIPromptServiceImpl.java create mode 100644 src/main/java/com/supervision/ai/service/hub/service/impl/ComfyUIServiceImpl.java create mode 100644 src/main/java/com/supervision/ai/service/hub/vo/comfyui/RunPromptReqVo.java create mode 100644 src/main/java/com/supervision/ai/service/hub/vo/comfyui/TaskResultResVo.java create mode 100644 src/main/resources/mapper/ComfyuiPromptMapper.xml create mode 100644 src/main/resources/mapper/ComfyuiPromptParamMapper.xml create mode 100644 src/test/java/com/supervision/ai/service/hub/ComfyUIApiServiceTest.java diff --git a/pom.xml b/pom.xml index 70f1d0c..a987d00 100644 --- a/pom.xml +++ b/pom.xml @@ -72,10 +72,20 @@ hutool-all 5.8.26 + + com.alibaba + fastjson + 1.2.83_noneautotype + com.fasterxml.jackson.core jackson-core 2.15.3 + + com.fasterxml.jackson.core + jackson-databind + 2.15.3 + diff --git a/src/main/java/com/supervision/ai/service/hub/config/ExceptionHandlerConfig.java b/src/main/java/com/supervision/ai/service/hub/config/ExceptionHandlerConfig.java new file mode 100644 index 0000000..c8aba9f --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/config/ExceptionHandlerConfig.java @@ -0,0 +1,63 @@ +package com.supervision.ai.service.hub.config; + +import com.supervision.ai.service.hub.constant.ResultStatusEnum; +import com.supervision.ai.service.hub.dto.common.R; +import com.supervision.ai.service.hub.exception.BusinessException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.multipart.MaxUploadSizeExceededException; + +/** + * 统一异常处理器配置 + * + * @author wb + * @date 2022/3/10 13:24 + */ +@Slf4j +@Configuration +@RestControllerAdvice(annotations = RestController.class, basePackages = {"com.supervision.ai.service.**.controller"}) +public class ExceptionHandlerConfig { + + /** + * 添加手动校验参数的异常处理 + * + * @param exception 参数验证异常 + * @return 通用返回值 + */ + @ExceptionHandler(IllegalArgumentException.class) + public R manualValidationExceptionResponse(IllegalArgumentException exception) { + log.error("=========手动校验参数异常=========>>>"); + log.error(exception.getMessage(), exception); + log.error("<<<=========手动校验参数异常========="); + return R.fail(ResultStatusEnum.ILLEGAL_ARGUMENT.getCode(), exception.getMessage()); + } + + @ExceptionHandler(BusinessException.class) + public R businessExceptionResponse(BusinessException exception) { + log.error("=========运行异常=========>>>"); + log.error(exception.getMessage(), exception); + log.error("<<<=========运行异常========="); + + return R.fail(511, exception.getMessage()); + } + + @ExceptionHandler(RuntimeException.class) + public R manualValidationExceptionResponse(RuntimeException exception) { + log.error("=========运行异常=========>>>"); + log.error(exception.getMessage(), exception); + log.error("<<<=========运行异常========="); + + return R.fail(ResultStatusEnum.RUNTIME_EXCEPTION.getCode(), exception.getMessage()); + } + + @ExceptionHandler(MaxUploadSizeExceededException.class) + public R handleMaxSizeException(MaxUploadSizeExceededException exception) { + log.error("=========文件大小超出限制异常=========>>>"); + log.error(exception.getMessage(), exception); + log.error("<<<=========文件大小超出限制异常========="); + return R.fail(ResultStatusEnum.EXCEED_FILE_SIZE.getCode(), exception.getMessage()); + } +} diff --git a/src/main/java/com/supervision/ai/service/hub/config/MyMetaObjectHandler.java b/src/main/java/com/supervision/ai/service/hub/config/MyMetaObjectHandler.java new file mode 100644 index 0000000..460ad5b --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/config/MyMetaObjectHandler.java @@ -0,0 +1,26 @@ +package com.supervision.ai.service.hub.config; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import org.apache.ibatis.reflection.MetaObject; + +import java.time.LocalDateTime; + +/** + * @author Ray + */ +public class MyMetaObjectHandler implements MetaObjectHandler { + public MyMetaObjectHandler() { + } + + @Override + public void insertFill(MetaObject metaObject) { + this.setFieldValByName("createTime", LocalDateTime.now(), metaObject); + this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject); + } + + @Override + public void updateFill(MetaObject metaObject) { + this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject); + } + +} \ No newline at end of file diff --git a/src/main/java/com/supervision/ai/service/hub/config/MybatisPlusConfig.java b/src/main/java/com/supervision/ai/service/hub/config/MybatisPlusConfig.java new file mode 100644 index 0000000..b9c416d --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/config/MybatisPlusConfig.java @@ -0,0 +1,43 @@ +package com.supervision.ai.service.hub.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * MybatisPlus配置 + * + * @author qmy + * @version 1.0.0 2020/10/22 9:47 + * @since JDK1.8 + */ +@Configuration +public class MybatisPlusConfig { + + @Bean + public MyMetaObjectHandler myMetaObjectHandler() { + return new MyMetaObjectHandler(); + } + + /** + * 拦截器配置 + */ + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(this.paginationInterceptor()); + return interceptor; + } + + private PaginationInnerInterceptor paginationInterceptor() { + PaginationInnerInterceptor paginationInterceptor = new PaginationInnerInterceptor(); + paginationInterceptor.setOverflow(false); + /** + * 注意! 此处要设置数据库类型. + */ + paginationInterceptor.setDbType(DbType.POSTGRE_SQL); + return paginationInterceptor; + } +} diff --git a/src/main/java/com/supervision/ai/service/hub/config/SecurityConfig.java b/src/main/java/com/supervision/ai/service/hub/config/SecurityConfig.java index 7266267..d9f10d9 100644 --- a/src/main/java/com/supervision/ai/service/hub/config/SecurityConfig.java +++ b/src/main/java/com/supervision/ai/service/hub/config/SecurityConfig.java @@ -2,6 +2,8 @@ package com.supervision.ai.service.hub.config; import com.supervision.ai.service.hub.filter.JwtAuthenticationFilter; import com.supervision.ai.service.hub.service.impl.SysUserService; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.security.Keys; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -18,6 +20,7 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import java.util.Base64; @Configuration @@ -70,4 +73,11 @@ public class SecurityConfig { return new BCryptPasswordEncoder(); } + public static void main(String[] args) { + String s = Base64.getEncoder().encodeToString(Keys.secretKeyFor(SignatureAlgorithm.HS256).getEncoded()); + BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(); + String encode = bCryptPasswordEncoder.encode("123456"); + System.out.println(encode); + } + } diff --git a/src/main/java/com/supervision/ai/service/hub/constant/ComfyuiParamTypeEnum.java b/src/main/java/com/supervision/ai/service/hub/constant/ComfyuiParamTypeEnum.java new file mode 100644 index 0000000..417d8d1 --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/constant/ComfyuiParamTypeEnum.java @@ -0,0 +1,87 @@ +package com.supervision.ai.service.hub.constant; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.NumberUtil; +import lombok.Getter; + +@Getter +public enum ComfyuiParamTypeEnum { + // 整数 + INTEGER(0,"整数", Integer.class) { + @Override + public Object coverType(Object value) { + if (null == value){ + return null; + } + if (value instanceof Integer){ + return value; + } + Assert.isTrue(NumberUtil.isNumber(value.toString()),"参数类型错误"); + return NumberUtil.parseInt(value.toString()); + } + }, + // 浮点型 + FLOAT(1,"浮点型", Float.class) { + @Override + public Object coverType(Object value) { + if (null == value){ + return null; + } + if (value instanceof Float){ + return value; + } + Assert.isTrue(NumberUtil.isNumber(value.toString()),"参数类型错误"); + return NumberUtil.parseFloat(value.toString()); + } + }, + // 字符串 + STRING(2,"字符串",String.class) { + @Override + public Object coverType(Object value) { + if (null == value){ + return null; + } + if (value instanceof String){ + return value; + } + return value.toString(); + } + }, + // 布尔值 + BOOLEAN(3,"布尔值",Boolean.class) { + @Override + public Object coverType(Object value) { + if (null == value){ + return null; + } + if (value instanceof Boolean){ + return value; + } + Assert.isTrue(false,"参数类型错误"); + return null; + } + }; + + private final int code; + private final String desc; + + private final Class type; + + ComfyuiParamTypeEnum(int code, String desc,Class type) { + this.code = code; + this.desc = desc; + this.type = type; + } + + + public static ComfyuiParamTypeEnum getByCode(int code){ + for (ComfyuiParamTypeEnum value : ComfyuiParamTypeEnum.values()) { + if (value.getCode() == code){ + return value; + } + } + return null; + } + + public abstract Object coverType(Object value); +} diff --git a/src/main/java/com/supervision/ai/service/hub/constant/ResultStatusEnum.java b/src/main/java/com/supervision/ai/service/hub/constant/ResultStatusEnum.java new file mode 100644 index 0000000..7bd7e32 --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/constant/ResultStatusEnum.java @@ -0,0 +1,55 @@ +package com.supervision.ai.service.hub.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +/** + * 响应结果状态枚举类 + * @author qimaoyu + * @create 2019-07-14 10:22 + */ +@NoArgsConstructor +@AllArgsConstructor +public enum ResultStatusEnum { + + AUTHENTICATION_FAILED(320, "token失效,请重新登录!"), + NO_ACCESS_TO_THIS_INTERFACE(320, "无权访问此接口!"), + FAILED_TO_GENERATE_TOKEN(321, "生成token失败!"), + ACCOUNT_PASSWORD_INCORRECT(322, "账号或密码错误!"), + ACCOUNT_NOT_CREATE(323, "账号未创建!"), + HAS_BEEN_PULLED_BLACK(324, "已被删除或禁用,无法登录!"), + USERNAME_MAIL_IS_EXIST(341, "登录名称已经被注册!"), + USERNAME_IS_BLANK(342, "登录名称为空!"), + VERIFICATION_CODE_EXPIRED(350,"验证码已过期,请重新获取。"), + VERIFICATION_CODE_FAILURE(351,"验证码输入错误。"), + OPERATE_FAIL(360,"修改毕业生信息失败。"), + DATA_IS_EMPTY(370,"查询到的结果为空"), + SYSTEM_ABNORMAL(500, "系统繁忙,请稍后重试!"), + UPLOAD_EXCEPTION(501, "文件上传异常!"), + EXPORT_EXCEPTION(502, "文件导出异常!"), + INCORRECT_FILE_FORMAT(503, "文件格式不正确!"), + PARAMETER_CANNOT_BE_EMPTY(504, "参数不能为空,操作失败!"), + NO_TEMP_UPLOADFILEPATH(505,"未配置文件上传临时存储路径"), + USER_DOES_NOT_EXIST(507, "用户不存在,操作失败!"), + + ILLEGAL_ARGUMENT(508, "参数校验失败!"), + RUNTIME_EXCEPTION(509, "程序运行异常!"), + EXCEED_FILE_SIZE(510, "文件大小超出限制!"), + IMPORT_COMPANY_FORMAT_ERROR(521,"Excel表格格式错误!"), + IMPORT_COMPANY_FAIL(522,"部分数据导入失败"), + INSERT_FAIL(600,"新增失败"), + DuplicateKeyException(601,"该条信息已经存在,请勿重复添加"), + UPDATE_FAIL(700,"更新失败"), + DELETE_FAIL(800,"删除失败"), + YEAR_IS_CLOSE(1001,"该年度暂未开启"); + + @Getter + @Setter + private int code; + + @Getter + @Setter + private String message; +} diff --git a/src/main/java/com/supervision/ai/service/hub/controller/ComfyUIController.java b/src/main/java/com/supervision/ai/service/hub/controller/ComfyUIController.java new file mode 100644 index 0000000..1b66916 --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/controller/ComfyUIController.java @@ -0,0 +1,48 @@ +package com.supervision.ai.service.hub.controller; + +import com.supervision.ai.service.hub.dto.common.R; +import com.supervision.ai.service.hub.service.ComfyUIService; +import com.supervision.ai.service.hub.vo.comfyui.RunPromptReqVo; +import com.supervision.ai.service.hub.vo.comfyui.TaskResultResVo; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import java.util.List; + +@RestController +@RequestMapping("/comfyui") +@RequiredArgsConstructor +public class ComfyUIController { + + private final ComfyUIService comfyUIService; + + /** + * 运行prompt + * @param runPromptReqVo prompt信息 + * @return + */ + @PostMapping("/run") + public R runPrompt(@RequestBody RunPromptReqVo runPromptReqVo) { + + String taskId = comfyUIService.runPrompt(runPromptReqVo); + return R.ok(taskId); + } + + @GetMapping("/queryHistory") + public R> queryHistory(@RequestParam(name = "promptId", required = false) String promptId) { + List taskResultResVos = comfyUIService.queryHistory(promptId); + return R.ok(taskResultResVos); + } + + @PostMapping("/uploadImage") + public R uploadImage(@RequestParam("file") MultipartFile file) throws Exception { + String imageId = comfyUIService.uploadImage(file); + return R.ok(imageId); + } + + @GetMapping("/downloadView") + public void downloadView(@RequestParam("fileName") String fileName, HttpServletResponse response) throws Exception { + comfyUIService.downloadView(fileName, response); + } +} diff --git a/src/main/java/com/supervision/ai/service/hub/domain/ComfyuiPrompt.java b/src/main/java/com/supervision/ai/service/hub/domain/ComfyuiPrompt.java new file mode 100644 index 0000000..d3de8fb --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/domain/ComfyuiPrompt.java @@ -0,0 +1,58 @@ +package com.supervision.ai.service.hub.domain; + +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler; +import lombok.Data; + +/** + * comfyui提示词表 + * @TableName comfyui_prompt + */ +@Data +@TableName(value ="comfyui_prompt",autoResultMap = true) +public class ComfyuiPrompt implements Serializable { + /** + * 主键 + */ + @TableId + private String id; + + /** + * 提示词名 + */ + private String promptName; + + /** + * 提示词类型 0:文生图 1:图生图 2:图生视频 + */ + private String promptType; + + /** + * 提示词 + */ + @TableField(typeHandler = FastjsonTypeHandler.class) + private JSONObject prompt; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; + +} \ No newline at end of file diff --git a/src/main/java/com/supervision/ai/service/hub/domain/ComfyuiPromptParam.java b/src/main/java/com/supervision/ai/service/hub/domain/ComfyuiPromptParam.java new file mode 100644 index 0000000..13f5df6 --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/domain/ComfyuiPromptParam.java @@ -0,0 +1,59 @@ +package com.supervision.ai.service.hub.domain; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +/** + * + * @TableName comfyui_prompt_param + */ +@TableName(value ="comfyui_prompt_param") +@Data +public class ComfyuiPromptParam implements Serializable { + /** + * 主键 + */ + @TableId + private String id; + + /** + * varchar(64) + */ + private String promptId; + + /** + * 参数key + */ + private String paramKey; + + /** + * 参数类型 0:整数 1:浮点型 2:字符串 3:布尔值 + */ + private Integer paramType; + + /** + * 是否必填 true:必填 false:非必填 + */ + private Boolean required; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; + +} \ No newline at end of file diff --git a/src/main/java/com/supervision/ai/service/hub/dto/comfyui/ImageUploadDTO.java b/src/main/java/com/supervision/ai/service/hub/dto/comfyui/ImageUploadDTO.java new file mode 100644 index 0000000..a1d459a --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/dto/comfyui/ImageUploadDTO.java @@ -0,0 +1,14 @@ +package com.supervision.ai.service.hub.dto.comfyui; + +import lombok.Data; + +/** + * 图片上传请求响应 + */ +@Data +public class ImageUploadDTO { + + private String name; + private String subfolder; + private String type; +} diff --git a/src/main/java/com/supervision/ai/service/hub/dto/comfyui/PromptRunDTO.java b/src/main/java/com/supervision/ai/service/hub/dto/comfyui/PromptRunDTO.java new file mode 100644 index 0000000..30fb6f1 --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/dto/comfyui/PromptRunDTO.java @@ -0,0 +1,19 @@ +package com.supervision.ai.service.hub.dto.comfyui; + +import lombok.Data; +import java.util.Map; + +/** + * 运行提示词请求结果 + */ +@Data +public class PromptRunDTO { + + private String prompt_id; + + private int number; + + private Map node_errors; + + private Map error; +} diff --git a/src/main/java/com/supervision/ai/service/hub/dto/comfyui/ResourceViewDTO.java b/src/main/java/com/supervision/ai/service/hub/dto/comfyui/ResourceViewDTO.java new file mode 100644 index 0000000..24ff20b --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/dto/comfyui/ResourceViewDTO.java @@ -0,0 +1,22 @@ +package com.supervision.ai.service.hub.dto.comfyui; + +import lombok.Data; + +@Data +public class ResourceViewDTO { + + private String fileName; + + private String contentType; + + private byte[] content; + + public ResourceViewDTO() { + } + + public ResourceViewDTO(String fileName, String contentType, byte[] content) { + this.fileName = fileName; + this.contentType = contentType; + this.content = content; + } +} diff --git a/src/main/java/com/supervision/ai/service/hub/exception/BusinessException.java b/src/main/java/com/supervision/ai/service/hub/exception/BusinessException.java new file mode 100644 index 0000000..b011871 --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/exception/BusinessException.java @@ -0,0 +1,76 @@ +/* + * 文 件 名: CustomException + * 版 权: + * 描 述: <描述> + * 修 改 人: RedName + * 修改时间: 2022/8/5 + * 跟踪单号: <跟踪单号> + * 修改单号: <修改单号> + * 修改内容: <修改内容> + */ +package com.supervision.ai.service.hub.exception; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; + +/** + * <功能详细描述> + * 自定义异常 + * + * @author ljt + * @version [版本号, 2022/8/5] + * @see [相关类/方法] + * @since [产品/模块版本] + */ +@Slf4j +public class BusinessException extends RuntimeException { + /** + * 异常编码 + */ + private final Integer code; + + /** + * 异常信息 + */ + private final String message; + + public BusinessException(Throwable cause) { + super(cause); + this.code = HttpStatus.INTERNAL_SERVER_ERROR.value(); + this.message = null; + + } + + public BusinessException(Throwable cause, String message) { + super(cause); + this.code = HttpStatus.INTERNAL_SERVER_ERROR.value(); + this.message = message; + + } + + public BusinessException(String message) { + this.code = HttpStatus.INTERNAL_SERVER_ERROR.value(); + this.message = message; + } + + public BusinessException(String message, Integer code) { + this.message = message; + this.code = code; + } + + public BusinessException(String message, Throwable e) { + super(message, e); + log.error(message, e); + this.code = HttpStatus.INTERNAL_SERVER_ERROR.value(); + this.message = message; + } + + @Override + public String getMessage() { + return message; + } + + public Integer getCode() { + return code; + } +} diff --git a/src/main/java/com/supervision/ai/service/hub/mapper/ComfyuiPromptMapper.java b/src/main/java/com/supervision/ai/service/hub/mapper/ComfyuiPromptMapper.java new file mode 100644 index 0000000..4efe384 --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/mapper/ComfyuiPromptMapper.java @@ -0,0 +1,18 @@ +package com.supervision.ai.service.hub.mapper; + +import com.supervision.ai.service.hub.domain.ComfyuiPrompt; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author Administrator +* @description 针对表【comfyui_prompt(comfyui提示词表)】的数据库操作Mapper +* @createDate 2025-03-31 17:49:56 +* @Entity com.supervision.ai.service.hub.domain.ComfyuiPrompt +*/ +public interface ComfyuiPromptMapper extends BaseMapper { + +} + + + + diff --git a/src/main/java/com/supervision/ai/service/hub/mapper/ComfyuiPromptParamMapper.java b/src/main/java/com/supervision/ai/service/hub/mapper/ComfyuiPromptParamMapper.java new file mode 100644 index 0000000..9e81416 --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/mapper/ComfyuiPromptParamMapper.java @@ -0,0 +1,18 @@ +package com.supervision.ai.service.hub.mapper; + +import com.supervision.ai.service.hub.domain.ComfyuiPromptParam; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author Administrator +* @description 针对表【comfyui_prompt_param】的数据库操作Mapper +* @createDate 2025-03-31 17:49:56 +* @Entity com.supervision.ai.service.hub.domain.ComfyuiPromptParam +*/ +public interface ComfyuiPromptParamMapper extends BaseMapper { + +} + + + + diff --git a/src/main/java/com/supervision/ai/service/hub/service/ComfyUIApiService.java b/src/main/java/com/supervision/ai/service/hub/service/ComfyUIApiService.java new file mode 100644 index 0000000..17ecd87 --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/service/ComfyUIApiService.java @@ -0,0 +1,32 @@ +package com.supervision.ai.service.hub.service; + +import com.alibaba.fastjson.JSONObject; +import com.supervision.ai.service.hub.dto.comfyui.ImageUploadDTO; +import com.supervision.ai.service.hub.dto.comfyui.PromptRunDTO; +import com.supervision.ai.service.hub.dto.comfyui.ResourceViewDTO; + +import java.util.Map; + +public interface ComfyUIApiService { + + /** + * 运行prompt + * @param prompt 提示词 + * @return + */ + PromptRunDTO runPrompt(JSONObject prompt); + + /** + * 查询执行历史 + * @param promptId 提示词id,为空时查询全部 + * @return + */ + Map queryHistory(String promptId); + + + ImageUploadDTO uploadImage(byte[] file, String fileName); + + ResourceViewDTO downloadView(String imageId); + + +} diff --git a/src/main/java/com/supervision/ai/service/hub/service/ComfyUIPromptParamService.java b/src/main/java/com/supervision/ai/service/hub/service/ComfyUIPromptParamService.java new file mode 100644 index 0000000..f51b50c --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/service/ComfyUIPromptParamService.java @@ -0,0 +1,37 @@ +package com.supervision.ai.service.hub.service; + +import com.supervision.ai.service.hub.domain.ComfyuiPromptParam; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; +import java.util.Map; + +/** +* @author Administrator +* @description 针对表【comfyui_prompt_param】的数据库操作Service +* @createDate 2025-03-31 17:49:56 +*/ +public interface ComfyUIPromptParamService extends IService { + + /** + * 参数校验 + * @param params 待校验参数 + * @param promptId 提示id + * @return true 通过校验 false 未通过校验 + */ + boolean requiredCheck(Map params, String promptId); + + + boolean requiredCheck(Map params, List promptParamList); + + /** + * 根据promptId查询参数 + * @param promptId 提示词id + * @return + */ + List listByPromptId(String promptId); + + + ComfyuiPromptParam selectPromptParam(String paramKey,List promptParamList); + +} diff --git a/src/main/java/com/supervision/ai/service/hub/service/ComfyUIPromptService.java b/src/main/java/com/supervision/ai/service/hub/service/ComfyUIPromptService.java new file mode 100644 index 0000000..384a657 --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/service/ComfyUIPromptService.java @@ -0,0 +1,21 @@ +package com.supervision.ai.service.hub.service; + +import com.supervision.ai.service.hub.domain.ComfyuiPrompt; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author Administrator +* @description 针对表【comfyui_prompt(comfyui提示词表)】的数据库操作Service +* @createDate 2025-03-31 17:49:56 +*/ +public interface ComfyUIPromptService extends IService { + + + /** + * 判断提示词是否存在 + * @param promptId 提示词id + * @return true 存在,false 不存在 + */ + boolean promptExist(String promptId); + +} diff --git a/src/main/java/com/supervision/ai/service/hub/service/ComfyUIService.java b/src/main/java/com/supervision/ai/service/hub/service/ComfyUIService.java new file mode 100644 index 0000000..11ece9a --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/service/ComfyUIService.java @@ -0,0 +1,20 @@ +package com.supervision.ai.service.hub.service; + +import com.supervision.ai.service.hub.vo.comfyui.RunPromptReqVo; +import com.supervision.ai.service.hub.vo.comfyui.TaskResultResVo; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; +import java.util.List; + +public interface ComfyUIService { + + + String runPrompt(RunPromptReqVo runPromptReqVo); + + List queryHistory(String promptId); + + String uploadImage(MultipartFile file) throws IOException; + + void downloadView(String imageId, HttpServletResponse response) throws IOException; +} diff --git a/src/main/java/com/supervision/ai/service/hub/service/impl/ComfyUIApiServiceImpl.java b/src/main/java/com/supervision/ai/service/hub/service/impl/ComfyUIApiServiceImpl.java new file mode 100644 index 0000000..6c874e4 --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/service/impl/ComfyUIApiServiceImpl.java @@ -0,0 +1,105 @@ +package com.supervision.ai.service.hub.service.impl; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.http.HttpUtil; +import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.supervision.ai.service.hub.dto.comfyui.ImageUploadDTO; +import com.supervision.ai.service.hub.dto.comfyui.PromptRunDTO; +import com.supervision.ai.service.hub.dto.comfyui.ResourceViewDTO; +import com.supervision.ai.service.hub.service.ComfyUIApiService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import java.util.Map; + +@Slf4j +@Service +public class ComfyUIApiServiceImpl implements ComfyUIApiService { + + @Value("${comfyUI.server.ip}") + private String comfyUIServiceIp; + + @Value("${comfyUI.server.port}") + private String comfyUIServicePort; + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public PromptRunDTO runPrompt(JSONObject prompt) { + String url = "http://" + comfyUIServiceIp + ":" + comfyUIServicePort + "/prompt"; + log.info("comfyUI runPrompt 请求地址:{}",url); + HttpRequest request = HttpUtil.createPost(url).body(prompt.toJSONString()); + try (HttpResponse execute = request.execute()){ + String body = execute.body(); + log.info("comfyUI runPrompt 请求结果:{}",body); + if (execute.isOk()){ + try { + return objectMapper.readValue(body, PromptRunDTO.class); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + }else { + throw new RuntimeException("/prompt请求失败"); + } + } + } + + @Override + public Map queryHistory(String promptId) { + + String url = "http://" + comfyUIServiceIp + ":" + comfyUIServicePort + "/history" + (StrUtil.isEmpty(promptId)? "" : "/"+promptId); + log.info("comfyUI queryHistory 请求地址:{}",url); + try (HttpResponse execute = HttpUtil.createGet(url).execute()){ + if (execute.isOk()){ + String body = execute.body(); + try { + return objectMapper.readValue(body, Map.class); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + }else { + throw new RuntimeException("/history请求失败"); + } + } + } + + @Override + public ImageUploadDTO uploadImage(byte[] file, String fileName) { + String url = "http://" + comfyUIServiceIp + ":" + comfyUIServicePort + "/upload/image"; + HttpRequest request = HttpUtil.createPost(url); + request.form("image",file,fileName); + try (HttpResponse execute = request.execute()){ + if (execute.isOk()){ + String body = execute.body(); + log.info("comfyUI uploadImage 请求结果:{}",body); + try { + return objectMapper.readValue(body, ImageUploadDTO.class); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + }else { + throw new RuntimeException("/upload/image请求失败"); + } + } + } + + @Override + public ResourceViewDTO downloadView(String imageId) { + Assert.notEmpty(imageId,"imageId不能为空"); + String url = "http://" + comfyUIServiceIp + ":" + comfyUIServicePort + "/view?filename=" + imageId; + log.info("comfyUI downloadImage 请求地址:{}",url); + try (HttpResponse execute = HttpUtil.createGet(url).execute()){ + if (execute.isOk()){ + return new ResourceViewDTO(execute.getFileNameFromDisposition("filename"), + execute.header("content-type"), execute.bodyBytes()); + }else { + throw new RuntimeException("下载图片请求失败"); + } + } + } +} diff --git a/src/main/java/com/supervision/ai/service/hub/service/impl/ComfyUIPromptParamServiceImpl.java b/src/main/java/com/supervision/ai/service/hub/service/impl/ComfyUIPromptParamServiceImpl.java new file mode 100644 index 0000000..45fb7ed --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/service/impl/ComfyUIPromptParamServiceImpl.java @@ -0,0 +1,76 @@ +package com.supervision.ai.service.hub.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.supervision.ai.service.hub.domain.ComfyuiPromptParam; +import com.supervision.ai.service.hub.service.ComfyUIPromptParamService; +import com.supervision.ai.service.hub.mapper.ComfyuiPromptParamMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +/** +* @author Administrator +* @description 针对表【comfyui_prompt_param】的数据库操作Service实现 +* @createDate 2025-03-31 17:49:56 +*/ +@Slf4j +@Service +public class ComfyUIPromptParamServiceImpl extends ServiceImpl + implements ComfyUIPromptParamService { + + + @Override + public boolean requiredCheck(Map params, String promptId) { + Assert.notEmpty(promptId, "promptId不能为空"); + List list = this.lambdaQuery() + .eq(ComfyuiPromptParam::getPromptId, promptId).eq(ComfyuiPromptParam::getRequired, true).list(); + + return requiredCheck(params, list); + } + + @Override + public boolean requiredCheck(Map params, List promptParamList) { + if (CollUtil.isEmpty(promptParamList)) { + return true; + } + if (CollUtil.isEmpty(params)){ + return false; + } + for (ComfyuiPromptParam comfyuiPromptParam : promptParamList) { + Object value = params.get(comfyuiPromptParam.getParamKey()); + if (null == value || "".equals(value)) { + log.error("参数{}为必填项,请检查",comfyuiPromptParam.getParamKey()); + return false; + } + } + return true; + } + + @Override + public List listByPromptId(String promptId) { + return super.lambdaQuery().eq(ComfyuiPromptParam::getPromptId, promptId).list(); + } + + @Override + public ComfyuiPromptParam selectPromptParam(String paramKey, List promptParamList) { + if (CollUtil.isEmpty(promptParamList)){ + return null; + } + for (ComfyuiPromptParam comfyuiPromptParam : promptParamList) { + if (StrUtil.equals(comfyuiPromptParam.getParamKey(), paramKey)){ + return comfyuiPromptParam; + } + } + return null; + } + +} + + + + diff --git a/src/main/java/com/supervision/ai/service/hub/service/impl/ComfyUIPromptServiceImpl.java b/src/main/java/com/supervision/ai/service/hub/service/impl/ComfyUIPromptServiceImpl.java new file mode 100644 index 0000000..7e73e6f --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/service/impl/ComfyUIPromptServiceImpl.java @@ -0,0 +1,28 @@ +package com.supervision.ai.service.hub.service.impl; + +import cn.hutool.core.lang.Assert; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.supervision.ai.service.hub.domain.ComfyuiPrompt; +import com.supervision.ai.service.hub.service.ComfyUIPromptService; +import com.supervision.ai.service.hub.mapper.ComfyuiPromptMapper; +import org.springframework.stereotype.Service; + +/** +* @author Administrator +* @description 针对表【comfyui_prompt(comfyui提示词表)】的数据库操作Service实现 +* @createDate 2025-03-31 17:49:56 +*/ +@Service +public class ComfyUIPromptServiceImpl extends ServiceImpl + implements ComfyUIPromptService { + + @Override + public boolean promptExist(String promptId) { + Assert.notEmpty(promptId,"promptId不能为空"); + return this.lambdaQuery().eq(ComfyuiPrompt::getId, promptId).exists(); + } +} + + + + diff --git a/src/main/java/com/supervision/ai/service/hub/service/impl/ComfyUIServiceImpl.java b/src/main/java/com/supervision/ai/service/hub/service/impl/ComfyUIServiceImpl.java new file mode 100644 index 0000000..190ae45 --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/service/impl/ComfyUIServiceImpl.java @@ -0,0 +1,137 @@ +package com.supervision.ai.service.hub.service.impl; + +import cn.hutool.core.bean.BeanPath; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONObject; +import com.supervision.ai.service.hub.constant.ComfyuiParamTypeEnum; +import com.supervision.ai.service.hub.domain.ComfyuiPrompt; +import com.supervision.ai.service.hub.domain.ComfyuiPromptParam; +import com.supervision.ai.service.hub.dto.comfyui.ImageUploadDTO; +import com.supervision.ai.service.hub.dto.comfyui.PromptRunDTO; +import com.supervision.ai.service.hub.dto.comfyui.ResourceViewDTO; +import com.supervision.ai.service.hub.service.ComfyUIApiService; +import com.supervision.ai.service.hub.service.ComfyUIService; +import com.supervision.ai.service.hub.service.ComfyUIPromptParamService; +import com.supervision.ai.service.hub.service.ComfyUIPromptService; +import com.supervision.ai.service.hub.vo.comfyui.RunPromptReqVo; +import com.supervision.ai.service.hub.vo.comfyui.TaskResultResVo; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ComfyUIServiceImpl implements ComfyUIService { + + private final ComfyUIApiService comfyUIApiService; + + private final ComfyUIPromptService comfyuiPromptService; + + private final ComfyUIPromptParamService comfyuiPromptParamService; + + + @Override + public String runPrompt(RunPromptReqVo runPromptReqVo) { + Assert.notEmpty(runPromptReqVo.getPromptId(),"promptId不能为空"); + boolean exist = comfyuiPromptService.promptExist(runPromptReqVo.getPromptId()); + Assert.isTrue(exist,"promptId不存在"); + + // 必填参数校验 + List promptParams = comfyuiPromptParamService.listByPromptId(runPromptReqVo.getPromptId()); + List requiredParams = promptParams.stream().filter(ComfyuiPromptParam::getRequired).toList(); + boolean checkPass = comfyuiPromptParamService.requiredCheck(runPromptReqVo.getParams(), requiredParams); + Assert.isTrue(checkPass, + "必填参数"+requiredParams.stream().map(ComfyuiPromptParam::getParamKey).collect(Collectors.joining(","))+"不能为空"); + + ComfyuiPrompt comfyuiPrompt = comfyuiPromptService.getById(runPromptReqVo.getPromptId()); + Assert.notNull(comfyuiPrompt.getPrompt(), "prompt不能为空"); + + // 设置参数 + JSONObject prompt = comfyuiPrompt.getPrompt(); + Map params = runPromptReqVo.getParams(); + for (Map.Entry entry : params.entrySet()) { + if (null != entry.getValue()){ + ComfyuiPromptParam comfyuiPromptParam = comfyuiPromptParamService.selectPromptParam(entry.getKey(), promptParams); + if (null == comfyuiPromptParam){ + continue; + } + ComfyuiParamTypeEnum comfyuiParamTypeEnum = ComfyuiParamTypeEnum.getByCode(comfyuiPromptParam.getParamType()); + Assert.notNull(comfyuiParamTypeEnum,"不支持的数据类型"); + Object value = comfyuiParamTypeEnum.coverType(entry.getValue()); + log.info("设置参数key:{},参数value:{}", entry.getKey(), value); + BeanPath.create(entry.getKey()).set(prompt, value); + } + } + // 运行提示词 + PromptRunDTO promptRunDTO = comfyUIApiService.runPrompt(prompt); + Map error = promptRunDTO.getError(); + if (CollUtil.isNotEmpty(error)){ + String errorMessage = (String) error.get("message"); + Assert.isTrue(StrUtil.isNotEmpty(errorMessage),errorMessage); + } + return promptRunDTO.getPrompt_id(); + } + + @Override + public List queryHistory(String promptId) { + Map history = comfyUIApiService.queryHistory(promptId); + if (CollUtil.isEmpty(history)){ + return new ArrayList<>(); + } + List resultResVos = new ArrayList<>(); + for (Map.Entry entry : history.entrySet()) { + TaskResultResVo taskResultResVo = new TaskResultResVo(); + Object value = entry.getValue(); + taskResultResVo.setPromptId(entry.getKey()); + if (null != value){ + Map status = (Map) ((Map) value).get("status"); + Boolean completed = (Boolean) status.get("completed"); + if (completed){ + Map outputs = (Map) ((Map) value).get("outputs"); + if (CollUtil.isNotEmpty(outputs)){ + for (Map.Entry outputEntry : outputs.entrySet()) { + Map outputEntryValue = (Map) outputEntry.getValue(); + List> images = (List>) outputEntryValue.get("images"); + taskResultResVo.setImages(images.stream().map(image -> (String)(image.get("filename"))).collect(Collectors.toList())); + } + } + } + } + resultResVos.add(taskResultResVo); + } + return resultResVos; + } + + @Override + public String uploadImage(MultipartFile file) throws IOException { + String filename = file.getOriginalFilename(); + byte[] bytes = file.getBytes(); + ImageUploadDTO imageUploadDTO = comfyUIApiService.uploadImage(bytes, filename); + if (StrUtil.isNotEmpty(imageUploadDTO.getSubfolder())){ + return imageUploadDTO.getSubfolder() + "/" + imageUploadDTO.getName(); + } + return imageUploadDTO.getName(); + } + + @Override + public void downloadView(String imageId, HttpServletResponse response) throws IOException { + Assert.notEmpty(imageId,"imageId不能为空"); + ResourceViewDTO resourceViewDTO = comfyUIApiService.downloadView(imageId); + response.setContentType(resourceViewDTO.getContentType()); + response.setHeader("Content-Disposition", "attachment; filename=" + resourceViewDTO.getFileName()); + try (ServletOutputStream outputStream = response.getOutputStream()){ + outputStream.write(resourceViewDTO.getContent()); + } + } +} diff --git a/src/main/java/com/supervision/ai/service/hub/service/impl/HeygemApiServiceImpl.java b/src/main/java/com/supervision/ai/service/hub/service/impl/HeygemApiServiceImpl.java index 366e046..e4c58e8 100644 --- a/src/main/java/com/supervision/ai/service/hub/service/impl/HeygemApiServiceImpl.java +++ b/src/main/java/com/supervision/ai/service/hub/service/impl/HeygemApiServiceImpl.java @@ -38,7 +38,7 @@ public class HeygemApiServiceImpl implements HeygemApiService { TimeInterval timer = DateUtil.timer(); HttpRequest request = HttpUtil.createPost(url).body(JSONUtil.toJsonStr(tranReqDTO)); try (HttpResponse response = request.execute()) { - log.info("/v1/preprocess_and_tran请求耗时:{}", timer.intervalMs()); + log.info("/v1/preprocess_and_tran请求耗时:{}毫秒", timer.intervalMs()); if (!response.isOk()){ throw new RuntimeException("请求失败"); } @@ -59,7 +59,7 @@ public class HeygemApiServiceImpl implements HeygemApiService { HttpRequest request = HttpUtil.createPost(url).body(JSONUtil.toJsonStr(textToAudioReqDTO)); TimeInterval timer = DateUtil.timer(); try (HttpResponse response = request.execute()) { - log.info("/v1/invoke请求耗时:{}", timer.intervalMs()); + log.info("/v1/invoke请求耗时:{}毫秒", timer.intervalMs()); if (!response.isOk()&& response.header("Content-Type").equals("application/json")){ try { String body = response.body(); @@ -88,7 +88,7 @@ public class HeygemApiServiceImpl implements HeygemApiService { HttpRequest request = HttpUtil.createPost(url).body(JSONUtil.toJsonStr(videoGenerateReqDTO)); TimeInterval timer = DateUtil.timer(); try (HttpResponse response = request.execute()) { - log.info("请求/easy/submit耗时:{}", timer.intervalMs()); + log.info("请求/easy/submit耗时:{}毫秒", timer.intervalMs()); String body = response.body(); log.info("/easy/submit接口response:{}", body); try { @@ -110,7 +110,7 @@ public class HeygemApiServiceImpl implements HeygemApiService { log.info("url:{}", url); TimeInterval timer = DateUtil.timer(); try (HttpResponse response = HttpUtil.createGet(url).form("taskCode", taskCode).execute()) { - log.info("请求/easy/query耗时:{}", timer.intervalMs()); + log.info("请求/easy/query耗时:{}毫秒", timer.intervalMs()); String body = response.body(); log.info("/easy/query接口response:{}", body); try { diff --git a/src/main/java/com/supervision/ai/service/hub/vo/comfyui/RunPromptReqVo.java b/src/main/java/com/supervision/ai/service/hub/vo/comfyui/RunPromptReqVo.java new file mode 100644 index 0000000..bc51ddf --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/vo/comfyui/RunPromptReqVo.java @@ -0,0 +1,20 @@ +package com.supervision.ai.service.hub.vo.comfyui; + +import lombok.Data; + +import java.util.Map; + +@Data +public class RunPromptReqVo { + + /** + * 提示词ID + */ + private String promptId; + + /** + * 参数 + */ + private Map params; + +} diff --git a/src/main/java/com/supervision/ai/service/hub/vo/comfyui/TaskResultResVo.java b/src/main/java/com/supervision/ai/service/hub/vo/comfyui/TaskResultResVo.java new file mode 100644 index 0000000..796881b --- /dev/null +++ b/src/main/java/com/supervision/ai/service/hub/vo/comfyui/TaskResultResVo.java @@ -0,0 +1,17 @@ +package com.supervision.ai.service.hub.vo.comfyui; + +import lombok.Data; +import java.util.List; + +/** + * 任务执行结果 + */ +@Data +public class TaskResultResVo { + + private String promptId; + + private boolean completed; + + private List images; +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 34aa94c..ed32ff9 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -6,7 +6,10 @@ spring: username: postgres password: 123456 driver-class-name: org.postgresql.Driver - + servlet: + multipart: + max-file-size: 10MB + max-request-size: 100MB server: port: 9901 servlet: @@ -28,3 +31,7 @@ heygem: port: 18180 f2f: port: 8383 +comfyUI: + server: + ip: 192.168.10.113 + port: 8188 diff --git a/src/main/resources/mapper/ComfyuiPromptMapper.xml b/src/main/resources/mapper/ComfyuiPromptMapper.xml new file mode 100644 index 0000000..2a44ee4 --- /dev/null +++ b/src/main/resources/mapper/ComfyuiPromptMapper.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + id,prompt_name,prompt_type, + prompt,create_time,update_time + + diff --git a/src/main/resources/mapper/ComfyuiPromptParamMapper.xml b/src/main/resources/mapper/ComfyuiPromptParamMapper.xml new file mode 100644 index 0000000..0a54a5c --- /dev/null +++ b/src/main/resources/mapper/ComfyuiPromptParamMapper.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + id,prompt_id,param_key, + param_type,required,create_time, + update_time + + diff --git a/src/test/java/com/supervision/ai/service/hub/ComfyUIApiServiceTest.java b/src/test/java/com/supervision/ai/service/hub/ComfyUIApiServiceTest.java new file mode 100644 index 0000000..13eaf00 --- /dev/null +++ b/src/test/java/com/supervision/ai/service/hub/ComfyUIApiServiceTest.java @@ -0,0 +1,60 @@ +package com.supervision.ai.service.hub; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.json.JSONUtil; +import com.alibaba.fastjson.JSON; +import com.supervision.ai.service.hub.domain.ComfyuiPrompt; +import com.supervision.ai.service.hub.dto.comfyui.ImageUploadDTO; +import com.supervision.ai.service.hub.dto.comfyui.PromptRunDTO; +import com.supervision.ai.service.hub.dto.comfyui.ResourceViewDTO; +import com.supervision.ai.service.hub.service.ComfyUIApiService; +import com.supervision.ai.service.hub.service.ComfyUIPromptService; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.Map; + +@Slf4j +@SpringBootTest +public class ComfyUIApiServiceTest { + + @Autowired + private ComfyUIApiService comfyUIApiService; + @Test + public void uploadImageTest() { + byte[] bytes = FileUtil.readBytes("C:\\Users\\Administrator\\Downloads\\Arya.png"); + ImageUploadDTO res = comfyUIApiService.uploadImage(bytes, "图片1"); + log.info(JSONUtil.toJsonStr(res)); + + } + + @Test + public void runPromptTest() { + String prompt = "{\"prompt\":{\"4\":{\"inputs\":{\"ckpt_name\":\"sd_xl_base_1.0.safetensors\"},\"class_type\":\"CheckpointLoaderSimple\",\"_meta\":{\"title\":\"Load Checkpoint - BASE\"}},\"5\":{\"inputs\":{\"width\":1024,\"height\":1024,\"batch_size\":1},\"class_type\":\"EmptyLatentImage\",\"_meta\":{\"title\":\"空Latent图像\"}},\"6\":{\"inputs\":{\"text\":\"a cat under the snow with blue eyes, covered by snow, cinematic style, medium shot, professional photo, animal\",\"clip\":[\"4\",1]},\"class_type\":\"CLIPTextEncode\",\"_meta\":{\"title\":\"CLIP文本编码\"}},\"7\":{\"inputs\":{\"text\":\"text, watermark\",\"clip\":[\"4\",1]},\"class_type\":\"CLIPTextEncode\",\"_meta\":{\"title\":\"CLIP文本编码\"}},\"10\":{\"inputs\":{\"add_noise\":\"enable\",\"noise_seed\":2025,\"steps\":25,\"cfg\":8,\"sampler_name\":\"euler\",\"scheduler\":\"normal\",\"start_at_step\":0,\"end_at_step\":20,\"return_with_leftover_noise\":\"enable\",\"model\":[\"4\",0],\"positive\":[\"6\",0],\"negative\":[\"7\",0],\"latent_image\":[\"5\",0]},\"class_type\":\"KSamplerAdvanced\",\"_meta\":{\"title\":\"KSampler (Advanced) - BASE\"}},\"11\":{\"inputs\":{\"add_noise\":\"disable\",\"noise_seed\":0,\"steps\":25,\"cfg\":8,\"sampler_name\":\"euler\",\"scheduler\":\"normal\",\"start_at_step\":20,\"end_at_step\":10000,\"return_with_leftover_noise\":\"disable\",\"model\":[\"12\",0],\"positive\":[\"15\",0],\"negative\":[\"16\",0],\"latent_image\":[\"10\",0]},\"class_type\":\"KSamplerAdvanced\",\"_meta\":{\"title\":\"KSampler (Advanced) - REFINER\"}},\"12\":{\"inputs\":{\"ckpt_name\":\"sd_xl_refiner_1.0.safetensors\"},\"class_type\":\"CheckpointLoaderSimple\",\"_meta\":{\"title\":\"Load Checkpoint - REFINER\"}},\"15\":{\"inputs\":{\"text\":\"evening sunset scenery blue sky nature, glass bottle with a galaxy in it\",\"clip\":[\"12\",1]},\"class_type\":\"CLIPTextEncode\",\"_meta\":{\"title\":\"CLIP文本编码\"}},\"16\":{\"inputs\":{\"text\":\"text, watermark\",\"clip\":[\"12\",1]},\"class_type\":\"CLIPTextEncode\",\"_meta\":{\"title\":\"CLIP文本编码\"}},\"17\":{\"inputs\":{\"samples\":[\"11\",0],\"vae\":[\"12\",2]},\"class_type\":\"VAEDecode\",\"_meta\":{\"title\":\"VAE解码\"}},\"19\":{\"inputs\":{\"filename_prefix\":\"ComfyUI\",\"images\":[\"17\",0]},\"class_type\":\"SaveImage\",\"_meta\":{\"title\":\"保存图像\"}}}}"; + PromptRunDTO res = comfyUIApiService.runPrompt(JSON.parseObject(prompt)); + log.info(JSONUtil.toJsonStr(res)); + } + + @Test + public void queryHistoryTest() { + Map res = comfyUIApiService.queryHistory("512f2ad2-2c7b-4227-8e52-86be11c3d5b9"); + log.info(JSONUtil.toJsonStr(res)); + } + + @Test + public void downloadImageTest() { + ResourceViewDTO resourceViewDTO = comfyUIApiService.downloadView("ComfyUI_00070_.png"); + FileUtil.writeBytes(resourceViewDTO.getContent(), "C:\\Users\\Administrator\\Downloads\\ComfyUI_00070_.png"); + } + + @Autowired + private ComfyUIPromptService comfyUIPromptService; + + @Test + public void test() { + ComfyuiPrompt comfyuiPrompt = comfyUIPromptService.getById("1"); + System.out.println(comfyuiPrompt); + } +}