Commit 937992fd163d76a66ae04a7e14646b27b513023c

Authored by cherishsince
1 parent 1ac1c007

【临时提交】增加 MidjourneyApi

yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/midjourney/MidjourneyProperties.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ai.core.model.midjourney;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * Midjourney 属性
  7 + *
  8 + * @author fansili
  9 + * @time 2024/6/5 15:02
  10 + * @since 1.0
  11 + */
  12 +@Data
  13 +public class MidjourneyProperties {
  14 +
  15 + private String key;
  16 + private String url;
  17 + private String notifyUrl;
  18 +}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/midjourney/api/MidjourneyApi.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ai.core.model.midjourney.api;
  2 +
  3 +import cn.iocoder.yudao.framework.ai.core.model.midjourney.MidjourneyProperties;
  4 +import cn.iocoder.yudao.framework.ai.core.model.midjourney.vo.MidjourneyActionRequest;
  5 +import cn.iocoder.yudao.framework.ai.core.model.midjourney.vo.MidjourneyImagineRequest;
  6 +import cn.iocoder.yudao.framework.ai.core.model.midjourney.vo.MidjourneyNotifyRequest;
  7 +import cn.iocoder.yudao.framework.ai.core.model.midjourney.vo.MidjourneySubmitResponse;
  8 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  9 +import com.google.common.collect.ImmutableMap;
  10 +import lombok.extern.slf4j.Slf4j;
  11 +import org.springframework.ai.openai.api.ApiUtils;
  12 +import org.springframework.web.reactive.function.client.WebClient;
  13 +import reactor.core.publisher.Mono;
  14 +
  15 +import java.util.Collection;
  16 +import java.util.List;
  17 +
  18 +/**
  19 + * Midjourney api
  20 + *
  21 + * @author fansili
  22 + * @time 2024/6/11 15:46
  23 + * @since 1.0
  24 + */
  25 +@Slf4j
  26 +public class MidjourneyApi {
  27 +
  28 + private static final String URI_IMAGINE = "/submit/imagine";
  29 + private static final String URI_ACTON = "/submit/action";
  30 + private static final String URI_LIST_BY_CONDITION = "/task/list-by-condition";
  31 + private final WebClient webClient;
  32 + private final MidjourneyProperties midjourneyProperties;
  33 +
  34 + public MidjourneyApi(MidjourneyProperties midjourneyProperties) {
  35 + this.midjourneyProperties = midjourneyProperties;
  36 + this.webClient = WebClient.builder()
  37 + .baseUrl(midjourneyProperties.getUrl())
  38 + .defaultHeaders(ApiUtils.getJsonContentHeaders(midjourneyProperties.getKey()))
  39 + .build();
  40 + }
  41 +
  42 +
  43 + /**
  44 + * imagine - 根据提示词提交绘画任务
  45 + *
  46 + * @param imagineReqVO
  47 + * @return
  48 + */
  49 + public MidjourneySubmitResponse imagine(MidjourneyImagineRequest imagineReqVO) {
  50 + // 1、发送 post 请求
  51 + String res = post(URI_IMAGINE, imagineReqVO);
  52 + // 2、转换 resp
  53 + return JsonUtils.parseObject(res, MidjourneySubmitResponse.class);
  54 + }
  55 +
  56 + /**
  57 + * action - 放大、缩小、U1、U2...
  58 + *
  59 + * @param actionReqVO
  60 + */
  61 + public MidjourneySubmitResponse action(MidjourneyActionRequest actionReqVO) {
  62 + // 1、发送 post 请求
  63 + String res = post(URI_ACTON, actionReqVO);
  64 + // 2、转换 resp
  65 + return JsonUtils.parseObject(res, MidjourneySubmitResponse.class);
  66 + }
  67 +
  68 + /**
  69 + * 批量查询 task 任务
  70 + *
  71 + * @param taskIds
  72 + * @return
  73 + */
  74 + public List<MidjourneyNotifyRequest> listByCondition(Collection<String> taskIds) {
  75 + // 1、发送 post 请求
  76 + String res = post(URI_LIST_BY_CONDITION, ImmutableMap.of("ids", taskIds));
  77 + // 2、转换 对象
  78 + return JsonUtils.parseArray(res, MidjourneyNotifyRequest.class);
  79 + }
  80 +
  81 + private String post(String uri, Object body) {
  82 + // 1、发送 post 请求
  83 + return webClient.post()
  84 + .uri(uri)
  85 + .body(Mono.just(JsonUtils.toJsonString(body)), String.class)
  86 + .retrieve()
  87 + .onStatus(status -> !status.is2xxSuccessful(),
  88 + response -> response.bodyToMono(String.class)
  89 + .handle((respBody, sink) -> {
  90 + log.error("【Midjourney api】调用失败!resp: 【{}】", respBody);
  91 + sink.error(new IllegalStateException("【Midjourney api】调用失败!"));
  92 + }))
  93 + .bodyToMono(String.class)
  94 + .block();
  95 + }
  96 +}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/midjourney/enums/MidjourneyModelEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ai.core.model.midjourney.enums;
  2 +
  3 +
  4 +import lombok.AllArgsConstructor;
  5 +import lombok.Getter;
  6 +
  7 +/**
  8 + * 来源于 midjourney-proxy
  9 + */
  10 +@Getter
  11 +@AllArgsConstructor
  12 +public enum MidjourneyModelEnum {
  13 +
  14 + MIDJOURNEY("midjourney", "midjourney"),
  15 + NIJI("Niji", "Niji"),
  16 +
  17 + ;
  18 +
  19 + private String model;
  20 + private String name;
  21 +
  22 + public static MidjourneyModelEnum valueOfModel(String model) {
  23 + for (MidjourneyModelEnum itemEnum : MidjourneyModelEnum.values()) {
  24 + if (itemEnum.getModel().equals(model)) {
  25 + return itemEnum;
  26 + }
  27 + }
  28 + throw new IllegalArgumentException("Invalid MessageType value: " + model);
  29 + }
  30 +}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/midjourney/enums/MidjourneySubmitCodeEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ai.core.model.midjourney.enums;
  2 +
  3 +import com.google.common.collect.Lists;
  4 +import lombok.AllArgsConstructor;
  5 +import lombok.Getter;
  6 +
  7 +import java.util.List;
  8 +
  9 +// TODO @fan:待定
  10 +/**
  11 + * Midjourney 提交任务 code 枚举
  12 + *
  13 + * @author fansili
  14 + */
  15 +@Getter
  16 +@AllArgsConstructor
  17 +public enum MidjourneySubmitCodeEnum {
  18 +
  19 + SUBMIT_SUCCESS("1", "提交成功"),
  20 + ALREADY_EXISTS("21", "已存在"),
  21 + QUEUING("22", "排队中"),
  22 + ;
  23 +
  24 + public static final List<String> SUCCESS_CODES = Lists.newArrayList(
  25 + SUBMIT_SUCCESS.code,
  26 + ALREADY_EXISTS.code,
  27 + QUEUING.code
  28 + );
  29 +
  30 + private final String code;
  31 + private final String name;
  32 +
  33 +}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/midjourney/enums/MidjourneyTaskActionEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ai.core.model.midjourney.enums;
  2 +
  3 +import lombok.Getter;
  4 +
  5 +/**
  6 + * 来源于 midjourney-proxy
  7 + */
  8 +@Getter
  9 +public enum MidjourneyTaskActionEnum {
  10 + /**
  11 + * 生成图片.
  12 + */
  13 + IMAGINE,
  14 + /**
  15 + * 选中放大.
  16 + */
  17 + UPSCALE,
  18 + /**
  19 + * 选中其中的一张图,生成四张相似的.
  20 + */
  21 + VARIATION,
  22 + /**
  23 + * 重新执行.
  24 + */
  25 + REROLL,
  26 + /**
  27 + * 图转prompt.
  28 + */
  29 + DESCRIBE,
  30 + /**
  31 + * 多图混合.
  32 + */
  33 + BLEND
  34 +
  35 +}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/midjourney/enums/MidjourneyTaskStatusEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ai.core.model.midjourney.enums;
  2 +
  3 +
  4 +import lombok.Getter;
  5 +
  6 +/**
  7 + * 来源于 midjourney-proxy
  8 + */
  9 +public enum MidjourneyTaskStatusEnum {
  10 + /**
  11 + * 未启动.
  12 + */
  13 + NOT_START(0),
  14 + /**
  15 + * 已提交.
  16 + */
  17 + SUBMITTED(1),
  18 + /**
  19 + * 执行中.
  20 + */
  21 + IN_PROGRESS(3),
  22 + /**
  23 + * 失败.
  24 + */
  25 + FAILURE(4),
  26 + /**
  27 + * 成功.
  28 + */
  29 + SUCCESS(4);
  30 +
  31 + @Getter
  32 + private final int order;
  33 +
  34 + MidjourneyTaskStatusEnum(int order) {
  35 + this.order = order;
  36 + }
  37 +
  38 +}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/midjourney/vo/MidjourneyActionRequest.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ai.core.model.midjourney.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +/**
  7 + * Midjourney:action 请求
  8 + *
  9 + * @author fansili
  10 + * @time 2024/5/30 14:02
  11 + * @since 1.0
  12 + */
  13 +@Data
  14 +public class MidjourneyActionRequest {
  15 +
  16 + @Schema(description = "操作按钮id", required = true)
  17 + private String customId;
  18 +
  19 + @Schema(description = "操作按钮id", required = true)
  20 + private String taskId;
  21 +
  22 + @Schema(description = "通知地址", required = false)
  23 + private String notifyHook;
  24 +
  25 + @Schema(description = "自定义参数", required = false)
  26 + private String state;
  27 +}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/midjourney/vo/MidjourneyImagineRequest.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ai.core.model.midjourney.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +import java.util.List;
  7 +
  8 +// TODO @fan:待定
  9 +/**
  10 + * Midjourney:Imagine 请求
  11 + *
  12 + * @author fansili
  13 + * @time 2024/5/30 14:02
  14 + * @since 1.0
  15 + */
  16 +@Data
  17 +public class MidjourneyImagineRequest {
  18 +
  19 + @Schema(description = "垫图(参考图)base64数组", required = false)
  20 + private List<String> base64Array;
  21 +
  22 + @Schema(description = "通知地址", required = false)
  23 + private String notifyHook;
  24 +
  25 + @Schema(description = "提示词", required = true)
  26 + private String prompt;
  27 +
  28 + @Schema(description = "自定义参数", required = false)
  29 + private String state;
  30 +}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/midjourney/vo/MidjourneyNotifyRequest.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ai.core.model.midjourney.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +import java.util.List;
  7 +
  8 +/**
  9 + * Midjourney Proxy 通知回调
  10 + *
  11 + * - Midjourney Proxy:通知回调 bean 是 com.github.novicezk.midjourney.support.Task
  12 + * - 毫秒 api 通知回调文档地址:https://gpt-best.apifox.cn/doc-3530863
  13 + *
  14 + * @author fansili
  15 + * @time 2024/5/31 10:37
  16 + * @since 1.0
  17 + */
  18 +@Data
  19 +public class MidjourneyNotifyRequest {
  20 +
  21 + @Schema(description = "job id")
  22 + private String id;
  23 +
  24 + @Schema(description = "任务类型 MidjourneyTaskActionEnum")
  25 + private String action;
  26 + @Schema(description = "任务状态 MidjourneyTaskStatusEnum")
  27 + private String status;
  28 +
  29 + @Schema(description = "提示词")
  30 + private String prompt;
  31 + @Schema(description = "提示词-英文")
  32 + private String promptEn;
  33 +
  34 + @Schema(description = "任务描述")
  35 + private String description;
  36 + @Schema(description = "自定义参数")
  37 + private String state;
  38 +
  39 + @Schema(description = "提交时间")
  40 + private Long submitTime;
  41 + @Schema(description = "开始执行时间")
  42 + private Long startTime;
  43 + @Schema(description = "结束时间")
  44 + private Long finishTime;
  45 +
  46 + @Schema(description = "图片url")
  47 + private String imageUrl;
  48 +
  49 + @Schema(description = "任务进度")
  50 + private String progress;
  51 + @Schema(description = "失败原因")
  52 + private String failReason;
  53 +
  54 + @Schema(description = "任务完成后的可执行按钮")
  55 + private List<Button> buttons;
  56 +
  57 + @Data
  58 + public static class Button {
  59 +
  60 + @Schema(description = "MJ::JOB::upsample::1::85a4b4c1-8835-46c5-a15c-aea34fad1862 动作标识")
  61 + private String customId;
  62 +
  63 + @Schema(description = "图标 emoji")
  64 + private String emoji;
  65 +
  66 + @Schema(description = "Make Variations 文本")
  67 + private String label;
  68 +
  69 + @Schema(description = "类型,系统内部使用")
  70 + private String type;
  71 +
  72 + @Schema(description = "样式: 2(Primary)、3(Green)")
  73 + private String style;
  74 + }
  75 +}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/midjourney/vo/MidjourneySubmitResponse.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ai.core.model.midjourney.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +import java.util.Map;
  7 +
  8 +// TODO @fan:待定
  9 +/**
  10 + * Midjourney:Imagine 请求
  11 + *
  12 + * @author fansili
  13 + * @time 2024/5/30 14:02
  14 + * @since 1.0
  15 + */
  16 +@Data
  17 +public class MidjourneySubmitResponse {
  18 +
  19 + @Schema(description = "状态码: 1(提交成功), 21(已存在), 22(排队中), other(错误)")
  20 + private String code;
  21 +
  22 + @Schema(description = "描述")
  23 + private String description;
  24 +
  25 + @Schema(description = "扩展字段")
  26 + private Map<String, Object> properties;
  27 +
  28 + @Schema(description = "任务ID")
  29 + private String result;
  30 +}