From 20ac7c64510696870f0fefba043bbf2bb5d54b91 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 3 Mar 2024 20:11:00 +0800 Subject: [PATCH 001/684] =?UTF-8?q?=E5=88=9B=E5=BB=BA=20yudao-module-ai=20?= =?UTF-8?q?=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 1 + yudao-module-ai/pom.xml | 33 +++++++++++++++++++ yudao-module-ai/yudao-module-ai-api/pom.xml | 20 +++++++++++ .../iocoder/yudao/module/ai/package-info.java | 5 +++ yudao-module-ai/yudao-module-ai-biz/pom.xml | 28 ++++++++++++++++ .../iocoder/yudao/module/ai/package-info.java | 5 +++ .../src/main/resources/application.yaml | 0 7 files changed, 92 insertions(+) create mode 100644 yudao-module-ai/pom.xml create mode 100644 yudao-module-ai/yudao-module-ai-api/pom.xml create mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/package-info.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/pom.xml create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/package-info.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.yaml diff --git a/pom.xml b/pom.xml index 3a66524bc..de20229fa 100644 --- a/pom.xml +++ b/pom.xml @@ -15,6 +15,7 @@ yudao-module-system yudao-module-infra + yudao-module-ai diff --git a/yudao-module-ai/pom.xml b/yudao-module-ai/pom.xml new file mode 100644 index 000000000..41f62ff4d --- /dev/null +++ b/yudao-module-ai/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + cn.iocoder.boot + yudao + ${revision} + + pom + yudao-module-ai + + + yudao-module-ai-api + /yudao-module-ai-biz + + + + 8 + 8 + UTF-8 + + + + + + org.springframework.ai + spring-ai-openai-spring-boot-starter + + + + \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-api/pom.xml b/yudao-module-ai/yudao-module-ai-api/pom.xml new file mode 100644 index 000000000..621c05171 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-api/pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + + cn.iocoder.boot + yudao-module-ai + ${revision} + + + yudao-module-ai-api + + + 17 + 17 + UTF-8 + + + \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/package-info.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/package-info.java new file mode 100644 index 000000000..6fa1f167a --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/package-info.java @@ -0,0 +1,5 @@ +/** + * author: fansili + * time: 2024/3/3 18:14 + */ +package cn.iocoder.yudao.module.ai; \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/pom.xml b/yudao-module-ai/yudao-module-ai-biz/pom.xml new file mode 100644 index 000000000..865dce912 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + + cn.iocoder.boot + yudao-module-ai + ${revision} + + + yudao-module-ai-biz + + + 8 + 8 + UTF-8 + + + + + + + org.springframework.ai + spring-ai-openai-spring-boot-starter + + + \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/package-info.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/package-info.java new file mode 100644 index 000000000..6fa1f167a --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/package-info.java @@ -0,0 +1,5 @@ +/** + * author: fansili + * time: 2024/3/3 18:14 + */ +package cn.iocoder.yudao.module.ai; \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.yaml b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.yaml new file mode 100644 index 000000000..e69de29bb From 33d77b9b160a1c5470fe805501255489d53e9c54 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 3 Mar 2024 20:19:06 +0800 Subject: [PATCH 002/684] =?UTF-8?q?=E9=85=8D=E7=BD=AE=20yudao-dependencies?= =?UTF-8?q?=20spring-ai=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 17 +++++++++++++++++ yudao-dependencies/pom.xml | 9 +++++++++ yudao-module-ai/pom.xml | 7 +------ yudao-server/pom.xml | 6 ++++++ 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index de20229fa..44f20e10e 100644 --- a/pom.xml +++ b/pom.xml @@ -150,6 +150,23 @@ aliyun https://maven.aliyun.com/repository/public + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + false + + diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 7c7ca609b..6b4f135ab 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -76,6 +76,7 @@ 2.12.2 4.6.0 2.2.9 + 0.8.0 @@ -628,6 +629,14 @@ ${ureport2.version} + + + org.springframework.ai + spring-ai-bom + ${spring-ai-bom.version} + pom + import + diff --git a/yudao-module-ai/pom.xml b/yudao-module-ai/pom.xml index 41f62ff4d..aaba1191d 100644 --- a/yudao-module-ai/pom.xml +++ b/yudao-module-ai/pom.xml @@ -13,7 +13,7 @@ yudao-module-ai-api - /yudao-module-ai-biz + yudao-module-ai-biz @@ -23,11 +23,6 @@ - - - org.springframework.ai - spring-ai-openai-spring-boot-starter - \ No newline at end of file diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index bc850b590..bb71ddddd 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -32,6 +32,12 @@ ${revision} + + cn.iocoder.boot + yudao-module-ai-biz + ${revision} + + From f4b3bb5aaa63db3c486e6bed21fe8c5c1ffed5eb Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 4 Mar 2024 17:02:03 +0800 Subject: [PATCH 003/684] =?UTF-8?q?=E5=AE=9A=E4=B9=89ai=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/enums/ServiceErrorCodeRange.java | 2 ++ .../yudao/module/ai/ErrorCodeConstants.java | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/enums/ServiceErrorCodeRange.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/enums/ServiceErrorCodeRange.java index 94dd67c9e..950ab2555 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/enums/ServiceErrorCodeRange.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/enums/ServiceErrorCodeRange.java @@ -43,4 +43,6 @@ public class ServiceErrorCodeRange { // 模块 crm 错误码区间 [1-020-000-000 ~ 1-021-000-000) + // 模块 ai 错误码区间 [1-022-000-000 ~ 1-023-000-000) + } diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java new file mode 100644 index 000000000..69795ead2 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.ai; + +import cn.iocoder.yudao.framework.common.exception.ErrorCode; + +/** + * System 错误码枚举类 + * + * system 系统,使用 1-002-000-000 段 + */ +public interface ErrorCodeConstants { + + // ========== 模块 ai 错误码区间 [1-022-000-000 ~ 1-023-000-000) ========== + + ErrorCode AI_MODULE_NOT_SUPPORTED = new ErrorCode(1_022_000_000, "AI模型暂不支持!"); + +} From ebd5cbfca291b645f8843314644c30cdc1b0a9c0 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 4 Mar 2024 17:03:41 +0800 Subject: [PATCH 004/684] =?UTF-8?q?=E5=9F=BA=E5=B1=82=20open=20ai=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20chat=20=E8=81=8A=E5=A4=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-module-ai/yudao-module-ai-api/pom.xml | 18 ++++++ .../yudao/module/ai/enums/AiModelEnum.java | 25 ++++++++ yudao-module-ai/yudao-module-ai-biz/pom.xml | 28 +++++++++ .../ai/controller/admin/ChatController.java | 60 +++++++++++++++++++ .../ai/controller/admin/vo/AiChatReqVO.java | 26 ++++++++ .../module/ai/controller/package-info.java | 5 ++ .../src/main/resources/application.properties | 6 ++ .../src/main/resources/application.yaml | 0 8 files changed, 168 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiModelEnum.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/vo/AiChatReqVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/package-info.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.properties delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.yaml diff --git a/yudao-module-ai/yudao-module-ai-api/pom.xml b/yudao-module-ai/yudao-module-ai-api/pom.xml index 621c05171..ce9c41527 100644 --- a/yudao-module-ai/yudao-module-ai-api/pom.xml +++ b/yudao-module-ai/yudao-module-ai-api/pom.xml @@ -17,4 +17,22 @@ UTF-8 + + + + cn.iocoder.boot + yudao-common + + + + org.projectlombok + lombok + + + + org.springframework.boot + spring-boot-starter-validation + true + + \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiModelEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiModelEnum.java new file mode 100644 index 000000000..ff1889fe7 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiModelEnum.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.ai.enums; + +import lombok.Getter; + +/** + * author: fansili + * time: 2024/3/4 12:36 + */ +@Getter +public enum AiModelEnum { + + OPEN_AI_GPT_3_5("gpt-3.5-turbo", "GPT3.5"), + OPEN_AI_GPT_4("gpt-4-turbo", "GPT4") + + ; + + AiModelEnum(String value, String message) { + this.value = value; + this.message = message; + } + + private String value; + + private String message; +} diff --git a/yudao-module-ai/yudao-module-ai-biz/pom.xml b/yudao-module-ai/yudao-module-ai-biz/pom.xml index 865dce912..0281c9ece 100644 --- a/yudao-module-ai/yudao-module-ai-biz/pom.xml +++ b/yudao-module-ai/yudao-module-ai-biz/pom.xml @@ -19,10 +19,38 @@ + + cn.iocoder.boot + yudao-module-ai-api + ${revision} + + + cn.iocoder.boot + yudao-common + + org.springframework.ai spring-ai-openai-spring-boot-starter + + + cn.iocoder.boot + yudao-spring-boot-starter-security + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 17 + 17 + + + + \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java new file mode 100644 index 000000000..b7ca740fb --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.ai.controller.admin; + +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.ai.ErrorCodeConstants; +import cn.iocoder.yudao.module.ai.controller.admin.vo.AiChatReqVO; +import cn.iocoder.yudao.module.ai.enums.AiModelEnum; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.openai.OpenAiChatClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * AI模块 + * + * author: fansili + * time: 2024/3/3 20:28 + */ +@Tag(name = "AI模块") +@RestController +@RequestMapping("/ai-api") +public class ChatController { + + @Autowired + private ApplicationContext applicationContext; + + @PostMapping("/chat") + @Operation(summary = "对话聊天", description = "简单的ai聊天") + public CommonResult chat(@RequestBody @Validated AiChatReqVO reqVO) { + ChatClient chatClient = getChatClient(reqVO.getAiModel()); + String res; + try { + res = chatClient.call(reqVO.getInputText()); + } catch (Exception e) { + res = e.getMessage(); + } + return CommonResult.success(res); + } + + /** + * 根据 ai模型 获取对于的 模型实现类 + * + * @param aiModelEnum + * @return + */ + private ChatClient getChatClient(AiModelEnum aiModelEnum) { + if (AiModelEnum.OPEN_AI_GPT_3_5 == aiModelEnum) { + return applicationContext.getBean(OpenAiChatClient.class); + } + // AI模型暂不支持 + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODULE_NOT_SUPPORTED); + } +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/vo/AiChatReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/vo/AiChatReqVO.java new file mode 100644 index 000000000..43b29d283 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/vo/AiChatReqVO.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.ai.controller.admin.vo; + +import cn.iocoder.yudao.module.ai.enums.AiModelEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * ai 聊天 req + * + * author: fansili + * time: 2024/3/4 12:33 + */ +@Schema(description = "用户 App - 上传文件 Request VO") +@Data +public class AiChatReqVO { + + @Schema(description = "输入内容", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "输入内容不能为空") + private String inputText; + + @Schema(description = "AI模型", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "AI模型不能为空") + private AiModelEnum aiModel; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/package-info.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/package-info.java new file mode 100644 index 000000000..f15447172 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/package-info.java @@ -0,0 +1,5 @@ +/** + * author: fansili + * time: 2024/3/4 13:08 + */ +package cn.iocoder.yudao.module.ai.controller; \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.properties b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.properties new file mode 100644 index 000000000..cb06af6ee --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.properties @@ -0,0 +1,6 @@ +# open ai + +# openAI https://openai.com/ +spring.ai.openai.api-key=${OPEN_AI_KEY} +spring.ai.openai.chat.options.model=gpt-3.5-turbo +spring.ai.openai.chat.options.temperature=0.7 \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.yaml b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.yaml deleted file mode 100644 index e69de29bb..000000000 From 37790d5fc13571316a7fbc8e2b0b95dce5966145 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 5 Mar 2024 18:53:41 +0800 Subject: [PATCH 005/684] =?UTF-8?q?=E4=B8=B4=E6=97=B6=E6=8F=90=E4=BA=A4=20?= =?UTF-8?q?=E5=AF=B9=E8=AF=9D=E8=81=8A=E5=A4=A9chatStream=20=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E8=B0=83=E7=94=A8=E4=BC=9A=E8=B6=85=E6=97=B6=EF=BC=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/admin/ChatController.java | 43 +++++++++++++++++++ .../src/main/resources/application.properties | 7 ++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java index b7ca740fb..eb97f92e5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java @@ -7,8 +7,13 @@ import cn.iocoder.yudao.module.ai.controller.admin.vo.AiChatReqVO; import cn.iocoder.yudao.module.ai.enums.AiModelEnum; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.openai.OpenAiChatClient; +import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.validation.annotation.Validated; @@ -16,6 +21,10 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Flux; + +import java.util.Scanner; +import java.util.function.Consumer; /** * AI模块 @@ -26,6 +35,7 @@ import org.springframework.web.bind.annotation.RestController; @Tag(name = "AI模块") @RestController @RequestMapping("/ai-api") +@Slf4j public class ChatController { @Autowired @@ -44,6 +54,39 @@ public class ChatController { return CommonResult.success(res); } + @PostMapping("/chatStream") + @Operation(summary = "对话聊天chatStream", description = "简单的ai聊天") + public CommonResult chatStream(HttpServletResponse response, @RequestBody @Validated AiChatReqVO reqVO) throws InterruptedException { + OpenAiChatClient chatClient = applicationContext.getBean(OpenAiChatClient.class); + Flux chatResponse = chatClient.stream(new Prompt(reqVO.getInputText())); + chatResponse.subscribe(new Consumer() { + @Override + public void accept(ChatResponse chatResponse) { + System.err.println(chatResponse.getResults().get(0).getOutput().getContent()); + } + }); + return CommonResult.success("1"); + } + + public static void main(String[] args) { + OpenAiChatClient openAiChatClient = new OpenAiChatClient(new OpenAiApi("openkey")); + Flux responseFlux = openAiChatClient.stream(new Prompt("最好的编程语言!")); + long now = System.currentTimeMillis(); + responseFlux.subscribe(new Consumer() { + @Override + public void accept(ChatResponse chatResponse) { + if (chatResponse.getResults().get(0).getOutput() == null) { + return; + } + System.err.println(chatResponse.getResults().get(0).getOutput().getContent()); + } + }); + + // 阻止退出 + Scanner scanner = new Scanner(System.in); + scanner.nextLine(); + } + /** * 根据 ai模型 获取对于的 模型实现类 * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.properties b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.properties index cb06af6ee..e53f358d0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.properties +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.properties @@ -3,4 +3,9 @@ # openAI https://openai.com/ spring.ai.openai.api-key=${OPEN_AI_KEY} spring.ai.openai.chat.options.model=gpt-3.5-turbo -spring.ai.openai.chat.options.temperature=0.7 \ No newline at end of file +spring.ai.openai.chat.options.temperature=0.7 +#spring.ai.vectorstore.milvus.client.connect-timeout-ms=50000 +#spring.ai.vectorstore.milvus.client.keep-alive-timeout-ms=50000 +#spring.ai.vectorstore.milvus.client.keep-alive-time-ms=80000 +#spring.ai.vectorstore.pinecone.server-side-timeout=100s + From f6ea1bda7685870ae3d7672df4b24bb2185eabcf Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 12 Mar 2024 21:07:09 +0800 Subject: [PATCH 006/684] =?UTF-8?q?=E4=BB=8Espring-ai=20=E8=BF=81=E7=A7=BB?= =?UTF-8?q?=20chat=20=E6=A8=A1=E5=9D=97=E5=92=8C=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E8=BF=87=E6=9D=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao-spring-boot-starter-ai/pom.xml | 105 +++++ .../yudao/framework/ai/chat/ChatClient.java | 36 ++ .../yudao/framework/ai/chat/ChatResponse.java | 112 +++++ .../yudao/framework/ai/chat/Generation.java | 83 ++++ .../ai/chat/StreamingChatClient.java | 29 ++ .../ai/chat/messages/AbstractMessage.java | 151 +++++++ .../ai/chat/messages/AssistantMessage.java | 47 +++ .../ai/chat/messages/ChatMessage.java | 39 ++ .../ai/chat/messages/FunctionMessage.java | 37 ++ .../framework/ai/chat/messages/MediaData.java | 46 +++ .../framework/ai/chat/messages/Message.java | 32 ++ .../ai/chat/messages/MessageType.java | 52 +++ .../ai/chat/messages/SystemMessage.java | 48 +++ .../ai/chat/messages/UserMessage.java | 51 +++ .../chat/metadata/ChatGenerationMetadata.java | 75 ++++ .../chat/metadata/ChatResponseMetadata.java | 58 +++ .../ai/chat/metadata/EmptyRateLimit.java | 59 +++ .../ai/chat/metadata/EmptyUsage.java | 37 ++ .../ai/chat/metadata/PromptMetadata.java | 136 ++++++ .../framework/ai/chat/metadata/RateLimit.java | 84 ++++ .../framework/ai/chat/metadata/Usage.java | 66 +++ .../yudao/framework/ai/chat/package-info.java | 14 + .../chat/prompt/AssistantPromptTemplate.java | 55 +++ .../framework/ai/chat/prompt/ChatOptions.java | 40 ++ .../ai/chat/prompt/ChatOptionsBuilder.java | 89 ++++ .../ai/chat/prompt/ChatPromptTemplate.java | 87 ++++ .../chat/prompt/FunctionPromptTemplate.java | 27 ++ .../framework/ai/chat/prompt/Prompt.java | 99 +++++ .../ai/chat/prompt/PromptTemplate.java | 218 ++++++++++ .../ai/chat/prompt/PromptTemplateActions.java | 34 ++ .../prompt/PromptTemplateChatActions.java | 18 + .../prompt/PromptTemplateMessageActions.java | 24 ++ .../prompt/PromptTemplateStringActions.java | 14 + .../ai/chat/prompt/SystemPromptTemplate.java | 55 +++ .../ai/chat/prompt/TemplateFormat.java | 42 ++ .../yudao/framework/ai/model/ModelClient.java | 40 ++ .../framework/ai/model/ModelOptions.java | 31 ++ .../framework/ai/model/ModelOptionsUtils.java | 387 ++++++++++++++++++ .../framework/ai/model/ModelRequest.java | 51 +++ .../framework/ai/model/ModelResponse.java | 62 +++ .../yudao/framework/ai/model/ModelResult.java | 43 ++ .../framework/ai/model/ResponseMetadata.java | 34 ++ .../framework/ai/model/ResultMetadata.java | 31 ++ .../ai/model/StreamingModelClient.java | 43 ++ .../function/AbstractFunctionCallSupport.java | 158 +++++++ .../function/AbstractFunctionCallback.java | 159 +++++++ .../ai/model/function/FunctionCallback.java | 53 +++ .../function/FunctionCallbackContext.java | 124 ++++++ .../function/FunctionCallbackWrapper.java | 140 +++++++ .../function/FunctionCallingOptions.java | 66 +++ .../FunctionCallingOptionsBuilder.java | 150 +++++++ .../ai/model/function/TypeResolverHelper.java | 87 ++++ .../framework/ai/model/package-info.java | 11 + .../yudao/framework/ai/package-info.java | 5 + ...AbstractConversionServiceOutputParser.java | 42 ++ .../AbstractMessageConverterOutputParser.java | 41 ++ .../framework/ai/parser/BeanOutputParser.java | 166 ++++++++ .../framework/ai/parser/FormatProvider.java | 33 ++ .../framework/ai/parser/ListOutputParser.java | 48 +++ .../framework/ai/parser/MapOutputParser.java | 57 +++ .../framework/ai/parser/OutputParser.java | 30 ++ .../yudao/framework/ai/parser/Parser.java | 24 ++ .../yudao/framework/ai/parser/README.md | 12 + 63 files changed, 4327 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatClient.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatResponse.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/Generation.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/StreamingChatClient.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/AbstractMessage.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/AssistantMessage.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/ChatMessage.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/FunctionMessage.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/MediaData.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/Message.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/MessageType.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/SystemMessage.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/UserMessage.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/ChatGenerationMetadata.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/ChatResponseMetadata.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/EmptyRateLimit.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/EmptyUsage.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/PromptMetadata.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/RateLimit.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/Usage.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/package-info.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/AssistantPromptTemplate.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/ChatOptions.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/ChatOptionsBuilder.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/ChatPromptTemplate.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/FunctionPromptTemplate.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/Prompt.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplate.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateActions.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateChatActions.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateMessageActions.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateStringActions.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/SystemPromptTemplate.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/TemplateFormat.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelClient.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelOptions.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelOptionsUtils.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelRequest.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelResponse.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelResult.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ResponseMetadata.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ResultMetadata.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/StreamingModelClient.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/AbstractFunctionCallSupport.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/AbstractFunctionCallback.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallback.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackContext.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackWrapper.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallingOptions.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallingOptionsBuilder.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/TypeResolverHelper.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/package-info.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/AbstractConversionServiceOutputParser.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/AbstractMessageConverterOutputParser.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/BeanOutputParser.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/FormatProvider.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/ListOutputParser.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/MapOutputParser.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/OutputParser.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/Parser.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/README.md diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml new file mode 100644 index 000000000..8ca4bccc3 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml @@ -0,0 +1,105 @@ + + + 4.0.0 + + cn.iocoder.boot + yudao-module-ai + ${revision} + + + yudao-spring-boot-starter-ai + + + 21 + 21 + UTF-8 + + + + org.springframework + spring-core + + + com.fasterxml.jackson.core + jackson-databind + + + org.springframework + spring-context + + + net.jodah + typetools + 0.6.3 + compile + + + com.github.victools + jsonschema-module-jackson + 4.31.1 + compile + + + com.github.victools + jsonschema-module-swagger-2 + 4.33.1 + + + com.github.victools + jsonschema-generator + 4.31.1 + compile + + + io.projectreactor + reactor-core + + + org.springframework.cloud + spring-cloud-function-context + 4.1.0 + compile + + + org.antlr + stringtemplate + 4.0.2 + compile + + + org.projectlombok + lombok + + + org.springframework + spring-web + + + org.springframework + spring-webflux + + + org.springframework.retry + spring-retry + + + junit + junit + test + + + cn.hutool + hutool-all + test + + + com.squareup.okhttp3 + okhttp + 4.12.0 + test + + + + \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatClient.java new file mode 100644 index 000000000..6fd8e8981 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatClient.java @@ -0,0 +1,36 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat; + + +import cn.iocoder.yudao.framework.ai.chat.messages.UserMessage; +import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; +import cn.iocoder.yudao.framework.ai.model.ModelClient; + +@FunctionalInterface +public interface ChatClient extends ModelClient { + + default String call(String message) { + Prompt prompt = new Prompt(new UserMessage(message)); + Generation generation = call(prompt).getResult(); + return (generation != null) ? generation.getOutput().getContent() : ""; + } + + @Override + ChatResponse call(Prompt prompt); + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatResponse.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatResponse.java new file mode 100644 index 000000000..1360336fb --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatResponse.java @@ -0,0 +1,112 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.iocoder.yudao.framework.ai.chat; + +import cn.iocoder.yudao.framework.ai.chat.metadata.ChatResponseMetadata; +import cn.iocoder.yudao.framework.ai.model.ModelResponse; +import org.springframework.util.CollectionUtils; + +import java.util.List; +import java.util.Objects; + +/** + * 人工智能提供商返回的聊天完成(例如生成)响应。 + * + * The chat completion (e.g. generation) response returned by an AI provider. + */ +public class ChatResponse implements ModelResponse { + + private final ChatResponseMetadata chatResponseMetadata; + + /** + * List of generated messages returned by the AI provider. + */ + private final List generations; + + /** + * Construct a new {@link ChatResponse} instance without metadata. + * @param generations the {@link List} of {@link Generation} returned by the AI + * provider. + */ + public ChatResponse(List generations) { + this(generations, ChatResponseMetadata.NULL); + } + + /** + * Construct a new {@link ChatResponse} instance. + * @param generations the {@link List} of {@link Generation} returned by the AI + * provider. + * @param chatResponseMetadata {@link ChatResponseMetadata} containing information + * about the use of the AI provider's API. + */ + public ChatResponse(List generations, ChatResponseMetadata chatResponseMetadata) { + this.chatResponseMetadata = chatResponseMetadata; + this.generations = List.copyOf(generations); + } + + /** + * The {@link List} of {@link Generation generated outputs}. + *

+ * It is a {@link List} of {@link List lists} because the Prompt could request + * multiple output {@link Generation generations}. + * @return the {@link List} of {@link Generation generated outputs}. + */ + + @Override + public List getResults() { + return this.generations; + } + + /** + * @return Returns the first {@link Generation} in the generations list. + */ + public Generation getResult() { + if (CollectionUtils.isEmpty(this.generations)) { + return null; + } + return this.generations.get(0); + } + + /** + * @return Returns {@link ChatResponseMetadata} containing information about the use + * of the AI provider's API. + */ + @Override + public ChatResponseMetadata getMetadata() { + return this.chatResponseMetadata; + } + + @Override + public String toString() { + return "ChatResponse [metadata=" + chatResponseMetadata + ", generations=" + generations + "]"; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof ChatResponse that)) + return false; + return Objects.equals(chatResponseMetadata, that.chatResponseMetadata) + && Objects.equals(generations, that.generations); + } + + @Override + public int hashCode() { + return Objects.hash(chatResponseMetadata, generations); + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/Generation.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/Generation.java new file mode 100644 index 000000000..e84ffd409 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/Generation.java @@ -0,0 +1,83 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat; + +import cn.iocoder.yudao.framework.ai.chat.messages.AssistantMessage; +import cn.iocoder.yudao.framework.ai.chat.metadata.ChatGenerationMetadata; +import cn.iocoder.yudao.framework.ai.model.ModelResult; +import org.springframework.lang.Nullable; + +import java.util.Map; +import java.util.Objects; + +/** + * 表示AI返回的响应。 + * + * Represents a response returned by the AI. + */ +public class Generation implements ModelResult { + + private AssistantMessage assistantMessage; + + private ChatGenerationMetadata chatGenerationMetadata; + + public Generation(String text) { + this.assistantMessage = new AssistantMessage(text); + } + + public Generation(String text, Map properties) { + this.assistantMessage = new AssistantMessage(text, properties); + } + + @Override + public AssistantMessage getOutput() { + return this.assistantMessage; + } + + @Override + public ChatGenerationMetadata getMetadata() { + ChatGenerationMetadata chatGenerationMetadata = this.chatGenerationMetadata; + return chatGenerationMetadata != null ? chatGenerationMetadata : ChatGenerationMetadata.NULL; + } + + public Generation withGenerationMetadata(@Nullable ChatGenerationMetadata chatGenerationMetadata) { + this.chatGenerationMetadata = chatGenerationMetadata; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof Generation that)) + return false; + return Objects.equals(assistantMessage, that.assistantMessage) + && Objects.equals(chatGenerationMetadata, that.chatGenerationMetadata); + } + + @Override + public int hashCode() { + return Objects.hash(assistantMessage, chatGenerationMetadata); + } + + @Override + public String toString() { + return "Generation{" + "assistantMessage=" + assistantMessage + ", chatGenerationMetadata=" + + chatGenerationMetadata + '}'; + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/StreamingChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/StreamingChatClient.java new file mode 100644 index 000000000..fdd604f4d --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/StreamingChatClient.java @@ -0,0 +1,29 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat; + +import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; +import cn.iocoder.yudao.framework.ai.model.StreamingModelClient; +import reactor.core.publisher.Flux; + +@FunctionalInterface +public interface StreamingChatClient extends StreamingModelClient { + + @Override + Flux stream(Prompt prompt); + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/AbstractMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/AbstractMessage.java new file mode 100644 index 000000000..d622cf9f8 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/AbstractMessage.java @@ -0,0 +1,151 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.messages; + +import org.springframework.core.io.Resource; +import org.springframework.util.Assert; +import org.springframework.util.StreamUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public abstract class AbstractMessage implements Message { + + protected final MessageType messageType; + + protected final String textContent; + + protected final List mediaData; + + /** + * Additional options for the message to influence the response, not a generative map. + */ + protected final Map properties; + + protected AbstractMessage(MessageType messageType, String content) { + this(messageType, content, Map.of()); + } + + protected AbstractMessage(MessageType messageType, String content, Map messageProperties) { + Assert.notNull(messageType, "Message type must not be null"); + // Assert.notNull(content, "Content must not be null"); + this.messageType = messageType; + this.textContent = content; + this.mediaData = new ArrayList<>(); + this.properties = messageProperties; + } + + protected AbstractMessage(MessageType messageType, String textContent, List mediaData) { + this(messageType, textContent, mediaData, Map.of()); + } + + protected AbstractMessage(MessageType messageType, String textContent, List mediaData, + Map messageProperties) { + + Assert.notNull(messageType, "Message type must not be null"); + Assert.notNull(textContent, "Content must not be null"); + Assert.notNull(mediaData, "media data must not be null"); + + this.messageType = messageType; + this.textContent = textContent; + this.mediaData = new ArrayList<>(mediaData); + this.properties = messageProperties; + } + + protected AbstractMessage(MessageType messageType, Resource resource) { + this(messageType, resource, Collections.emptyMap()); + } + + @SuppressWarnings("null") + protected AbstractMessage(MessageType messageType, Resource resource, Map messageProperties) { + Assert.notNull(messageType, "Message type must not be null"); + Assert.notNull(resource, "Resource must not be null"); + + this.messageType = messageType; + this.properties = messageProperties; + this.mediaData = new ArrayList<>(); + + try (InputStream inputStream = resource.getInputStream()) { + this.textContent = StreamUtils.copyToString(inputStream, Charset.defaultCharset()); + } + catch (IOException ex) { + throw new RuntimeException("Failed to read resource", ex); + } + } + + @Override + public String getContent() { + return this.textContent; + } + + @Override + public List getMediaData() { + return this.mediaData; + } + + @Override + public Map getProperties() { + return this.properties; + } + + @Override + public MessageType getMessageType() { + return this.messageType; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((mediaData == null) ? 0 : mediaData.hashCode()); + result = prime * result + ((properties == null) ? 0 : properties.hashCode()); + result = prime * result + ((messageType == null) ? 0 : messageType.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AbstractMessage other = (AbstractMessage) obj; + if (mediaData == null) { + if (other.mediaData != null) + return false; + } + else if (!mediaData.equals(other.mediaData)) + return false; + if (properties == null) { + if (other.properties != null) + return false; + } + else if (!properties.equals(other.properties)) + return false; + if (messageType != other.messageType) + return false; + return true; + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/AssistantMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/AssistantMessage.java new file mode 100644 index 000000000..6a18eeba8 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/AssistantMessage.java @@ -0,0 +1,47 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.messages; + +import java.util.Map; + +/** + * 让生成人员知道内容是作为对用户的响应生成的。 + * 此角色指示生成者先前在会话中生成的消息。 + * 通过包括该系列中的辅助消息,您可以为生成的关于提供上下文之前在谈话中的交流。 + * + * Lets the generative know the content was generated as a response to the user. This role + * indicates messages that the generative has previously generated in the conversation. By + * including assistant messages in the series, you provide context to the generative about + * prior exchanges in the conversation. + */ +public class AssistantMessage extends AbstractMessage { + + public AssistantMessage(String content) { + super(MessageType.ASSISTANT, content); + } + + public AssistantMessage(String content, Map properties) { + super(MessageType.ASSISTANT, content, properties); + } + + @Override + public String toString() { + return "AssistantMessage{" + "content='" + getContent() + '\'' + ", properties=" + properties + ", messageType=" + + messageType + '}'; + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/ChatMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/ChatMessage.java new file mode 100644 index 000000000..16470135b --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/ChatMessage.java @@ -0,0 +1,39 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.messages; + +import java.util.Map; + +public class ChatMessage extends AbstractMessage { + + public ChatMessage(String role, String content) { + super(MessageType.valueOf(role), content); + } + + public ChatMessage(String role, String content, Map properties) { + super(MessageType.valueOf(role), content, properties); + } + + public ChatMessage(MessageType messageType, String content) { + super(messageType, content); + } + + public ChatMessage(MessageType messageType, String content, Map properties) { + super(messageType, content, properties); + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/FunctionMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/FunctionMessage.java new file mode 100644 index 000000000..d8b6fccbd --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/FunctionMessage.java @@ -0,0 +1,37 @@ +/* + * Copyright 2023-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.messages; + +import java.util.Map; + +public class FunctionMessage extends AbstractMessage { + + public FunctionMessage(String content) { + super(MessageType.SYSTEM, content); + } + + public FunctionMessage(String content, Map properties) { + super(MessageType.SYSTEM, content, properties); + } + + @Override + public String toString() { + return "FunctionMessage{" + "content='" + getContent() + '\'' + ", properties=" + properties + ", messageType=" + + messageType + '}'; + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/MediaData.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/MediaData.java new file mode 100644 index 000000000..fed60221f --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/MediaData.java @@ -0,0 +1,46 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.messages; + +import org.springframework.util.Assert; +import org.springframework.util.MimeType; + +/** + * @author Christian Tzolov + */ +public class MediaData { + + private final MimeType mimeType; + + private final Object data; + + public MediaData(MimeType mimeType, Object data) { + Assert.notNull(mimeType, "MimeType must not be null"); + // Assert.notNull(data, "Data must not be null"); + this.mimeType = mimeType; + this.data = data; + } + + public MimeType getMimeType() { + return this.mimeType; + } + + public Object getData() { + return this.data; + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/Message.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/Message.java new file mode 100644 index 000000000..89c7b4fb4 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/Message.java @@ -0,0 +1,32 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.messages; + +import java.util.List; +import java.util.Map; + +public interface Message { + + String getContent(); + + List getMediaData(); + + Map getProperties(); + + MessageType getMessageType(); + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/MessageType.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/MessageType.java new file mode 100644 index 000000000..2c803a060 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/MessageType.java @@ -0,0 +1,52 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.iocoder.yudao.framework.ai.chat.messages; + +public enum MessageType { + + // 用户消息 + USER("user"), + + // 之前会话的消息 + ASSISTANT("assistant"), + + // 根据注释说明:您可以使用系统消息来指示具有生成性,表现得像某个角色或以特定的方式提供答案总体安排 + // 简单理解:在对话前,发送一条具有角色的信息让模型理解(如:你现在是一个10年拍摄经验的导演,拥有丰富的经验。 这样你就可以去问他,怎么拍一个短视频可以在抖音上火) + SYSTEM("system"), + + // 函数?根据引用现在不支持,会抛出一个异常 ---> throw new IllegalArgumentException("Tool execution results are not supported for Bedrock models"); + FUNCTION("function"); + + private final String value; + + MessageType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public static MessageType fromValue(String value) { + for (MessageType messageType : MessageType.values()) { + if (messageType.getValue().equals(value)) { + return messageType; + } + } + throw new IllegalArgumentException("Invalid MessageType value: " + value); + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/SystemMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/SystemMessage.java new file mode 100644 index 000000000..c474f24bd --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/SystemMessage.java @@ -0,0 +1,48 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.messages; + +import org.springframework.core.io.Resource; + +/** + * 作为输入传递的“system”类型的消息。系统消息给出高级别对话说明。 + * 此角色通常提供高级说明对话。 + * 例如,您可以使用系统消息来指示具有生成性,表现得像某个角色或以特定的方式提供答案总体安排 + * + * A message of the type 'system' passed as input. The system message gives high level + * instructions for the conversation. This role typically provides high-level instructions + * for the conversation. For example, you might use a system message to instruct the + * generative to behave like a certain character or to provide answers in a specific + * format. + */ +public class SystemMessage extends AbstractMessage { + + public SystemMessage(String content) { + super(MessageType.SYSTEM, content); + } + + public SystemMessage(Resource resource) { + super(MessageType.SYSTEM, resource); + } + + @Override + public String toString() { + return "SystemMessage{" + "content='" + getContent() + '\'' + ", properties=" + properties + ", messageType=" + + messageType + '}'; + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/UserMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/UserMessage.java new file mode 100644 index 000000000..2b8f547f7 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/UserMessage.java @@ -0,0 +1,51 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.messages; + +import org.springframework.core.io.Resource; + +import java.util.List; + +/** + * 作为输入传递的“user”类型的消息具有用户角色的消息来自最终用户或开发者。 + * 它们表示问题、提示或您想要的任何输入产生反应的。 + * + * A message of the type 'user' passed as input Messages with the user role are from the + * end-user or developer. They represent questions, prompts, or any input that you want + * the generative to respond to. + */ +public class UserMessage extends AbstractMessage { + + public UserMessage(String message) { + super(MessageType.USER, message); + } + + public UserMessage(Resource resource) { + super(MessageType.USER, resource); + } + + public UserMessage(String textContent, List mediaDataList) { + super(MessageType.USER, textContent, mediaDataList); + } + + @Override + public String toString() { + return "UserMessage{" + "content='" + getContent() + '\'' + ", properties=" + properties + ", messageType=" + + messageType + '}'; + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/ChatGenerationMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/ChatGenerationMetadata.java new file mode 100644 index 000000000..a90dda5bf --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/ChatGenerationMetadata.java @@ -0,0 +1,75 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.metadata; + +import cn.iocoder.yudao.framework.ai.model.ResultMetadata; +import org.springframework.lang.Nullable; + +/** + * Abstract Data Type (ADT) encapsulating information on the completion choices in the AI + * response. + * + * @author John Blum + * @since 0.7.0 + */ +public interface ChatGenerationMetadata extends ResultMetadata { + + ChatGenerationMetadata NULL = ChatGenerationMetadata.from(null, null); + + /** + * Factory method used to construct a new {@link ChatGenerationMetadata} from the + * given {@link String finish reason} and content filter metadata. + * @param finishReason {@link String} contain the reason for the choice completion. + * @param contentFilterMetadata underlying AI provider metadata for filtering applied + * to generation content. + * @return a new {@link ChatGenerationMetadata} from the given {@link String finish + * reason} and content filter metadata. + */ + static ChatGenerationMetadata from(String finishReason, Object contentFilterMetadata) { + return new ChatGenerationMetadata() { + + @Override + @SuppressWarnings("unchecked") + public T getContentFilterMetadata() { + return (T) contentFilterMetadata; + } + + @Override + public String getFinishReason() { + return finishReason; + } + }; + } + + /** + * Returns the underlying AI provider metadata for filtering applied to generation + * content. + * @param {@link Class Type} used to cast the filtered content metadata into the + * AI provider-specific type. + * @return the underlying AI provider metadata for filtering applied to generation + * content. + */ + @Nullable + T getContentFilterMetadata(); + + /** + * Get the {@link String reason} this choice completed for the generation. + * @return the {@link String reason} this choice completed for the generation. + */ + String getFinishReason(); + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/ChatResponseMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/ChatResponseMetadata.java new file mode 100644 index 000000000..ebcb4ab06 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/ChatResponseMetadata.java @@ -0,0 +1,58 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.metadata; + + +import cn.iocoder.yudao.framework.ai.model.ResponseMetadata; + +/** + * Abstract Data Type (ADT) modeling common AI provider metadata returned in an AI + * response. + * + * 抽象数据类型(ADT)建模AI响应中返回的常见AI提供者元数据。 + * + * @author John Blum + * @since 0.7.0 + */ +public interface ChatResponseMetadata extends ResponseMetadata { + + ChatResponseMetadata NULL = new ChatResponseMetadata() { + }; + + /** + * Returns AI provider specific metadata on rate limits. + * @return AI provider specific metadata on rate limits. + * @see RateLimit + */ + default RateLimit getRateLimit() { + return new EmptyRateLimit(); + } + + /** + * Returns AI provider specific metadata on API usage. + * @return AI provider specific metadata on API usage. + * @see Usage + */ + default Usage getUsage() { + return new EmptyUsage(); + } + + default PromptMetadata getPromptMetadata() { + return PromptMetadata.empty(); + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/EmptyRateLimit.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/EmptyRateLimit.java new file mode 100644 index 000000000..62aeeb531 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/EmptyRateLimit.java @@ -0,0 +1,59 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.metadata; + +import java.time.Duration; + +/** + * A RateLimit implementation that returns zero for all property getters + * + * @author John Blum + * @since 0.7.0 + */ +public class EmptyRateLimit implements RateLimit { + + @Override + public Long getRequestsLimit() { + return 0L; + } + + @Override + public Long getRequestsRemaining() { + return 0L; + } + + @Override + public Duration getRequestsReset() { + return Duration.ZERO; + } + + @Override + public Long getTokensLimit() { + return 0L; + } + + @Override + public Long getTokensRemaining() { + return 0L; + } + + @Override + public Duration getTokensReset() { + return Duration.ZERO; + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/EmptyUsage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/EmptyUsage.java new file mode 100644 index 000000000..11f0255c1 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/EmptyUsage.java @@ -0,0 +1,37 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.metadata; + +/** + * A EmpytUsage implementation that returns zero for all property getters + * + * @author John Blum + * @since 0.7.0 + */ +public class EmptyUsage implements Usage { + + @Override + public Long getPromptTokens() { + return 0L; + } + + @Override + public Long getGenerationTokens() { + return 0L; + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/PromptMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/PromptMetadata.java new file mode 100644 index 000000000..94bad3aa5 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/PromptMetadata.java @@ -0,0 +1,136 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.iocoder.yudao.framework.ai.chat.metadata; + +import org.springframework.util.Assert; + +import java.util.Arrays; +import java.util.Optional; +import java.util.stream.StreamSupport; + +/** + * Abstract Data Type (ADT) modeling metadata gathered by the AI during request + * processing. + * + * @author John Blum + * @since 0.7.0 + */ +@FunctionalInterface +public interface PromptMetadata extends Iterable { + + /** + * Factory method used to create empty {@link PromptMetadata} when the information is + * not supplied by the AI provider. + * @return empty {@link PromptMetadata}. + */ + static PromptMetadata empty() { + return of(); + } + + /** + * Factory method used to create a new {@link PromptMetadata} composed of an array of + * {@link PromptFilterMetadata}. + * @param array array of {@link PromptFilterMetadata} used to compose the + * {@link PromptMetadata}. + * @return a new {@link PromptMetadata} composed of an array of + * {@link PromptFilterMetadata}. + */ + static PromptMetadata of(PromptFilterMetadata... array) { + return of(Arrays.asList(array)); + } + + /** + * Factory method used to create a new {@link PromptMetadata} composed of an + * {@link Iterable} of {@link PromptFilterMetadata}. + * @param iterable {@link Iterable} of {@link PromptFilterMetadata} used to compose + * the {@link PromptMetadata}. + * @return a new {@link PromptMetadata} composed of an {@link Iterable} of + * {@link PromptFilterMetadata}. + */ + static PromptMetadata of(Iterable iterable) { + Assert.notNull(iterable, "An Iterable of PromptFilterMetadata must not be null"); + return iterable::iterator; + } + + /** + * Returns an {@link Optional} {@link PromptFilterMetadata} at the given index. + * @param promptIndex index of the {@link PromptFilterMetadata} contained in this + * {@link PromptMetadata}. + * @return {@link Optional} {@link PromptFilterMetadata} at the given index. + * @throws IllegalArgumentException if the prompt index is less than 0. + */ + default Optional findByPromptIndex(int promptIndex) { + + Assert.isTrue(promptIndex > -1, "Prompt index [%d] must be greater than equal to 0".formatted(promptIndex)); + + return StreamSupport.stream(this.spliterator(), false) + .filter(promptFilterMetadata -> promptFilterMetadata.getPromptIndex() == promptIndex) + .findFirst(); + } + + /** + * Abstract Data Type (ADT) modeling filter metadata for all prompts sent during an AI + * request. + */ + interface PromptFilterMetadata { + + /** + * Factory method used to construct a new {@link PromptFilterMetadata} with the + * given prompt index and content filter metadata. + * @param promptIndex index of the prompt filter metadata contained in the AI + * response. + * @param contentFilterMetadata underlying AI provider metadata for filtering + * applied to prompt content. + * @return a new instance of {@link PromptFilterMetadata} with the given prompt + * index and content filter metadata. + */ + static PromptFilterMetadata from(int promptIndex, Object contentFilterMetadata) { + + return new PromptFilterMetadata() { + + @Override + public int getPromptIndex() { + return promptIndex; + } + + @Override + @SuppressWarnings("unchecked") + public T getContentFilterMetadata() { + return (T) contentFilterMetadata; + } + }; + } + + /** + * Index of the prompt filter metadata contained in the AI response. + * @return an {@link Integer index} fo the prompt filter metadata contained in the + * AI response. + */ + int getPromptIndex(); + + /** + * Returns the underlying AI provider metadata for filtering applied to prompt + * content. + * @param {@link Class Type} used to cast the filtered content metadata into + * the AI provider-specific type. + * @return the underlying AI provider metadata for filtering applied to prompt + * content. + */ + T getContentFilterMetadata(); + + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/RateLimit.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/RateLimit.java new file mode 100644 index 000000000..6842783ba --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/RateLimit.java @@ -0,0 +1,84 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.metadata; + +import java.time.Duration; + +/** + * Abstract Data Type (ADT) encapsulating metadata from an AI provider's API rate limits + * granted to the API key in use and the API key's current balance. + * + * @author John Blum + * @since 0.7.0 + */ +public interface RateLimit { + + /** + * Returns the maximum number of requests that are permitted before exhausting the + * rate limit. + * @return an {@link Long} with the maximum number of requests that are permitted + * before exhausting the rate limit. + * @see #getRequestsRemaining() + */ + Long getRequestsLimit(); + + /** + * Returns the remaining number of requests that are permitted before exhausting the + * {@link #getRequestsLimit() rate limit}. + * @return an {@link Long} with the remaining number of requests that are permitted + * before exhausting the {@link #getRequestsLimit() rate limit}. + * @see #getRequestsLimit() + */ + Long getRequestsRemaining(); + + /** + * Returns the {@link Duration time} until the rate limit (based on requests) resets + * to its {@link #getRequestsLimit() initial state}. + * @return a {@link Duration} representing the time until the rate limit (based on + * requests) resets to its {@link #getRequestsLimit() initial state}. + * @see #getRequestsLimit() + */ + Duration getRequestsReset(); + + /** + * Returns the maximum number of tokens that are permitted before exhausting the rate + * limit. + * @return an {@link Long} with the maximum number of tokens that are permitted before + * exhausting the rate limit. + * @see #getTokensRemaining() + */ + Long getTokensLimit(); + + /** + * Returns the remaining number of tokens that are permitted before exhausting the + * {@link #getTokensLimit() rate limit}. + * @return an {@link Long} with the remaining number of tokens that are permitted + * before exhausting the {@link #getTokensLimit() rate limit}. + * @see #getTokensLimit() + */ + Long getTokensRemaining(); + + /** + * Returns the {@link Duration time} until the rate limit (based on tokens) resets to + * its {@link #getTokensLimit() initial state}. + * @return a {@link Duration} with the time until the rate limit (based on tokens) + * resets to its {@link #getTokensLimit() initial state}. + * @see #getTokensLimit() + */ + Duration getTokensReset(); + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/Usage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/Usage.java new file mode 100644 index 000000000..cecbc828e --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/Usage.java @@ -0,0 +1,66 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.metadata; + +/** + * 抽象数据类型(ADT)封装关于人工智能提供商API使用的元数据根据AI请求。 + * + * Abstract Data Type (ADT) encapsulating metadata on the usage of an AI provider's API + * per AI request. + * + * @author John Blum + * @since 0.7.0 + */ +public interface Usage { + + /** + * 返回AI请求的{@literal prompt}中使用的令牌数。 + * @返回一个{@link Long},其中包含在的{@literal提示符}中使用的令牌数AI请求。 + * + * Returns the number of tokens used in the {@literal prompt} of the AI request. + * @return an {@link Long} with the number of tokens used in the {@literal prompt} of + * the AI request. + * @see #getGenerationTokens() + */ + Long getPromptTokens(); + + /** + * Returns the number of tokens returned in the {@literal generation (aka completion)} + * of the AI's response. + * @return an {@link Long} with the number of tokens returned in the + * {@literal generation (aka completion)} of the AI's response. + * @see #getPromptTokens() + */ + Long getGenerationTokens(); + + /** + * Return the total number of tokens from both the {@literal prompt} of an AI request + * and {@literal generation} of the AI's response. + * @return the total number of tokens from both the {@literal prompt} of an AI request + * and {@literal generation} of the AI's response. + * @see #getPromptTokens() + * @see #getGenerationTokens() + */ + default Long getTotalTokens() { + Long promptTokens = getPromptTokens(); + promptTokens = promptTokens != null ? promptTokens : 0; + Long completionTokens = getGenerationTokens(); + completionTokens = completionTokens != null ? completionTokens : 0; + return promptTokens + completionTokens; + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/package-info.java new file mode 100644 index 000000000..17c341f00 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/package-info.java @@ -0,0 +1,14 @@ +/** + * The org.sf.ai.chat package represents the bounded context for the Chat Model within the + * AI generative model domain. This package extends the core domain defined in + * org.sf.ai.generative, providing implementations specific to chat-based generative AI + * interactions. + * + * In line with Domain-Driven Design principles, this package includes implementations of + * entities and value objects specific to the chat context, such as ChatPrompt and + * ChatResponse, adhering to the ubiquitous language of chat interactions in AI models. + * + * This bounded context is designed to encapsulate all aspects of chat-based AI + * functionalities, maintaining a clear boundary from other contexts within the AI domain. + */ +package cn.iocoder.yudao.framework.ai.chat; \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/AssistantPromptTemplate.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/AssistantPromptTemplate.java new file mode 100644 index 000000000..cfe91527e --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/AssistantPromptTemplate.java @@ -0,0 +1,55 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.prompt; + +import cn.iocoder.yudao.framework.ai.chat.messages.AssistantMessage; +import cn.iocoder.yudao.framework.ai.chat.messages.Message; +import org.springframework.core.io.Resource; + +import java.util.Map; + +public class AssistantPromptTemplate extends PromptTemplate { + + public AssistantPromptTemplate(String template) { + super(template); + } + + public AssistantPromptTemplate(Resource resource) { + super(resource); + } + + @Override + public Prompt create() { + return new Prompt(new AssistantMessage(render())); + } + + @Override + public Prompt create(Map model) { + return new Prompt(new AssistantMessage(render(model))); + } + + @Override + public Message createMessage() { + return new AssistantMessage(render()); + } + + @Override + public Message createMessage(Map model) { + return new AssistantMessage(render(model)); + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/ChatOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/ChatOptions.java new file mode 100644 index 000000000..979ca6b20 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/ChatOptions.java @@ -0,0 +1,40 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.prompt; + +import cn.iocoder.yudao.framework.ai.model.ModelOptions; + +/** + * 聊天选项代表了常见的选项,可在不同的聊天模式中移植。 + * + * The ChatOptions represent the common options, portable across different chat models. + */ +public interface ChatOptions extends ModelOptions { + + Float getTemperature(); + + void setTemperature(Float temperature); + + Float getTopP(); + + void setTopP(Float topP); + + Integer getTopK(); + + void setTopK(Integer topK); + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/ChatOptionsBuilder.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/ChatOptionsBuilder.java new file mode 100644 index 000000000..c3e236ea0 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/ChatOptionsBuilder.java @@ -0,0 +1,89 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.prompt; + +public class ChatOptionsBuilder { + + private class ChatOptionsImpl implements ChatOptions { + + private Float temperature; + + private Float topP; + + private Integer topK; + + @Override + public Float getTemperature() { + return temperature; + } + + @Override + public void setTemperature(Float temperature) { + this.temperature = temperature; + } + + @Override + public Float getTopP() { + return topP; + } + + @Override + public void setTopP(Float topP) { + this.topP = topP; + } + + @Override + public Integer getTopK() { + return topK; + } + + @Override + public void setTopK(Integer topK) { + this.topK = topK; + } + + } + + private final ChatOptionsImpl options = new ChatOptionsImpl(); + + private ChatOptionsBuilder() { + } + + public static ChatOptionsBuilder builder() { + return new ChatOptionsBuilder(); + } + + public ChatOptionsBuilder withTemperature(Float temperature) { + options.setTemperature(temperature); + return this; + } + + public ChatOptionsBuilder withTopP(Float topP) { + options.setTopP(topP); + return this; + } + + public ChatOptionsBuilder withTopK(Integer topK) { + options.setTopK(topK); + return this; + } + + public ChatOptions build() { + return options; + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/ChatPromptTemplate.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/ChatPromptTemplate.java new file mode 100644 index 000000000..a06c981c7 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/ChatPromptTemplate.java @@ -0,0 +1,87 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.prompt; + +import cn.iocoder.yudao.framework.ai.chat.messages.Message; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * PromptTemplate,用于将角色指定为字符串实现及其角色不足以满足您的需求。 + * + * A PromptTemplate that lets you specify the role as a string should the current + * implementations and their roles not suffice for your needs. + */ +public class ChatPromptTemplate implements PromptTemplateActions, PromptTemplateChatActions { + + private final List promptTemplates; + + public ChatPromptTemplate(List promptTemplates) { + this.promptTemplates = promptTemplates; + } + + @Override + public String render() { + StringBuilder sb = new StringBuilder(); + for (PromptTemplate promptTemplate : promptTemplates) { + sb.append(promptTemplate.render()); + } + return sb.toString(); + } + + @Override + public String render(Map model) { + StringBuilder sb = new StringBuilder(); + for (PromptTemplate promptTemplate : promptTemplates) { + sb.append(promptTemplate.render(model)); + } + return sb.toString(); + } + + @Override + public List createMessages() { + List messages = new ArrayList<>(); + for (PromptTemplate promptTemplate : promptTemplates) { + messages.add(promptTemplate.createMessage()); + } + return messages; + } + + @Override + public List createMessages(Map model) { + List messages = new ArrayList<>(); + for (PromptTemplate promptTemplate : promptTemplates) { + messages.add(promptTemplate.createMessage(model)); + } + return messages; + } + + @Override + public Prompt create() { + List messages = createMessages(); + return new Prompt(messages); + } + + @Override + public Prompt create(Map model) { + List messages = createMessages(model); + return new Prompt(messages); + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/FunctionPromptTemplate.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/FunctionPromptTemplate.java new file mode 100644 index 000000000..e94545c23 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/FunctionPromptTemplate.java @@ -0,0 +1,27 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.prompt; + +public class FunctionPromptTemplate extends PromptTemplate { + + private String name; + + public FunctionPromptTemplate(String template) { + super(template); + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/Prompt.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/Prompt.java new file mode 100644 index 000000000..f9eb37409 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/Prompt.java @@ -0,0 +1,99 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.prompt; + +import cn.iocoder.yudao.framework.ai.chat.messages.Message; +import cn.iocoder.yudao.framework.ai.chat.messages.UserMessage; +import cn.iocoder.yudao.framework.ai.model.ModelOptions; +import cn.iocoder.yudao.framework.ai.model.ModelRequest; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +/** + * 文字内容 + */ +public class Prompt implements ModelRequest> { + + private final List messages; + + private ChatOptions modelOptions; + + public Prompt(String contents) { + this(new UserMessage(contents)); + } + + public Prompt(Message message) { + this(Collections.singletonList(message)); + } + + public Prompt(List messages) { + this.messages = messages; + } + + public Prompt(String contents, ChatOptions modelOptions) { + this(new UserMessage(contents), modelOptions); + } + + public Prompt(Message message, ChatOptions modelOptions) { + this(Collections.singletonList(message), modelOptions); + } + + public Prompt(List messages, ChatOptions modelOptions) { + this.messages = messages; + this.modelOptions = modelOptions; + } + + public String getContents() { + StringBuilder sb = new StringBuilder(); + for (Message message : getInstructions()) { + sb.append(message.getContent()); + } + return sb.toString(); + } + + @Override + public ModelOptions getOptions() { + return this.modelOptions; + } + + @Override + public List getInstructions() { + return this.messages; + } + + @Override + public String toString() { + return "Prompt{" + "messages=" + this.messages + ", modelOptions=" + this.modelOptions + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof Prompt prompt)) + return false; + return Objects.equals(this.messages, prompt.messages) && Objects.equals(this.modelOptions, prompt.modelOptions); + } + + @Override + public int hashCode() { + return Objects.hash(this.messages, this.modelOptions); + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplate.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplate.java new file mode 100644 index 000000000..7c0c0f7f3 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplate.java @@ -0,0 +1,218 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.prompt; + +import cn.iocoder.yudao.framework.ai.chat.messages.Message; +import cn.iocoder.yudao.framework.ai.chat.messages.UserMessage; +import cn.iocoder.yudao.framework.ai.parser.OutputParser; +import org.antlr.runtime.Token; +import org.antlr.runtime.TokenStream; +import org.springframework.core.io.Resource; +import org.springframework.util.StreamUtils; +import org.stringtemplate.v4.ST; +import org.stringtemplate.v4.compiler.STLexer; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.*; +import java.util.Map.Entry; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +/** + * 用户输入的提示内容模板 + * + * 实现:提示词模板操作 提示词模板message相关操作 + */ +public class PromptTemplate implements PromptTemplateActions, PromptTemplateMessageActions { + + private ST st; + + private Map dynamicModel = new HashMap<>(); + + protected String template; + + protected TemplateFormat templateFormat = TemplateFormat.ST; + + private OutputParser outputParser; + + public PromptTemplate(Resource resource) { + try (InputStream inputStream = resource.getInputStream()) { + this.template = StreamUtils.copyToString(inputStream, Charset.defaultCharset()); + } + catch (IOException ex) { + throw new RuntimeException("Failed to read resource", ex); + } + try { + this.st = new ST(this.template, '{', '}'); + } + catch (Exception ex) { + throw new IllegalArgumentException("The template string is not valid.", ex); + } + } + + public PromptTemplate(String template) { + this.template = template; + // If the template string is not valid, an exception will be thrown + try { + this.st = new ST(this.template, '{', '}'); + } + catch (Exception ex) { + throw new IllegalArgumentException("The template string is not valid.", ex); + } + } + + public PromptTemplate(String template, Map model) { + this.template = template; + // If the template string is not valid, an exception will be thrown + try { + this.st = new ST(this.template, '{', '}'); + for (Entry entry : model.entrySet()) { + add(entry.getKey(), entry.getValue()); + dynamicModel.put(entry.getKey(), entry.getValue()); + } + } + catch (Exception ex) { + throw new IllegalArgumentException("The template string is not valid.", ex); + } + } + + public PromptTemplate(Resource resource, Map model) { + try (InputStream inputStream = resource.getInputStream()) { + this.template = StreamUtils.copyToString(inputStream, Charset.defaultCharset()); + } + catch (IOException ex) { + throw new RuntimeException("Failed to read resource", ex); + } + // If the template string is not valid, an exception will be thrown + try { + this.st = new ST(this.template, '{', '}'); + for (Entry entry : model.entrySet()) { + add(entry.getKey(), entry.getValue()); + dynamicModel.put(entry.getKey(), entry.getValue()); + } + } + catch (Exception ex) { + throw new IllegalArgumentException("The template string is not valid.", ex); + } + } + + public OutputParser getOutputParser() { + return outputParser; + } + + public void setOutputParser(OutputParser outputParser) { + Objects.requireNonNull(outputParser, "Output Parser can not be null"); + this.outputParser = outputParser; + } + + public void add(String name, Object value) { + this.st.add(name, value); + this.dynamicModel.put(name, value); + } + + public String getTemplate() { + return this.template; + } + + public TemplateFormat getTemplateFormat() { + return this.templateFormat; + } + + // Render Methods + @Override + public String render() { + validate(this.dynamicModel); + return st.render(); + } + + @Override + public String render(Map model) { + validate(model); + for (Entry entry : model.entrySet()) { + if (st.getAttribute(entry.getKey()) != null) { + st.remove(entry.getKey()); + } + if (entry.getValue() instanceof Resource) { + st.add(entry.getKey(), renderResource((Resource) entry.getValue())); + } + else { + st.add(entry.getKey(), entry.getValue()); + } + + } + return st.render(); + } + + private String renderResource(Resource resource) { + try { + return resource.getContentAsString(Charset.defaultCharset()); + } + catch (IOException e) { + throw new RuntimeException(e); + } + // try (InputStream inputStream = resource.getInputStream()) { + // return StreamUtils.copyToString(inputStream, Charset.defaultCharset()); + // } + // catch (IOException ex) { + // throw new RuntimeException(ex); + // } + } + + @Override + public Message createMessage() { + return new UserMessage(render()); + } + + @Override + public Message createMessage(Map model) { + return new UserMessage(render(model)); + } + + @Override + public Prompt create() { + return new Prompt(render(new HashMap<>())); + } + + @Override + public Prompt create(Map model) { + return new Prompt(render(model)); + } + + public Set getInputVariables() { + TokenStream tokens = this.st.impl.tokens; + return IntStream.range(0, tokens.range()) + .mapToObj(tokens::get) + .filter(token -> token.getType() == STLexer.ID) + .map(Token::getText) + .collect(Collectors.toSet()); + } + + protected void validate(Map model) { + Set dynamicVariableNames = new HashSet<>(this.dynamicModel.keySet()); + Set modelVariables = new HashSet<>(model.keySet()); + modelVariables.addAll(dynamicVariableNames); + Set missingEntries = new HashSet<>(getInputVariables()); + missingEntries.removeAll(modelVariables); + if (!missingEntries.isEmpty()) { + throw new IllegalStateException( + "All template variables were not replaced. Missing variable names are " + missingEntries); + } + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateActions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateActions.java new file mode 100644 index 000000000..bdee00acb --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateActions.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.prompt; + +import java.util.Map; + +/** + * 提示词模板操作 + */ +public interface PromptTemplateActions extends PromptTemplateStringActions { + + /** + * 创建 Prompt + * @return + */ + Prompt create(); + + Prompt create(Map model); + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateChatActions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateChatActions.java new file mode 100644 index 000000000..922d57c8d --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateChatActions.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.framework.ai.chat.prompt; + +import cn.iocoder.yudao.framework.ai.chat.messages.Message; + +import java.util.List; +import java.util.Map; + +/** + * 聊天操作 + * + */ +public interface PromptTemplateChatActions { + + List createMessages(); + + List createMessages(Map model); + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateMessageActions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateMessageActions.java new file mode 100644 index 000000000..8de851a89 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateMessageActions.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.framework.ai.chat.prompt; + +import cn.iocoder.yudao.framework.ai.chat.messages.Message; + +import java.util.Map; + +/** + * 用户输入的提示内容 模板信息操作 + */ +public interface PromptTemplateMessageActions { + + /** + * 创建一个 message + * @return + */ + Message createMessage(); + + /** + * 创建一个 message + * @return + */ + Message createMessage(Map model); + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateStringActions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateStringActions.java new file mode 100644 index 000000000..58015b47d --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateStringActions.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.framework.ai.chat.prompt; + +import java.util.Map; + +/** + * 提示次模板字符串操作 + */ +public interface PromptTemplateStringActions { + + String render(); + + String render(Map model); + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/SystemPromptTemplate.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/SystemPromptTemplate.java new file mode 100644 index 000000000..cafade4bb --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/SystemPromptTemplate.java @@ -0,0 +1,55 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.prompt; + +import cn.iocoder.yudao.framework.ai.chat.messages.Message; +import cn.iocoder.yudao.framework.ai.chat.messages.SystemMessage; +import org.springframework.core.io.Resource; + +import java.util.Map; + +public class SystemPromptTemplate extends PromptTemplate { + + public SystemPromptTemplate(String template) { + super(template); + } + + public SystemPromptTemplate(Resource resource) { + super(resource); + } + + @Override + public Message createMessage() { + return new SystemMessage(render()); + } + + @Override + public Message createMessage(Map model) { + return new SystemMessage(render(model)); + } + + @Override + public Prompt create() { + return new Prompt(new SystemMessage(render())); + } + + @Override + public Prompt create(Map model) { + return new Prompt(new SystemMessage(render(model))); + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/TemplateFormat.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/TemplateFormat.java new file mode 100644 index 000000000..c22a78db3 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/TemplateFormat.java @@ -0,0 +1,42 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.chat.prompt; + +public enum TemplateFormat { + + ST("ST"); + + private final String value; + + TemplateFormat(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public static TemplateFormat fromValue(String value) { + for (TemplateFormat templateFormat : TemplateFormat.values()) { + if (templateFormat.getValue().equals(value)) { + return templateFormat; + } + } + throw new IllegalArgumentException("Invalid TemplateFormat value: " + value); + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelClient.java new file mode 100644 index 000000000..705a7a976 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelClient.java @@ -0,0 +1,40 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.model; + +/** + * The ModelClient interface provides a generic API for invoking AI models. It is designed + * to handle the interaction with various types of AI models by abstracting the process of + * sending requests and receiving responses. The interface uses Java generics to + * accommodate different types of requests and responses, enhancing flexibility and + * adaptability across different AI model implementations. + * + * @param the generic type of the request to the AI model + * @param the generic type of the response from the AI model + * @author Mark Pollack + * @since 0.8.0 + */ +public interface ModelClient, TRes extends ModelResponse> { + + /** + * Executes a method call to the AI model. + * @param request the request object to be sent to the AI model + * @return the response from the AI model + */ + TRes call(TReq request) throws Throwable; + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelOptions.java new file mode 100644 index 000000000..6a5a738fe --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelOptions.java @@ -0,0 +1,31 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.model; + +/** + * Interface representing the customizable options for AI model interactions. This marker + * interface allows for the specification of various settings and parameters that can + * influence the behavior and output of AI models. It is designed to provide flexibility + * and adaptability in different AI scenarios, ensuring that the AI models can be + * fine-tuned according to specific requirements. + * + * @author Mark Pollack + * @since 0.8.0 + */ +public interface ModelOptions { + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelOptionsUtils.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelOptionsUtils.java new file mode 100644 index 000000000..0d6f74007 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelOptionsUtils.java @@ -0,0 +1,387 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.github.victools.jsonschema.generator.*; +import com.github.victools.jsonschema.module.jackson.JacksonModule; +import com.github.victools.jsonschema.module.jackson.JacksonOption; +import com.github.victools.jsonschema.module.swagger2.Swagger2Module; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeanWrapperImpl; +import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; + +import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; + +/** + * Utility class for manipulating {@link ModelOptions} objects. + * + * @author Christian Tzolov + * @since 0.8.0 + */ +public final class ModelOptionsUtils { + + private final static ObjectMapper OBJECT_MAPPER = new ObjectMapper() + .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); + + private final static List BEAN_MERGE_FIELD_EXCISIONS = List.of("class"); + + private static ConcurrentHashMap, List> REQUEST_FIELD_NAMES_PER_CLASS = new ConcurrentHashMap, List>(); + + private static AtomicReference SCHEMA_GENERATOR_CACHE = new AtomicReference<>(); + + private ModelOptionsUtils() { + + } + + /** + * Converts the given JSON string to a Map of String and Object. + * @param json the JSON string to convert to a Map. + * @return the converted Map. + */ + public static Map jsonToMap(String json) { + try { + return OBJECT_MAPPER.readValue(json, MAP_TYPE_REF); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static TypeReference> MAP_TYPE_REF = new TypeReference>() { + }; + + /** + * Converts the given JSON string to an Object of the given type. + * @param the type of the object to return. + * @param json the JSON string to convert to an object. + * @param type the type of the object to return. + * @return Object instance of the given type. + */ + public static T jsonToObject(String json, Class type) { + try { + return OBJECT_MAPPER.readValue(json, type); + } + catch (Exception e) { + throw new RuntimeException("Failed to json: " + json, e); + } + } + + /** + * Converts the given object to a JSON string. + * @param object the object to convert to a JSON string. + * @return the JSON string. + */ + public static String toJsonString(Object object) { + try { + return OBJECT_MAPPER.writeValueAsString(object); + } + catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + /** + * Merges the source object into the target object and returns an object represented + * by the given class. The JSON property names are used to match the fields to merge. + * The source non-null values override the target values with the same field name. The + * source null values are ignored. If the acceptedFieldNames is not empty, only the + * fields with the given names are merged and returned. If the acceptedFieldNames is + * empty, use the {@code @JsonProperty} names, inferred from the provided clazz. + * @param they type of the class to return. + * @param source the source object to merge. + * @param target the target object to merge into. + * @param clazz the class to return. + * @param acceptedFieldNames the list of field names accepted for the target object. + * @return the merged object represented by the given class. + */ + public static T merge(Object source, Object target, Class clazz, List acceptedFieldNames) { + + if (source == null) { + source = Map.of(); + } + + List requestFieldNames = CollectionUtils.isEmpty(acceptedFieldNames) + ? REQUEST_FIELD_NAMES_PER_CLASS.computeIfAbsent(clazz, ModelOptionsUtils::getJsonPropertyValues) + : acceptedFieldNames; + + if (CollectionUtils.isEmpty(requestFieldNames)) { + throw new IllegalArgumentException("No @JsonProperty fields found in the " + clazz.getName()); + } + + Map sourceMap = ModelOptionsUtils.objectToMap(source); + Map targetMap = ModelOptionsUtils.objectToMap(target); + + targetMap.putAll(sourceMap.entrySet() + .stream() + .filter(e -> e.getValue() != null) + .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()))); + + targetMap = targetMap.entrySet() + .stream() + .filter(e -> requestFieldNames.contains(e.getKey())) + .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue())); + + return ModelOptionsUtils.mapToClass(targetMap, clazz); + } + + /** + * Merges the source object into the target object and returns an object represented + * by the given class. The JSON property names are used to match the fields to merge. + * The source non-null values override the target values with the same field name. The + * source null values are ignored. Returns the only field names that match the + * {@code @JsonProperty} names, inferred from the provided clazz. + * @param they type of the class to return. + * @param source the source object to merge. + * @param target the target object to merge into. + * @param clazz the class to return. + * @return the merged object represented by the given class. + */ + public static T merge(Object source, Object target, Class clazz) { + return ModelOptionsUtils.merge(source, target, clazz, null); + } + + /** + * Converts the given object to a Map. + * @param source the object to convert to a Map. + * @return the converted Map. + */ + public static Map objectToMap(Object source) { + if (source == null) { + return new HashMap<>(); + } + try { + String json = OBJECT_MAPPER.writeValueAsString(source); + return OBJECT_MAPPER.readValue(json, new TypeReference>() { + }) + .entrySet() + .stream() + .filter(e -> e.getValue() != null) + .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue())); + } + catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + /** + * Converts the given Map to the given class. + * @param the type of the class to return. + * @param source the Map to convert to the given class. + * @param clazz the class to convert the Map to. + * @return the converted class. + */ + public static T mapToClass(Map source, Class clazz) { + try { + String json = OBJECT_MAPPER.writeValueAsString(source); + return OBJECT_MAPPER.readValue(json, clazz); + } + catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + /** + * Returns the list of name values of the {@link JsonProperty} annotations. + * @param clazz the class that contains fields annotated with {@link JsonProperty}. + * @return the list of values of the {@link JsonProperty} annotations. + */ + public static List getJsonPropertyValues(Class clazz) { + List values = new ArrayList<>(); + Field[] fields = clazz.getDeclaredFields(); + for (Field field : fields) { + JsonProperty jsonPropertyAnnotation = field.getAnnotation(JsonProperty.class); + if (jsonPropertyAnnotation != null) { + values.add(jsonPropertyAnnotation.value()); + } + } + return values; + } + + /** + * Returns a new instance of the targetBeanClazz that copies the bean values from the + * sourceBean instance. + * @param sourceBean the source bean to copy the values from. + * @param sourceInterfaceClazz the source interface class. Only the fields with the + * same name as the interface methods are copied. This allow the source object to be a + * subclass of the source interface with additional, non-interface fields. + * @param targetBeanClazz the target class, a subclass of the ChatOptions, to convert + * into. + * @param the target class type. + * @return a new instance of the targetBeanClazz with the values from the sourceBean + * instance. + */ + public static T copyToTarget(S sourceBean, Class sourceInterfaceClazz, + Class targetBeanClazz) { + + Assert.notNull(sourceInterfaceClazz, "SourceOptionsClazz must not be null"); + Assert.notNull(targetBeanClazz, "TargetOptionsClazz must not be null"); + + if (sourceBean == null) { + return null; + } + + if (sourceBean.getClass().isAssignableFrom(targetBeanClazz)) { + return (T) sourceBean; + } + + try { + T targetOptions = targetBeanClazz.getConstructor().newInstance(); + + ModelOptionsUtils.mergeBeans(sourceBean, targetOptions, sourceInterfaceClazz, true); + + return targetOptions; + } + catch (Exception e) { + throw new RuntimeException( + "Failed to convert the " + sourceInterfaceClazz.getName() + " into " + targetBeanClazz.getName(), + e); + } + } + + /** + * Merges the source object into the target object. The source null values are + * ignored. Only objects with Getter and Setter methods are supported. + * @param the type of the source and target object. + * @param source the source object to merge. + * @param target the target object to merge into. + * @param sourceInterfaceClazz the source interface class. Only the fields with the + * same name as the interface methods are merged. This allow the source object to be a + * subclass of the source interface with additional, non-interface fields. + * @param overrideNonNullTargetValues if true, the source non-null values override the + * target values with the same field name. If false, the source non-null values are + * ignored. + * @return the merged target object. + */ + public static T mergeBeans(S source, T target, Class sourceInterfaceClazz, + boolean overrideNonNullTargetValues) { + Assert.notNull(source, "Source object must not be null"); + Assert.notNull(target, "Target object must not be null"); + + BeanWrapper sourceBeanWrap = new BeanWrapperImpl(source); + BeanWrapper targetBeanWrap = new BeanWrapperImpl(target); + + List interfaceNames = Arrays.stream(sourceInterfaceClazz.getMethods()).map(m -> m.getName()).toList(); + + for (PropertyDescriptor descriptor : sourceBeanWrap.getPropertyDescriptors()) { + + if (!BEAN_MERGE_FIELD_EXCISIONS.contains(descriptor.getName()) + && interfaceNames.contains(toGetName(descriptor.getName()))) { + + String propertyName = descriptor.getName(); + Object value = sourceBeanWrap.getPropertyValue(propertyName); + + // Copy value to the target object + if (value != null) { + var targetValue = targetBeanWrap.getPropertyValue(propertyName); + + if (targetValue == null || overrideNonNullTargetValues) { + targetBeanWrap.setPropertyValue(propertyName, value); + } + } + } + } + + return target; + } + + private static String toGetName(String name) { + return "get" + name.substring(0, 1).toUpperCase() + name.substring(1); + } + + /** + * Generates JSON Schema (version 2020_12) for the given class. + * @param clazz the class to generate JSON Schema for. + * @param toUpperCaseTypeValues if true, the type values are converted to upper case. + * @return the generated JSON Schema as a String. + */ + public static String getJsonSchema(Class clazz, boolean toUpperCaseTypeValues) { + + if (SCHEMA_GENERATOR_CACHE.get() == null) { + + JacksonModule jacksonModule = new JacksonModule(JacksonOption.RESPECT_JSONPROPERTY_REQUIRED); + Swagger2Module swaggerModule = new Swagger2Module(); + + SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(SchemaVersion.DRAFT_2020_12, + OptionPreset.PLAIN_JSON) + .with(Option.EXTRA_OPEN_API_FORMAT_VALUES) + .with(Option.PLAIN_DEFINITION_KEYS) + .with(swaggerModule) + .with(jacksonModule); + + SchemaGeneratorConfig config = configBuilder.build(); + SchemaGenerator generator = new SchemaGenerator(config); + SCHEMA_GENERATOR_CACHE.compareAndSet(null, generator); + } + + ObjectNode node = SCHEMA_GENERATOR_CACHE.get().generateSchema(clazz); + if (toUpperCaseTypeValues) { // Required for OpenAPI 3.0 (at least Vertex AI + // version of it). + toUpperCaseTypeValues(node); + } + + return node.toPrettyString(); + } + + public static void toUpperCaseTypeValues(ObjectNode node) { + if (node == null) { + return; + } + if (node.isObject()) { + node.fields().forEachRemaining(entry -> { + JsonNode value = entry.getValue(); + if (value.isObject()) { + toUpperCaseTypeValues((ObjectNode) value); + } + else if (value.isArray()) { + ((ArrayNode) value).elements().forEachRemaining(element -> { + if (element.isObject() || element.isArray()) { + toUpperCaseTypeValues((ObjectNode) element); + } + }); + } + else if (value.isTextual() && entry.getKey().equals("type")) { + String oldValue = ((ObjectNode) node).get("type").asText(); + ((ObjectNode) node).put("type", oldValue.toUpperCase()); + } + }); + } + else if (node.isArray()) { + node.elements().forEachRemaining(element -> { + if (element.isObject() || element.isArray()) { + toUpperCaseTypeValues((ObjectNode) element); + } + }); + } + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelRequest.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelRequest.java new file mode 100644 index 000000000..915aba26e --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelRequest.java @@ -0,0 +1,51 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.model; + +/** + * 表示对AI模型的请求的接口。此接口封装了 与人工智能模型交互所需的必要信息,包括指令或 输入(通用类型T)和附加模型选项。它提供了一种标准化的方式 + * 向人工智能模型发送请求,确保包括所有必要的细节,并且可以易于管理。 + * + * Interface representing a request to an AI model. This interface encapsulates the + * necessary information required to interact with an AI model, including instructions or + * inputs (of generic type T) and additional model options. It provides a standardized way + * to send requests to AI models, ensuring that all necessary details are included and can + * be easily managed. + * + * @param the type of instructions or input required by the AI model + * @author Mark Pollack + * @since 0.8.0 + */ +public interface ModelRequest { + + /** + * 检索AI模型所需的指令或输入。 返回AI模型所需的指令或输入 + * + * Retrieves the instructions or input required by the AI model. + * @return the instructions or input required by the AI model + */ + T getInstructions(); // required input + + /** + * 检索人工智能模型交互的可自定义选项。 返回AI模型交互的自定义选项 + * + * Retrieves the customizable options for AI model interactions. + * @return the customizable options for AI model interactions + */ + ModelOptions getOptions(); + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelResponse.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelResponse.java new file mode 100644 index 000000000..0bc0cc593 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelResponse.java @@ -0,0 +1,62 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.model; + +import java.util.List; + +/** + * + * 表示从AI模型接收到的响应的接口。此接口提供 访问AI模型生成的主要结果或结果列表的方法,以及 以及响应元数据。它是封装和管理的标准化方式 + * 人工智能模型的输出,确保轻松检索和处理生成的信息 + * + * Interface representing the response received from an AI model. This interface provides + * methods to access the main result or a list of results generated by the AI model, along + * with the response metadata. It serves as a standardized way to encapsulate and manage + * the output from AI models, ensuring easy retrieval and processing of the generated + * information. + * + * @param the type of the result(s) provided by the AI model + * @author Mark Pollack + * @since 0.8.0 + */ +public interface ModelResponse> { + + /** + * 检索AI模型的结果。 + * + * Retrieves the result of the AI model. + * @return the result generated by the AI model + */ + T getResult(); + + /** + * 检索AI模型生成的输出列表。 + * + * Retrieves the list of generated outputs by the AI model. + * @return the list of generated outputs + */ + List getResults(); + + /** + * 检索与AI模型的响应相关联的响应元数据。 + * + * Retrieves the response metadata associated with the AI model's response. + * @return the response metadata + */ + ResponseMetadata getMetadata(); + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelResult.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelResult.java new file mode 100644 index 000000000..616be1817 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelResult.java @@ -0,0 +1,43 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.model; + +/** + * This interface provides methods to access the main output of the AI model and the + * metadata associated with this result. It is designed to offer a standardized and + * comprehensive way to handle and interpret the outputs generated by AI models, catering + * to diverse AI applications and use cases. + * + * @param the type of the output generated by the AI model + * @author Mark Pollack + * @since 0.8.0 + */ +public interface ModelResult { + + /** + * Retrieves the output generated by the AI model. + * @return the output generated by the AI model + */ + T getOutput(); + + /** + * Retrieves the metadata associated with the result of an AI model. + * @return the metadata associated with the result + */ + ResultMetadata getMetadata(); + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ResponseMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ResponseMetadata.java new file mode 100644 index 000000000..2a85cdf7a --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ResponseMetadata.java @@ -0,0 +1,34 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.model; + +/** + * 表示与AI模型的响应相关联的元数据的接口。此接口 旨在提供有关人工智能生成反应的附加信息 模型,包括处理细节和模型特定数据。它是一种价值 + * 核心领域内的对象,增强对人工智能模型的理解和管理 在各种应用中的响应。 + * + * Interface representing metadata associated with an AI model's response. This interface + * is designed to provide additional information about the generative response from an AI + * model, including processing details and model-specific data. It serves as a value + * object within the core domain, enhancing the understanding and management of AI model + * responses in various applications. + * + * @author Mark Pollack + * @since 0.8.0 + */ +public interface ResponseMetadata { + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ResultMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ResultMetadata.java new file mode 100644 index 000000000..528b76459 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ResultMetadata.java @@ -0,0 +1,31 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.model; + +/** + * Interface representing metadata associated with the results of an AI model. This + * interface focuses on providing additional context and insights into the results + * generated by AI models. It could include information like computation time, model + * version, or other relevant details that enhance understanding and management of AI + * model outputs in various applications. + * + * @author Mark Pollack + * @since 0.8.0 + */ +public interface ResultMetadata { + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/StreamingModelClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/StreamingModelClient.java new file mode 100644 index 000000000..abbe8598c --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/StreamingModelClient.java @@ -0,0 +1,43 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.model; + +import reactor.core.publisher.Flux; + +/** + * The StreamingModelClient interface provides a generic API for invoking a AI models with + * streaming response. It abstracts the process of sending requests and receiving a + * streaming responses. The interface uses Java generics to accommodate different types of + * requests and responses, enhancing flexibility and adaptability across different AI + * model implementations. + * + * @param the generic type of the request to the AI model + * @param the generic type of a single item in the streaming response from the + * AI model + * @author Christian Tzolov + * @since 0.8.0 + */ +public interface StreamingModelClient, TResChunk extends ModelResponse> { + + /** + * Executes a method call to the AI model. + * @param request the request object to be sent to the AI model + * @return the streaming response from the AI model + */ + Flux stream(TReq request); + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/AbstractFunctionCallSupport.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/AbstractFunctionCallSupport.java new file mode 100644 index 000000000..d5becdbb5 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/AbstractFunctionCallSupport.java @@ -0,0 +1,158 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.model.function; + +import org.springframework.util.CollectionUtils; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author Christian Tzolov + */ +public abstract class AbstractFunctionCallSupport { + + protected final static boolean IS_RUNTIME_CALL = true; + + /** + * The function callback register is used to resolve the function callbacks by name. + */ + protected final Map functionCallbackRegister = new ConcurrentHashMap<>(); + + /** + * The function callback context is used to resolve the function callbacks by name + * from the Spring context. It is optional and usually used with Spring + * auto-configuration. + */ + protected final FunctionCallbackContext functionCallbackContext; + + public AbstractFunctionCallSupport(FunctionCallbackContext functionCallbackContext) { + this.functionCallbackContext = functionCallbackContext; + } + + public Map getFunctionCallbackRegister() { + return this.functionCallbackRegister; + } + + protected Set handleFunctionCallbackConfigurations(FunctionCallingOptions options, boolean isRuntimeCall) { + + Set functionToCall = new HashSet<>(); + + if (options != null) { + if (!CollectionUtils.isEmpty(options.getFunctionCallbacks())) { + options.getFunctionCallbacks().stream().forEach(functionCallback -> { + + // Register the tool callback. + if (isRuntimeCall) { + this.functionCallbackRegister.put(functionCallback.getName(), functionCallback); + } + else { + this.functionCallbackRegister.putIfAbsent(functionCallback.getName(), functionCallback); + } + + // Automatically enable the function, usually from prompt callback. + if (isRuntimeCall) { + functionToCall.add(functionCallback.getName()); + } + }); + } + + // Add the explicitly enabled functions. + if (!CollectionUtils.isEmpty(options.getFunctions())) { + functionToCall.addAll(options.getFunctions()); + } + } + + return functionToCall; + } + + /** + * Resolve the function callbacks by name. Retrieve them from the registry or try to + * resolve them from the Application Context. + * @param functionNames Name of function callbacks to retrieve. + * @return list of resolved FunctionCallbacks. + */ + protected List resolveFunctionCallbacks(Set functionNames) { + + List retrievedFunctionCallbacks = new ArrayList<>(); + + for (String functionName : functionNames) { + if (!this.functionCallbackRegister.containsKey(functionName)) { + + if (this.functionCallbackContext != null) { + FunctionCallback functionCallback = this.functionCallbackContext.getFunctionCallback(functionName, + null); + if (functionCallback != null) { + this.functionCallbackRegister.put(functionName, functionCallback); + } + else { + throw new IllegalStateException( + "No function callback [" + functionName + "] fund in tht FunctionCallbackContext"); + } + } + else { + throw new IllegalStateException("No function callback found for name: " + functionName); + } + } + FunctionCallback functionCallback = this.functionCallbackRegister.get(functionName); + + retrievedFunctionCallbacks.add(functionCallback); + } + + return retrievedFunctionCallbacks; + } + + /// + protected Resp callWithFunctionSupport(Req request) { + Resp response = this.doChatCompletion(request); + return this.handleFunctionCallOrReturn(request, response); + } + + protected Resp handleFunctionCallOrReturn(Req request, Resp response) { + + if (!this.isToolFunctionCall(response)) { + return response; + } + + // The chat completion tool call requires the complete conversation + // history. Including the initial user message. + List conversationHistory = new ArrayList<>(); + + conversationHistory.addAll(this.doGetUserMessages(request)); + + Msg responseMessage = this.doGetToolResponseMessage(response); + + // Add the assistant response to the message conversation history. + conversationHistory.add(responseMessage); + + Req newRequest = this.doCreateToolResponseRequest(request, responseMessage, conversationHistory); + + return this.callWithFunctionSupport(newRequest); + } + + abstract protected Req doCreateToolResponseRequest(Req previousRequest, Msg responseMessage, + List conversationHistory); + + abstract protected List doGetUserMessages(Req request); + + abstract protected Msg doGetToolResponseMessage(Resp response); + + abstract protected Resp doChatCompletion(Req request); + + abstract protected boolean isToolFunctionCall(Resp response); + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/AbstractFunctionCallback.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/AbstractFunctionCallback.java new file mode 100644 index 000000000..044c1813c --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/AbstractFunctionCallback.java @@ -0,0 +1,159 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.model.function; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.util.Assert; + +import java.util.function.Function; + +/** + * Abstract implementation of the {@link FunctionCallback} for interacting with the + * Model's function calling protocol and a {@link Function} wrapping the interaction with + * the 3rd party service/function. + * + * Implement the {@code O apply(I request) } method to implement the interaction with the + * 3rd party service/function. + * + * The {@link #responseConverter} function is responsible to convert the 3rd party + * function's output type into a string expected by the LLM model. + * + * @param the 3rd party service input type. + * @param the 3rd party service output type. + * @author Christian Tzolov + */ +abstract class AbstractFunctionCallback implements Function, FunctionCallback { + + private final String name; + + private final String description; + + private final Class inputType; + + private final String inputTypeSchema; + + private final ObjectMapper objectMapper; + + private final Function responseConverter; + + /** + * Constructs a new {@link AbstractFunctionCallback} with the given name, description, + * input type and default object mapper. + * @param name Function name. Should be unique within the ChatClient's function + * registry. + * @param description Function description. Used as a "system prompt" by the model to + * decide if the function should be called. + * @param inputTypeSchema Used to compute, the argument's Schema (such as JSON Schema + * or OpenAPI Schema)required by the Model's function calling protocol. + * @param inputType Used to compute, the argument's JSON schema required by the + * Model's function calling protocol. + * @param responseConverter Used to convert the function's output type to a string. + * @param objectMapper Used to convert the function's input and output types to and + * from JSON. + */ + protected AbstractFunctionCallback(String name, String description, String inputTypeSchema, Class inputType, + Function responseConverter, ObjectMapper objectMapper) { + Assert.notNull(name, "Name must not be null"); + Assert.notNull(description, "Description must not be null"); + Assert.notNull(inputType, "InputType must not be null"); + Assert.notNull(inputTypeSchema, "InputTypeSchema must not be null"); + Assert.notNull(responseConverter, "ResponseConverter must not be null"); + Assert.notNull(objectMapper, "ObjectMapper must not be null"); + this.name = name; + this.description = description; + this.inputType = inputType; + this.inputTypeSchema = inputTypeSchema; + this.responseConverter = responseConverter; + this.objectMapper = objectMapper; + } + + @Override + public String getName() { + return this.name; + } + + @Override + public String getDescription() { + return this.description; + } + + @Override + public String getInputTypeSchema() { + return this.inputTypeSchema; + } + + @Override + public String call(String functionArguments) { + + // Convert the tool calls JSON arguments into a Java function request object. + I request = fromJson(functionArguments, inputType); + + // extend conversation with function response. + return this.andThen(this.responseConverter).apply(request); + } + + private T fromJson(String json, Class targetClass) { + try { + return this.objectMapper.readValue(json, targetClass); + } + catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((inputType == null) ? 0 : inputType.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AbstractFunctionCallback other = (AbstractFunctionCallback) obj; + if (name == null) { + if (other.name != null) + return false; + } + else if (!name.equals(other.name)) + return false; + if (description == null) { + if (other.description != null) + return false; + } + else if (!description.equals(other.description)) + return false; + if (inputType == null) { + if (other.inputType != null) + return false; + } + else if (!inputType.equals(other.inputType)) + return false; + return true; + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallback.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallback.java new file mode 100644 index 000000000..d644d517a --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallback.java @@ -0,0 +1,53 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.model.function; + +/** + * Represents a model function call handler. Implementations are registered with the + * Models and called on prompts that trigger the function call. + * + * @author Christian Tzolov + */ +public interface FunctionCallback { + + /** + * @return Returns the Function name. Unique within the model. + */ + public String getName(); + + /** + * @return Returns the function description. This description is used by the model do + * decide if the function should be called or not. + */ + public String getDescription(); + + /** + * @return Returns the JSON schema of the function input type. + */ + public String getInputTypeSchema(); + + /** + * Called when a model detects and triggers a function call. The model is responsible + * to pass the function arguments in the pre-configured JSON schema format. + * @param functionInput JSON string with the function arguments to be passed to the + * function. The arguments are defined as JSON schema usually registered with the the + * model. + * @return String containing the function call response. + */ + public String call(String functionInput); + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackContext.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackContext.java new file mode 100644 index 000000000..dd5b0ee7c --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackContext.java @@ -0,0 +1,124 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.iocoder.yudao.framework.ai.model.function; + +import com.fasterxml.jackson.annotation.JsonClassDescription; +import org.springframework.beans.BeansException; +import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; +import org.springframework.cloud.function.context.config.FunctionContextUtils; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.annotation.Description; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; +import org.springframework.util.StringUtils; + +import java.lang.reflect.Type; +import java.util.function.Function; + +/** + * A Spring {@link ApplicationContextAware} implementation that provides a way to retrieve + * a {@link Function} from the Spring context and wrap it into a {@link FunctionCallback}. + * + * The name of the function is determined by the bean name. + * + * The description of the function is determined by the following rules: + *

    + *
  • Provided as a default description
  • + *
  • Provided as a {@code @Description} annotation on the bean
  • + *
  • Provided as a {@code @JsonClassDescription} annotation on the input class
  • + *
+ * + * @author Christian Tzolov + * @author Christopher Smith + */ +public class FunctionCallbackContext implements ApplicationContextAware { + + private GenericApplicationContext applicationContext; + + private FunctionCallbackWrapper.Builder.SchemaType schemaType = FunctionCallbackWrapper.Builder.SchemaType.JSON_SCHEMA; + + public void setSchemaType(FunctionCallbackWrapper.Builder.SchemaType schemaType) { + this.schemaType = schemaType; + } + + @Override + public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException { + this.applicationContext = (GenericApplicationContext) applicationContext; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public FunctionCallback getFunctionCallback(@NonNull String beanName, @Nullable String defaultDescription) { + + Type beanType = FunctionContextUtils.findType(this.applicationContext.getBeanFactory(), beanName); + + if (beanType == null) { + throw new IllegalArgumentException( + "Functional bean with name: " + beanName + " does not exist in the context."); + } + + if (!Function.class.isAssignableFrom(FunctionTypeUtils.getRawType(beanType))) { + throw new IllegalArgumentException( + "Function call Bean must be of type Function. Found: " + beanType.getTypeName()); + } + + Type functionInputType = TypeResolverHelper.getFunctionArgumentType(beanType, 0); + + Class functionInputClass = FunctionTypeUtils.getRawType(functionInputType); + String functionName = beanName; + String functionDescription = defaultDescription; + + if (!StringUtils.hasText(functionDescription)) { + // Look for a Description annotation on the bean + Description descriptionAnnotation = applicationContext.findAnnotationOnBean(beanName, Description.class); + + if (descriptionAnnotation != null) { + functionDescription = descriptionAnnotation.value(); + } + + if (!StringUtils.hasText(functionDescription)) { + // Look for a JsonClassDescription annotation on the input class + JsonClassDescription jsonClassDescriptionAnnotation = functionInputClass + .getAnnotation(JsonClassDescription.class); + if (jsonClassDescriptionAnnotation != null) { + functionDescription = jsonClassDescriptionAnnotation.value(); + } + } + + if (!StringUtils.hasText(functionDescription)) { + throw new IllegalStateException("Could not determine function description." + + "Please provide a description either as a default parameter, via @Description annotation on the bean " + + "or @JsonClassDescription annotation on the input class."); + } + } + + Object bean = this.applicationContext.getBean(beanName); + + if (bean instanceof Function function) { + return FunctionCallbackWrapper.builder(function) + .withName(functionName) + .withSchemaType(this.schemaType) + .withDescription(functionDescription) + .withInputType(functionInputClass) + .build(); + } + else { + throw new IllegalArgumentException("Bean must be of type Function"); + } + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackWrapper.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackWrapper.java new file mode 100644 index 000000000..d82412125 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackWrapper.java @@ -0,0 +1,140 @@ +package cn.iocoder.yudao.framework.ai.model.function; + +import cn.iocoder.yudao.framework.ai.model.ModelOptionsUtils; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.util.Assert; + +import java.util.function.Function; + +/** + * Note that the underlying function is responsible for converting the output into format + * that can be consumed by the Model. The default implementation converts the output into + * String before sending it to the Model. Provide a custom function responseConverter + * implementation to override this. + * + */ +public class FunctionCallbackWrapper extends AbstractFunctionCallback { + + private final Function function; + + private FunctionCallbackWrapper(String name, String description, String inputTypeSchema, Class inputType, + Function responseConverter, Function function) { + super(name, description, inputTypeSchema, inputType, responseConverter, + new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)); + Assert.notNull(function, "Function must not be null"); + this.function = function; + } + + @SuppressWarnings("unchecked") + private static Class resolveInputType(Function function) { + return (Class) TypeResolverHelper.getFunctionInputClass((Class>) function.getClass()); + } + + @Override + public O apply(I input) { + return this.function.apply(input); + } + + public static Builder builder(Function function) { + return new Builder<>(function); + } + + public static class Builder { + + public enum SchemaType { + + JSON_SCHEMA, OPEN_API_SCHEMA + + } + + private String name; + + private String description; + + private Class inputType; + + private final Function function; + + private SchemaType schemaType = SchemaType.JSON_SCHEMA; + + public Builder(Function function) { + Assert.notNull(function, "Function must not be null"); + this.function = function; + } + + // By default the response is converted to a JSON string. + private Function responseConverter = (response) -> ModelOptionsUtils.toJsonString(response); + + private String inputTypeSchema; + + private ObjectMapper objectMapper = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + public Builder withName(String name) { + Assert.hasText(name, "Name must not be empty"); + this.name = name; + return this; + } + + public Builder withDescription(String description) { + Assert.hasText(description, "Description must not be empty"); + this.description = description; + return this; + } + + @SuppressWarnings("unchecked") + public Builder withInputType(Class inputType) { + this.inputType = (Class) inputType; + return this; + } + + public Builder withResponseConverter(Function responseConverter) { + Assert.notNull(responseConverter, "ResponseConverter must not be null"); + this.responseConverter = responseConverter; + return this; + } + + public Builder withInputTypeSchema(String inputTypeSchema) { + Assert.hasText(inputTypeSchema, "InputTypeSchema must not be empty"); + this.inputTypeSchema = inputTypeSchema; + return this; + } + + public Builder withObjectMapper(ObjectMapper objectMapper) { + Assert.notNull(objectMapper, "ObjectMapper must not be null"); + this.objectMapper = objectMapper; + return this; + } + + public Builder withSchemaType(SchemaType schemaType) { + Assert.notNull(schemaType, "SchemaType must not be null"); + this.schemaType = schemaType; + return this; + } + + public FunctionCallbackWrapper build() { + + Assert.hasText(this.name, "Name must not be empty"); + Assert.hasText(this.description, "Description must not be empty"); + // Assert.notNull(this.inputType, "InputType must not be null"); + Assert.notNull(this.function, "Function must not be null"); + Assert.notNull(this.responseConverter, "ResponseConverter must not be null"); + Assert.notNull(this.objectMapper, "ObjectMapper must not be null"); + + if (this.inputType == null) { + this.inputType = resolveInputType(this.function); + } + + if (this.inputTypeSchema == null) { + boolean upperCaseTypeValues = this.schemaType == SchemaType.OPEN_API_SCHEMA; + this.inputTypeSchema = ModelOptionsUtils.getJsonSchema(this.inputType, upperCaseTypeValues); + } + + return new FunctionCallbackWrapper<>(this.name, this.description, this.inputTypeSchema, this.inputType, + this.responseConverter, this.function); + } + + } + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallingOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallingOptions.java new file mode 100644 index 000000000..fdb42d6a4 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallingOptions.java @@ -0,0 +1,66 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.model.function; + +import java.util.List; +import java.util.Set; + +/** + * @author Christian Tzolov + */ +public interface FunctionCallingOptions { + + /** + * Function Callbacks to be registered with the ChatClient. For Prompt Options the + * functionCallbacks are automatically enabled for the duration of the prompt + * execution. For Default Options the FunctionCallbacks are registered but disabled by + * default. You have to use "functions" property to list the function names from the + * ChatClient registry to be used in the chat completion requests. + * @return Return the Function Callbacks to be registered with the ChatClient. + */ + List getFunctionCallbacks(); + + /** + * Set the Function Callbacks to be registered with the ChatClient. + * @param functionCallbacks the Function Callbacks to be registered with the + * ChatClient. + */ + void setFunctionCallbacks(List functionCallbacks); + + /** + * @return List of function names from the ChatClient registry to be used in the next + * chat completion requests. + */ + Set getFunctions(); + + /** + * Set the list of function names from the ChatClient registry to be used in the next + * chat completion requests. + * @param functions the list of function names from the ChatClient registry to be used + * in the next chat completion requests. + */ + void setFunctions(Set functions); + + /** + * @return Returns FunctionCallingOptionsBuilder to create a new instance of + * FunctionCallingOptions. + */ + public static FunctionCallingOptionsBuilder builder() { + return new FunctionCallingOptionsBuilder(); + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallingOptionsBuilder.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallingOptionsBuilder.java new file mode 100644 index 000000000..4fc258b4a --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallingOptionsBuilder.java @@ -0,0 +1,150 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.model.function; + +import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; +import org.springframework.util.Assert; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Builder for {@link FunctionCallingOptions}. Using the {@link FunctionCallingOptions} + * permits options portability between different AI providers that support + * function-calling. + * + * @author Christian Tzolov + * @since 0.8.1 + */ +public class FunctionCallingOptionsBuilder { + + private final PortableFunctionCallingOptions options; + + public FunctionCallingOptionsBuilder() { + this.options = new PortableFunctionCallingOptions(); + } + + public FunctionCallingOptionsBuilder withFunctionCallbacks(List functionCallbacks) { + this.options.setFunctionCallbacks(functionCallbacks); + return this; + } + + public FunctionCallingOptionsBuilder withFunctionCallback(FunctionCallback functionCallback) { + Assert.notNull(functionCallback, "FunctionCallback must not be null"); + this.options.getFunctionCallbacks().add(functionCallback); + return this; + } + + public FunctionCallingOptionsBuilder withFunctions(Set functions) { + this.options.setFunctions(functions); + return this; + } + + public FunctionCallingOptionsBuilder withFunction(String function) { + Assert.notNull(function, "Function must not be null"); + this.options.getFunctions().add(function); + return this; + } + + public FunctionCallingOptionsBuilder withTemperature(Float temperature) { + this.options.setTemperature(temperature); + return this; + } + + public FunctionCallingOptionsBuilder withTopP(Float topP) { + this.options.setTopP(topP); + return this; + } + + public FunctionCallingOptionsBuilder withTopK(Integer topK) { + this.options.setTopK(topK); + return this; + } + + public PortableFunctionCallingOptions build() { + return this.options; + } + + public static class PortableFunctionCallingOptions implements FunctionCallingOptions, ChatOptions { + + private List functionCallbacks = new ArrayList<>(); + + private Set functions = new HashSet<>(); + + private Float temperature; + + private Float topP; + + private Integer topK; + + @Override + public List getFunctionCallbacks() { + return this.functionCallbacks; + } + + @Override + public void setFunctionCallbacks(List functionCallbacks) { + Assert.notNull(functionCallbacks, "FunctionCallbacks must not be null"); + this.functionCallbacks = functionCallbacks; + } + + @Override + public Set getFunctions() { + return this.functions; + } + + @Override + public void setFunctions(Set functions) { + Assert.notNull(functions, "Functions must not be null"); + this.functions = functions; + } + + @Override + public Float getTemperature() { + return this.temperature; + } + + @Override + public void setTemperature(Float temperature) { + this.temperature = temperature; + } + + @Override + public Float getTopP() { + return this.topP; + } + + @Override + public void setTopP(Float topP) { + this.topP = topP; + } + + @Override + public Integer getTopK() { + return this.topK; + } + + @Override + public void setTopK(Integer topK) { + this.topK = topK; + } + + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/TypeResolverHelper.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/TypeResolverHelper.java new file mode 100644 index 000000000..e1c8c4932 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/TypeResolverHelper.java @@ -0,0 +1,87 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.model.function; + +import net.jodah.typetools.TypeResolver; + +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.function.Function; + +/** + * @author Christian Tzolov + */ +public class TypeResolverHelper { + + public static Class getFunctionInputClass(Class> functionClass) { + return getFunctionArgumentClass(functionClass, 0); + } + + public static Class getFunctionOutputClass(Class> functionClass) { + return getFunctionArgumentClass(functionClass, 1); + } + + public static Class getFunctionArgumentClass(Class> functionClass, int argumentIndex) { + Type type = TypeResolver.reify(Function.class, functionClass); + + var argumentType = type instanceof ParameterizedType + ? ((ParameterizedType) type).getActualTypeArguments()[argumentIndex] : Object.class; + + return toRawClass(argumentType); + } + + public static Type getFunctionInputType(Class> functionClass) { + return getFunctionArgumentType(functionClass, 0); + } + + public static Type getFunctionOutputType(Class> functionClass) { + return getFunctionArgumentType(functionClass, 1); + } + + public static Type getFunctionArgumentType(Class> functionClass, int argumentIndex) { + Type functionType = TypeResolver.reify(Function.class, functionClass); + return getFunctionArgumentType(functionType, argumentIndex); + } + + public static Type getFunctionArgumentType(Type functionType, int argumentIndex) { + var argumentType = functionType instanceof ParameterizedType + ? ((ParameterizedType) functionType).getActualTypeArguments()[argumentIndex] : Object.class; + + return argumentType; + } + + /** + * Effectively converts {@link Type} which could be {@link ParameterizedType} to raw + * Class (no generics). + * @param type actual {@link Type} instance + * @return instance of {@link Class} as raw representation of the provided + * {@link Type} + */ + public static Class toRawClass(Type type) { + return type != null + ? TypeResolver.resolveRawClass(type instanceof GenericArrayType ? type : TypeResolver.reify(type), null) + : null; + } + + // public static void main(String[] args) { + // Class> clazz = MockWeatherService.class; + // System.out.println(getFunctionInputType(clazz)); + + // } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/package-info.java new file mode 100644 index 000000000..d2cf8e37b --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/package-info.java @@ -0,0 +1,11 @@ +/** + * Provides a set of interfaces and classes for a generic API designed to interact with + * various AI models. This package includes interfaces for handling AI model calls, + * requests, responses, results, and associated metadata. It is designed to offer a + * flexible and adaptable framework for interacting with different types of AI models, + * abstracting the complexities involved in model invocation and result processing. The + * use of generics enhances the API's capability to work with a wide range of models, + * ensuring a broad applicability across diverse AI scenarios. + * + */ +package cn.iocoder.yudao.framework.ai.model; \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java new file mode 100644 index 000000000..de43c748b --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java @@ -0,0 +1,5 @@ +/** + * author: fansili + * time: 2024/3/12 20:29 + */ +package cn.iocoder.yudao.framework.ai; \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/AbstractConversionServiceOutputParser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/AbstractConversionServiceOutputParser.java new file mode 100644 index 000000000..cee9fff42 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/AbstractConversionServiceOutputParser.java @@ -0,0 +1,42 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.parser; + +import org.springframework.core.convert.support.DefaultConversionService; + +/** + * Abstract {@link OutputParser} implementation that uses a pre-configured + * {@link DefaultConversionService} to convert the LLM output into the desired type + * format. + * + * @param Specifies the desired response type. + * @author Mark Pollack + * @author Christian Tzolov + */ +public abstract class AbstractConversionServiceOutputParser implements OutputParser { + + private final DefaultConversionService conversionService; + + public AbstractConversionServiceOutputParser(DefaultConversionService conversionService) { + this.conversionService = conversionService; + } + + public DefaultConversionService getConversionService() { + return conversionService; + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/AbstractMessageConverterOutputParser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/AbstractMessageConverterOutputParser.java new file mode 100644 index 000000000..abe5005ab --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/AbstractMessageConverterOutputParser.java @@ -0,0 +1,41 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.parser; + +import org.springframework.messaging.converter.MessageConverter; + +/** + * Abstract {@link OutputParser} implementation that uses a pre-configured + * {@link MessageConverter} to convert the LLM output into the desired type format. + * + * @param Specifies the desired response type. + * @author Mark Pollack + * @author Christian Tzolov + */ +public abstract class AbstractMessageConverterOutputParser implements OutputParser { + + private MessageConverter messageConverter; + + public AbstractMessageConverterOutputParser(MessageConverter messageConverter) { + this.messageConverter = messageConverter; + } + + public MessageConverter getMessageConverter() { + return this.messageConverter; + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/BeanOutputParser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/BeanOutputParser.java new file mode 100644 index 000000000..4eb08ce29 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/BeanOutputParser.java @@ -0,0 +1,166 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.parser; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.util.DefaultIndenter; +import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectWriter; +import com.github.victools.jsonschema.generator.SchemaGenerator; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfig; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfigBuilder; +import com.github.victools.jsonschema.module.jackson.JacksonModule; + +import java.util.Map; +import java.util.Objects; + +import static com.github.victools.jsonschema.generator.OptionPreset.PLAIN_JSON; +import static com.github.victools.jsonschema.generator.SchemaVersion.DRAFT_2020_12; + +/** + * An implementation of {@link OutputParser} that transforms the LLM output to a specific + * object type using JSON schema. This parser works by generating a JSON schema based on a + * given Java class, which is then used to validate and transform the LLM output into the + * desired type. + * + * @param The target type to which the output will be converted. + * @author Mark Pollack + * @author Christian Tzolov + * @author Sebastian Ullrich + * @author Kirk Lund + */ +public class BeanOutputParser implements OutputParser { + + /** Holds the generated JSON schema for the target type. */ + private String jsonSchema; + + /** The Java class representing the target type. */ + @SuppressWarnings({ "FieldMayBeFinal", "rawtypes" }) + private Class clazz; + + /** The object mapper used for deserialization and other JSON operations. */ + @SuppressWarnings("FieldMayBeFinal") + private ObjectMapper objectMapper; + + /** + * Constructor to initialize with the target type's class. + * @param clazz The target type's class. + */ + public BeanOutputParser(Class clazz) { + this(clazz, null); + } + + /** + * Constructor to initialize with the target type's class, a custom object mapper, and + * a line endings normalizer to ensure consistent line endings on any platform. + * @param clazz The target type's class. + * @param objectMapper Custom object mapper for JSON operations. endings. + */ + public BeanOutputParser(Class clazz, ObjectMapper objectMapper) { + Objects.requireNonNull(clazz, "Java Class cannot be null;"); + this.clazz = clazz; + this.objectMapper = objectMapper != null ? objectMapper : getObjectMapper(); + generateSchema(); + } + + /** + * Generates the JSON schema for the target type. + */ + private void generateSchema() { + JacksonModule jacksonModule = new JacksonModule(); + SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(DRAFT_2020_12, PLAIN_JSON) + .with(jacksonModule); + SchemaGeneratorConfig config = configBuilder.build(); + SchemaGenerator generator = new SchemaGenerator(config); + JsonNode jsonNode = generator.generateSchema(this.clazz); + ObjectWriter objectWriter = new ObjectMapper() + .writer(new DefaultPrettyPrinter().withObjectIndenter(new DefaultIndenter().withLinefeed("\n"))); + try { + this.jsonSchema = objectWriter.writeValueAsString(jsonNode); + } + catch (JsonProcessingException e) { + throw new RuntimeException("Could not pretty print json schema for " + this.clazz, e); + } + } + + @Override + /** + * Parses the given text to transform it to the desired target type. + * @param text The LLM output in string format. + * @return The parsed output in the desired target type. + */ + public T parse(String text) { + try { + // If the response is a JSON Schema, extract the properties and use them as + // the response. + text = this.jsonSchemaToInstance(text); + return (T) this.objectMapper.readValue(text, this.clazz); + } + catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + /** + * Converts a JSON Schema to an instance based on a given text. + * @param text The JSON Schema in string format. + * @return The JSON instance generated from the JSON Schema, or the original text if + * the input is not a JSON Schema. + */ + private String jsonSchemaToInstance(String text) { + try { + Map map = this.objectMapper.readValue(text, Map.class); + if (map.containsKey("$schema")) { + return this.objectMapper.writeValueAsString(map.get("properties")); + } + } + catch (Exception e) { + } + return text; + } + + /** + * Configures and returns an object mapper for JSON operations. + * @return Configured object mapper. + */ + protected ObjectMapper getObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + return mapper; + } + + /** + * Provides the expected format of the response, instructing that it should adhere to + * the generated JSON schema. + * @return The instruction format string. + */ + @Override + public String getFormat() { + String template = """ + Your response should be in JSON format. + Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation. + Do not include markdown code blocks in your response. + Here is the JSON Schema instance your output must adhere to: + ```%s``` + """; + return String.format(template, this.jsonSchema); + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/FormatProvider.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/FormatProvider.java new file mode 100644 index 000000000..53d001729 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/FormatProvider.java @@ -0,0 +1,33 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.parser; + +/** + * Implementations of this interface provides instructions for how the output of a + * language generative should be formatted. + * + * @author Mark Pollack + */ +public interface FormatProvider { + + /** + * @return Returns a string containing instructions for how the output of a language + * generative should be formatted. + */ + String getFormat(); + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/ListOutputParser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/ListOutputParser.java new file mode 100644 index 000000000..1eb936eac --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/ListOutputParser.java @@ -0,0 +1,48 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.iocoder.yudao.framework.ai.parser; + +import org.springframework.core.convert.support.DefaultConversionService; + +import java.util.List; + +/** + * {@link OutputParser} implementation that uses a {@link DefaultConversionService} to + * convert the LLM output into a {@link List} instance. + * + * @author Mark Pollack + * @author Christian Tzolov + */ +public class ListOutputParser extends AbstractConversionServiceOutputParser> { + + public ListOutputParser(DefaultConversionService defaultConversionService) { + super(defaultConversionService); + } + + @Override + public String getFormat() { + return """ + Your response should be a list of comma separated values + eg: `foo, bar, baz` + """; + } + + @Override + public List parse(String text) { + return getConversionService().convert(text, List.class); + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/MapOutputParser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/MapOutputParser.java new file mode 100644 index 000000000..3aa217f2a --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/MapOutputParser.java @@ -0,0 +1,57 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.parser; + +import org.springframework.messaging.Message; +import org.springframework.messaging.converter.MappingJackson2MessageConverter; +import org.springframework.messaging.support.MessageBuilder; + +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +/** + * {@link OutputParser} implementation that uses a pre-configured + * {@link MappingJackson2MessageConverter} to convert the LLM output into a + * java.util.Map<String, Object> instance. + * + * @author Mark Pollack + * @author Christian Tzolov + */ +public class MapOutputParser extends AbstractMessageConverterOutputParser> { + + public MapOutputParser() { + super(new MappingJackson2MessageConverter()); + } + + @Override + public Map parse(String text) { + Message message = MessageBuilder.withPayload(text.getBytes(StandardCharsets.UTF_8)).build(); + return (Map) getMessageConverter().fromMessage(message, HashMap.class); + } + + @Override + public String getFormat() { + String raw = """ + Your response should be in JSON format. + The data structure for the JSON should match this Java class: %s + Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation. + """; + return String.format(raw, "java.util.HashMap"); + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/OutputParser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/OutputParser.java new file mode 100644 index 000000000..1543532b3 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/OutputParser.java @@ -0,0 +1,30 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.parser; + +/** + * Converts the (raw) LLM output into a structured responses of type. The + * {@link FormatProvider#getFormat()} method should provide the LLM prompt description of + * the desired format. + * + * @param Specifies the desired response type. + * @author Mark Pollack + * @author Christian Tzolov + */ +public interface OutputParser extends Parser, FormatProvider { + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/Parser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/Parser.java new file mode 100644 index 000000000..6016ee51c --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/Parser.java @@ -0,0 +1,24 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.parser; + +@FunctionalInterface +public interface Parser { + + T parse(String text); + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/README.md b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/README.md new file mode 100644 index 000000000..740e330f2 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/README.md @@ -0,0 +1,12 @@ +# Output Parsing + +* [Documentation](https://docs.spring.io/spring-ai/reference/concepts.html#_output_parsing) +* [Usage examples](https://github.com/spring-projects/spring-ai/blob/main/spring-ai-openai/src/test/java/org/springframework/ai/openai/client/ClientIT.java) + +The output of AI models traditionally arrives as a java.util.String, even if you ask for the reply to be in JSON. It may be the correct JSON, but it isn’t a JSON data structure. It is just a string. Also, asking "for JSON" as part of the prompt isn’t 100% accurate. + +This intricacy has led to the emergence of a specialized field involving the creation of prompts to yield the intended output, followed by parsing the resulting simple string into a usable data structure for application integration. + +Output parsing employs meticulously crafted prompts, often necessitating multiple interactions with the model to achieve the desired formatting. + +This challenge has prompted OpenAI to introduce 'OpenAI Functions' as a means to specify the desired output format from the model precisely. From 1828d1953ab15beb501720e2a066f7ce7d8f8069 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 12 Mar 2024 21:44:07 +0800 Subject: [PATCH 007/684] =?UTF-8?q?=E8=BF=81=E7=A7=BB=E6=96=87=E5=BF=83?= =?UTF-8?q?=E4=B8=80=E8=A8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ai/chatyiyan/YiYanApi.java | 97 ++++++++++ .../ai/chatyiyan/YiYanChatClient.java | 137 ++++++++++++++ .../ai/chatyiyan/YiYanChatModel.java | 35 ++++ .../ai/chatyiyan/api/YiYanAuthRes.java | 48 +++++ .../ai/chatyiyan/api/YiYanChatCompletion.java | 91 +++++++++ .../api/YiYanChatCompletionMessage.java | 8 + .../api/YiYanChatCompletionRequest.java | 176 ++++++++++++++++++ .../exception/YiYanApiException.java | 16 ++ 8 files changed, 608 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanApi.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatModel.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanAuthRes.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletion.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletionMessage.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletionRequest.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/exception/YiYanApiException.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanApi.java new file mode 100644 index 000000000..d22e8ffc9 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanApi.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.framework.ai.chatyiyan; + +import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanAuthRes; +import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletion; +import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletionRequest; +import cn.iocoder.yudao.framework.ai.chatyiyan.exception.YiYanApiException; +import lombok.Data; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.ResponseEntity; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/** + * 文心一言 + *

+ * author: fansili + * time: 2024/3/8 21:47 + */ +@Data +public class YiYanApi { + + private static final String DEFAULT_BASE_URL = "https://aip.baidubce.com"; + + private static final String AUTH_2_TOKEN_URI = "/oauth/2.0/token"; + + public static final String DEFAULT_CHAT_MODEL = "ERNIE 4.0"; + + // 获取access_token流程 https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Ilkkrb0i5 + private String appKey; + private String secretKey; + private String token; + // token刷新时间(秒) + private int refreshTokenSecondTime; + // 发送请求 webClient + private final WebClient webClient; + // 使用的模型 + private YiYanChatModel useChatModel; + + public YiYanApi(String appKey, String secretKey, YiYanChatModel useChatModel, int refreshTokenSecondTime) { + this.appKey = appKey; + this.secretKey = secretKey; + this.useChatModel = useChatModel; + this.refreshTokenSecondTime = refreshTokenSecondTime; + + this.webClient = WebClient.builder() + .baseUrl(DEFAULT_BASE_URL) + .build(); + + token = getToken(); + } + + private String getToken() { + // 文档地址: https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Ilkkrb0i5 + ResponseEntity response = this.webClient.post() + .uri(uriBuilder -> uriBuilder.path(AUTH_2_TOKEN_URI) + .queryParam("grant_type", "client_credentials") + .queryParam("client_id", appKey) + .queryParam("client_secret", secretKey) + .build() + ) + .retrieve() + .toEntity(YiYanAuthRes.class) + .block(); + // 检查请求状态 + if (HttpStatusCode.valueOf(200) != response.getStatusCode()) { + throw new YiYanApiException("一言认证失败! api:https://aip.baidubce.com/oauth/2.0/token 请检查 client_id、client_secret 是否正确!"); + } + YiYanAuthRes body = response.getBody(); + return body.getAccess_token(); + } + + public ResponseEntity chatCompletionEntity(YiYanChatCompletionRequest request) { + // TODO: 2024/3/10 小范 这里错误信息返回的结构不一样 +// {"error_code":17,"error_msg":"Open api daily request limit reached"} + return this.webClient.post() + .uri(uriBuilder + -> uriBuilder.path(useChatModel.getUri()) + .queryParam("access_token", token) + .build()) + .body(Mono.just(request), YiYanChatCompletionRequest.class) + .retrieve() + .toEntity(YiYanChatCompletion.class) + .block(); + } + + public Flux chatCompletionStream(YiYanChatCompletionRequest request) { + return this.webClient.post() + .uri(uriBuilder + -> uriBuilder.path(useChatModel.getUri()) + .queryParam("access_token", token) + .build()) + .body(Mono.just(request), YiYanChatCompletionRequest.class) + .retrieve() + .bodyToFlux(YiYanChatCompletion.class); + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java new file mode 100644 index 000000000..fb7f155b4 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java @@ -0,0 +1,137 @@ +package cn.iocoder.yudao.framework.ai.chatyiyan; + +import cn.iocoder.yudao.framework.ai.chat.ChatClient; +import cn.iocoder.yudao.framework.ai.chat.ChatResponse; +import cn.iocoder.yudao.framework.ai.chat.Generation; +import cn.iocoder.yudao.framework.ai.chat.StreamingChatClient; +import cn.iocoder.yudao.framework.ai.chat.messages.Message; +import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; +import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletion; +import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletionMessage; +import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletionRequest; +import cn.iocoder.yudao.framework.ai.chatyiyan.exception.YiYanApiException; +import cn.iocoder.yudao.framework.ai.model.function.AbstractFunctionCallSupport; +import cn.iocoder.yudao.framework.ai.model.function.FunctionCallbackContext; +import lombok.extern.slf4j.Slf4j; + +import org.springframework.http.ResponseEntity; +import org.springframework.retry.RetryCallback; +import org.springframework.retry.RetryContext; +import org.springframework.retry.RetryListener; +import org.springframework.retry.support.RetryTemplate; +import reactor.core.publisher.Flux; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; + +/** + * 文心一言 + * + * author: fansili + * time: 2024/3/8 19:11 + */ +@Slf4j +public class YiYanChatClient + extends AbstractFunctionCallSupport> + implements ChatClient, StreamingChatClient { + + private YiYanApi yiYanApi; + + public YiYanChatClient(YiYanApi yiYanApi) { + super(new FunctionCallbackContext()); + this.yiYanApi = yiYanApi; + } + + public final RetryTemplate retryTemplate = RetryTemplate.builder() + // 最大重试次数 10 + .maxAttempts(10) + .retryOn(YiYanApiException.class) + // 最大重试5次,第一次间隔3000ms,第二次3000ms * 2,第三次3000ms * 3,以此类推,最大间隔3 * 60000ms + .exponentialBackoff(Duration.ofMillis(3000), 2, Duration.ofMillis(3 * 60000)) + .withListener(new RetryListener() { + @Override + public void onError(RetryContext context, + RetryCallback callback, Throwable throwable) { + log.warn("重试异常:" + context.getRetryCount(), throwable); + }; + }) + .build(); + + @Override + public String call(String message) { + return ChatClient.super.call(message); + } + + @Override + public ChatResponse call(Prompt prompt) { + return this.retryTemplate.execute(ctx -> { + // ctx 会有重试的信息 + // 创建 request 请求,stream模式需要供应商支持 + YiYanChatCompletionRequest request = this.createRequest(prompt, false); + // 调用 callWithFunctionSupport 发送请求 + ResponseEntity response = this.callWithFunctionSupport(request); + // 获取结果封装 ChatResponse + YiYanChatCompletion chatCompletion = response.getBody(); + return new ChatResponse(List.of(new Generation(chatCompletion.getResult()))); + }); + } + + private YiYanChatCompletionRequest createRequest(Prompt prompt, boolean stream) { + List messages = new ArrayList<>(); + List instructions = prompt.getInstructions(); + for (Message instruction : instructions) { + YiYanChatCompletionRequest.Message message = new YiYanChatCompletionRequest.Message(); + message.setContent(instruction.getContent()); + message.setRole(instruction.getMessageType().getValue()); + messages.add(message); + } + YiYanChatCompletionRequest request = new YiYanChatCompletionRequest(messages); + request.setStream(stream); + return request; + } + + @Override + public Flux stream(Prompt prompt) { + // ctx 会有重试的信息 + // 创建 request 请求,stream模式需要供应商支持 + YiYanChatCompletionRequest request = this.createRequest(prompt, true); + // 调用 callWithFunctionSupport 发送请求 + Flux response = this.yiYanApi.chatCompletionStream(request); +// response.subscribe(new Consumer() { +// @Override +// public void accept(YiYanChatCompletion chatCompletion) { +// // {"id":"as-p0nfjuuasg","object":"chat.completion","created":1710033402,"sentence_id":0,"is_end":false,"is_truncated":false,"result":"编程语","need_clear_history":false,"finish_reason":"normal","usage":{"prompt_tokens":5,"completion_tokens":0,"total_tokens":5}} +// System.err.println(chatCompletion); +// } +// }); + return response.map(res -> { + return new ChatResponse(List.of(new Generation(res.getResult()))); + }); + } + + @Override + protected YiYanChatCompletionRequest doCreateToolResponseRequest(YiYanChatCompletionRequest previousRequest, YiYanChatCompletionMessage responseMessage, List conversationHistory) { + return null; + } + + @Override + protected List doGetUserMessages(YiYanChatCompletionRequest request) { + return null; + } + + @Override + protected YiYanChatCompletionMessage doGetToolResponseMessage(ResponseEntity response) { + return null; + } + + @Override + protected ResponseEntity doChatCompletion(YiYanChatCompletionRequest request) { + return yiYanApi.chatCompletionEntity(request); + } + + @Override + protected boolean isToolFunctionCall(ResponseEntity response) { + return false; + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatModel.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatModel.java new file mode 100644 index 000000000..77675430e --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatModel.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.framework.ai.chatyiyan; + +import lombok.Getter; + +/** + * 一言模型 + * + * 可参考百度文档:https://cloud.baidu.com/doc/WENXINWORKSHOP/s/clntwmv7t + * + * author: fansili + * time: 2024/3/9 12:01 + */ +@Getter +public enum YiYanChatModel { + + ERNIE4_0("ERNIE 4.0", "/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions_pro"), + ERNIE4_3_5_8K("ERNIE-3.5-8K", "/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions"), + ERNIE4_3_5_8K_0205("ERNIE-3.5-8K-0205", "/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-3.5-8k-0205"), + + ERNIE4_3_5_8K_1222("ERNIE-3.5-8K-1222", "/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-3.5-8k-1222"), + ERNIE4_BOT_8K("ERNIE-Bot-8K", "/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie_bot_8k"), + ERNIE4_3_5_4K_0205("ERNIE-3.5-4K-0205", "/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-3.5-4k-0205"), + + ; + + YiYanChatModel(String value, String uri) { + this.value = value; + this.uri = uri; + } + + private String value; + + private String uri; + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanAuthRes.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanAuthRes.java new file mode 100644 index 000000000..e828858c2 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanAuthRes.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.framework.ai.chatyiyan.api; + +import lombok.Data; + +/** + * 一言 获取access_token + * + * author: fansili + * time: 2024/3/10 08:51 + */ +@Data +public class YiYanAuthRes { + + /** + * 访问凭证 + */ + private String access_token; + /** + * 有效期,Access Token的有效期。 + * 说明:单位是秒,有效期30天 + */ + private int expires_in; + /** + * 错误码,说明:响应失败时返回该字段,成功时不返回 + */ + private String error; + /** + * 错误描述信息,帮助理解和解决发生的错误 + * 说明:响应失败时返回该字段,成功时不返回 + */ + private String error_description; + /** + * 暂时未使用,可忽略 + */ + private String session_key; + /** + * 暂时未使用,可忽略 + */ + private String refresh_token; + /** + * 暂时未使用,可忽略 + */ + private String scope; + /** + * 暂时未使用,可忽略 + */ + private String session_secret; +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletion.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletion.java new file mode 100644 index 000000000..b995da82a --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletion.java @@ -0,0 +1,91 @@ +package cn.iocoder.yudao.framework.ai.chatyiyan.api; + +import lombok.Data; + +/** + * 聊天返回 + * 百度链接: https://cloud.baidu.com/doc/WENXINWORKSHOP/s/clntwmv7t + * + * author: fansili + * time: 2024/3/9 10:34 + */ +@Data +public class YiYanChatCompletion { + + /** + * 本轮对话的id + */ + private String id; + /** + * 回包类型,chat.completion:多轮对话返回 + */ + private String object; + /** + * 时间戳 + */ + private int created; + /** + * 表示当前子句的序号。只有在流式接口模式下会返回该字段 + */ + private int sentence_id; + /** + * 表示当前子句是否是最后一句。只有在流式接口模式下会返回该字段 + */ + private boolean is_end; + /** + * 当前生成的结果是否被截断 + */ + private boolean is_truncated; + /** + * 输出内容标识,说明: + * · normal:输出内容完全由大模型生成,未触发截断、替换 + * · stop:输出结果命中入参stop中指定的字段后被截断 + * · length:达到了最大的token数,根据EB返回结果is_truncated来截断 + * · content_filter:输出内容被截断、兜底、替换为**等 + */ + private String finish_reason; + /** + * 搜索数据,当请求参数enable_citation为true并且触发搜索时,会返回该字段 + */ + private String search_info; + /** + * 对话返回结果 + */ + private String result; + /** + * 表示用户输入是否存在安全,是否关闭当前会话,清理历史会话信息 + * true:是,表示用户输入存在安全风险,建议关闭当前会话,清理历史会话信息 + * false:否,表示用户输入无安全风险 + */ + private boolean need_clear_history; + /** + * 说明: + * · 0:正常返回 + * · 其他:非正常 + */ + private int flag; + /** + * 当need_clear_history为true时,此字段会告知第几轮对话有敏感信息,如果是当前问题,ban_round=-1 + */ + private int ban_round; + /** + * token统计信息 + */ + private Usage usage; + + @Data + public static class Usage { + /** + * 问题tokens数 + */ + private int prompt_tokens; + /** + * 回答tokens数 + */ + private int completion_tokens; + /** + * tokens总数 + */ + private int total_tokens; + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletionMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletionMessage.java new file mode 100644 index 000000000..ce6259c76 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletionMessage.java @@ -0,0 +1,8 @@ +package cn.iocoder.yudao.framework.ai.chatyiyan.api; + +/** + * author: fansili + * time: 2024/3/9 10:37 + */ +public class YiYanChatCompletionMessage { +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletionRequest.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletionRequest.java new file mode 100644 index 000000000..8c80d55f7 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletionRequest.java @@ -0,0 +1,176 @@ +package cn.iocoder.yudao.framework.ai.chatyiyan.api; + +import lombok.Data; + +import java.util.List; + +/** + * 一言 Completion req + * + * 百度千帆文档:https://cloud.baidu.com/doc/WENXINWORKSHOP/s/jlil56u11 + * + * author: fansili + * time: 2024/3/9 10:34 + */ +@Data +public class YiYanChatCompletionRequest { + + public YiYanChatCompletionRequest(List messages) { + this.messages = messages; + } + + /** + * 聊天上下文信息。 + * 必填:是 + */ + private List messages; + /** + * 一个可触发函数的描述列表,说明: + * (1)支持的function数量无限制 + * (2)长度限制,最后一个message的content长度(即此轮对话的问题)、functions和system字段总内容不能超过20480 个字符,且不能超过5120 tokens + * 必填:否 + */ + private List functions; + /** + * 说明: + * (1)较高的数值会使输出更加随机,而较低的数值会使其更加集中和确定 + * (2)默认0.8,范围 (0, 1.0],不能为0 + * 必填:否 + */ + private String temperature; + /** + * 说明: + * (1)影响输出文本的多样性,取值越大,生成文本的多样性越强 + * (2)默认0.8,取值范围 [0, 1.0] + * 必填:否 + */ + private String top_p; + /** + * 通过对已生成的token增加惩罚,减少重复生成的现象。说明: + * (1)值越大表示惩罚越大 + * (2)默认1.0,取值范围:[1.0, 2.0] + * + * 必填:否 + */ + private String penalty_score; + /** + * 是否以流式接口的形式返回数据,默认false + * 必填:否 + */ + private Boolean stream; + /** + * 模型人设,主要用于人设设定,例如,你是xxx公司制作的AI助手,说明: + * (1)长度限制,最后一个message的content长度(即此轮对话的问题)、functions和system字段总内容不能超过20480 个字符,且不能超过5120 tokens + * (2)如果同时使用system和functions,可能暂无法保证使用效果,持续进行优化 + * 必填:否 + */ + private String system; + /** + * 生成停止标识,当模型生成结果以stop中某个元素结尾时,停止文本生成。说明: + * (1)每个元素长度不超过20字符 + * (2)最多4个元素 + * 必填:否 + */ + private String stop; + /** + * 是否强制关闭实时搜索功能,默认false,表示不关闭 + * 必填:否 + */ + private Boolean disable_search; + /** + * 是否开启上角标返回,说明: + * (1)开启后,有概率触发搜索溯源信息search_info,search_info内容见响应参数介绍 + * (2)默认false,不开启 + * 必填:否 + */ + private Boolean enable_citation; + /** + * 指定模型最大输出token数,范围[2, 2048] + * 必填:否 + */ + private Integer max_output_tokens; + /** + * 指定响应内容的格式,说明: + * (1)可选值: + * · json_object:以json格式返回,可能出现不满足效果情况 + * · text:以文本格式返回 + * (2)如果不填写参数response_format值,默认为text + * 必填:否 + */ + private String response_format; + /** + * 表示最终用户的唯一标识符 + * 必填:否 + */ + private String user_id; + /** + * 在函数调用场景下,提示大模型选择指定的函数(非强制),说明:指定的函数名必须在functions中存在 + * 必填:否 + */ + private String tool_choice; + + + @Data + public static class Message { + private String role; + + private String content; + } + + @Data + public static class ToolChoice { + /** + * 指定工具类型,function + * 必填: 是 + */ + private String type; + /** + * 指定要使用的函数 + * 必填: 是 + */ + private Function function; + /** + * 指定要使用的函数名 + * 必填: 是 + */ + private String name; + } + + @Data + public static class Function { + /** + * 函数名 + * 必填: 是 + */ + private String name; + /** + * 函数描述 + * 必填: 是 + */ + private String description; + /** + * 函数请求参数,说明: + * (1)JSON Schema 格式,参考JSON Schema描述 + * (2)如果函数没有请求参数,parameters值格式如下: + * {"type": "object","properties": {}} + * 必填: 是 + */ + private String parameters; + /** + * 函数响应参数,JSON Schema 格式,参考JSON Schema描述 + * 必填: 否 + */ + private String responses; + /** + * function调用的一些历史示例,说明: + * (1)可以提供正例(正常触发)和反例(无需触发)的example + * ·正例:从历史请求数据中获取 + * ·反例: + * 当role = user,不会触发请求的query + * 当role = assistant,有固定的格式。function_call的name为空,arguments是空对象:"{}",thought可以填固定的:"我不需要调用任何工具" + * (2)兼容之前的 List(example) 格式 + */ + private String examples; + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/exception/YiYanApiException.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/exception/YiYanApiException.java new file mode 100644 index 000000000..dbb8ed93a --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/exception/YiYanApiException.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.framework.ai.chatyiyan.exception; + +/** + * 一言 api 调用异常 + */ +public class YiYanApiException extends RuntimeException { + + public YiYanApiException(String message) { + super(message); + } + + public YiYanApiException(String message, Throwable cause) { + super(message, cause); + } + +} \ No newline at end of file From de32611794f0ec3282109dcc8d799b37ab8d3a7c Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 13 Mar 2024 20:51:53 +0800 Subject: [PATCH 008/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=AE=AF=E9=A3=9E?= =?UTF-8?q?=E6=98=9F=E7=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-module-ai/pom.xml | 1 + .../yudao-spring-boot-starter-ai/pom.xml | 8 + .../framework/ai/chatxinghuo/XingHuoApi.java | 154 ++++++++++++++++++ .../ai/chatxinghuo/XingHuoChatClient.java | 130 +++++++++++++++ .../ai/chatxinghuo/XingHuoChatModel.java | 44 +++++ .../api/XingHuoChatCompletion.java | 48 ++++++ .../api/XingHuoChatCompletionMessage.java | 8 + .../api/XingHuoChatCompletionRequest.java | 92 +++++++++++ .../exception/XingHuoApiException.java | 14 ++ .../ai/chat/XingHuoChatClientMainTests.java | 117 +++++++++++++ .../ai/chat/XingHuoChatClientTests.java | 56 +++++++ .../framework/ai/chat/XingHuoOkHttpTests.java | 130 +++++++++++++++ .../framework/ai/chat/YiYanChatTests.java | 54 ++++++ .../yudao/framework/ai/package-info.java | 5 + 14 files changed, 861 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoApi.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatModel.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletion.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletionMessage.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletionRequest.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/exception/XingHuoApiException.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientMainTests.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoOkHttpTests.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/package-info.java diff --git a/yudao-module-ai/pom.xml b/yudao-module-ai/pom.xml index aaba1191d..d7241b3ec 100644 --- a/yudao-module-ai/pom.xml +++ b/yudao-module-ai/pom.xml @@ -14,6 +14,7 @@ yudao-module-ai-api yudao-module-ai-biz + yudao-spring-boot-starter-ai diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml index 8ca4bccc3..862f7fe8d 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml @@ -100,6 +100,14 @@ 4.12.0 test + + io.projectreactor.netty + reactor-netty + + + cn.hutool + hutool-all + \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoApi.java new file mode 100644 index 000000000..58c21349b --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoApi.java @@ -0,0 +1,154 @@ +package cn.iocoder.yudao.framework.ai.chatxinghuo; + +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONUtil; +import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletion; +import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletionRequest; +import lombok.Data; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.ResponseEntity; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.net.URI; +import java.nio.charset.Charset; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 讯飞星火 属性、api + *

+ * 文档地址:https://www.xfyun.cn/doc/spark/Web.html#_1-%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E + *

+ * author: fansili + * time: 2024/3/11 10:12 + */ +@Data +public class XingHuoApi { + + private static final String DEFAULT_BASE_URL = "wss://spark-api.xf-yun.com"; + + private String appId; + private String appKey; + private String secretKey; + private WebClient webClient; + private XingHuoChatModel useChatModel; + // 创建 WebSocketClient 实例 + private ReactorNettyWebSocketClient socketClient = new ReactorNettyWebSocketClient(); + + public XingHuoApi(String appId, String appKey, String secretKey, XingHuoChatModel useChatModel) { + this.appId = appId; + this.appKey = appKey; + this.secretKey = secretKey; + this.useChatModel = useChatModel; + + } + + public ResponseEntity chatCompletionEntity(XingHuoChatCompletionRequest request) { + String authUrl; + try { + authUrl = getAuthorizationUrl("spark-api.xf-yun.com", useChatModel.getUri()); + } catch (NoSuchAlgorithmException | InvalidKeyException e) { + throw new RuntimeException(e); + } + // wss 请求的 URI + URI uri = URI.create(authUrl); + // 发起 wss 请求并处理响应 + Flux messageFlux = Flux.create(sink -> { + socketClient.execute(uri, session -> + session.send(Mono.just(session.textMessage(JSONUtil.toJsonStr(request)))) + .thenMany(session.receive() + .map(WebSocketMessage -> { + return JSONUtil.toBean(WebSocketMessage.getPayloadAsText(), XingHuoChatCompletion.class); + }) + .doOnNext(sink::next) // 将接收到的消息推送到 Flux 中 + .doOnError(sink::error) // 处理错误 + .doOnTerminate(sink::complete)) // 完成时关闭 sink + .then()) + .subscribe(); // 订阅以开始会话 + }); + // 阻塞获取所有结果 + List responseList = messageFlux.collectList().block(); + // 拼接 content + String responseContent = responseList.stream().map(item -> { + // 获取 content + return item.getPayload().getChoices().getText().stream().map(XingHuoChatCompletion.Text::getContent).collect(Collectors.joining()); + }).collect(Collectors.joining()); + // 将多个合并成一个 + XingHuoChatCompletion xingHuoChatCompletion = new XingHuoChatCompletion(); + xingHuoChatCompletion.setPayload(new XingHuoChatCompletion.Payload().setChoices(new XingHuoChatCompletion.Choices().setText(List.of(new XingHuoChatCompletion.Text().setContent(responseContent))))); + return new ResponseEntity<>(xingHuoChatCompletion, HttpStatusCode.valueOf(200)); + } + + + /** + * 获取验证请求url + * + * @return + */ + public String getAuthorizationUrl(String host, String path) throws NoSuchAlgorithmException, InvalidKeyException { + // 获取鉴权时间 date + SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); + format.setTimeZone(TimeZone.getTimeZone("GMT")); + String date = format.format(new Date()); + + // 获取signature_origin字段 + StringBuilder builder = new StringBuilder("host: ").append(host).append("\n"). + append("date: ").append(date).append("\n"). + append("GET ").append(path).append(" HTTP/1.1"); + + // 获得signatue + Charset charset = Charset.forName("UTF-8"); + Mac mac = Mac.getInstance("hmacsha256"); + SecretKeySpec sp = new SecretKeySpec(secretKey.getBytes(charset), "hmacsha256"); + mac.init(sp); + byte[] basebefore = mac.doFinal(builder.toString().getBytes(charset)); + String signature = Base64.getEncoder().encodeToString(basebefore); + //获得 authorization_origin + String authorization_origin = String.format("api_key=\"%s\",algorithm=\"%s\",headers=\"%s\",signature=\"%s\"", appKey, "hmac-sha256", "host date request-line", signature); + //获得authorization + String authorization = Base64.getEncoder().encodeToString(authorization_origin.getBytes(charset)); + // 获取httpUrl + Map param = new HashMap<>(); + param.put("authorization", authorization); + param.put("date", date); + param.put("host", host); + + String toParams = HttpUtil.toParams(param); + return "wss://" + host + path + "?" + toParams; + } + + public Flux chatCompletionStream(XingHuoChatCompletionRequest request) { + String authUrl; + try { + authUrl = getAuthorizationUrl("spark-api.xf-yun.com", useChatModel.getUri()); + } catch (NoSuchAlgorithmException | InvalidKeyException e) { + throw new RuntimeException(e); + } + System.err.println(authUrl); + System.err.println(JSONUtil.toJsonPrettyStr(request)); + // wss 请求的 URI + URI uri = URI.create(authUrl); + // 发起 wss 请求并处理响应 + // 创建一个 Flux 来处理接收到的消息 + Flux messageFlux = Flux.create(sink -> { + socketClient.execute(uri, session -> + session.send(Mono.just(session.textMessage(JSONUtil.toJsonStr(request)))) + .thenMany(session.receive() + .map(WebSocketMessage -> JSONUtil.toBean(WebSocketMessage.getPayloadAsText(), XingHuoChatCompletion.class)) + .doOnNext(sink::next) // 将接收到的消息推送到 Flux 中 + .doOnError(sink::error) // 处理错误 + .doOnTerminate(sink::complete)) // 完成时关闭 sink + .then()) + .subscribe(); // 订阅以开始会话 + }); + return messageFlux; + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java new file mode 100644 index 000000000..a750e1c8f --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java @@ -0,0 +1,130 @@ +package cn.iocoder.yudao.framework.ai.chatxinghuo; + +import cn.iocoder.yudao.framework.ai.chat.ChatClient; +import cn.iocoder.yudao.framework.ai.chat.ChatResponse; +import cn.iocoder.yudao.framework.ai.chat.Generation; +import cn.iocoder.yudao.framework.ai.chat.StreamingChatClient; +import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; +import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletion; +import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletionMessage; +import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletionRequest; +import cn.iocoder.yudao.framework.ai.chatxinghuo.exception.XingHuoApiException; +import cn.iocoder.yudao.framework.ai.model.function.AbstractFunctionCallSupport; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.retry.RetryCallback; +import org.springframework.retry.RetryContext; +import org.springframework.retry.RetryListener; +import org.springframework.retry.support.RetryTemplate; +import reactor.core.publisher.Flux; + +import java.time.Duration; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 讯飞星火 client + *

+ * author: fansili + * time: 2024/3/11 10:19 + */ +@Slf4j +public class XingHuoChatClient extends AbstractFunctionCallSupport> + implements ChatClient, StreamingChatClient { + + private XingHuoApi xingHuoApi; + + public final RetryTemplate retryTemplate = RetryTemplate.builder() + // 最大重试次数 10 + .maxAttempts(10) + .retryOn(XingHuoApiException.class) + // 最大重试5次,第一次间隔3000ms,第二次3000ms * 2,第三次3000ms * 3,以此类推,最大间隔3 * 60000ms + .exponentialBackoff(Duration.ofMillis(3000), 2, Duration.ofMillis(3 * 60000)) + .withListener(new RetryListener() { + @Override + public void onError(RetryContext context, + RetryCallback callback, Throwable throwable) { + log.warn("重试异常:" + context.getRetryCount(), throwable); + } + + ; + }) + .build(); + + public XingHuoChatClient(XingHuoApi xingHuoApi) { + super(null); + this.xingHuoApi = xingHuoApi; + } + + @Override + public ChatResponse call(Prompt prompt) { + + return this.retryTemplate.execute(ctx -> { + // ctx 会有重试的信息 + // 创建 request 请求,stream模式需要供应商支持 + XingHuoChatCompletionRequest request = this.createRequest(prompt, false); + // 调用 callWithFunctionSupport 发送请求 + ResponseEntity response = this.callWithFunctionSupport(request); + // 获取结果封装 ChatResponse + return new ChatResponse(List.of(new Generation(response.getBody().getPayload().getChoices().getText().get(0).getContent()))); + }); + } + + private XingHuoChatCompletionRequest createRequest(Prompt prompt, boolean b) { + // 创建 header + XingHuoChatCompletionRequest.Header header = new XingHuoChatCompletionRequest.Header().setApp_id(xingHuoApi.getAppId()); + // 创建 params + XingHuoChatCompletionRequest.Parameter parameter = new XingHuoChatCompletionRequest.Parameter() + .setChat(new XingHuoChatCompletionRequest.Parameter.Chat().setDomain(xingHuoApi.getUseChatModel().getValue())); + // 创建 payload text 信息 + XingHuoChatCompletionRequest.Payload.Message.Text text = new XingHuoChatCompletionRequest.Payload.Message.Text(); + text.setRole(XingHuoChatCompletionRequest.Payload.Message.Text.Role.USER.getName()); + text.setContent(prompt.getContents()); + // 创建 payload + XingHuoChatCompletionRequest.Payload payload = new XingHuoChatCompletionRequest.Payload() + .setMessage(new XingHuoChatCompletionRequest.Payload.Message().setText(List.of(text))); + // 创建 request + return new XingHuoChatCompletionRequest() + .setHeader(header) + .setParameter(parameter) + .setPayload(payload); + } + + @Override + public Flux stream(Prompt prompt) { + // 创建 request 请求,stream模式需要供应商支持 + XingHuoChatCompletionRequest request = this.createRequest(prompt, false); + // 发送请求 + Flux response = this.xingHuoApi.chatCompletionStream(request); + return response.map(res -> { + String content = res.getPayload().getChoices().getText().stream() + .map(item -> item.getContent()).collect(Collectors.joining()); + return new ChatResponse(List.of(new Generation(content))); + }); + } + + @Override + protected XingHuoChatCompletionRequest doCreateToolResponseRequest(XingHuoChatCompletionRequest previousRequest, XingHuoChatCompletionMessage responseMessage, List conversationHistory) { + return null; + } + + @Override + protected List doGetUserMessages(XingHuoChatCompletionRequest request) { + return null; + } + + @Override + protected XingHuoChatCompletionMessage doGetToolResponseMessage(ResponseEntity response) { + return null; + } + + @Override + protected ResponseEntity doChatCompletion(XingHuoChatCompletionRequest request) { + return xingHuoApi.chatCompletionEntity(request); + } + + @Override + protected boolean isToolFunctionCall(ResponseEntity response) { + return false; + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatModel.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatModel.java new file mode 100644 index 000000000..e00a622b0 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatModel.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.framework.ai.chatxinghuo; + +import lombok.Getter; + +/** + * 讯飞星火 模型 + * + * 文档地址:https://www.xfyun.cn/doc/spark/Web.html#_1-%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E + * + * 1tokens 约等于1.5个中文汉字 或者 0.8个英文单词 + * 星火V1.5支持[搜索]内置插件;星火V2.0、V3.0和V3.5支持[搜索]、[天气]、[日期]、[诗词]、[字词]、[股票]六个内置插件 + * 星火V3.5 现已支持system、Function Call 功能。 + * + * author: fansili + * time: 2024/3/11 10:12 + */ +@Getter +public enum XingHuoChatModel { + +// 文档地址:https://www.xfyun.cn/doc/spark/Web.html#_1-%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E +// general指向V1.5版本; +// generalv2指向V2版本; +// generalv3指向V3版本; +// generalv3.5指向V3.5版本; + + XING_HUO_1_5("星火大模型1.5", "general", "/v1.1/chat"), + XING_HUO_2_0("星火大模型2.0", "generalv2", "/v2.1/chat"), + XING_HUO_3_0("星火大模型3.0", "generalv3", "/v3.1/chat"), + XING_HUO_3_5("星火大模型3.5", "generalv3.5", "/v3.5/chat"), + + ; + + XingHuoChatModel(String name, String value, String uri) { + this.name = name; + this.value = value; + this.uri = uri; + } + + private String name; + + private String value; + + private String uri; +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletion.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletion.java new file mode 100644 index 000000000..a0f965327 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletion.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.framework.ai.chatxinghuo.api; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; + +/** + * author: fansili + * time: 2024/3/11 10:20 + */ +@Data +@Accessors(chain = true) +public class XingHuoChatCompletion { + private Header header; + private Payload payload; + + @Data + @Accessors(chain = true) + public static class Header { + private int code; + private String message; + private String sid; + private int status; + } + + @Data + @Accessors(chain = true) + public static class Payload { + private Choices choices; + } + + @Data + @Accessors(chain = true) + public static class Choices { + private int status; + private int seq; + private List text; + } + + @Data + @Accessors(chain = true) + public static class Text { + private String content; + private String role; + private int index; + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletionMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletionMessage.java new file mode 100644 index 000000000..faa3c8c73 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletionMessage.java @@ -0,0 +1,8 @@ +package cn.iocoder.yudao.framework.ai.chatxinghuo.api; + +/** + * author: fansili + * time: 2024/3/11 10:20 + */ +public class XingHuoChatCompletionMessage { +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletionRequest.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletionRequest.java new file mode 100644 index 000000000..009789cb3 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletionRequest.java @@ -0,0 +1,92 @@ +package cn.iocoder.yudao.framework.ai.chatxinghuo.api; + +import lombok.Data; +import lombok.Getter; +import lombok.experimental.Accessors; + +import java.util.List; + +/** + * 讯飞星火 request + * + * author: fansili + * time: 2024/3/11 10:20 + */ +@Data +@Accessors(chain = true) +public class XingHuoChatCompletionRequest { + + private Header header; + private Parameter parameter; + private Payload payload; + + @Data + @Accessors(chain = true) + public static class Header { + private String app_id; + private String uid; + } + + @Data + @Accessors(chain = true) + public static class Parameter { + private Chat chat; + + @Data + @Accessors(chain = true) + public static class Chat { + /** + * https://www.xfyun.cn/doc/spark/Web.html#_1-%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E + * + * 指定访问的领域: + * general指向V1.5版本; + * generalv2指向V2版本; + * generalv3指向V3版本; + * generalv3.5指向V3.5版本; + * 注意:不同的取值对应的url也不一样! + */ + private String domain = "general"; + private Double temperature = 0.5; + private Integer max_tokens = 2048; + } + } + + @Data + @Accessors(chain = true) + public static class Payload { + private Message message; + + @Data + @Accessors(chain = true) + public static class Message { + private List text; + + + @Data + @Accessors(chain = true) + public static class Text { + /** + * 角色 + */ + private String role; + /** + * 消息内容 + */ + private String content; + private Integer index; + + @Getter + public static enum Role { + SYSTEM("system"), + USER("user"), + ASSISTANT("assistant"); + private String name; + + private Role(String name) { + this.name = name; + } + } + } + } + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/exception/XingHuoApiException.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/exception/XingHuoApiException.java new file mode 100644 index 000000000..cde6147c7 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/exception/XingHuoApiException.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.framework.ai.chatxinghuo.exception; + +/** + * 讯飞星火 exception + * + * author: fansili + * time: 2024/3/11 10:22 + */ +public class XingHuoApiException extends RuntimeException { + + public XingHuoApiException(String message) { + super(message); + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientMainTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientMainTests.java new file mode 100644 index 000000000..674e4dc6d --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientMainTests.java @@ -0,0 +1,117 @@ +package cn.iocoder.yudao.framework.ai.chat; + +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONUtil; +import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletion; +import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletionRequest; +import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient; +import org.springframework.web.reactive.socket.client.WebSocketClient; +import reactor.core.publisher.Flux; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.net.MalformedURLException; +import java.net.URI; +import java.nio.charset.Charset; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.text.SimpleDateFormat; +import java.util.*; + +/** + * author: fansili + * time: 2024/3/13 20:47 + */ +public class XingHuoChatClientMainTests { + + + private static final String HOST_URL = "http://spark-api.xf-yun.com/v3.5/chat"; + private static final String API_KEY = "cb6415c19d6162cda07b47316fcb0416"; + private static final String API_SECRET = "Y2JiYTIxZjA3MDMxMjNjZjQzYzVmNzdh"; + + public static void main(String[] args) throws MalformedURLException, NoSuchAlgorithmException, InvalidKeyException { + String authUrl = getAuthorizationUrl("spark-api.xf-yun.com", "/v3.5/chat"); + System.err.println(authUrl); + + XingHuoChatCompletionRequest.Header header = new XingHuoChatCompletionRequest.Header().setApp_id("13c8cca6"); + XingHuoChatCompletionRequest.Parameter parameter + = new XingHuoChatCompletionRequest.Parameter() + .setChat(new XingHuoChatCompletionRequest.Parameter.Chat().setDomain("generalv3.5")); + + + XingHuoChatCompletionRequest.Payload.Message.Text text = new XingHuoChatCompletionRequest.Payload.Message.Text(); + text.setRole(XingHuoChatCompletionRequest.Payload.Message.Text.Role.USER.getName()); + text.setContent("世界上最好的开发语言是什么?"); + XingHuoChatCompletionRequest.Payload payload = new XingHuoChatCompletionRequest.Payload() + .setMessage(new XingHuoChatCompletionRequest.Payload.Message().setText(List.of(text))); + XingHuoChatCompletionRequest request = new XingHuoChatCompletionRequest() + .setHeader(header) + .setParameter(parameter) + .setPayload(payload); + + System.err.println(JSONUtil.toJsonPrettyStr(request)); + + + // 创建 WebSocketClient 实例 + WebSocketClient client = new ReactorNettyWebSocketClient(); + + // wss 请求的 URI + URI uri = URI.create(authUrl); + + // 发起 wss 请求并处理响应 + client.execute(uri, session -> + // 使用会话发送消息,并接收回应 + session.send(Flux.just(session.textMessage(JSONUtil.toJsonStr(request)))) + .thenMany(session.receive() + .map(WebSocketMessage -> { + System.err.println(WebSocketMessage.getPayloadAsText()); + return JSONUtil.toBean(WebSocketMessage.getPayloadAsText(), XingHuoChatCompletion.class); + }) + .log()) // 打印接收到的消息 + .then()) + .block(); // 等待操作完成或超时 + + // 阻止退出 + Scanner scanner = new Scanner(System.in); + scanner.nextLine(); + } + + + /** + * 获取验证请求url + * + * @return + */ + public static String getAuthorizationUrl(String host, String path) throws NoSuchAlgorithmException, InvalidKeyException { + // 获取鉴权时间 date + SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); + format.setTimeZone(TimeZone.getTimeZone("GMT")); + String date = format.format(new Date()); + + // 获取signature_origin字段 + StringBuilder builder = new StringBuilder("host: ").append(host).append("\n"). + append("date: ").append(date).append("\n"). + append("GET ").append(path).append(" HTTP/1.1"); + + // 获得signatue + Charset charset = Charset.forName("UTF-8"); + Mac mac = Mac.getInstance("hmacsha256"); + SecretKeySpec sp = new SecretKeySpec(API_SECRET.getBytes(charset), "hmacsha256"); + mac.init(sp); + byte[] basebefore = mac.doFinal(builder.toString().getBytes(charset)); + String signature = Base64.getEncoder().encodeToString(basebefore); + //获得 authorization_origin + String authorization_origin = String.format("api_key=\"%s\",algorithm=\"%s\",headers=\"%s\",signature=\"%s\"", API_KEY, "hmac-sha256", "host date request-line", signature); + //获得authorization + String authorization = Base64.getEncoder().encodeToString(authorization_origin.getBytes(charset)); + // 获取httpUrl + Map param = new HashMap<>(); + param.put("authorization", authorization); + param.put("date", date); + param.put("host", host); + + String toParams = HttpUtil.toParams(param); + return "wss://" + host + path + "?" + toParams; + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java new file mode 100644 index 000000000..da8bc9d5d --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.framework.ai.chat; + +import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; +import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoApi; +import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatClient; +import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel; +import org.junit.Before; +import org.junit.Test; +import reactor.core.publisher.Flux; + +import java.util.Scanner; +import java.util.function.Consumer; + +/** + * 讯飞星火 tests + *

+ * author: fansili + * time: 2024/3/11 11:00 + */ +public class XingHuoChatClientTests { + + private XingHuoChatClient xingHuoChatClient; + + @Before + public void setup() { + // 初始化 xingHuoChatClient + xingHuoChatClient = new XingHuoChatClient( + new XingHuoApi( + "13c8cca6", + "cb6415c19d6162cda07b47316fcb0416", + "Y2JiYTIxZjA3MDMxMjNjZjQzYzVmNzdh", + XingHuoChatModel.XING_HUO_3_5 + ) + ); + } + + @Test + public void callTest() { + ChatResponse call = xingHuoChatClient.call(new Prompt("java和go那个性能更好!")); + System.err.println(call.getResult()); + } + + @Test + public void streamTest() { + Flux stream = xingHuoChatClient.stream(new Prompt("java和go那个性能更好!")); + stream.subscribe(new Consumer() { + @Override + public void accept(ChatResponse chatResponse) { + System.err.print(chatResponse.getResult().getOutput().getContent()); + } + }); + // 阻止退出 + Scanner scanner = new Scanner(System.in); + scanner.nextLine(); + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoOkHttpTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoOkHttpTests.java new file mode 100644 index 000000000..3f2903201 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoOkHttpTests.java @@ -0,0 +1,130 @@ +package cn.iocoder.yudao.framework.ai.chat; + +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONUtil; +import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatClient; +import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletion; +import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletionRequest; +import okhttp3.*; +import org.jetbrains.annotations.NotNull; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.net.MalformedURLException; +import java.nio.charset.Charset; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.text.SimpleDateFormat; +import java.util.*; + +/** + * 讯飞星火 tests + *

+ * author: fansili + * time: 2024/3/11 11:00 + */ +public class XingHuoOkHttpTests { + + private static final String HOST_URL = "http://spark-api.xf-yun.com/v3.5/chat"; + private static final String API_KEY = "cb6415c19d6162cda07b47316fcb0416"; + private static final String API_SECRET = "Y2JiYTIxZjA3MDMxMjNjZjQzYzVmNzdh"; + + private XingHuoChatClient xingHuoChatClient; + + public static void main(String[] args) throws MalformedURLException, NoSuchAlgorithmException, InvalidKeyException { + String authUrl = getAuthorizationUrl("spark-api.xf-yun.com", "/v3.5/chat"); + System.err.println(authUrl); + + XingHuoChatCompletionRequest.Header header = new XingHuoChatCompletionRequest.Header().setApp_id("13c8cca6"); + XingHuoChatCompletionRequest.Parameter parameter + = new XingHuoChatCompletionRequest.Parameter() + .setChat(new XingHuoChatCompletionRequest.Parameter.Chat().setDomain("generalv3.5")); + + + XingHuoChatCompletionRequest.Payload.Message.Text text = new XingHuoChatCompletionRequest.Payload.Message.Text(); + text.setRole(XingHuoChatCompletionRequest.Payload.Message.Text.Role.USER.getName()); + text.setContent("世界上最好的开发语言是什么?"); + XingHuoChatCompletionRequest.Payload payload = new XingHuoChatCompletionRequest.Payload() + .setMessage(new XingHuoChatCompletionRequest.Payload.Message().setText(List.of(text))); + XingHuoChatCompletionRequest request = new XingHuoChatCompletionRequest() + .setHeader(header) + .setParameter(parameter) + .setPayload(payload); + + System.err.println(JSONUtil.toJsonPrettyStr(request)); + + OkHttpClient client = new OkHttpClient(); + Request request2 = new Request.Builder() + .url(authUrl) // 替换为你的 wss URL + .build(); + + WebSocketListener webSocketListener = new WebSocketListener() { + + @Override + public void onOpen(@NotNull WebSocket webSocket, @NotNull Response response) { + boolean send = webSocket.send(JSONUtil.toJsonStr(request)); + System.err.println("发送 -> " + send); + System.err.println("链接成功!"); + } + + @Override + public void onMessage(@NotNull WebSocket webSocket, @NotNull String text) { + super.onMessage(webSocket, text); +// System.err.println(text); + XingHuoChatCompletion response = JSONUtil.toBean(text, XingHuoChatCompletion.class); + for (XingHuoChatCompletion.Text text1 : response.getPayload().getChoices().getText()) { + System.err.print(text1.getContent()); + } + } + }; + + WebSocket webSocket = client.newWebSocket(request2, webSocketListener); +// webSocket.send(JSONUtil.toJsonStr(request)); + + + // Trigger shutdown of the dispatcher's executor so this process can exit cleanly. + client.dispatcher().executorService().shutdown(); + // 阻止退出 + Scanner scanner = new Scanner(System.in); + scanner.nextLine(); + } + + + /** + * 获取验证请求url + * + * @return + */ + public static String getAuthorizationUrl(String host, String path) throws NoSuchAlgorithmException, InvalidKeyException { + // 获取鉴权时间 date + SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); + format.setTimeZone(TimeZone.getTimeZone("GMT")); + String date = format.format(new Date()); + + // 获取signature_origin字段 + StringBuilder builder = new StringBuilder("host: ").append(host).append("\n"). + append("date: ").append(date).append("\n"). + append("GET ").append(path).append(" HTTP/1.1"); + + // 获得signatue + Charset charset = Charset.forName("UTF-8"); + Mac mac = Mac.getInstance("hmacsha256"); + SecretKeySpec sp = new SecretKeySpec(API_SECRET.getBytes(charset), "hmacsha256"); + mac.init(sp); + byte[] basebefore = mac.doFinal(builder.toString().getBytes(charset)); + String signature = Base64.getEncoder().encodeToString(basebefore); + //获得 authorization_origin + String authorization_origin = String.format("api_key=\"%s\",algorithm=\"%s\",headers=\"%s\",signature=\"%s\"", API_KEY, "hmac-sha256", "host date request-line", signature); + //获得authorization + String authorization = Base64.getEncoder().encodeToString(authorization_origin.getBytes(charset)); + // 获取httpUrl + Map param = new HashMap<>(); + param.put("authorization", authorization); + param.put("date", date); + param.put("host", host); + + String toParams = HttpUtil.toParams(param); + return "wss://" + host + path + "?" + toParams; + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java new file mode 100644 index 000000000..346ffedb1 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.framework.ai.chat; + +import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; +import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanApi; +import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatClient; +import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel; +import org.junit.Before; +import org.junit.Test; +import reactor.core.publisher.Flux; + +import java.util.Scanner; +import java.util.function.Consumer; + +/** + * chat 文心一言 + * + * author: fansili + * time: 2024/3/12 20:59 + */ +public class YiYanChatTests { + + private YiYanChatClient yiYanChatClient; + + @Before + public void setup() { + YiYanApi yiYanApi = new YiYanApi( + "x0cuLZ7XsaTCU08vuJWO87Lg", + "R9mYF9dl9KASgi5RUq0FQt3wRisSnOcK", + YiYanChatModel.ERNIE4_3_5_8K, + 86400 + ); + yiYanChatClient = new YiYanChatClient(yiYanApi); + } + + @Test + public void callTest() { + ChatResponse call = yiYanChatClient.call(new Prompt("什么编程语言最好?")); + System.err.println(call.getResult()); + } + + @Test + public void streamTest() { + Flux fluxResponse = yiYanChatClient.stream(new Prompt("用java帮我写一个快排算法?")); + fluxResponse.subscribe(new Consumer() { + @Override + public void accept(ChatResponse chatResponse) { + System.err.print(chatResponse.getResult().getOutput().getContent()); + } + }); + // 阻止退出 + Scanner scanner = new Scanner(System.in); + scanner.nextLine(); + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/package-info.java new file mode 100644 index 000000000..1678ee0ae --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/package-info.java @@ -0,0 +1,5 @@ +/** + * author: fansili + * time: 2024/3/12 21:03 + */ +package cn.iocoder.yudao.framework.ai; \ No newline at end of file From 0f73b61db203b9ab00597eec9265abb4368ff7ea Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 14 Mar 2024 20:16:07 +0800 Subject: [PATCH 009/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=98=BF=E9=87=8C=20?= =?UTF-8?q?=E9=80=9A=E4=B9=89=E5=8D=83=E9=97=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao-spring-boot-starter-ai/pom.xml | 6 + .../framework/ai/chatqianwen/QianWenApi.java | 82 +++++++++++ .../ai/chatqianwen/QianWenChatClient.java | 128 ++++++++++++++++++ .../api/QianWenChatCompletion.java | 10 ++ .../api/QianWenChatCompletionMessage.java | 8 ++ .../api/QianWenChatCompletionRequest.java | 12 ++ .../ai/chatqianwen/package-info.java | 9 ++ .../framework/ai/chatxinghuo/XingHuoApi.java | 2 - .../ai/chat/QianWenChatClientTests.java | 53 ++++++++ 9 files changed, 308 insertions(+), 2 deletions(-) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletion.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletionMessage.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletionRequest.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/package-info.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml index 862f7fe8d..276e87733 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml @@ -108,6 +108,12 @@ cn.hutool hutool-all + + + com.aliyun + broadscope-bailian-sdk-java + 1.3.0 + \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java new file mode 100644 index 000000000..dbf6a7d70 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.framework.ai.chatqianwen; + +import com.aliyun.broadscope.bailian.sdk.AccessTokenClient; +import com.aliyun.broadscope.bailian.sdk.ApplicationClient; +import com.aliyun.broadscope.bailian.sdk.models.ChatRequestMessage; +import com.aliyun.broadscope.bailian.sdk.models.CompletionsRequest; +import com.aliyun.broadscope.bailian.sdk.models.CompletionsResponse; +import lombok.Getter; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.ResponseEntity; +import reactor.core.publisher.Flux; + +import java.util.List; + +/** + * 阿里 通义千问 + * + * https://www.aliyun.com/search?k=%E9%80%9A%E4%B9%89%E5%A4%A7%E6%A8%A1%E5%9E%8B&scene=all + * + * author: fansili + * time: 2024/3/13 21:09 + */ +@Getter +public class QianWenApi { + + /** + * accessKeyId、accessKeySecret、agentKey、appId 获取方式如下链接 + * https://help.aliyun.com/document_detail/2587494.html?spm=a2c4g.2587492.0.0.53f33c566sXskp + */ + private String accessKeyId; + private String accessKeySecret; + private String agentKey; + private String appId; + private String endpoint = "bailian.cn-beijing.aliyuncs.com"; + private String token; + private ApplicationClient client; + + public QianWenApi(String accessKeyId, String accessKeySecret, String agentKey, String appId, String endpoint) { + this.accessKeyId = accessKeyId; + this.accessKeySecret = accessKeySecret; + this.agentKey = agentKey; + this.appId = appId; + + if (endpoint != null) { + this.endpoint = endpoint; + } + + // 获取token + AccessTokenClient accessTokenClient = new AccessTokenClient(accessKeyId, accessKeySecret, agentKey); + token = accessTokenClient.getToken(); + // 构建client + client = ApplicationClient.builder() + .token(token) + .build(); + } + + public ResponseEntity chatCompletionEntity(ChatRequestMessage message) { + // 创建request + CompletionsRequest request = new CompletionsRequest() + .setAppId(appId) + .setMessages(List.of(message)) + .setParameters(new CompletionsRequest.Parameter().setResultFormat("message")); + // + CompletionsResponse response = client.completions(request); + int httpCode = 200; + if (!response.isSuccess()) { + System.out.printf("failed to create completion, requestId: %s, code: %s, message: %s\n", + response.getRequestId(), response.getCode(), response.getMessage()); + httpCode = 500; + } + return new ResponseEntity<>(response, HttpStatusCode.valueOf(httpCode)); + } + + public Flux chatCompletionStream(ChatRequestMessage message) { + return client.streamCompletions( + new CompletionsRequest() + .setAppId(appId) + .setMessages(List.of(message)) + .setParameters(new CompletionsRequest.Parameter().setIncrementalOutput(true)) + ); + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java new file mode 100644 index 000000000..7b4a60baf --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java @@ -0,0 +1,128 @@ +package cn.iocoder.yudao.framework.ai.chatqianwen; + +import cn.iocoder.yudao.framework.ai.chat.ChatClient; +import cn.iocoder.yudao.framework.ai.chat.ChatResponse; +import cn.iocoder.yudao.framework.ai.chat.Generation; +import cn.iocoder.yudao.framework.ai.chat.StreamingChatClient; +import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; +import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenChatCompletionMessage; +import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenChatCompletionRequest; +import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletion; +import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletionRequest; +import cn.iocoder.yudao.framework.ai.chatyiyan.exception.YiYanApiException; +import cn.iocoder.yudao.framework.ai.model.function.AbstractFunctionCallSupport; +import cn.iocoder.yudao.framework.ai.model.function.FunctionCallbackContext; +import com.aliyun.broadscope.bailian.sdk.models.ChatRequestMessage; +import com.aliyun.broadscope.bailian.sdk.models.ChatUserMessage; +import com.aliyun.broadscope.bailian.sdk.models.CompletionsResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.retry.RetryCallback; +import org.springframework.retry.RetryContext; +import org.springframework.retry.RetryListener; +import org.springframework.retry.support.RetryTemplate; +import reactor.core.publisher.Flux; + +import java.time.Duration; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 阿里 通义千问 client + * + * 文档地址:https://help.aliyun.com/document_detail/2587494.html?spm=a2c4g.2587492.0.0.53f33c566sXskp + * + * author: fansili + * time: 2024/3/13 21:06 + */ +@Slf4j +public class QianWenChatClient extends AbstractFunctionCallSupport> + implements ChatClient, StreamingChatClient { + + private QianWenApi qianWenApi; + + public QianWenChatClient(QianWenApi qianWenApi) { + super(null); + this.qianWenApi = qianWenApi; + } + + public final RetryTemplate retryTemplate = RetryTemplate.builder() + // 最大重试次数 10 + .maxAttempts(10) + .retryOn(YiYanApiException.class) + // 最大重试5次,第一次间隔3000ms,第二次3000ms * 2,第三次3000ms * 3,以此类推,最大间隔3 * 60000ms + .exponentialBackoff(Duration.ofMillis(3000), 2, Duration.ofMillis(3 * 60000)) + .withListener(new RetryListener() { + @Override + public void onError(RetryContext context, + RetryCallback callback, Throwable throwable) { + log.warn("重试异常:" + context.getRetryCount(), throwable); + }; + }) + .build(); + + public QianWenChatClient(FunctionCallbackContext functionCallbackContext) { + super(functionCallbackContext); + } + + @Override + public ChatResponse call(Prompt prompt) { + return this.retryTemplate.execute(ctx -> { + // ctx 会有重试的信息 + // 创建 request 请求,stream模式需要供应商支持 + ChatRequestMessage request = this.createRequest(prompt, false); + // 调用 callWithFunctionSupport 发送请求 + ResponseEntity responseEntity = this.callWithFunctionSupport(request); + // 获取结果封装 chatCompletion + CompletionsResponse response = responseEntity.getBody(); + if (!response.isSuccess()) { + return new ChatResponse(List.of(new Generation(String.format("failed to create completion, requestId: %s, code: %s, message: %s\n", + response.getRequestId(), response.getCode(), response.getMessage())))); + } + List generations = response.getData().getChoices().stream() + .map(item -> new Generation(item.getMessage().getContent())).collect(Collectors.toList()); + return new ChatResponse(generations); + }); + } + + private ChatRequestMessage createRequest(Prompt prompt, boolean b) { + return new ChatUserMessage(prompt.getContents()); + } + + @Override + public Flux stream(Prompt prompt) { + // ctx 会有重试的信息 + // 创建 request 请求,stream模式需要供应商支持 + ChatRequestMessage request = this.createRequest(prompt, true); + // 调用 callWithFunctionSupport 发送请求 + Flux response = this.qianWenApi.chatCompletionStream(request); + return response.map(res -> { + return new ChatResponse(List.of(new Generation(res.getData().getText()))); + }); + } + + @Override + protected QianWenChatCompletionRequest doCreateToolResponseRequest(ChatRequestMessage previousRequest, QianWenChatCompletionMessage responseMessage, List conversationHistory) { + return null; + } + + @Override + protected List doGetUserMessages(ChatRequestMessage request) { + return null; + } + + @Override + protected QianWenChatCompletionMessage doGetToolResponseMessage(ResponseEntity response) { + return null; + } + + @Override + protected ResponseEntity doChatCompletion(ChatRequestMessage request) { + return qianWenApi.chatCompletionEntity(request); + } + + @Override + protected boolean isToolFunctionCall(ResponseEntity response) { + return false; + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletion.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletion.java new file mode 100644 index 000000000..4e646748e --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletion.java @@ -0,0 +1,10 @@ +package cn.iocoder.yudao.framework.ai.chatqianwen.api; + +import com.aliyun.broadscope.bailian.sdk.models.CompletionsResponse; + +/** + * author: fansili + * time: 2024/3/13 21:07 + */ +public class QianWenChatCompletion extends CompletionsResponse { +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletionMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletionMessage.java new file mode 100644 index 000000000..07680cbf4 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletionMessage.java @@ -0,0 +1,8 @@ +package cn.iocoder.yudao.framework.ai.chatqianwen.api; + +/** + * author: fansili + * time: 2024/3/13 21:07 + */ +public class QianWenChatCompletionMessage { +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletionRequest.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletionRequest.java new file mode 100644 index 000000000..c3e27da62 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletionRequest.java @@ -0,0 +1,12 @@ +package cn.iocoder.yudao.framework.ai.chatqianwen.api; + +import com.aliyun.broadscope.bailian.sdk.models.ChatRequestMessage; +import com.aliyun.broadscope.bailian.sdk.models.ChatUserMessage; + +/** + * author: fansili + * time: 2024/3/13 21:07 + */ +public class QianWenChatCompletionRequest extends ChatRequestMessage { + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/package-info.java new file mode 100644 index 000000000..eb46035e0 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/package-info.java @@ -0,0 +1,9 @@ +/** + * 阿里的 通义千问 + * + * 链接:https://www.aliyun.com/search?k=%E9%80%9A%E4%B9%89%E5%A4%A7%E6%A8%A1%E5%9E%8B&scene=all + * + * author: fansili + * time: 2024/3/13 21:05 + */ +package cn.iocoder.yudao.framework.ai.chatqianwen; \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoApi.java index 58c21349b..a053884a2 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoApi.java @@ -132,8 +132,6 @@ public class XingHuoApi { } catch (NoSuchAlgorithmException | InvalidKeyException e) { throw new RuntimeException(e); } - System.err.println(authUrl); - System.err.println(JSONUtil.toJsonPrettyStr(request)); // wss 请求的 URI URI uri = URI.create(authUrl); // 发起 wss 请求并处理响应 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java new file mode 100644 index 000000000..745af8263 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.framework.ai.chat; + +import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; +import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenApi; +import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient; +import org.junit.Before; +import org.junit.Test; +import reactor.core.publisher.Flux; + +import java.util.Scanner; +import java.util.function.Consumer; + +/** + * author: fansili + * time: 2024/3/13 21:37 + */ +public class QianWenChatClientTests { + + private QianWenChatClient qianWenChatClient; + + @Before + public void setup() { + QianWenApi qianWenApi = new QianWenApi( + "", + "", + "", + "", + null + ); + qianWenChatClient = new QianWenChatClient(qianWenApi); + } + + @Test + public void callTest() { + ChatResponse call = qianWenChatClient.call(new Prompt("Java语言怎么样?")); + System.err.println(call.getResult()); + } + + @Test + public void streamTest() { + Flux flux = qianWenChatClient.stream(new Prompt("Java语言怎么样?")); + flux.subscribe(new Consumer() { + @Override + public void accept(ChatResponse chatResponse) { + System.err.print(chatResponse.getResult().getOutput().getContent()); + } + }); + + // 阻止退出 + Scanner scanner = new Scanner(System.in); + scanner.nextLine(); + } +} From 26afa04e80c51f108897acfbf3e2715af9b3848f Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 14 Mar 2024 20:23:13 +0800 Subject: [PATCH 010/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20=E9=98=BF=E9=87=8C?= =?UTF-8?q?=20=E5=8D=83=E9=97=AE=E5=8F=82=E6=95=B0=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java index dbf6a7d70..93a92364c 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java @@ -57,8 +57,10 @@ public class QianWenApi { public ResponseEntity chatCompletionEntity(ChatRequestMessage message) { // 创建request CompletionsRequest request = new CompletionsRequest() + // 设置 appid .setAppId(appId) .setMessages(List.of(message)) + // 返回choice message结果 .setParameters(new CompletionsRequest.Parameter().setResultFormat("message")); // CompletionsResponse response = client.completions(request); @@ -74,8 +76,10 @@ public class QianWenApi { public Flux chatCompletionStream(ChatRequestMessage message) { return client.streamCompletions( new CompletionsRequest() + // 设置 appid .setAppId(appId) .setMessages(List.of(message)) + //开启增量输出模式,后面输出不会包含已经输出的内容 .setParameters(new CompletionsRequest.Parameter().setIncrementalOutput(true)) ); } From 711cfcb3f6f3427258b03a62f2a82fe257eb7392 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 15 Mar 2024 19:45:52 +0800 Subject: [PATCH 011/684] =?UTF-8?q?client=20=E7=A7=BB=E9=99=A4=20AbstractF?= =?UTF-8?q?unctionCallSupport?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ai/chatqianwen/QianWenApi.java | 2 + .../ai/chatqianwen/QianWenChatClient.java | 41 +--------------- .../ai/chatxinghuo/XingHuoChatClient.java | 33 +------------ .../ai/chatyiyan/YiYanChatClient.java | 47 ++----------------- .../function/AbstractFunctionCallSupport.java | 5 ++ .../ai/model/function/FunctionCallback.java | 7 +++ 6 files changed, 21 insertions(+), 114 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java index 93a92364c..08d3b8ca5 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java @@ -78,6 +78,8 @@ public class QianWenApi { new CompletionsRequest() // 设置 appid .setAppId(appId) + // 开启 stream + .setStream(true) .setMessages(List.of(message)) //开启增量输出模式,后面输出不会包含已经输出的内容 .setParameters(new CompletionsRequest.Parameter().setIncrementalOutput(true)) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java index 7b4a60baf..cf0eae0dd 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java @@ -5,13 +5,7 @@ import cn.iocoder.yudao.framework.ai.chat.ChatResponse; import cn.iocoder.yudao.framework.ai.chat.Generation; import cn.iocoder.yudao.framework.ai.chat.StreamingChatClient; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; -import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenChatCompletionMessage; -import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenChatCompletionRequest; -import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletion; -import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletionRequest; import cn.iocoder.yudao.framework.ai.chatyiyan.exception.YiYanApiException; -import cn.iocoder.yudao.framework.ai.model.function.AbstractFunctionCallSupport; -import cn.iocoder.yudao.framework.ai.model.function.FunctionCallbackContext; import com.aliyun.broadscope.bailian.sdk.models.ChatRequestMessage; import com.aliyun.broadscope.bailian.sdk.models.ChatUserMessage; import com.aliyun.broadscope.bailian.sdk.models.CompletionsResponse; @@ -36,13 +30,11 @@ import java.util.stream.Collectors; * time: 2024/3/13 21:06 */ @Slf4j -public class QianWenChatClient extends AbstractFunctionCallSupport> - implements ChatClient, StreamingChatClient { +public class QianWenChatClient implements ChatClient, StreamingChatClient { private QianWenApi qianWenApi; public QianWenChatClient(QianWenApi qianWenApi) { - super(null); this.qianWenApi = qianWenApi; } @@ -61,10 +53,6 @@ public class QianWenChatClient extends AbstractFunctionCallSupport { @@ -72,7 +60,7 @@ public class QianWenChatClient extends AbstractFunctionCallSupport responseEntity = this.callWithFunctionSupport(request); + ResponseEntity responseEntity = qianWenApi.chatCompletionEntity(request); // 获取结果封装 chatCompletion CompletionsResponse response = responseEntity.getBody(); if (!response.isSuccess()) { @@ -100,29 +88,4 @@ public class QianWenChatClient extends AbstractFunctionCallSupport conversationHistory) { - return null; - } - - @Override - protected List doGetUserMessages(ChatRequestMessage request) { - return null; - } - - @Override - protected QianWenChatCompletionMessage doGetToolResponseMessage(ResponseEntity response) { - return null; - } - - @Override - protected ResponseEntity doChatCompletion(ChatRequestMessage request) { - return qianWenApi.chatCompletionEntity(request); - } - - @Override - protected boolean isToolFunctionCall(ResponseEntity response) { - return false; - } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java index a750e1c8f..23e85be6d 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java @@ -6,10 +6,8 @@ import cn.iocoder.yudao.framework.ai.chat.Generation; import cn.iocoder.yudao.framework.ai.chat.StreamingChatClient; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletion; -import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletionMessage; import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletionRequest; import cn.iocoder.yudao.framework.ai.chatxinghuo.exception.XingHuoApiException; -import cn.iocoder.yudao.framework.ai.model.function.AbstractFunctionCallSupport; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.retry.RetryCallback; @@ -29,8 +27,7 @@ import java.util.stream.Collectors; * time: 2024/3/11 10:19 */ @Slf4j -public class XingHuoChatClient extends AbstractFunctionCallSupport> - implements ChatClient, StreamingChatClient { +public class XingHuoChatClient implements ChatClient, StreamingChatClient { private XingHuoApi xingHuoApi; @@ -52,7 +49,6 @@ public class XingHuoChatClient extends AbstractFunctionCallSupport response = this.callWithFunctionSupport(request); + ResponseEntity response = xingHuoApi.chatCompletionEntity(request); // 获取结果封装 ChatResponse return new ChatResponse(List.of(new Generation(response.getBody().getPayload().getChoices().getText().get(0).getContent()))); }); @@ -102,29 +98,4 @@ public class XingHuoChatClient extends AbstractFunctionCallSupport conversationHistory) { - return null; - } - - @Override - protected List doGetUserMessages(XingHuoChatCompletionRequest request) { - return null; - } - - @Override - protected XingHuoChatCompletionMessage doGetToolResponseMessage(ResponseEntity response) { - return null; - } - - @Override - protected ResponseEntity doChatCompletion(XingHuoChatCompletionRequest request) { - return xingHuoApi.chatCompletionEntity(request); - } - - @Override - protected boolean isToolFunctionCall(ResponseEntity response) { - return false; - } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java index fb7f155b4..58cc622c4 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java @@ -7,13 +7,9 @@ import cn.iocoder.yudao.framework.ai.chat.StreamingChatClient; import cn.iocoder.yudao.framework.ai.chat.messages.Message; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletion; -import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletionMessage; import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletionRequest; import cn.iocoder.yudao.framework.ai.chatyiyan.exception.YiYanApiException; -import cn.iocoder.yudao.framework.ai.model.function.AbstractFunctionCallSupport; -import cn.iocoder.yudao.framework.ai.model.function.FunctionCallbackContext; import lombok.extern.slf4j.Slf4j; - import org.springframework.http.ResponseEntity; import org.springframework.retry.RetryCallback; import org.springframework.retry.RetryContext; @@ -32,14 +28,11 @@ import java.util.List; * time: 2024/3/8 19:11 */ @Slf4j -public class YiYanChatClient - extends AbstractFunctionCallSupport> - implements ChatClient, StreamingChatClient { +public class YiYanChatClient implements ChatClient, StreamingChatClient { private YiYanApi yiYanApi; public YiYanChatClient(YiYanApi yiYanApi) { - super(new FunctionCallbackContext()); this.yiYanApi = yiYanApi; } @@ -70,7 +63,7 @@ public class YiYanChatClient // 创建 request 请求,stream模式需要供应商支持 YiYanChatCompletionRequest request = this.createRequest(prompt, false); // 调用 callWithFunctionSupport 发送请求 - ResponseEntity response = this.callWithFunctionSupport(request); + ResponseEntity response = yiYanApi.chatCompletionEntity(request); // 获取结果封装 ChatResponse YiYanChatCompletion chatCompletion = response.getBody(); return new ChatResponse(List.of(new Generation(chatCompletion.getResult()))); @@ -98,40 +91,6 @@ public class YiYanChatClient YiYanChatCompletionRequest request = this.createRequest(prompt, true); // 调用 callWithFunctionSupport 发送请求 Flux response = this.yiYanApi.chatCompletionStream(request); -// response.subscribe(new Consumer() { -// @Override -// public void accept(YiYanChatCompletion chatCompletion) { -// // {"id":"as-p0nfjuuasg","object":"chat.completion","created":1710033402,"sentence_id":0,"is_end":false,"is_truncated":false,"result":"编程语","need_clear_history":false,"finish_reason":"normal","usage":{"prompt_tokens":5,"completion_tokens":0,"total_tokens":5}} -// System.err.println(chatCompletion); -// } -// }); - return response.map(res -> { - return new ChatResponse(List.of(new Generation(res.getResult()))); - }); - } - - @Override - protected YiYanChatCompletionRequest doCreateToolResponseRequest(YiYanChatCompletionRequest previousRequest, YiYanChatCompletionMessage responseMessage, List conversationHistory) { - return null; - } - - @Override - protected List doGetUserMessages(YiYanChatCompletionRequest request) { - return null; - } - - @Override - protected YiYanChatCompletionMessage doGetToolResponseMessage(ResponseEntity response) { - return null; - } - - @Override - protected ResponseEntity doChatCompletion(YiYanChatCompletionRequest request) { - return yiYanApi.chatCompletionEntity(request); - } - - @Override - protected boolean isToolFunctionCall(ResponseEntity response) { - return false; + return response.map(res -> new ChatResponse(List.of(new Generation(res.getResult())))); } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/AbstractFunctionCallSupport.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/AbstractFunctionCallSupport.java index d5becdbb5..33409f72d 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/AbstractFunctionCallSupport.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/AbstractFunctionCallSupport.java @@ -29,11 +29,16 @@ public abstract class AbstractFunctionCallSupport { protected final static boolean IS_RUNTIME_CALL = true; /** + * 函数回调寄存器用于按名称解析函数回调。 + * * The function callback register is used to resolve the function callbacks by name. */ protected final Map functionCallbackRegister = new ConcurrentHashMap<>(); /** + * 函数回调上下文用于按名称解析函数回调来自Spring上下文。 + * 它是可选的,通常与Spring一起使用自动配置。 + * * The function callback context is used to resolve the function callbacks by name * from the Spring context. It is optional and usually used with Spring * auto-configuration. diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallback.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallback.java index d644d517a..a14a59b8f 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallback.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallback.java @@ -17,6 +17,13 @@ package cn.iocoder.yudao.framework.ai.model.function; /** + * + * 表示模型函数调用处理程序。实现已向注册对触发函数调用的提示进行建模和调用。 + * + * https://blog.csdn.net/weixin_37546425/article/details/136402740 + * + * https://www.163.com/dy/article/ICE2S20P05119NPR.html + * * Represents a model function call handler. Implementations are registered with the * Models and called on prompts that trigger the function call. * From 7a785b1ec073171e849cd775f3bf6dfc06b8a1be Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 16 Mar 2024 10:00:13 +0800 Subject: [PATCH 012/684] =?UTF-8?q?=E9=98=BF=E9=87=8C=E9=80=9A=E4=B9=89?= =?UTF-8?q?=E5=8D=83=E9=97=AE=EF=BC=8C=E7=BB=A7=E6=89=BF=20chat=20options?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ai/chat/ChatException.java | 15 ++ .../framework/ai/chatqianwen/QianWenApi.java | 39 +----- .../ai/chatqianwen/QianWenChatClient.java | 83 ++++++++++-- .../ai/chatqianwen/QianWenOptions.java | 128 ++++++++++++++++++ .../ai/chat/QianWenChatClientTests.java | 9 +- 5 files changed, 226 insertions(+), 48 deletions(-) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatException.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenOptions.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatException.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatException.java new file mode 100644 index 000000000..2b9660154 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatException.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.framework.ai.chat; + +/** + * 聊天异常 + * + * author: fansili + * time: 2024/3/15 20:45 + */ +public class ChatException extends RuntimeException { + + public ChatException(String message) { + super(message); + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java index 08d3b8ca5..aefabc62a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.framework.ai.chatqianwen; import com.aliyun.broadscope.bailian.sdk.AccessTokenClient; import com.aliyun.broadscope.bailian.sdk.ApplicationClient; -import com.aliyun.broadscope.bailian.sdk.models.ChatRequestMessage; import com.aliyun.broadscope.bailian.sdk.models.CompletionsRequest; import com.aliyun.broadscope.bailian.sdk.models.CompletionsResponse; import lombok.Getter; @@ -10,8 +9,6 @@ import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; import reactor.core.publisher.Flux; -import java.util.List; - /** * 阿里 通义千问 * @@ -35,11 +32,10 @@ public class QianWenApi { private String token; private ApplicationClient client; - public QianWenApi(String accessKeyId, String accessKeySecret, String agentKey, String appId, String endpoint) { + public QianWenApi(String accessKeyId, String accessKeySecret, String agentKey, String endpoint) { this.accessKeyId = accessKeyId; this.accessKeySecret = accessKeySecret; this.agentKey = agentKey; - this.appId = appId; if (endpoint != null) { this.endpoint = endpoint; @@ -54,35 +50,14 @@ public class QianWenApi { .build(); } - public ResponseEntity chatCompletionEntity(ChatRequestMessage message) { - // 创建request - CompletionsRequest request = new CompletionsRequest() - // 设置 appid - .setAppId(appId) - .setMessages(List.of(message)) - // 返回choice message结果 - .setParameters(new CompletionsRequest.Parameter().setResultFormat("message")); - // + public ResponseEntity chatCompletionEntity(CompletionsRequest request) { + // 发送请求 CompletionsResponse response = client.completions(request); - int httpCode = 200; - if (!response.isSuccess()) { - System.out.printf("failed to create completion, requestId: %s, code: %s, message: %s\n", - response.getRequestId(), response.getCode(), response.getMessage()); - httpCode = 500; - } - return new ResponseEntity<>(response, HttpStatusCode.valueOf(httpCode)); + // 阿里云的这个 http code 随便设置,外面判断是否成功用的 CompletionsResponse.isSuccess + return new ResponseEntity<>(response, HttpStatusCode.valueOf(200)); } - public Flux chatCompletionStream(ChatRequestMessage message) { - return client.streamCompletions( - new CompletionsRequest() - // 设置 appid - .setAppId(appId) - // 开启 stream - .setStream(true) - .setMessages(List.of(message)) - //开启增量输出模式,后面输出不会包含已经输出的内容 - .setParameters(new CompletionsRequest.Parameter().setIncrementalOutput(true)) - ); + public Flux chatCompletionStream(CompletionsRequest request) { + return client.streamCompletions(request); } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java index cf0eae0dd..4be2bf03e 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java @@ -1,14 +1,13 @@ package cn.iocoder.yudao.framework.ai.chatqianwen; -import cn.iocoder.yudao.framework.ai.chat.ChatClient; -import cn.iocoder.yudao.framework.ai.chat.ChatResponse; -import cn.iocoder.yudao.framework.ai.chat.Generation; -import cn.iocoder.yudao.framework.ai.chat.StreamingChatClient; +import cn.hutool.core.util.IdUtil; +import cn.hutool.json.JSONUtil; +import cn.iocoder.yudao.framework.ai.chat.*; +import cn.iocoder.yudao.framework.ai.chat.messages.MessageType; +import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.ai.chatyiyan.exception.YiYanApiException; -import com.aliyun.broadscope.bailian.sdk.models.ChatRequestMessage; -import com.aliyun.broadscope.bailian.sdk.models.ChatUserMessage; -import com.aliyun.broadscope.bailian.sdk.models.CompletionsResponse; +import com.aliyun.broadscope.bailian.sdk.models.*; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.retry.RetryCallback; @@ -19,6 +18,7 @@ import reactor.core.publisher.Flux; import java.time.Duration; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; /** @@ -34,10 +34,17 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient { private QianWenApi qianWenApi; + private ChatOptions chatOptions; + public QianWenChatClient(QianWenApi qianWenApi) { this.qianWenApi = qianWenApi; } + public QianWenChatClient(QianWenApi qianWenApi, ChatOptions chatOptions) { + this.qianWenApi = qianWenApi; + this.chatOptions = chatOptions; + } + public final RetryTemplate retryTemplate = RetryTemplate.builder() // 最大重试次数 10 .maxAttempts(10) @@ -58,7 +65,7 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient { return this.retryTemplate.execute(ctx -> { // ctx 会有重试的信息 // 创建 request 请求,stream模式需要供应商支持 - ChatRequestMessage request = this.createRequest(prompt, false); + CompletionsRequest request = this.createRequest(prompt, false); // 调用 callWithFunctionSupport 发送请求 ResponseEntity responseEntity = qianWenApi.chatCompletionEntity(request); // 获取结果封装 chatCompletion @@ -67,21 +74,69 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient { return new ChatResponse(List.of(new Generation(String.format("failed to create completion, requestId: %s, code: %s, message: %s\n", response.getRequestId(), response.getCode(), response.getMessage())))); } - List generations = response.getData().getChoices().stream() - .map(item -> new Generation(item.getMessage().getContent())).collect(Collectors.toList()); - return new ChatResponse(generations); + // 转换为 Generation 返回 + return new ChatResponse(List.of(new Generation(response.getData().getText()))); }); } - private ChatRequestMessage createRequest(Prompt prompt, boolean b) { - return new ChatUserMessage(prompt.getContents()); + private CompletionsRequest createRequest(Prompt prompt, boolean stream) { + // 两个都为null 则没有配置文件 + if (chatOptions == null && prompt.getOptions() == null) { + throw new ChatException("ChatOptions 未配置参数!"); + } + // 优先使用 Prompt 里面的 ChatOptions + ChatOptions options = chatOptions; + if (prompt.getOptions() != null) { + options = (ChatOptions) prompt.getOptions(); + } + QianWenOptions qianWenOptions = (QianWenOptions) options; + // 需要额外处理 + if (!stream) { + // 如果不需要 stream 输出,那么需要将这个设置为false,不然只会输出最后几个文字 + if (qianWenOptions.getParameters() == null) { + qianWenOptions.setParameters(new CompletionsRequest.Parameter().setIncrementalOutput(false)); + } else { + qianWenOptions.getParameters().setIncrementalOutput(false); + } + } else { + // 如果不需要 stream 输出,设置为true这样不会输出累加内容 + if (qianWenOptions.getParameters() == null) { + qianWenOptions.setParameters(new CompletionsRequest.Parameter().setIncrementalOutput(true)); + } else { + qianWenOptions.getParameters().setIncrementalOutput(true); + } + } + + // 创建request + return new CompletionsRequest() + // 请求唯一标识,请确保RequestId不重复。 + .setRequestId(IdUtil.getSnowflakeNextIdStr()) + // 设置 appid + .setAppId(qianWenOptions.getAppId()) + .setMessages(prompt.getInstructions().stream().map(m -> { + // 转换成 千问 对于的请求message + if (MessageType.USER == m.getMessageType()) { + return new ChatUserMessage(m.getContent()); + } else if (MessageType.SYSTEM == m.getMessageType()) { + return new ChatSystemMessage(m.getContent()); + } else if (MessageType.ASSISTANT == m.getMessageType()) { + return new ChatAssistantMessage(m.getContent()); + } + throw new ChatException(String.format("存在不能适配的消息! %s", JSONUtil.toJsonPrettyStr(m))); + }).collect(Collectors.toList())) + // 返回choice message结果 + .setParameters(qianWenOptions.getParameters()) + // 设置 ChatOptions 里面公共的参数 + .setTopP(options.getTopP() == null ? null : options.getTopP().doubleValue()) + // 设置输出方式 + .setStream(stream); } @Override public Flux stream(Prompt prompt) { // ctx 会有重试的信息 // 创建 request 请求,stream模式需要供应商支持 - ChatRequestMessage request = this.createRequest(prompt, true); + CompletionsRequest request = this.createRequest(prompt, true); // 调用 callWithFunctionSupport 发送请求 Flux response = this.qianWenApi.chatCompletionStream(request); return response.map(res -> { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenOptions.java new file mode 100644 index 000000000..26c6ef66f --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenOptions.java @@ -0,0 +1,128 @@ +package cn.iocoder.yudao.framework.ai.chatqianwen; + +import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; +import com.aliyun.broadscope.bailian.sdk.models.CompletionsRequest; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; + +/** + * 阿里云 千问 属性 + * + * 地址:https://help.aliyun.com/document_detail/2684682.html?spm=a2c4g.2621347.0.0.195117e7Ytpkyo + * + * author: fansili + * time: 2024/3/15 19:57 + */ +@Data +@Accessors +public class QianWenOptions implements ChatOptions { + + private String appId; + /** + * 是否流式输出, 默认为否。 + */ + private Boolean stream; + /** + * 用户与模型的对话历史 + */ + private List messages; + /** + * 生成时,核采样方法的概率阈值。例如,取值为0.8时,仅保留累计概率之和大于等于0.8的概率分布中的token, + * 作为随机采样的候选集。取值范围为(0,1.0),取值越大,生成的随机性越高;取值越低,生成的随机性越低。 + * 默认值为0.8。注意,取值不要大于等于1 + */ + private Float topP; + /** + * 模型参数设置。 + */ + private CompletionsRequest.Parameter parameters = new CompletionsRequest.Parameter(); + + // + // 适配 ChatOptions + + @Override + public Float getTemperature() { + return Float.parseFloat(this.parameters.getTemperature().toString()); + } + + @Override + public void setTemperature(Float temperature) { + this.parameters.setTemperature(Double.valueOf(temperature.toString())); + } + + @Override + public void setTopP(Float topP) { + this.topP = topP; + } + + @Override + public Integer getTopK() { + return this.parameters.getTopK(); + } + + @Override + public void setTopK(Integer topK) { + this.parameters.setTopK(topK); + } + + @Data + @Accessors + public static class Message { + /** + * 角色: system、user或assistant + */ + private String role; + /** + * 提示词或模型内容 + */ + private String content; + } + + @Data + @Accessors + public static class Parameters { + /** + * 输出格式, 默认为"text" + * "text"表示旧版本的text + * "message"表示兼容openai的message + */ + private String resultFormat; + /** + * 生成时,采样候选集的大小。例如,取值为50时,仅将单次生成中得分最高的50个token组成随机采样的候选集。 + * 取值越大,生成的随机性越高;取值越小,生成的确定性越高。 + * 注意:如果top_k参数为空或者top_k的值大于100,表示不启用top_k策略,此时仅有top_p策略生效,默认是空。 + */ + private Integer topK; + /** + * 生成时使用的随机数种子,用户控制模型生成内容的随机性。 + * seed支持无符号64位整数,默认值为1234。在使用seed时,模型将尽可能生成相同或相似的结果,但目前不保证每次生成的结果完全相同。 + */ + private Integer seed; + /** + * 用于控制随机性和多样性的程度。具体来说,temperature值控制了生成文本时对每个候选词的概率分布进行平滑的程度。 + * 较高的temperature值会降低概率分布的峰值,使得更多的低概率词被选择, + * 生成结果更加多样化;而较低的temperature值则会增强概率分布的峰值,使得高概率词更容易被选择,生成结果更加确定。 + * 取值范围: [0, 2),系统默认值1.0。不建议取值为0,无意义。 + */ + private Float temperature; + /** + * 用于限制模型生成token的数量,max_tokens设置的是生成上限,并不表示一定会生成这么多的token数量。 + * 其中qwen-turbo 最大值和默认值为1500, qwen-max、qwen-max-1201 、qwen-max-longcontext 和 qwen-plus最大值和默认值均为2000。 + */ + private Integer maxTokens; + /** + * stop参数用于实现内容生成过程的精确控制,在生成内容即将包含指定的字符串或token_ids时自动停止,生成内容不包含指定的内容。 + * 例如,如果指定stop为"你好",表示将要生成"你好"时停止;如果指定stop为[37763, 367],表示将要生成"Observation"时停止。 + */ + private List stop; + /** + * 用于控制流式输出模式,默认False,即后面内容会包含已经输出的内容;设置为True,将开启增量输出模式, + * 后面输出不会包含已经输出的内容,您需要自行拼接整体输出,参考流式输出示例代码。 + */ + private Boolean incrementalOutput; + } +} + + diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java index 745af8263..2c2b44685 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java @@ -3,6 +3,8 @@ package cn.iocoder.yudao.framework.ai.chat; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenApi; import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient; +import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenOptions; +import com.aliyun.broadscope.bailian.sdk.models.CompletionsRequest; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; @@ -24,10 +26,13 @@ public class QianWenChatClientTests { "", "", "", - "", null ); - qianWenChatClient = new QianWenChatClient(qianWenApi); + qianWenChatClient = new QianWenChatClient( + qianWenApi, + new QianWenOptions() + .setAppId("5f14955f201a44eb8dbe0c57250a32ce") + ); } @Test From 6415422f7dfb823fe0c5c5bf494dde1d78062f72 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 16 Mar 2024 19:47:14 +0800 Subject: [PATCH 013/684] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20client=20=E6=9E=84?= =?UTF-8?q?=E9=80=A0=E6=96=B9=E6=B3=95=EF=BC=8C=E5=88=B6=E5=AE=9A=E4=BC=A0?= =?UTF-8?q?=E5=85=A5=20QianWenOptions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ai/chatqianwen/QianWenChatClient.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java index 4be2bf03e..52b2c7b79 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java @@ -34,15 +34,15 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient { private QianWenApi qianWenApi; - private ChatOptions chatOptions; + private QianWenOptions qianWenOptions; public QianWenChatClient(QianWenApi qianWenApi) { this.qianWenApi = qianWenApi; } - public QianWenChatClient(QianWenApi qianWenApi, ChatOptions chatOptions) { + public QianWenChatClient(QianWenApi qianWenApi, QianWenOptions qianWenOptions) { this.qianWenApi = qianWenApi; - this.chatOptions = chatOptions; + this.qianWenOptions = qianWenOptions; } public final RetryTemplate retryTemplate = RetryTemplate.builder() @@ -81,11 +81,11 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient { private CompletionsRequest createRequest(Prompt prompt, boolean stream) { // 两个都为null 则没有配置文件 - if (chatOptions == null && prompt.getOptions() == null) { + if (qianWenOptions == null && prompt.getOptions() == null) { throw new ChatException("ChatOptions 未配置参数!"); } // 优先使用 Prompt 里面的 ChatOptions - ChatOptions options = chatOptions; + ChatOptions options = qianWenOptions; if (prompt.getOptions() != null) { options = (ChatOptions) prompt.getOptions(); } From 1fada268ac9dd4314c10085234f24f035e46adb7 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 16 Mar 2024 19:54:20 +0800 Subject: [PATCH 014/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20QianWenOptions=20?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E5=88=A4=E6=96=AD=EF=BC=8C=E9=81=BF=E5=85=8D?= =?UTF-8?q?=E5=BC=BA=E8=BD=AC=E5=A4=B1=E8=B4=A5=EF=BC=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/framework/ai/chatqianwen/QianWenChatClient.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java index 52b2c7b79..f704dee1c 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.ai.chat.*; import cn.iocoder.yudao.framework.ai.chat.messages.MessageType; import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; +import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanOptions; import cn.iocoder.yudao.framework.ai.chatyiyan.exception.YiYanApiException; import com.aliyun.broadscope.bailian.sdk.models.*; import lombok.extern.slf4j.Slf4j; @@ -89,6 +90,10 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient { if (prompt.getOptions() != null) { options = (ChatOptions) prompt.getOptions(); } + // Prompt 里面是一个 ChatOptions,用户可以随意传入,这里做一下判断 + if (!(options instanceof QianWenOptions)) { + throw new ChatException("Prompt 传入的不是 QianWenOptions!"); + } QianWenOptions qianWenOptions = (QianWenOptions) options; // 需要额外处理 if (!stream) { From f41e43713c9ca32bf72420f6c135b5bb7ea1e01e Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 16 Mar 2024 20:28:35 +0800 Subject: [PATCH 015/684] =?UTF-8?q?=E7=99=BE=E5=BA=A6=20=E6=96=87=E5=BF=83?= =?UTF-8?q?=E4=B8=80=E8=A8=80=20=E9=80=82=E9=85=8DchatOptions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/chatyiyan/YiYanChatClient.java | 61 +++++--- .../framework/ai/chatyiyan/YiYanOptions.java | 144 ++++++++++++++++++ .../api/YiYanChatCompletionRequest.java | 10 +- .../ai/chat/QianWenChatClientTests.java | 6 +- .../framework/ai/chat/YiYanChatTests.java | 11 +- 5 files changed, 197 insertions(+), 35 deletions(-) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanOptions.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java index 58cc622c4..c38dae493 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java @@ -1,10 +1,8 @@ package cn.iocoder.yudao.framework.ai.chatyiyan; -import cn.iocoder.yudao.framework.ai.chat.ChatClient; -import cn.iocoder.yudao.framework.ai.chat.ChatResponse; -import cn.iocoder.yudao.framework.ai.chat.Generation; -import cn.iocoder.yudao.framework.ai.chat.StreamingChatClient; -import cn.iocoder.yudao.framework.ai.chat.messages.Message; +import cn.hutool.core.bean.BeanUtil; +import cn.iocoder.yudao.framework.ai.chat.*; +import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletion; import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletionRequest; @@ -18,7 +16,6 @@ import org.springframework.retry.support.RetryTemplate; import reactor.core.publisher.Flux; import java.time.Duration; -import java.util.ArrayList; import java.util.List; /** @@ -32,10 +29,17 @@ public class YiYanChatClient implements ChatClient, StreamingChatClient { private YiYanApi yiYanApi; + private YiYanOptions yiYanOptions; + public YiYanChatClient(YiYanApi yiYanApi) { this.yiYanApi = yiYanApi; } + public YiYanChatClient(YiYanApi yiYanApi, YiYanOptions yiYanOptions) { + this.yiYanApi = yiYanApi; + this.yiYanOptions = yiYanOptions; + } + public final RetryTemplate retryTemplate = RetryTemplate.builder() // 最大重试次数 10 .maxAttempts(10) @@ -70,20 +74,6 @@ public class YiYanChatClient implements ChatClient, StreamingChatClient { }); } - private YiYanChatCompletionRequest createRequest(Prompt prompt, boolean stream) { - List messages = new ArrayList<>(); - List instructions = prompt.getInstructions(); - for (Message instruction : instructions) { - YiYanChatCompletionRequest.Message message = new YiYanChatCompletionRequest.Message(); - message.setContent(instruction.getContent()); - message.setRole(instruction.getMessageType().getValue()); - messages.add(message); - } - YiYanChatCompletionRequest request = new YiYanChatCompletionRequest(messages); - request.setStream(stream); - return request; - } - @Override public Flux stream(Prompt prompt) { // ctx 会有重试的信息 @@ -93,4 +83,35 @@ public class YiYanChatClient implements ChatClient, StreamingChatClient { Flux response = this.yiYanApi.chatCompletionStream(request); return response.map(res -> new ChatResponse(List.of(new Generation(res.getResult())))); } + + private YiYanChatCompletionRequest createRequest(Prompt prompt, boolean stream) { + // 两个都为null 则没有配置文件 + if (yiYanOptions == null && prompt.getOptions() == null) { + throw new ChatException("ChatOptions 未配置参数!"); + } + // 优先使用 Prompt 里面的 ChatOptions + ChatOptions options = yiYanOptions; + if (prompt.getOptions() != null) { + options = (ChatOptions) prompt.getOptions(); + } + // Prompt 里面是一个 ChatOptions,用户可以随意传入,这里做一下判断 + if (!(options instanceof YiYanOptions)) { + throw new ChatException("Prompt 传入的不是 YiYanOptions!"); + } + // 转换 YiYanOptions + YiYanOptions qianWenOptions = (YiYanOptions) options; + // 创建 request + List messageList = prompt.getInstructions().stream().map( + msg -> new YiYanChatCompletionRequest.Message() + .setRole(msg.getMessageType().getValue()) + .setContent(msg.getContent()) + ).toList(); + YiYanChatCompletionRequest request = new YiYanChatCompletionRequest(messageList); + // 复制 qianWenOptions 属性取 request(这里 options 属性和 request 基本保持一致) + // top: 由于遵循 spring-ai规范,支持在构建client的时候传入默认的 chatOptions + BeanUtil.copyProperties(qianWenOptions, request); + // 设置 stream + request.setStream(stream); + return request; + } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanOptions.java new file mode 100644 index 000000000..4b1bc3fe6 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanOptions.java @@ -0,0 +1,144 @@ +package cn.iocoder.yudao.framework.ai.chatyiyan; + +import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; +import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletionRequest; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; + +/** + * 百度 问心一言 + * + * 文档地址:https://cloud.baidu.com/doc/WENXINWORKSHOP/s/clntwmv7t + * + * author: fansili + * time: 2024/3/16 19:33 + */ +@Data +@Accessors(chain = true) +public class YiYanOptions implements ChatOptions { + + /** + * 一个可触发函数的描述列表,说明: + * (1)支持的function数量无限制 + * (2)长度限制,最后一个message的content长度(即此轮对话的问题)、functions和system字段总内容不能超过20480 个字符,且不能超过5120 tokens + * 必填:否 + */ + private List functions; + /** + * 说明: + * (1)较高的数值会使输出更加随机,而较低的数值会使其更加集中和确定 + * (2)默认0.8,范围 (0, 1.0],不能为0 + * 必填:否 + */ + private Float temperature; + /** + * 说明: + * (1)影响输出文本的多样性,取值越大,生成文本的多样性越强 + * (2)默认0.8,取值范围 [0, 1.0] + * 必填:否 + */ + private Float top_p; + /** + * 通过对已生成的token增加惩罚,减少重复生成的现象。说明: + * (1)值越大表示惩罚越大 + * (2)默认1.0,取值范围:[1.0, 2.0] + * + * 必填:否 + */ + private Float penalty_score; + /** + * 是否以流式接口的形式返回数据,默认false + * 必填:否 + */ + private Boolean stream; + /** + * 模型人设,主要用于人设设定,例如,你是xxx公司制作的AI助手,说明: + * (1)长度限制,最后一个message的content长度(即此轮对话的问题)、functions和system字段总内容不能超过20480 个字符,且不能超过5120 tokens + * (2)如果同时使用system和functions,可能暂无法保证使用效果,持续进行优化 + * 必填:否 + */ + private String system; + /** + * 生成停止标识,当模型生成结果以stop中某个元素结尾时,停止文本生成。说明: + * (1)每个元素长度不超过20字符 + * (2)最多4个元素 + * 必填:否 + */ + private List stop; + /** + * 是否强制关闭实时搜索功能,默认false,表示不关闭 + * 必填:否 + */ + private Boolean disable_search; + /** + * 是否开启上角标返回,说明: + * (1)开启后,有概率触发搜索溯源信息search_info,search_info内容见响应参数介绍 + * (2)默认false,不开启 + * 必填:否 + */ + private Boolean enable_citation; + /** + * 指定模型最大输出token数,范围[2, 2048] + * 必填:否 + */ + private Integer max_output_tokens; + /** + * 指定响应内容的格式,说明: + * (1)可选值: + * · json_object:以json格式返回,可能出现不满足效果情况 + * · text:以文本格式返回 + * (2)如果不填写参数response_format值,默认为text + * 必填:否 + */ + private String response_format; + /** + * 表示最终用户的唯一标识符 + * 必填:否 + */ + private String user_id; + /** + * 在函数调用场景下,提示大模型选择指定的函数(非强制),说明:指定的函数名必须在functions中存在 + * 必填:否 + * + * ERNIE-4.0-8K 模型没有这个字段 + */ + private String tool_choice; + + // + // 以下兼容 spring-ai ChatOptions 暂时没有其他地方用到 + + @Override + public Float getTemperature() { + return this.temperature; + } + + @Override + public void setTemperature(Float temperature) { + this.temperature = temperature; + } + + @Override + public Float getTopP() { + return top_p; + } + + @Override + public void setTopP(Float topP) { + this.top_p = topP; + } + + // 百度么有 topK + + @Override + public Integer getTopK() { + return null; + } + + @Override + public void setTopK(Integer topK) { + + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletionRequest.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletionRequest.java index 8c80d55f7..de6c19ee1 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletionRequest.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletionRequest.java @@ -37,14 +37,14 @@ public class YiYanChatCompletionRequest { * (2)默认0.8,范围 (0, 1.0],不能为0 * 必填:否 */ - private String temperature; + private Float temperature; /** * 说明: * (1)影响输出文本的多样性,取值越大,生成文本的多样性越强 * (2)默认0.8,取值范围 [0, 1.0] * 必填:否 */ - private String top_p; + private Float top_p; /** * 通过对已生成的token增加惩罚,减少重复生成的现象。说明: * (1)值越大表示惩罚越大 @@ -52,7 +52,7 @@ public class YiYanChatCompletionRequest { * * 必填:否 */ - private String penalty_score; + private Float penalty_score; /** * 是否以流式接口的形式返回数据,默认false * 必填:否 @@ -71,7 +71,7 @@ public class YiYanChatCompletionRequest { * (2)最多4个元素 * 必填:否 */ - private String stop; + private List stop; /** * 是否强制关闭实时搜索功能,默认false,表示不关闭 * 必填:否 @@ -106,6 +106,8 @@ public class YiYanChatCompletionRequest { /** * 在函数调用场景下,提示大模型选择指定的函数(非强制),说明:指定的函数名必须在functions中存在 * 必填:否 + * + * ERNIE-4.0-8K 模型没有这个字段 */ private String tool_choice; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java index 2c2b44685..14b839747 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java @@ -23,9 +23,9 @@ public class QianWenChatClientTests { @Before public void setup() { QianWenApi qianWenApi = new QianWenApi( - "", - "", - "", + "LTAI5tNTVhXW4fLKUjMrr98z", + "ZJ0JQeyjzxxm5CfeTV6k1wNE9UsvZP", + "f0c1088824594f589c8f10567ccd929f_p_efm", null ); qianWenChatClient = new QianWenChatClient( diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java index 346ffedb1..cff4caa17 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java @@ -4,12 +4,12 @@ import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanApi; import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatClient; import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel; +import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanOptions; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; import java.util.Scanner; -import java.util.function.Consumer; /** * chat 文心一言 @@ -29,7 +29,7 @@ public class YiYanChatTests { YiYanChatModel.ERNIE4_3_5_8K, 86400 ); - yiYanChatClient = new YiYanChatClient(yiYanApi); + yiYanChatClient = new YiYanChatClient(yiYanApi, new YiYanOptions().setMax_output_tokens(2048)); } @Test @@ -41,12 +41,7 @@ public class YiYanChatTests { @Test public void streamTest() { Flux fluxResponse = yiYanChatClient.stream(new Prompt("用java帮我写一个快排算法?")); - fluxResponse.subscribe(new Consumer() { - @Override - public void accept(ChatResponse chatResponse) { - System.err.print(chatResponse.getResult().getOutput().getContent()); - } - }); + fluxResponse.subscribe(chatResponse -> System.err.print(chatResponse.getResult().getOutput().getContent())); // 阻止退出 Scanner scanner = new Scanner(System.in); scanner.nextLine(); From 94e9ee959017cf8ab45c3449fe2c3da5d5687bb6 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 16 Mar 2024 21:24:57 +0800 Subject: [PATCH 016/684] =?UTF-8?q?=E9=80=82=E9=85=8D=E8=AE=AF=E9=A3=9E?= =?UTF-8?q?=E6=98=9F=E7=81=AB=20chatOptions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/chatqianwen/QianWenChatClient.java | 2 - .../framework/ai/chatxinghuo/XingHuoApi.java | 14 ++-- .../ai/chatxinghuo/XingHuoChatClient.java | 80 +++++++++++++------ .../ai/chatxinghuo/XingHuoOptions.java | 76 ++++++++++++++++++ .../api/XingHuoChatCompletionRequest.java | 21 ++++- .../exception/XingHuoApiException.java | 14 ---- .../ai/chat/QianWenChatClientTests.java | 6 +- .../ai/chat/XingHuoChatClientTests.java | 7 +- 8 files changed, 162 insertions(+), 58 deletions(-) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoOptions.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/exception/XingHuoApiException.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java index f704dee1c..60b533559 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java @@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.ai.chat.*; import cn.iocoder.yudao.framework.ai.chat.messages.MessageType; import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; -import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanOptions; import cn.iocoder.yudao.framework.ai.chatyiyan.exception.YiYanApiException; import com.aliyun.broadscope.bailian.sdk.models.*; import lombok.extern.slf4j.Slf4j; @@ -19,7 +18,6 @@ import reactor.core.publisher.Flux; import java.time.Duration; import java.util.List; -import java.util.Optional; import java.util.stream.Collectors; /** diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoApi.java index a053884a2..323b8a7b7 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoApi.java @@ -39,22 +39,20 @@ public class XingHuoApi { private String appKey; private String secretKey; private WebClient webClient; - private XingHuoChatModel useChatModel; // 创建 WebSocketClient 实例 private ReactorNettyWebSocketClient socketClient = new ReactorNettyWebSocketClient(); - public XingHuoApi(String appId, String appKey, String secretKey, XingHuoChatModel useChatModel) { + public XingHuoApi(String appId, String appKey, String secretKey) { this.appId = appId; this.appKey = appKey; this.secretKey = secretKey; - this.useChatModel = useChatModel; - } - public ResponseEntity chatCompletionEntity(XingHuoChatCompletionRequest request) { + public ResponseEntity chatCompletionEntity(XingHuoChatCompletionRequest request, XingHuoChatModel xingHuoChatModel) { String authUrl; try { - authUrl = getAuthorizationUrl("spark-api.xf-yun.com", useChatModel.getUri()); +// XingHuoChatModel useChatModel; + authUrl = getAuthorizationUrl("spark-api.xf-yun.com", xingHuoChatModel.getUri()); } catch (NoSuchAlgorithmException | InvalidKeyException e) { throw new RuntimeException(e); } @@ -125,10 +123,10 @@ public class XingHuoApi { return "wss://" + host + path + "?" + toParams; } - public Flux chatCompletionStream(XingHuoChatCompletionRequest request) { + public Flux chatCompletionStream(XingHuoChatCompletionRequest request, XingHuoChatModel xingHuoChatModel) { String authUrl; try { - authUrl = getAuthorizationUrl("spark-api.xf-yun.com", useChatModel.getUri()); + authUrl = getAuthorizationUrl("spark-api.xf-yun.com", xingHuoChatModel.getUri()); } catch (NoSuchAlgorithmException | InvalidKeyException e) { throw new RuntimeException(e); } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java index 23e85be6d..eef59cac0 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java @@ -1,13 +1,12 @@ package cn.iocoder.yudao.framework.ai.chatxinghuo; -import cn.iocoder.yudao.framework.ai.chat.ChatClient; -import cn.iocoder.yudao.framework.ai.chat.ChatResponse; -import cn.iocoder.yudao.framework.ai.chat.Generation; -import cn.iocoder.yudao.framework.ai.chat.StreamingChatClient; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.exceptions.ExceptionUtil; +import cn.iocoder.yudao.framework.ai.chat.*; +import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletion; import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletionRequest; -import cn.iocoder.yudao.framework.ai.chatxinghuo.exception.XingHuoApiException; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.retry.RetryCallback; @@ -31,16 +30,19 @@ public class XingHuoChatClient implements ChatClient, StreamingChatClient { private XingHuoApi xingHuoApi; + private XingHuoOptions xingHuoOptions; + public final RetryTemplate retryTemplate = RetryTemplate.builder() // 最大重试次数 10 - .maxAttempts(10) - .retryOn(XingHuoApiException.class) + .maxAttempts(3) + .retryOn(ChatException.class) // 最大重试5次,第一次间隔3000ms,第二次3000ms * 2,第三次3000ms * 3,以此类推,最大间隔3 * 60000ms .exponentialBackoff(Duration.ofMillis(3000), 2, Duration.ofMillis(3 * 60000)) .withListener(new RetryListener() { @Override public void onError(RetryContext context, RetryCallback callback, Throwable throwable) { + System.err.println("正在重试... " + ExceptionUtil.getMessage(throwable)); log.warn("重试异常:" + context.getRetryCount(), throwable); } @@ -52,26 +54,67 @@ public class XingHuoChatClient implements ChatClient, StreamingChatClient { this.xingHuoApi = xingHuoApi; } + public XingHuoChatClient(XingHuoApi xingHuoApi, XingHuoOptions xingHuoOptions) { + this.xingHuoApi = xingHuoApi; + this.xingHuoOptions = xingHuoOptions; + } + @Override public ChatResponse call(Prompt prompt) { return this.retryTemplate.execute(ctx -> { // ctx 会有重试的信息 + // 获取 chatOptions 属性 + XingHuoOptions chatOptions = this.getChatOptions(prompt); // 创建 request 请求,stream模式需要供应商支持 - XingHuoChatCompletionRequest request = this.createRequest(prompt, false); + XingHuoChatCompletionRequest request = this.createRequest(prompt, chatOptions); // 调用 callWithFunctionSupport 发送请求 - ResponseEntity response = xingHuoApi.chatCompletionEntity(request); + ResponseEntity response = xingHuoApi.chatCompletionEntity(request, chatOptions.getDomain()); // 获取结果封装 ChatResponse return new ChatResponse(List.of(new Generation(response.getBody().getPayload().getChoices().getText().get(0).getContent()))); }); } - private XingHuoChatCompletionRequest createRequest(Prompt prompt, boolean b) { + @Override + public Flux stream(Prompt prompt) { + // 获取 chatOptions 属性 + XingHuoOptions chatOptions = this.getChatOptions(prompt); + // 创建 request 请求,stream模式需要供应商支持 + XingHuoChatCompletionRequest request = this.createRequest(prompt, chatOptions); + // 发送请求 + Flux response = this.xingHuoApi.chatCompletionStream(request, chatOptions.getDomain()); + return response.map(res -> { + String content = res.getPayload().getChoices().getText().stream() + .map(item -> item.getContent()).collect(Collectors.joining()); + return new ChatResponse(List.of(new Generation(content))); + }); + } + + private XingHuoOptions getChatOptions(Prompt prompt) { + // 两个都为null 则没有配置文件 + if (xingHuoOptions == null && prompt.getOptions() == null) { + throw new ChatException("ChatOptions 未配置参数!"); + } + // 优先使用 Prompt 里面的 ChatOptions + ChatOptions options = xingHuoOptions; + if (prompt.getOptions() != null) { + options = (ChatOptions) prompt.getOptions(); + } + // Prompt 里面是一个 ChatOptions,用户可以随意传入,这里做一下判断 + if (!(options instanceof XingHuoOptions)) { + throw new ChatException("Prompt 传入的不是 XingHuoOptions!"); + } + return (XingHuoOptions) options; + } + + private XingHuoChatCompletionRequest createRequest(Prompt prompt, XingHuoOptions xingHuoOptions) { // 创建 header XingHuoChatCompletionRequest.Header header = new XingHuoChatCompletionRequest.Header().setApp_id(xingHuoApi.getAppId()); // 创建 params - XingHuoChatCompletionRequest.Parameter parameter = new XingHuoChatCompletionRequest.Parameter() - .setChat(new XingHuoChatCompletionRequest.Parameter.Chat().setDomain(xingHuoApi.getUseChatModel().getValue())); + XingHuoChatCompletionRequest.Parameter.Chat chatParameter = new XingHuoChatCompletionRequest.Parameter.Chat(); + BeanUtil.copyProperties(xingHuoOptions, chatParameter); + chatParameter.setDomain(xingHuoOptions.getDomain().getValue()); + XingHuoChatCompletionRequest.Parameter parameter = new XingHuoChatCompletionRequest.Parameter().setChat(chatParameter); // 创建 payload text 信息 XingHuoChatCompletionRequest.Payload.Message.Text text = new XingHuoChatCompletionRequest.Payload.Message.Text(); text.setRole(XingHuoChatCompletionRequest.Payload.Message.Text.Role.USER.getName()); @@ -85,17 +128,4 @@ public class XingHuoChatClient implements ChatClient, StreamingChatClient { .setParameter(parameter) .setPayload(payload); } - - @Override - public Flux stream(Prompt prompt) { - // 创建 request 请求,stream模式需要供应商支持 - XingHuoChatCompletionRequest request = this.createRequest(prompt, false); - // 发送请求 - Flux response = this.xingHuoApi.chatCompletionStream(request); - return response.map(res -> { - String content = res.getPayload().getChoices().getText().stream() - .map(item -> item.getContent()).collect(Collectors.joining()); - return new ChatResponse(List.of(new Generation(content))); - }); - } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoOptions.java new file mode 100644 index 000000000..5c539d491 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoOptions.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.framework.ai.chatxinghuo; + +import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 讯飞星火 + * + * author: fansili + * time: 2024/3/16 20:29 + */ +@Data +@Accessors(chain = true) +public class XingHuoOptions implements ChatOptions { + + /** + * https://www.xfyun.cn/doc/spark/Web.html#_1-%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E + * + * 指定访问的领域: + * general指向V1.5版本; + * generalv2指向V2版本; + * generalv3指向V3版本; + * generalv3.5指向V3.5版本; + * 注意:不同的取值对应的url也不一样! + */ + private XingHuoChatModel domain = XingHuoChatModel.XING_HUO_3_5; + /** + * 取值范围 (0,1] ,默认值0.5 + */ + private Float temperature; + /** + * V1.5取值为[1,4096] + * V2.0、V3.0和V3.5取值为[1,8192],默认为2048。 + */ + private Integer max_tokens; + /** + * 取值为[1,6],默认为4 + */ + private Integer top_k; + /** + * 需要保障用户下的唯一性,用于关联用户会话 + */ + private String chat_id; + + + @Override + public Float getTemperature() { + return null; + } + + @Override + public void setTemperature(Float temperature) { + + } + + @Override + public Float getTopP() { + return null; + } + + @Override + public void setTopP(Float topP) { + + } + + @Override + public Integer getTopK() { + return null; + } + + @Override + public void setTopK(Integer topK) { + + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletionRequest.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletionRequest.java index 009789cb3..a90697bfc 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletionRequest.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletionRequest.java @@ -45,9 +45,24 @@ public class XingHuoChatCompletionRequest { * generalv3.5指向V3.5版本; * 注意:不同的取值对应的url也不一样! */ - private String domain = "general"; - private Double temperature = 0.5; - private Integer max_tokens = 2048; + private String domain = "generalv3.5"; + /** + * 取值范围 (0,1] ,默认值0.5 + */ + private Float temperature; + /** + * V1.5取值为[1,4096] + * V2.0、V3.0和V3.5取值为[1,8192],默认为2048。 + */ + private Integer max_tokens; + /** + * 取值为[1,6],默认为4 + */ + private Integer top_k; + /** + * 需要保障用户下的唯一性,用于关联用户会话 + */ + private String chat_id; } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/exception/XingHuoApiException.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/exception/XingHuoApiException.java deleted file mode 100644 index cde6147c7..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/exception/XingHuoApiException.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.framework.ai.chatxinghuo.exception; - -/** - * 讯飞星火 exception - * - * author: fansili - * time: 2024/3/11 10:22 - */ -public class XingHuoApiException extends RuntimeException { - - public XingHuoApiException(String message) { - super(message); - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java index 14b839747..2c2b44685 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java @@ -23,9 +23,9 @@ public class QianWenChatClientTests { @Before public void setup() { QianWenApi qianWenApi = new QianWenApi( - "LTAI5tNTVhXW4fLKUjMrr98z", - "ZJ0JQeyjzxxm5CfeTV6k1wNE9UsvZP", - "f0c1088824594f589c8f10567ccd929f_p_efm", + "", + "", + "", null ); qianWenChatClient = new QianWenChatClient( diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java index da8bc9d5d..4a4b06b81 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoApi; import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatClient; import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel; +import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoOptions; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; @@ -28,9 +29,9 @@ public class XingHuoChatClientTests { new XingHuoApi( "13c8cca6", "cb6415c19d6162cda07b47316fcb0416", - "Y2JiYTIxZjA3MDMxMjNjZjQzYzVmNzdh", - XingHuoChatModel.XING_HUO_3_5 - ) + "Y2JiYTIxZjA3MDMxMjNjZjQzYzVmNzdh" + ), + new XingHuoOptions().setDomain(XingHuoChatModel.XING_HUO_3_5) ); } From e889b8c1e0addb87d81c9d1f2f796899852c9813 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 16 Mar 2024 21:38:31 +0800 Subject: [PATCH 017/684] =?UTF-8?q?=E9=80=82=E9=85=8Djdk8(=E6=9A=82?= =?UTF-8?q?=E6=97=B6=E7=BC=96=E8=AF=91=E6=B2=A1=E6=8A=A5=E9=94=99)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao-spring-boot-starter-ai/pom.xml | 4 +- .../yudao/framework/ai/chat/ChatResponse.java | 11 +- .../yudao/framework/ai/chat/Generation.java | 5 +- .../framework/ai/chat/prompt/Prompt.java | 7 +- .../function/FunctionCallbackContext.java | 248 +++++++++--------- .../framework/ai/parser/BeanOutputParser.java | 19 +- .../framework/ai/parser/ListOutputParser.java | 10 +- .../framework/ai/parser/MapOutputParser.java | 13 +- 8 files changed, 171 insertions(+), 146 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml index 276e87733..a90180516 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml @@ -12,8 +12,8 @@ yudao-spring-boot-starter-ai - 21 - 21 + 8 + 8 UTF-8 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatResponse.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatResponse.java index 1360336fb..a6de72d7a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatResponse.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatResponse.java @@ -19,6 +19,8 @@ import cn.iocoder.yudao.framework.ai.chat.metadata.ChatResponseMetadata; import cn.iocoder.yudao.framework.ai.model.ModelResponse; import org.springframework.util.CollectionUtils; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Objects; @@ -54,7 +56,8 @@ public class ChatResponse implements ModelResponse { */ public ChatResponse(List generations, ChatResponseMetadata chatResponseMetadata) { this.chatResponseMetadata = chatResponseMetadata; - this.generations = List.copyOf(generations); +// this.generations = List.copyOf(generations); + this.generations = Collections.unmodifiableList(generations); } /** @@ -98,8 +101,12 @@ public class ChatResponse implements ModelResponse { public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof ChatResponse that)) +// if (!(o instanceof ChatResponse that)) +// return false; + if (!(o instanceof ChatResponse)) { return false; + } + ChatResponse that = (ChatResponse) o; return Objects.equals(chatResponseMetadata, that.chatResponseMetadata) && Objects.equals(generations, that.generations); } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/Generation.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/Generation.java index e84ffd409..1835d16d2 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/Generation.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/Generation.java @@ -63,8 +63,11 @@ public class Generation implements ModelResult { public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof Generation that)) + + if (!(o instanceof Generation)) { return false; + } + Generation that = (Generation) o; return Objects.equals(assistantMessage, that.assistantMessage) && Objects.equals(chatGenerationMetadata, that.chatGenerationMetadata); } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/Prompt.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/Prompt.java index f9eb37409..95b5cd8aa 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/Prompt.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/Prompt.java @@ -16,6 +16,7 @@ package cn.iocoder.yudao.framework.ai.chat.prompt; +import cn.iocoder.yudao.framework.ai.chat.ChatResponse; import cn.iocoder.yudao.framework.ai.chat.messages.Message; import cn.iocoder.yudao.framework.ai.chat.messages.UserMessage; import cn.iocoder.yudao.framework.ai.model.ModelOptions; @@ -86,8 +87,12 @@ public class Prompt implements ModelRequest> { public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof Prompt prompt)) +// if (!(o instanceof Prompt prompt)) +// return false; + if (!(o instanceof Prompt)) { return false; + } + Prompt prompt = (Prompt) o; return Objects.equals(this.messages, prompt.messages) && Objects.equals(this.modelOptions, prompt.modelOptions); } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackContext.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackContext.java index dd5b0ee7c..917882358 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackContext.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackContext.java @@ -1,124 +1,124 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package cn.iocoder.yudao.framework.ai.model.function; - -import com.fasterxml.jackson.annotation.JsonClassDescription; -import org.springframework.beans.BeansException; -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.cloud.function.context.config.FunctionContextUtils; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.annotation.Description; -import org.springframework.context.support.GenericApplicationContext; -import org.springframework.lang.NonNull; -import org.springframework.lang.Nullable; -import org.springframework.util.StringUtils; - -import java.lang.reflect.Type; -import java.util.function.Function; - -/** - * A Spring {@link ApplicationContextAware} implementation that provides a way to retrieve - * a {@link Function} from the Spring context and wrap it into a {@link FunctionCallback}. - * - * The name of the function is determined by the bean name. - * - * The description of the function is determined by the following rules: - *

    - *
  • Provided as a default description
  • - *
  • Provided as a {@code @Description} annotation on the bean
  • - *
  • Provided as a {@code @JsonClassDescription} annotation on the input class
  • - *
- * - * @author Christian Tzolov - * @author Christopher Smith - */ -public class FunctionCallbackContext implements ApplicationContextAware { - - private GenericApplicationContext applicationContext; - - private FunctionCallbackWrapper.Builder.SchemaType schemaType = FunctionCallbackWrapper.Builder.SchemaType.JSON_SCHEMA; - - public void setSchemaType(FunctionCallbackWrapper.Builder.SchemaType schemaType) { - this.schemaType = schemaType; - } - - @Override - public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException { - this.applicationContext = (GenericApplicationContext) applicationContext; - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - public FunctionCallback getFunctionCallback(@NonNull String beanName, @Nullable String defaultDescription) { - - Type beanType = FunctionContextUtils.findType(this.applicationContext.getBeanFactory(), beanName); - - if (beanType == null) { - throw new IllegalArgumentException( - "Functional bean with name: " + beanName + " does not exist in the context."); - } - - if (!Function.class.isAssignableFrom(FunctionTypeUtils.getRawType(beanType))) { - throw new IllegalArgumentException( - "Function call Bean must be of type Function. Found: " + beanType.getTypeName()); - } - - Type functionInputType = TypeResolverHelper.getFunctionArgumentType(beanType, 0); - - Class functionInputClass = FunctionTypeUtils.getRawType(functionInputType); - String functionName = beanName; - String functionDescription = defaultDescription; - - if (!StringUtils.hasText(functionDescription)) { - // Look for a Description annotation on the bean - Description descriptionAnnotation = applicationContext.findAnnotationOnBean(beanName, Description.class); - - if (descriptionAnnotation != null) { - functionDescription = descriptionAnnotation.value(); - } - - if (!StringUtils.hasText(functionDescription)) { - // Look for a JsonClassDescription annotation on the input class - JsonClassDescription jsonClassDescriptionAnnotation = functionInputClass - .getAnnotation(JsonClassDescription.class); - if (jsonClassDescriptionAnnotation != null) { - functionDescription = jsonClassDescriptionAnnotation.value(); - } - } - - if (!StringUtils.hasText(functionDescription)) { - throw new IllegalStateException("Could not determine function description." - + "Please provide a description either as a default parameter, via @Description annotation on the bean " - + "or @JsonClassDescription annotation on the input class."); - } - } - - Object bean = this.applicationContext.getBean(beanName); - - if (bean instanceof Function function) { - return FunctionCallbackWrapper.builder(function) - .withName(functionName) - .withSchemaType(this.schemaType) - .withDescription(functionDescription) - .withInputType(functionInputClass) - .build(); - } - else { - throw new IllegalArgumentException("Bean must be of type Function"); - } - } - -} +///* +// * Copyright 2024-2024 the original author or authors. +// * +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * https://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the License is distributed on an "AS IS" BASIS, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// * See the License for the specific language governing permissions and +// * limitations under the License. +// */ +//package cn.iocoder.yudao.framework.ai.model.function; +// +//import com.fasterxml.jackson.annotation.JsonClassDescription; +//import org.springframework.beans.BeansException; +//import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; +//import org.springframework.cloud.function.context.config.FunctionContextUtils; +//import org.springframework.context.ApplicationContext; +//import org.springframework.context.ApplicationContextAware; +//import org.springframework.context.annotation.Description; +//import org.springframework.context.support.GenericApplicationContext; +//import org.springframework.lang.NonNull; +//import org.springframework.lang.Nullable; +//import org.springframework.util.StringUtils; +// +//import java.lang.reflect.Type; +//import java.util.function.Function; +// +///** +// * A Spring {@link ApplicationContextAware} implementation that provides a way to retrieve +// * a {@link Function} from the Spring context and wrap it into a {@link FunctionCallback}. +// * +// * The name of the function is determined by the bean name. +// * +// * The description of the function is determined by the following rules: +// *
    +// *
  • Provided as a default description
  • +// *
  • Provided as a {@code @Description} annotation on the bean
  • +// *
  • Provided as a {@code @JsonClassDescription} annotation on the input class
  • +// *
+// * +// * @author Christian Tzolov +// * @author Christopher Smith +// */ +//public class FunctionCallbackContext implements ApplicationContextAware { +// +// private GenericApplicationContext applicationContext; +// +// private FunctionCallbackWrapper.Builder.SchemaType schemaType = FunctionCallbackWrapper.Builder.SchemaType.JSON_SCHEMA; +// +// public void setSchemaType(FunctionCallbackWrapper.Builder.SchemaType schemaType) { +// this.schemaType = schemaType; +// } +// +// @Override +// public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException { +// this.applicationContext = (GenericApplicationContext) applicationContext; +// } +// +// @SuppressWarnings({ "rawtypes", "unchecked" }) +// public FunctionCallback getFunctionCallback(@NonNull String beanName, @Nullable String defaultDescription) { +// +// Type beanType = FunctionContextUtils.findType(this.applicationContext.getBeanFactory(), beanName); +// +// if (beanType == null) { +// throw new IllegalArgumentException( +// "Functional bean with name: " + beanName + " does not exist in the context."); +// } +// +// if (!Function.class.isAssignableFrom(FunctionTypeUtils.getRawType(beanType))) { +// throw new IllegalArgumentException( +// "Function call Bean must be of type Function. Found: " + beanType.getTypeName()); +// } +// +// Type functionInputType = TypeResolverHelper.getFunctionArgumentType(beanType, 0); +// +// Class functionInputClass = FunctionTypeUtils.getRawType(functionInputType); +// String functionName = beanName; +// String functionDescription = defaultDescription; +// +// if (!StringUtils.hasText(functionDescription)) { +// // Look for a Description annotation on the bean +// Description descriptionAnnotation = applicationContext.findAnnotationOnBean(beanName, Description.class); +// +// if (descriptionAnnotation != null) { +// functionDescription = descriptionAnnotation.value(); +// } +// +// if (!StringUtils.hasText(functionDescription)) { +// // Look for a JsonClassDescription annotation on the input class +// JsonClassDescription jsonClassDescriptionAnnotation = functionInputClass +// .getAnnotation(JsonClassDescription.class); +// if (jsonClassDescriptionAnnotation != null) { +// functionDescription = jsonClassDescriptionAnnotation.value(); +// } +// } +// +// if (!StringUtils.hasText(functionDescription)) { +// throw new IllegalStateException("Could not determine function description." +// + "Please provide a description either as a default parameter, via @Description annotation on the bean " +// + "or @JsonClassDescription annotation on the input class."); +// } +// } +// +// Object bean = this.applicationContext.getBean(beanName); +// +// if (bean instanceof Function function) { +// return FunctionCallbackWrapper.builder(function) +// .withName(functionName) +// .withSchemaType(this.schemaType) +// .withDescription(functionDescription) +// .withInputType(functionInputClass) +// .build(); +// } +// else { +// throw new IllegalArgumentException("Bean must be of type Function"); +// } +// } +// +//} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/BeanOutputParser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/BeanOutputParser.java index 4eb08ce29..109e75fc4 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/BeanOutputParser.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/BeanOutputParser.java @@ -153,13 +153,18 @@ public class BeanOutputParser implements OutputParser { */ @Override public String getFormat() { - String template = """ - Your response should be in JSON format. - Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation. - Do not include markdown code blocks in your response. - Here is the JSON Schema instance your output must adhere to: - ```%s``` - """; +// String template = """ +// Your response should be in JSON format. +// Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation. +// Do not include markdown code blocks in your response. +// Here is the JSON Schema instance your output must adhere to: +// ```%s``` +// """; + String template = "Your response should be in JSON format.\n" + + "\t\t\t\tDo not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation.\n" + + "\t\t\t\tDo not include markdown code blocks in your response.\n" + + "\t\t\t\tHere is the JSON Schema instance your output must adhere to:\n" + + "\t\t\t\t```%s```"; return String.format(template, this.jsonSchema); } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/ListOutputParser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/ListOutputParser.java index 1eb936eac..37fd49b89 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/ListOutputParser.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/ListOutputParser.java @@ -34,10 +34,12 @@ public class ListOutputParser extends AbstractConversionServiceOutputParser Date: Sat, 16 Mar 2024 21:40:04 +0800 Subject: [PATCH 018/684] =?UTF-8?q?maven=20=E7=BC=96=E8=AF=91=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=2021?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-module-ai/pom.xml | 4 ++-- yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/yudao-module-ai/pom.xml b/yudao-module-ai/pom.xml index d7241b3ec..ad49018f0 100644 --- a/yudao-module-ai/pom.xml +++ b/yudao-module-ai/pom.xml @@ -18,8 +18,8 @@ - 8 - 8 + 21 + 21 UTF-8 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml index a90180516..276e87733 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml @@ -12,8 +12,8 @@ yudao-spring-boot-starter-ai - 8 - 8 + 21 + 21 UTF-8 From 6a3cafb41ee43b4f27d995a892a8fd013784bbe3 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 16 Mar 2024 21:42:31 +0800 Subject: [PATCH 019/684] =?UTF-8?q?=E9=80=82=E9=85=8Djdk8=20-=202=EF=BC=8C?= =?UTF-8?q?=E8=BF=99=E4=B8=AA=E5=9C=B0=E6=96=B9=E4=B8=8D=E4=BC=9A=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../function/FunctionCallbackContext.java | 228 +++++++++--------- 1 file changed, 115 insertions(+), 113 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackContext.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackContext.java index 917882358..ca24e2673 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackContext.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackContext.java @@ -1,113 +1,115 @@ -///* -// * Copyright 2024-2024 the original author or authors. -// * -// * Licensed under the Apache License, Version 2.0 (the "License"); -// * you may not use this file except in compliance with the License. -// * You may obtain a copy of the License at -// * -// * https://www.apache.org/licenses/LICENSE-2.0 -// * -// * Unless required by applicable law or agreed to in writing, software -// * distributed under the License is distributed on an "AS IS" BASIS, -// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// * See the License for the specific language governing permissions and -// * limitations under the License. -// */ -//package cn.iocoder.yudao.framework.ai.model.function; -// -//import com.fasterxml.jackson.annotation.JsonClassDescription; -//import org.springframework.beans.BeansException; -//import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -//import org.springframework.cloud.function.context.config.FunctionContextUtils; -//import org.springframework.context.ApplicationContext; -//import org.springframework.context.ApplicationContextAware; -//import org.springframework.context.annotation.Description; -//import org.springframework.context.support.GenericApplicationContext; -//import org.springframework.lang.NonNull; -//import org.springframework.lang.Nullable; -//import org.springframework.util.StringUtils; -// -//import java.lang.reflect.Type; -//import java.util.function.Function; -// -///** -// * A Spring {@link ApplicationContextAware} implementation that provides a way to retrieve -// * a {@link Function} from the Spring context and wrap it into a {@link FunctionCallback}. -// * -// * The name of the function is determined by the bean name. -// * -// * The description of the function is determined by the following rules: -// *
    -// *
  • Provided as a default description
  • -// *
  • Provided as a {@code @Description} annotation on the bean
  • -// *
  • Provided as a {@code @JsonClassDescription} annotation on the input class
  • -// *
-// * -// * @author Christian Tzolov -// * @author Christopher Smith -// */ -//public class FunctionCallbackContext implements ApplicationContextAware { -// -// private GenericApplicationContext applicationContext; -// -// private FunctionCallbackWrapper.Builder.SchemaType schemaType = FunctionCallbackWrapper.Builder.SchemaType.JSON_SCHEMA; -// -// public void setSchemaType(FunctionCallbackWrapper.Builder.SchemaType schemaType) { -// this.schemaType = schemaType; -// } -// -// @Override -// public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException { -// this.applicationContext = (GenericApplicationContext) applicationContext; -// } -// -// @SuppressWarnings({ "rawtypes", "unchecked" }) -// public FunctionCallback getFunctionCallback(@NonNull String beanName, @Nullable String defaultDescription) { -// -// Type beanType = FunctionContextUtils.findType(this.applicationContext.getBeanFactory(), beanName); -// -// if (beanType == null) { -// throw new IllegalArgumentException( -// "Functional bean with name: " + beanName + " does not exist in the context."); -// } -// -// if (!Function.class.isAssignableFrom(FunctionTypeUtils.getRawType(beanType))) { -// throw new IllegalArgumentException( -// "Function call Bean must be of type Function. Found: " + beanType.getTypeName()); -// } -// -// Type functionInputType = TypeResolverHelper.getFunctionArgumentType(beanType, 0); -// -// Class functionInputClass = FunctionTypeUtils.getRawType(functionInputType); -// String functionName = beanName; -// String functionDescription = defaultDescription; -// -// if (!StringUtils.hasText(functionDescription)) { -// // Look for a Description annotation on the bean -// Description descriptionAnnotation = applicationContext.findAnnotationOnBean(beanName, Description.class); -// -// if (descriptionAnnotation != null) { -// functionDescription = descriptionAnnotation.value(); -// } -// -// if (!StringUtils.hasText(functionDescription)) { -// // Look for a JsonClassDescription annotation on the input class -// JsonClassDescription jsonClassDescriptionAnnotation = functionInputClass -// .getAnnotation(JsonClassDescription.class); -// if (jsonClassDescriptionAnnotation != null) { -// functionDescription = jsonClassDescriptionAnnotation.value(); -// } -// } -// -// if (!StringUtils.hasText(functionDescription)) { -// throw new IllegalStateException("Could not determine function description." -// + "Please provide a description either as a default parameter, via @Description annotation on the bean " -// + "or @JsonClassDescription annotation on the input class."); -// } -// } -// -// Object bean = this.applicationContext.getBean(beanName); -// +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.iocoder.yudao.framework.ai.model.function; + +import com.fasterxml.jackson.annotation.JsonClassDescription; +import org.springframework.beans.BeansException; +import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; +import org.springframework.cloud.function.context.config.FunctionContextUtils; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.annotation.Description; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; +import org.springframework.util.StringUtils; + +import java.lang.reflect.Type; +import java.util.function.Function; + +/** + * A Spring {@link ApplicationContextAware} implementation that provides a way to retrieve + * a {@link Function} from the Spring context and wrap it into a {@link FunctionCallback}. + * + * The name of the function is determined by the bean name. + * + * The description of the function is determined by the following rules: + *
    + *
  • Provided as a default description
  • + *
  • Provided as a {@code @Description} annotation on the bean
  • + *
  • Provided as a {@code @JsonClassDescription} annotation on the input class
  • + *
+ * + * @author Christian Tzolov + * @author Christopher Smith + */ +public class FunctionCallbackContext implements ApplicationContextAware { + + private GenericApplicationContext applicationContext; + + private FunctionCallbackWrapper.Builder.SchemaType schemaType = FunctionCallbackWrapper.Builder.SchemaType.JSON_SCHEMA; + + public void setSchemaType(FunctionCallbackWrapper.Builder.SchemaType schemaType) { + this.schemaType = schemaType; + } + + @Override + public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException { + this.applicationContext = (GenericApplicationContext) applicationContext; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public FunctionCallback getFunctionCallback(@NonNull String beanName, @Nullable String defaultDescription) { + + Type beanType = FunctionContextUtils.findType(this.applicationContext.getBeanFactory(), beanName); + + if (beanType == null) { + throw new IllegalArgumentException( + "Functional bean with name: " + beanName + " does not exist in the context."); + } + + if (!Function.class.isAssignableFrom(FunctionTypeUtils.getRawType(beanType))) { + throw new IllegalArgumentException( + "Function call Bean must be of type Function. Found: " + beanType.getTypeName()); + } + + Type functionInputType = TypeResolverHelper.getFunctionArgumentType(beanType, 0); + + Class functionInputClass = FunctionTypeUtils.getRawType(functionInputType); + String functionName = beanName; + String functionDescription = defaultDescription; + + if (!StringUtils.hasText(functionDescription)) { + // Look for a Description annotation on the bean + Description descriptionAnnotation = applicationContext.findAnnotationOnBean(beanName, Description.class); + + if (descriptionAnnotation != null) { + functionDescription = descriptionAnnotation.value(); + } + + if (!StringUtils.hasText(functionDescription)) { + // Look for a JsonClassDescription annotation on the input class + JsonClassDescription jsonClassDescriptionAnnotation = functionInputClass + .getAnnotation(JsonClassDescription.class); + if (jsonClassDescriptionAnnotation != null) { + functionDescription = jsonClassDescriptionAnnotation.value(); + } + } + + if (!StringUtils.hasText(functionDescription)) { + throw new IllegalStateException("Could not determine function description." + + "Please provide a description either as a default parameter, via @Description annotation on the bean " + + "or @JsonClassDescription annotation on the input class."); + } + } + + Object bean = this.applicationContext.getBean(beanName); + + // TODO: 2024/3/16 fansili 适配jdk8 + return null; // if (bean instanceof Function function) { // return FunctionCallbackWrapper.builder(function) // .withName(functionName) @@ -119,6 +121,6 @@ // else { // throw new IllegalArgumentException("Bean must be of type Function"); // } -// } -// -//} + } + +} From c3e36c19ead84ae4706103470c49cccb440a0ce7 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 17 Mar 2024 09:46:38 +0800 Subject: [PATCH 020/684] =?UTF-8?q?=E5=A4=8D=E5=88=B6=20spring-ai=20image?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/framework/ai/image/Image.java | 73 +++++++++++ .../yudao/framework/ai/image/ImageClient.java | 27 ++++ .../framework/ai/image/ImageGeneration.java | 52 ++++++++ .../ai/image/ImageGenerationMetadata.java | 23 ++++ .../framework/ai/image/ImageMessage.java | 63 ++++++++++ .../framework/ai/image/ImageOptions.java | 37 ++++++ .../ai/image/ImageOptionsBuilder.java | 119 ++++++++++++++++++ .../yudao/framework/ai/image/ImagePrompt.java | 84 +++++++++++++ .../framework/ai/image/ImageResponse.java | 75 +++++++++++ .../ai/image/ImageResponseMetadata.java | 31 +++++ 10 files changed, 584 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/Image.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageClient.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageGeneration.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageGenerationMetadata.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageMessage.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageOptions.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageOptionsBuilder.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImagePrompt.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageResponse.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageResponseMetadata.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/Image.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/Image.java new file mode 100644 index 000000000..b56ceb746 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/Image.java @@ -0,0 +1,73 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.image; + +import java.util.Objects; + +public class Image { + + /** + * The URL where the image can be accessed. + */ + private String url; + + /** + * Base64 encoded image string. + */ + private String b64Json; + + public Image(String url, String b64Json) { + this.url = url; + this.b64Json = b64Json; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getB64Json() { + return b64Json; + } + + public void setB64Json(String b64Json) { + this.b64Json = b64Json; + } + + @Override + public String toString() { + return "Image{" + "url='" + url + '\'' + ", b64Json='" + b64Json + '\'' + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof Image image)) + return false; + return Objects.equals(url, image.url) && Objects.equals(b64Json, image.b64Json); + } + + @Override + public int hashCode() { + return Objects.hash(url, b64Json); + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageClient.java new file mode 100644 index 000000000..3034fbf02 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageClient.java @@ -0,0 +1,27 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.image; + + +import cn.iocoder.yudao.framework.ai.model.ModelClient; + +@FunctionalInterface +public interface ImageClient extends ModelClient { + + ImageResponse call(ImagePrompt request); + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageGeneration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageGeneration.java new file mode 100644 index 000000000..16942fde1 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageGeneration.java @@ -0,0 +1,52 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.image; + + +import cn.iocoder.yudao.framework.ai.model.ModelResult; + +public class ImageGeneration implements ModelResult { + + private ImageGenerationMetadata imageGenerationMetadata; + + private Image image; + + public ImageGeneration(Image image) { + this.image = image; + } + + public ImageGeneration(Image image, ImageGenerationMetadata imageGenerationMetadata) { + this.image = image; + this.imageGenerationMetadata = imageGenerationMetadata; + } + + @Override + public Image getOutput() { + return image; + } + + @Override + public ImageGenerationMetadata getMetadata() { + return imageGenerationMetadata; + } + + @Override + public String toString() { + return "ImageGeneration{" + "imageGenerationMetadata=" + imageGenerationMetadata + ", image=" + image + '}'; + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageGenerationMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageGenerationMetadata.java new file mode 100644 index 000000000..1d620d2c7 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageGenerationMetadata.java @@ -0,0 +1,23 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.image; + +import cn.iocoder.yudao.framework.ai.model.ResultMetadata; + +public interface ImageGenerationMetadata extends ResultMetadata { + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageMessage.java new file mode 100644 index 000000000..6a01c6c21 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageMessage.java @@ -0,0 +1,63 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.image; + +import java.util.Objects; + +public class ImageMessage { + + private String text; + + private Float weight; + + public ImageMessage(String text) { + this.text = text; + } + + public ImageMessage(String text, Float weight) { + this.text = text; + this.weight = weight; + } + + public String getText() { + return text; + } + + public Float getWeight() { + return weight; + } + + @Override + public String toString() { + return "mageMessage{" + "text='" + text + '\'' + ", weight=" + weight + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof ImageMessage that)) + return false; + return Objects.equals(text, that.text) && Objects.equals(weight, that.weight); + } + + @Override + public int hashCode() { + return Objects.hash(text, weight); + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageOptions.java new file mode 100644 index 000000000..d9cfd0e86 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageOptions.java @@ -0,0 +1,37 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.image; + +import cn.iocoder.yudao.framework.ai.model.ModelOptions; + +/** + * ImageOptions represent the common options, portable across different image generation + * models. + */ +public interface ImageOptions extends ModelOptions { + + Integer getN(); + + String getModel(); + + Integer getWidth(); + + Integer getHeight(); + + String getResponseFormat(); // openai - url or base64 : stability ai byte[] or base64 + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageOptionsBuilder.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageOptionsBuilder.java new file mode 100644 index 000000000..d1bc47473 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageOptionsBuilder.java @@ -0,0 +1,119 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.image; + +public class ImageOptionsBuilder { + + private class ImageModelOptionsImpl implements ImageOptions { + + private Integer n; + + private String model; + + private Integer width; + + private Integer height; + + private String responseFormat; + + @Override + public Integer getN() { + return n; + } + + public void setN(Integer n) { + this.n = n; + } + + @Override + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + @Override + public String getResponseFormat() { + return responseFormat; + } + + public void setResponseFormat(String responseFormat) { + this.responseFormat = responseFormat; + } + + @Override + public Integer getWidth() { + return width; + } + + public void setWidth(Integer width) { + this.width = width; + } + + @Override + public Integer getHeight() { + return height; + } + + public void setHeight(Integer height) { + this.height = height; + } + + } + + private final ImageModelOptionsImpl options = new ImageModelOptionsImpl(); + + private ImageOptionsBuilder() { + + } + + public static ImageOptionsBuilder builder() { + return new ImageOptionsBuilder(); + } + + public ImageOptionsBuilder withN(Integer n) { + options.setN(n); + return this; + } + + public ImageOptionsBuilder withModel(String model) { + options.setModel(model); + return this; + } + + public ImageOptionsBuilder withResponseFormat(String responseFormat) { + options.setResponseFormat(responseFormat); + return this; + } + + public ImageOptionsBuilder withWidth(Integer width) { + options.setWidth(width); + return this; + } + + public ImageOptionsBuilder withHeight(Integer height) { + options.setHeight(height); + return this; + } + + public ImageOptions build() { + return options; + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImagePrompt.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImagePrompt.java new file mode 100644 index 000000000..c8fac6ef6 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImagePrompt.java @@ -0,0 +1,84 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.image; + +import cn.iocoder.yudao.framework.ai.model.ModelRequest; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +/** + * 图片内容 + */ +public class ImagePrompt implements ModelRequest> { + + private final List messages; + + private ImageOptions imageModelOptions; + + public ImagePrompt(List messages) { + this.messages = messages; + } + + public ImagePrompt(List messages, ImageOptions imageModelOptions) { + this.messages = messages; + this.imageModelOptions = imageModelOptions; + } + + public ImagePrompt(ImageMessage imageMessage, ImageOptions imageOptions) { + this(Collections.singletonList(imageMessage), imageOptions); + } + + public ImagePrompt(String instructions, ImageOptions imageOptions) { + this(new ImageMessage(instructions), imageOptions); + } + + public ImagePrompt(String instructions) { + this(new ImageMessage(instructions), ImageOptionsBuilder.builder().build()); + } + + @Override + public List getInstructions() { + return messages; + } + + @Override + public ImageOptions getOptions() { + return imageModelOptions; + } + + @Override + public String toString() { + return "NewImagePrompt{" + "messages=" + messages + ", imageModelOptions=" + imageModelOptions + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof ImagePrompt that)) + return false; + return Objects.equals(messages, that.messages) && Objects.equals(imageModelOptions, that.imageModelOptions); + } + + @Override + public int hashCode() { + return Objects.hash(messages, imageModelOptions); + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageResponse.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageResponse.java new file mode 100644 index 000000000..ca91be5c0 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageResponse.java @@ -0,0 +1,75 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.image; + +import cn.iocoder.yudao.framework.ai.model.ModelResponse; + +import java.util.List; +import java.util.Objects; + +public class ImageResponse implements ModelResponse { + + private final ImageResponseMetadata imageResponseMetadata; + + private final List imageGenerations; + + public ImageResponse(List generations) { + this(generations, ImageResponseMetadata.NULL); + } + + public ImageResponse(List generations, ImageResponseMetadata imageResponseMetadata) { + this.imageResponseMetadata = imageResponseMetadata; + this.imageGenerations = List.copyOf(generations); + } + + @Override + public ImageGeneration getResult() { + return imageGenerations.get(0); + } + + @Override + public List getResults() { + return imageGenerations; + } + + @Override + public ImageResponseMetadata getMetadata() { + return imageResponseMetadata; + } + + @Override + public String toString() { + return "ImageResponse{" + "imageResponseMetadata=" + imageResponseMetadata + ", imageGenerations=" + + imageGenerations + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof ImageResponse that)) + return false; + return Objects.equals(imageResponseMetadata, that.imageResponseMetadata) + && Objects.equals(imageGenerations, that.imageGenerations); + } + + @Override + public int hashCode() { + return Objects.hash(imageResponseMetadata, imageGenerations); + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageResponseMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageResponseMetadata.java new file mode 100644 index 000000000..c4332c6c3 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageResponseMetadata.java @@ -0,0 +1,31 @@ +/* + * Copyright 2024-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.framework.ai.image; + + +import cn.iocoder.yudao.framework.ai.model.ResponseMetadata; + +public interface ImageResponseMetadata extends ResponseMetadata { + + ImageResponseMetadata NULL = new ImageResponseMetadata() { + }; + + default Long created() { + return System.currentTimeMillis(); + } + +} From 7fe1b7791992fee313bbaad6db0d41f7e65f2d9e Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 17 Mar 2024 09:50:48 +0800 Subject: [PATCH 021/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20spring=20ai=20Imag?= =?UTF-8?q?e=E6=A8=A1=E5=9D=97=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/cn/iocoder/yudao/framework/ai/image/Image.java | 4 ++++ .../cn/iocoder/yudao/framework/ai/image/ImageClient.java | 5 +++++ .../cn/iocoder/yudao/framework/ai/image/ImageGeneration.java | 1 + 3 files changed, 10 insertions(+) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/Image.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/Image.java index b56ceb746..d6fc44da0 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/Image.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/Image.java @@ -21,11 +21,15 @@ import java.util.Objects; public class Image { /** + * 可以访问图像的URL。 + * * The URL where the image can be accessed. */ private String url; /** + * Base64编码的图像字符串。 + * * Base64 encoded image string. */ private String b64Json; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageClient.java index 3034fbf02..3c9d68743 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageClient.java @@ -22,6 +22,11 @@ import cn.iocoder.yudao.framework.ai.model.ModelClient; @FunctionalInterface public interface ImageClient extends ModelClient { + /** + * 跟 chat一样 + * @param request the request object to be sent to the AI model + * @return + */ ImageResponse call(ImagePrompt request); } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageGeneration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageGeneration.java index 16942fde1..5ec655de8 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageGeneration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageGeneration.java @@ -21,6 +21,7 @@ import cn.iocoder.yudao.framework.ai.model.ModelResult; public class ImageGeneration implements ModelResult { + // metadata 信息为空现在 private ImageGenerationMetadata imageGenerationMetadata; private Image image; From 633b1126032ac6217fe0556cdc00cd05df7625a0 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 17 Mar 2024 11:19:16 +0800 Subject: [PATCH 022/684] =?UTF-8?q?=E4=B8=8D=E4=BC=A0=E5=85=A5options=20?= =?UTF-8?q?=E5=8F=82=E6=95=B0=EF=BC=8C=E5=B0=B1=E5=85=88=E4=B8=8Dbuilder?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/iocoder/yudao/framework/ai/image/ImageClient.java | 4 ++-- .../java/cn/iocoder/yudao/framework/ai/image/ImagePrompt.java | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageClient.java index 3c9d68743..00bd3e176 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageClient.java @@ -24,9 +24,9 @@ public interface ImageClient extends ModelClient { /** * 跟 chat一样 - * @param request the request object to be sent to the AI model + * @param imagePrompt the request object to be sent to the AI model * @return */ - ImageResponse call(ImagePrompt request); + ImageResponse call(ImagePrompt imagePrompt); } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImagePrompt.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImagePrompt.java index c8fac6ef6..75ec51948 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImagePrompt.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImagePrompt.java @@ -49,7 +49,8 @@ public class ImagePrompt implements ModelRequest> { } public ImagePrompt(String instructions) { - this(new ImageMessage(instructions), ImageOptionsBuilder.builder().build()); +// this(new ImageMessage(instructions), ImageOptionsBuilder.builder().build()); + this(new ImageMessage(instructions), null); } @Override From a14aebd5ee2a71b2548a8b71ab1cf74ea17f4efc Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 17 Mar 2024 11:19:58 +0800 Subject: [PATCH 023/684] =?UTF-8?q?=E5=AF=B9=E6=8E=A5=20openai=20dall-e-3?= =?UTF-8?q?=EF=BC=8C=E5=8F=91=E9=80=81=E8=AF=B7=E6=B1=82=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E5=9C=B0=E5=9D=80=E5=AD=98=E5=9C=A8=E9=97=AE=E9=A2=98=EF=BC=8C?= =?UTF-8?q?=E9=93=BE=E6=8E=A5=E4=B8=8D=E4=B8=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/imageopenai/OpenAiImageApi.java | 54 ++++++++++++ .../ai/imageopenai/OpenAiImageClient.java | 82 +++++++++++++++++++ .../ai/imageopenai/OpenAiImageOptions.java | 77 +++++++++++++++++ .../imageopenai/api/OpenAiImageRequest.java | 58 +++++++++++++ .../imageopenai/api/OpenAiImageResponse.java | 28 +++++++ .../yudao/framework/ai/util/JacksonUtil.java | 79 ++++++++++++++++++ .../ai/chat/QianWenChatClientTests.java | 6 +- .../ai/image/OpenAiImageClientTests.java | 31 +++++++ 8 files changed, 412 insertions(+), 3 deletions(-) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageApi.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageClient.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageRequest.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageResponse.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/util/JacksonUtil.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/OpenAiImageClientTests.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageApi.java new file mode 100644 index 000000000..bcc03f2ee --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageApi.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.framework.ai.imageopenai; + +import cn.iocoder.yudao.framework.ai.imageopenai.api.OpenAiImageRequest; +import cn.iocoder.yudao.framework.ai.imageopenai.api.OpenAiImageResponse; +import cn.iocoder.yudao.framework.ai.util.JacksonUtil; +import io.netty.channel.ChannelOption; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.netty.http.client.HttpClient; + +import java.time.Duration; + +/** + * open ai image + *

+ * author: fansili + * time: 2024/3/17 09:53 + */ +public class OpenAiImageApi { + + private static final String DEFAULT_BASE_URL = "https://api.openai.com"; + private String apiKey = "your-api-key"; + // 发送请求 webClient + private final WebClient webClient; + + public OpenAiImageApi(String apiKey) { + this.apiKey = apiKey; + // 创建一个HttpClient实例并设置超时 + HttpClient httpClient = HttpClient.create() + .responseTimeout(Duration.ofSeconds(300)) // 设置响应超时时间为30秒 + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000 * 100); // 设置连接超时为5秒 + this.webClient = WebClient.builder() + .baseUrl(DEFAULT_BASE_URL) + .clientConnector(new ReactorClientHttpConnector(httpClient)) + .build(); + } + + public OpenAiImageResponse createImage(OpenAiImageRequest request) { + String res = webClient.post() + .uri(uriBuilder -> uriBuilder.path("/v1/images/generations").build()) + .header("Content-Type", "application/json") + .header("Authorization", "Bearer " + apiKey) + // 设置请求体(这里假设jsonStr是一个JSON格式的字符串) + .body(BodyInserters.fromValue(JacksonUtil.toJson(request))) + // 发送请求并获取响应体 + .retrieve() + // 转换响应体为String类型 + .bodyToMono(String.class) + .block(); + // TODO: 2024/3/17 这里发送请求会失败! + return null; + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageClient.java new file mode 100644 index 000000000..a1bb59db1 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageClient.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.framework.ai.imageopenai; + +import cn.hutool.core.bean.BeanUtil; +import cn.iocoder.yudao.framework.ai.chat.ChatException; +import cn.iocoder.yudao.framework.ai.chatyiyan.exception.YiYanApiException; +import cn.iocoder.yudao.framework.ai.image.ImageClient; +import cn.iocoder.yudao.framework.ai.image.ImageOptions; +import cn.iocoder.yudao.framework.ai.image.ImagePrompt; +import cn.iocoder.yudao.framework.ai.image.ImageResponse; +import cn.iocoder.yudao.framework.ai.imageopenai.api.OpenAiImageRequest; +import cn.iocoder.yudao.framework.ai.imageopenai.api.OpenAiImageResponse; +import jdk.jfr.Frequency; +import lombok.extern.slf4j.Slf4j; +import org.springframework.retry.RetryCallback; +import org.springframework.retry.RetryContext; +import org.springframework.retry.RetryListener; +import org.springframework.retry.support.RetryTemplate; + +import java.time.Duration; + +/** + * open ai 生成 image + * + * author: fansili + * time: 2024/3/17 09:51 + */ +@Slf4j +public class OpenAiImageClient implements ImageClient { + + /** + * open image ai + */ + private OpenAiImageApi openAiImageApi; + /** + * 默认使用的 ImageOptions + */ + private OpenAiImageOptions defaultImageOptions; + + + public final RetryTemplate retryTemplate = RetryTemplate.builder() + // 最大重试次数 10 + .maxAttempts(10) + .retryOn(YiYanApiException.class) + // 最大重试5次,第一次间隔3000ms,第二次3000ms * 2,第三次3000ms * 3,以此类推,最大间隔3 * 60000ms + .exponentialBackoff(Duration.ofMillis(3000), 2, Duration.ofMillis(3 * 60000)) + .withListener(new RetryListener() { + @Override + public void onError(RetryContext context, + RetryCallback callback, Throwable throwable) { + log.warn("重试异常:" + context.getRetryCount(), throwable); + }; + }) + .build(); + + public OpenAiImageClient(OpenAiImageApi openAiImageApi, OpenAiImageOptions defaultImageOptions) { + this.openAiImageApi = openAiImageApi; + this.defaultImageOptions = defaultImageOptions; + } + + @Override + public ImageResponse call(ImagePrompt imagePrompt) { + return this.retryTemplate.execute(ctx -> { + // 检查是否配置了 OpenAiImageOptions + if (defaultImageOptions == null && imagePrompt.getOptions() == null) { + throw new ChatException("OpenAiImageOptions 未配置参数!"); + } + // 优先使用 request 中的 ImageOptions + ImageOptions useImageOptions = imagePrompt.getOptions() == null ? defaultImageOptions : imagePrompt.getOptions(); + if (!(useImageOptions instanceof OpenAiImageOptions)) { + throw new ChatException("配置信息不正确,传入的必须是 OpenAiImageOptions!"); + } + // 转换 OpenAiImageOptions + OpenAiImageOptions openAiImageOptions = (OpenAiImageOptions) useImageOptions; + // 创建请求 + OpenAiImageRequest request = new OpenAiImageRequest(); + BeanUtil.copyProperties(openAiImageOptions, request); + // 发送请求 + OpenAiImageResponse response = openAiImageApi.createImage(request); + return null; + }); + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java new file mode 100644 index 000000000..f18ccd298 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java @@ -0,0 +1,77 @@ +package cn.iocoder.yudao.framework.ai.imageopenai; + +import cn.iocoder.yudao.framework.ai.image.ImageOptions; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * open ai 配置文件 + * + * 文档地址:https://platform.openai.com/docs/api-reference/images/create + * + * author: fansili + * time: 2024/3/17 09:53 + */ +@Data +@Accessors(chain = true) +public class OpenAiImageOptions implements ImageOptions { + + // 必填字段,用于描述期望生成图像的文字说明。对于dall-e-2模型最大长度为1000个字符,对于dall-e-3模型最大长度为4000个字符。 + private String prompt; + + // 可选字段,默认为dall-e-2 + // 指定用于生成图像的模型名称。 + private String model = "dall-e-2"; + + // 可选字段,默认为1 + // 生成图像的数量,必须在1到10之间。对于dall-e-3模型,目前仅支持n=1。 + private Integer n = 1; + + // 可选字段,默认为standard + // 设置生成图像的质量。hd质量将创建细节更丰富、图像整体一致性更高的图片。该参数仅对dall-e-3模型有效。 + private String quality = "standard"; + + // 可选字段,默认为url + // 返回生成图像的格式。必须是url或b64_json中的一种。URL链接的有效期是从生成图像后开始计算的60分钟内有效。 + private String responseFormat = "url"; + + // 可选字段,默认为1024x1024 + // 生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。 + private String imageSize = "1024x1024"; + + // 可选字段,默认为vivid + // 图像生成的风格。可为vivid(生动)或natural(自然)。vivid会使模型偏向生成超现实和戏剧性的图像,而natural则会让模型产出更自然、不那么超现实的图像。该参数仅对dall-e-3模型有效。 + private String style = "vivid"; + + // 可选字段 + // 代表您的终端用户的唯一标识符,有助于OpenAI监控并检测滥用行为。了解更多信息请参考官方文档。 + private String endUserId; + + // + // 适配 spring ai + + @Override + public Integer getN() { + return this.n; + } + + @Override + public String getModel() { + return this.model; + } + + @Override + public Integer getWidth() { + return null; + } + + @Override + public Integer getHeight() { + return null; + } + + @Override + public String getResponseFormat() { + return this.responseFormat; + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageRequest.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageRequest.java new file mode 100644 index 000000000..865dbd136 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageRequest.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.framework.ai.imageopenai.api; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * open ai 配置文件 + * + * 文档地址:https://platform.openai.com/docs/api-reference/images/create + * + * author: fansili + * time: 2024/3/17 09:53 + */ +@Data +@Accessors(chain = true) +public class OpenAiImageRequest { + + // 必填字段,用于描述期望生成图像的文字说明。对于dall-e-2模型最大长度为1000个字符,对于dall-e-3模型最大长度为4000个字符。 + @JsonProperty("prompt") + private String prompt; + + // 可选字段,默认为dall-e-2、dall-e-3 + // 指定用于生成图像的模型名称。 + @JsonProperty("model") + private String model = "dall-e-2"; + + // 可选字段,默认为1 + // 生成图像的数量,必须在1到10之间。对于dall-e-3模型,目前仅支持n=1。 + @JsonProperty("n") + private Integer n = 1; + + // 可选字段,默认为standard + // 设置生成图像的质量。hd质量将创建细节更丰富、图像整体一致性更高的图片。该参数仅对dall-e-3模型有效。 + @JsonProperty("quality") + private String quality = "standard"; + + // 可选字段,默认为url + // 返回生成图像的格式。必须是url或b64_json中的一种。URL链接的有效期是从生成图像后开始计算的60分钟内有效。 + @JsonProperty("response_format") + private String responseFormat = "url"; + + // 可选字段,默认为1024x1024 + // 生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。 + @JsonProperty("size") + private String imageSize = "1024x1024"; + + // 可选字段,默认为vivid + // 图像生成的风格。可为vivid(生动)或natural(自然)。vivid会使模型偏向生成超现实和戏剧性的图像,而natural则会让模型产出更自然、不那么超现实的图像。该参数仅对dall-e-3模型有效。 + @JsonProperty("style") + private String style = "vivid"; + + // 可选字段 + // 代表您的终端用户的唯一标识符,有助于OpenAI监控并检测滥用行为。了解更多信息请参考官方文档。 + @JsonProperty("user") + private String endUserId; + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageResponse.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageResponse.java new file mode 100644 index 000000000..04de1494d --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageResponse.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.framework.ai.imageopenai.api; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; + +/** + * image 返回 + * + * author: fansili + * time: 2024/3/17 10:27 + */ +@Data +@Accessors(chain = true) +public class OpenAiImageResponse { + + private long created; + private List data; + + @Data + @Accessors(chain = true) + public static class Item { + + private String url; + + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/util/JacksonUtil.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/util/JacksonUtil.java new file mode 100644 index 000000000..046a481dc --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/util/JacksonUtil.java @@ -0,0 +1,79 @@ +package cn.iocoder.yudao.framework.ai.util; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; + +import java.io.IOException; + +/** + * Jackson工具类 + * + * author: fansili + * time: 2024/3/17 10:13 + */ +public class JacksonUtil { + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + /** + * 初始化 ObjectMapper 以美化输出(即格式化JSON内容) + */ + static { + // 美化输出(缩进) + objectMapper.enable(SerializationFeature.INDENT_OUTPUT); + // 忽略值为 null 的属性 + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + // 配置一个模块来将 Long 类型转换为 String 类型 + SimpleModule module = new SimpleModule(); + module.addSerializer(Long.class, ToStringSerializer.instance); + objectMapper.registerModule(module); + } + + /** + * 将对象转换为 JSON 字符串 + * + * @param obj 需要序列化的Java对象 + * @return 序列化后的 JSON 字符串 + * @throws JsonProcessingException 当 JSON 序列化过程中出现错误时抛出异常 + */ + public static String toJson(Object obj) { + try { + return objectMapper.writeValueAsString(obj); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + /** + * 将 JSON 字符串反序列化为指定类型的对象 + * + * @param json JSON 字符串 + * @param clazz 目标类型 Class 对象 + * @param 泛型类型参数 + * @return 反序列化后的 Java 对象 + * @throws IOException 当 JSON 解析过程中出现错误时抛出异常 + */ + public static T fromJson(String json, Class clazz) { + try { + return objectMapper.readValue(json, clazz); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + /** + * 将对象转换为格式化的 JSON 字符串(已启用 INDENT_OUTPUT 功能,所以所有方法都会返回格式化后的 JSON) + * + * @param obj 需要序列化的Java对象 + * @return 格式化后的 JSON 字符串 + * @throws JsonProcessingException 当 JSON 序列化过程中出现错误时抛出异常 + */ + public static String toFormattedJson(Object obj) { + // 已在类初始化时设置了 SerializationFeature.INDENT_OUTPUT,此处无需额外操作 + return toJson(obj); + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java index 2c2b44685..14b839747 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java @@ -23,9 +23,9 @@ public class QianWenChatClientTests { @Before public void setup() { QianWenApi qianWenApi = new QianWenApi( - "", - "", - "", + "LTAI5tNTVhXW4fLKUjMrr98z", + "ZJ0JQeyjzxxm5CfeTV6k1wNE9UsvZP", + "f0c1088824594f589c8f10567ccd929f_p_efm", null ); qianWenChatClient = new QianWenChatClient( diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/OpenAiImageClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/OpenAiImageClientTests.java new file mode 100644 index 000000000..83d556930 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/OpenAiImageClientTests.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.framework.ai.image; + +import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageApi; +import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageClient; +import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageOptions; +import org.junit.Before; +import org.junit.Test; + +/** + * author: fansili + * time: 2024/3/17 10:40 + */ +public class OpenAiImageClientTests { + + + private OpenAiImageClient openAiImageClient; + + @Before + public void setup() { + // 初始化 openAiImageClient + this.openAiImageClient = new OpenAiImageClient( + new OpenAiImageApi(""), + new OpenAiImageOptions() + ); + } + + @Test + public void callTest() { + openAiImageClient.call(new ImagePrompt("我和我的小狗,一起在北极和企鹅玩排球。")); + } +} From 5999b80471136848746f4d6f048dacc6ea9ae81c Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 24 Mar 2024 20:09:06 +0800 Subject: [PATCH 024/684] =?UTF-8?q?=E5=AF=B9=E6=8E=A5openai=20image?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/framework/ai/image/ImageClient.java | 1 - .../ai/imageopenai/OpenAiImageApi.java | 62 +++++++++++++++---- .../ai/imageopenai/OpenAiImageClient.java | 16 +++-- .../ai/imageopenai/OpenAiImageOptions.java | 16 +++++ .../imageopenai/api/OpenAiImageResponse.java | 1 + .../ai/image/OpenAiImageClientTests.java | 40 +++++++++++- 6 files changed, 114 insertions(+), 22 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageClient.java index 00bd3e176..98fc44ff6 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageClient.java @@ -19,7 +19,6 @@ package cn.iocoder.yudao.framework.ai.image; import cn.iocoder.yudao.framework.ai.model.ModelClient; -@FunctionalInterface public interface ImageClient extends ModelClient { /** diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageApi.java index bcc03f2ee..0f651ac09 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageApi.java @@ -1,14 +1,25 @@ package cn.iocoder.yudao.framework.ai.imageopenai; +import cn.hutool.json.JSONUtil; import cn.iocoder.yudao.framework.ai.imageopenai.api.OpenAiImageRequest; import cn.iocoder.yudao.framework.ai.imageopenai.api.OpenAiImageResponse; import cn.iocoder.yudao.framework.ai.util.JacksonUtil; import io.netty.channel.ChannelOption; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.WebClient; import reactor.netty.http.client.HttpClient; +import java.io.IOException; +import java.net.URI; import java.time.Duration; /** @@ -17,6 +28,7 @@ import java.time.Duration; * author: fansili * time: 2024/3/17 09:53 */ +@Slf4j public class OpenAiImageApi { private static final String DEFAULT_BASE_URL = "https://api.openai.com"; @@ -24,6 +36,8 @@ public class OpenAiImageApi { // 发送请求 webClient private final WebClient webClient; + private CloseableHttpClient httpclient = HttpClients.createDefault(); + public OpenAiImageApi(String apiKey) { this.apiKey = apiKey; // 创建一个HttpClient实例并设置超时 @@ -37,18 +51,40 @@ public class OpenAiImageApi { } public OpenAiImageResponse createImage(OpenAiImageRequest request) { - String res = webClient.post() - .uri(uriBuilder -> uriBuilder.path("/v1/images/generations").build()) - .header("Content-Type", "application/json") - .header("Authorization", "Bearer " + apiKey) - // 设置请求体(这里假设jsonStr是一个JSON格式的字符串) - .body(BodyInserters.fromValue(JacksonUtil.toJson(request))) - // 发送请求并获取响应体 - .retrieve() - // 转换响应体为String类型 - .bodyToMono(String.class) - .block(); - // TODO: 2024/3/17 这里发送请求会失败! - return null; + HttpPost httpPost = new HttpPost(); + httpPost.setURI(URI.create(DEFAULT_BASE_URL.concat("/v1/images/generations"))); + httpPost.setHeader("Content-Type", "application/json"); + httpPost.setHeader("Authorization", "Bearer " + apiKey); + httpPost.setEntity(new StringEntity(JacksonUtil.toJson(request), "UTF-8")); + + CloseableHttpResponse response= null; + try { + response = httpclient.execute(httpPost); + HttpEntity entity = response.getEntity(); + String resultJson = EntityUtils.toString(entity); + log.info("openai 图片生成结果: {}", resultJson); + return JSONUtil.toBean(resultJson, OpenAiImageResponse.class); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + if (response != null) { + try { + response.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } +// String res = webClient.post() +// .uri(uriBuilder -> uriBuilder.path("/v1/images/generations").build()) +// .header("Content-Type", "application/json") +// .header("Authorization", "Bearer " + apiKey) +// // 设置请求体(这里假设jsonStr是一个JSON格式的字符串) +// .body(BodyInserters.fromValue(JacksonUtil.toJson(request))) +// // 发送请求并获取响应体 +// .retrieve() +// // 转换响应体为String类型 +// .bodyToMono(String.class) +// .block(); } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageClient.java index a1bb59db1..a1083cd18 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageClient.java @@ -1,15 +1,13 @@ package cn.iocoder.yudao.framework.ai.imageopenai; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.codec.Base64; +import cn.hutool.http.HttpUtil; import cn.iocoder.yudao.framework.ai.chat.ChatException; import cn.iocoder.yudao.framework.ai.chatyiyan.exception.YiYanApiException; -import cn.iocoder.yudao.framework.ai.image.ImageClient; -import cn.iocoder.yudao.framework.ai.image.ImageOptions; -import cn.iocoder.yudao.framework.ai.image.ImagePrompt; -import cn.iocoder.yudao.framework.ai.image.ImageResponse; +import cn.iocoder.yudao.framework.ai.image.*; import cn.iocoder.yudao.framework.ai.imageopenai.api.OpenAiImageRequest; import cn.iocoder.yudao.framework.ai.imageopenai.api.OpenAiImageResponse; -import jdk.jfr.Frequency; import lombok.extern.slf4j.Slf4j; import org.springframework.retry.RetryCallback; import org.springframework.retry.RetryContext; @@ -74,9 +72,15 @@ public class OpenAiImageClient implements ImageClient { // 创建请求 OpenAiImageRequest request = new OpenAiImageRequest(); BeanUtil.copyProperties(openAiImageOptions, request); + request.setPrompt(imagePrompt.getInstructions().get(0).getText()); // 发送请求 OpenAiImageResponse response = openAiImageApi.createImage(request); - return null; + return new ImageResponse(response.getData().stream().map(res -> { + byte[] bytes = HttpUtil.downloadBytes(res.getUrl()); + String base64 = Base64.encode(bytes); + return new ImageGeneration(new Image(res.getUrl(), base64)); + }).toList()); }); } + } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java index f18ccd298..c80396521 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.ai.imageopenai; import cn.iocoder.yudao.framework.ai.image.ImageOptions; import lombok.Data; +import lombok.Getter; import lombok.experimental.Accessors; /** @@ -47,6 +48,21 @@ public class OpenAiImageOptions implements ImageOptions { // 代表您的终端用户的唯一标识符,有助于OpenAI监控并检测滥用行为。了解更多信息请参考官方文档。 private String endUserId; + @Getter + public enum ResponseFormatEnum { + + URL("url"), + BASE64("b64_json"), + + ; + + ResponseFormatEnum(String value) { + this.value = value; + } + + private String value; + } + // // 适配 spring ai diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageResponse.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageResponse.java index 04de1494d..1f4ab6152 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageResponse.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageResponse.java @@ -23,6 +23,7 @@ public class OpenAiImageResponse { public static class Item { private String url; + private String b64_json; } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/OpenAiImageClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/OpenAiImageClientTests.java index 83d556930..8a6fb5f23 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/OpenAiImageClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/OpenAiImageClientTests.java @@ -6,6 +6,14 @@ import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageOptions; import org.junit.Before; import org.junit.Test; +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.Base64; +import java.util.Scanner; + /** * author: fansili * time: 2024/3/17 10:40 @@ -20,12 +28,40 @@ public class OpenAiImageClientTests { // 初始化 openAiImageClient this.openAiImageClient = new OpenAiImageClient( new OpenAiImageApi(""), - new OpenAiImageOptions() + new OpenAiImageOptions().setResponseFormat(OpenAiImageOptions.ResponseFormatEnum.URL.getValue()) ); } @Test public void callTest() { - openAiImageClient.call(new ImagePrompt("我和我的小狗,一起在北极和企鹅玩排球。")); + ImageResponse call = openAiImageClient.call(new ImagePrompt("我和我的小狗,一起在北极和企鹅玩排球。")); + System.err.println("url: " + call.getResult().getOutput().getUrl()); + System.err.println("base64: " + call.getResult().getOutput().getB64Json()); + + String base64String = call.getResult().getOutput().getB64Json(); + ImageIcon imageIcon = new ImageIcon(decodeBase64ToImage(base64String)); + JLabel label = new JLabel(imageIcon); + + JFrame frame = new JFrame("Base64 Image Display"); + frame.getContentPane().add(label); + frame.pack(); + frame.setVisible(true); + + // 阻止退出 + Scanner scanner = new Scanner(System.in); + scanner.nextLine(); + } + + + // 将Base64解码为BufferedImage + private static BufferedImage decodeBase64ToImage(String base64String) { + try { + byte[] decodedBytes = Base64.getDecoder().decode(base64String); + ByteArrayInputStream bis = new ByteArrayInputStream(decodedBytes); + return ImageIO.read(bis); + } catch (IOException e) { + System.out.println("Error decoding the base64 image: " + e.getMessage()); + return null; + } } } From 6e261de03e3b28cd293bd60f51cc9e4fdad1c31f Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 24 Mar 2024 20:10:34 +0800 Subject: [PATCH 025/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0http=20client?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml index 276e87733..a4e1deae2 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml @@ -114,6 +114,12 @@ broadscope-bailian-sdk-java 1.3.0 + + org.apache.httpcomponents + httpclient + 4.5.14 + compile + \ No newline at end of file From 73631fb364a947d047e553dcc75988b12c6d0670 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 1 Apr 2024 21:25:35 +0800 Subject: [PATCH 026/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/framework/ai/Midjourney/MidjourneyApi.java | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MidjourneyApi.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MidjourneyApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MidjourneyApi.java new file mode 100644 index 000000000..9bda3a00b --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MidjourneyApi.java @@ -0,0 +1,10 @@ +package cn.iocoder.yudao.framework.ai.Midjourney; + +/** + * 文档: https://www.xiubbs.com/t-401-1-1.html + * + * https://github.com/novicezk/midjourney-proxy/blob/main/README_CN.md + * + */ +public class MidjourneyApi { +} From e7e5b729a6712de905a1eba79dc4adcb42bbaf33 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 1 Apr 2024 22:12:23 +0800 Subject: [PATCH 027/684] =?UTF-8?q?mj=20=E5=91=BD=E4=BB=A4=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/Midjourney/MjCommandEnum.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjCommandEnum.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjCommandEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjCommandEnum.java new file mode 100644 index 000000000..b4ad8f1b2 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjCommandEnum.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.framework.ai.Midjourney; + +import lombok.Getter; + +/** + * MJ 命令类型 + */ +@Getter +public enum MjCommandEnum { + + IMAGINE("imagine", "生成图片"), + DESCRIBE("describe", "生成描述"), + FAST("fast", "快速生成"), + SETTINGS("settings", "设置"), + ASK("ask", "提问"), + BLEND("blend", "融合"), + + ; + + MjCommandEnum(String value, String message) { + this.value =value; + this.message =message; + } + + private String value; + private String message; + +} From 7543875e324ae0f9884c04aaf19d0b7e19330cb2 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 1 Apr 2024 22:13:01 +0800 Subject: [PATCH 028/684] =?UTF-8?q?mj=20=E5=91=BD=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/iocoder/yudao/framework/ai/Midjourney/MjCommandEnum.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjCommandEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjCommandEnum.java index b4ad8f1b2..9ae051822 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjCommandEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjCommandEnum.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.framework.ai.Midjourney; import lombok.Getter; /** - * MJ 命令类型 + * MJ 命令 */ @Getter public enum MjCommandEnum { From 196b9ab39c784c40b9e93b4ecbdf38dd98ecf4e9 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 1 Apr 2024 22:14:38 +0800 Subject: [PATCH 029/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20interactions=20?= =?UTF-8?q?=E6=A0=B8=E5=BF=83=E6=8E=A5=E5=8F=A3=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/framework/ai/Midjourney/MidjourneyApi.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MidjourneyApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MidjourneyApi.java index 9bda3a00b..bf1c89aa4 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MidjourneyApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MidjourneyApi.java @@ -7,4 +7,11 @@ package cn.iocoder.yudao.framework.ai.Midjourney; * */ public class MidjourneyApi { + + +// https://discord.com/api/v9/interactions +// +// payload_json: {"type":2,"application_id":"936929561302675456","guild_id":"1224337694918971392","channel_id":"1224337694918971396","session_id":"696318caed5180a2210e358e44801449","data":{"version":"1166847114203123795","id":"938956540159881230","name":"imagine","type":1,"options":[{"type":3,"name":"prompt","value":"中国的是什么样子"}],"application_command":{"id":"938956540159881230","type":1,"application_id":"936929561302675456","version":"1166847114203123795","name":"imagine","description":"Create images with Midjourney","options":[{"type":3,"name":"prompt","description":"The prompt to imagine","required":true,"description_localized":"The prompt to imagine","name_localized":"prompt"}],"dm_permission":true,"integration_types":[0],"global_popularity_rank":1,"description_localized":"Create images with Midjourney","name_localized":"imagine"},"attachments":[]},"nonce":"1224342266261274624","analytics_location":"slash_ui"} +// + } From 5d4a1111703057f7f86c04e4d418dacd5686ae72 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 1 Apr 2024 22:32:07 +0800 Subject: [PATCH 030/684] =?UTF-8?q?mj=E6=89=A7=E8=A1=8C=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ai/Midjourney/MjExecute.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjExecute.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjExecute.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjExecute.java new file mode 100644 index 000000000..60eff553e --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjExecute.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.framework.ai.Midjourney; + +/** + * mj 命令 + */ +public interface MjExecute { + + /** + * 执行命令 + * + * @param mjCommand + * @param prompt + * @return + */ + boolean execute(MjCommandEnum mjCommand, String prompt); + +} From e91e7355dc437420780f00ad10d4c1e21c9a4a1f Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 2 Apr 2024 00:43:38 +0800 Subject: [PATCH 031/684] =?UTF-8?q?=E5=8F=91=E9=80=81=E6=B6=88=E6=81=AF=20?= =?UTF-8?q?type2=20=E5=92=8C=20type3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/Midjourney/interactions_type2.json | 48 +++++++++++++++++++ .../ai/Midjourney/interactions_type3.json | 14 ++++++ 2 files changed, 62 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/interactions_type2.json create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/interactions_type3.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/interactions_type2.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/interactions_type2.json new file mode 100644 index 000000000..da4858dd1 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/interactions_type2.json @@ -0,0 +1,48 @@ +{ + "type": 2, + "application_id": "936929561302675456", + "guild_id": "1224337694918971392", + "channel_id": "1224337694918971396", + "session_id": "696318caed5180a2210e358e44801449", + "data": { + "version": "1166847114203123795", + "id": "938956540159881230", + "name": "imagine", + "type": 1, + "options": [ + { + "type": 3, + "name": "prompt", + "value": "中国的是什么样子" + } + ], + "application_command": { + "id": "938956540159881230", + "type": 1, + "application_id": "936929561302675456", + "version": "1166847114203123795", + "name": "imagine", + "description": "Create images with Midjourney", + "options": [ + { + "type": 3, + "name": "prompt", + "description": "The prompt to imagine", + "required": true, + "description_localized": "The prompt to imagine", + "name_localized": "prompt" + } + ], + "dm_permission": true, + "integration_types": [ + 0 + ], + "global_popularity_rank": 1, + "description_localized": "Create images with Midjourney", + "name_localized": "imagine" + }, + "attachments": [] + }, + "nonce": "1224342266261274624", + "analytics_location": "slash_ui" +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/interactions_type3.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/interactions_type3.json new file mode 100644 index 000000000..4d85c1cc9 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/interactions_type3.json @@ -0,0 +1,14 @@ +{ + "type": 3, + "nonce": "1224397626158350336", + "guild_id": "1224337694918971392", + "channel_id": "1224337694918971396", + "message_flags": 64, + "message_id": "1224397599197368330", + "application_id": "936929561302675456", + "session_id": "0d9ae3c799f2fb55ff435df5e6deb121", + "data": { + "component_type": 2, + "custom_id": "MJ::ModMsg::Ack::2744093999977583880" + } +} \ No newline at end of file From bd8e6c2b406fb00b2a88c2d89d34e29a1287d769 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 2 Apr 2024 00:44:04 +0800 Subject: [PATCH 032/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0mj=20=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E5=99=A8(=E5=85=88=E6=8F=90=E4=BA=A4=E4=B8=80?= =?UTF-8?q?=E4=B8=8B)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/Midjourney/MjHttpExecute.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjHttpExecute.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjHttpExecute.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjHttpExecute.java new file mode 100644 index 000000000..2fc61bda7 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjHttpExecute.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.framework.ai.Midjourney; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.web.client.RestTemplate; + +public class MjHttpExecute implements MjExecute { + + private static final String URL = "https://discord.com/"; + + private RestTemplate restTemplate = new RestTemplate(); + + + @Override + public boolean execute(MjCommandEnum mjCommand, String prompt) { + // 发送的 uri + String uri = "api/v9/interactions"; + // restTemplate 发送post请求 + String result = restTemplate.postForObject(URL + uri, prompt, String.class); + // 加载当前目录下文件 + + return false; + } +} From 84825579b6f5a15231d2bbb884cda61c020d1c6c Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 3 Apr 2024 16:54:49 +0800 Subject: [PATCH 033/684] =?UTF-8?q?=F0=9F=98=84=E6=A8=A1=E6=8B=9F=E5=8F=91?= =?UTF-8?q?=E9=80=81=E3=80=81=E6=8E=A5=E6=94=B6discard=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E6=88=90=E5=8A=9F=EF=BC=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/Midjourney/MjHttpExecute.java | 24 -- .../ai/midjourney/DiscordJadMain.java | 10 + .../ai/midjourney/DiscordWebSocketClient.java | 141 ++++++++++ .../MidjourneyApi.java | 4 +- .../MjCommandEnum.java | 2 +- .../{Midjourney => midjourney}/MjExecute.java | 2 +- .../ai/midjourney/MjHttpExecute.java | 52 ++++ .../interactions_type2.json | 6 +- .../interactions_type3.json | 0 .../ai/midjourney/jad/Constants.java | 22 ++ .../ai/midjourney/jad/DiscordAccount.java | 35 +++ .../ai/midjourney/jad/DomainObject.java | 70 +++++ .../ai/midjourney/wss/AsyncLockUtils.java | 61 +++++ .../ai/midjourney/wss/DiscordHelper.java | 57 +++++ .../framework/ai/midjourney/wss/Main.java | 39 +++ .../ai/midjourney/wss/MessageType.java | 26 ++ .../ai/midjourney/wss/ReturnCode.java | 42 +++ .../ai/midjourney/wss/WebSocketStarter.java | 8 + .../midjourney/wss/user/FailureCallback.java | 6 + .../wss/user/SpringUserWebSocketStarter.java | 189 ++++++++++++++ .../wss/user/SpringWebSocketHandler.java | 240 ++++++++++++++++++ .../midjourney/wss/user/SuccessCallback.java | 7 + .../wss/user/UserMessageListener.java | 28 ++ 23 files changed, 1041 insertions(+), 30 deletions(-) delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjHttpExecute.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/DiscordJadMain.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/DiscordWebSocketClient.java rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/{Midjourney => midjourney}/MidjourneyApi.java (91%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/{Midjourney => midjourney}/MjCommandEnum.java (90%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/{Midjourney => midjourney}/MjExecute.java (81%) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjHttpExecute.java rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/{Midjourney => midjourney}/interactions_type2.json (89%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/{Midjourney => midjourney}/interactions_type3.json (100%) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/jad/Constants.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/jad/DiscordAccount.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/jad/DomainObject.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/AsyncLockUtils.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/DiscordHelper.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/Main.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/MessageType.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/ReturnCode.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/WebSocketStarter.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/FailureCallback.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/SpringUserWebSocketStarter.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/SpringWebSocketHandler.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/SuccessCallback.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/UserMessageListener.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjHttpExecute.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjHttpExecute.java deleted file mode 100644 index 2fc61bda7..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjHttpExecute.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.framework.ai.Midjourney; - -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.web.client.RestTemplate; - -public class MjHttpExecute implements MjExecute { - - private static final String URL = "https://discord.com/"; - - private RestTemplate restTemplate = new RestTemplate(); - - - @Override - public boolean execute(MjCommandEnum mjCommand, String prompt) { - // 发送的 uri - String uri = "api/v9/interactions"; - // restTemplate 发送post请求 - String result = restTemplate.postForObject(URL + uri, prompt, String.class); - // 加载当前目录下文件 - - return false; - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/DiscordJadMain.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/DiscordJadMain.java new file mode 100644 index 000000000..5da1b667c --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/DiscordJadMain.java @@ -0,0 +1,10 @@ +package cn.iocoder.yudao.framework.ai.midjourney; + +/** + * author: fansili + * time: 2024/4/3 15:54 + */ +public class DiscordJadMain { + + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/DiscordWebSocketClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/DiscordWebSocketClient.java new file mode 100644 index 000000000..6b77be884 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/DiscordWebSocketClient.java @@ -0,0 +1,141 @@ +package cn.iocoder.yudao.framework.ai.midjourney; +import cn.hutool.http.useragent.UserAgent; +import cn.hutool.http.useragent.UserAgentUtil; +import cn.hutool.json.JSONObject; +import com.alibaba.fastjson.JSON; +import org.springframework.web.socket.*; +import org.springframework.web.socket.client.standard.StandardWebSocketClient; +import org.springframework.web.socket.handler.TextWebSocketHandler; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +/** + * https://blog.csdn.net/qq_38490457/article/details/125250135 + */ +public class DiscordWebSocketClient { + + private static final String DISCORD_GATEWAY_URL = "wss://gateway.discord.gg/?v=9&encoding=json"; + + public static void main(String[] args) throws InterruptedException, ExecutionException, IOException, URISyntaxException { + StandardWebSocketClient client = new StandardWebSocketClient(); + DiscordWebSocketHandler handler = new DiscordWebSocketHandler(); + + + WebSocketHttpHeaders headers = new WebSocketHttpHeaders(); + headers.add("Accept-Encoding", "gzip, deflate, br"); + headers.add("Accept-Language", "zh-CN,zh;q=0.9"); + headers.add("Cache-Control", "no-cache"); + headers.add("Pragma", "no-cache"); + headers.add("Sec-Websocket-Extensions", "permessage-deflate; client_max_window_bits"); + headers.add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36"); + + Future futureSession = client.doHandshake(handler, headers, new URI(DISCORD_GATEWAY_URL)); + WebSocketSession session = futureSession.get(); // 这会阻塞直到连接建立 + + // 登录过程(你需要替换 TOKEN 为你的 Discord Bot Token) +// String token = "YOUR_DISCORD_BOT_TOKEN"; // 请替换为你的 Bot Token +// String identifyPayload = "{\"op\":2,\"d\":{\"token\":\"" + token + "\",\"properties\":{\"$os\":\"java\",\"$browser\":\"spring-websocket\",\"$device\":\"spring-websocket\"},\"compress\":false,\"large_threshold\":256,\"shard\":[0,1]}}"; +// session.sendMessage(new TextMessage(identifyPayload)); + + // 发送心跳以保持连接活跃 + Thread heartbeatThread = new Thread(() -> { + int interval = 0; // 初始心跳间隔,后续从 Discord 服务器获取 + while (!Thread.currentThread().isInterrupted()) { + try { + Thread.sleep(interval * 1000); // 等待指定的心跳间隔 + session.sendMessage(new TextMessage("{\"op\":1,\"d\":null}")); // 发送心跳包 + } catch (Exception e) { + e.printStackTrace(); + break; + } + } + }); + heartbeatThread.start(); + + // 等待用户输入来保持程序运行(仅用于示例) + System.in.read(); + + // 关闭连接和线程 + session.close(); + heartbeatThread.interrupt(); + } + + private static class DiscordWebSocketHandler implements WebSocketHandler { + + @Override + public void afterConnectionEstablished(WebSocketSession session) throws Exception { + + } + + @Override + public void handleMessage(WebSocketSession session, WebSocketMessage message) throws Exception { + Object payload = message.getPayload(); + + session.sendMessage(new TextMessage(JSON.toJSONString(createAuthData()))); + String a= ""; + } + + @Override + public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { + + } + + @Override + public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { + + } + + @Override + public boolean supportsPartialMessages() { + return false; + } + + + private JSONObject createAuthData() { + String userAgentStr = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36"; + UserAgent userAgent = UserAgentUtil.parse(userAgentStr); + String token = "NTY5MDY4NDAxNzEyOTU1Mzky.G4-Fu0.MzD-7ll-ElbXTTgDPHF-WS_UyhMAfbKN3WyyBc"; + + JSONObject connectionProperties = new JSONObject() + .put("browser", userAgent.getBrowser().getName()) + .put("browser_user_agent", userAgentStr) + .put("browser_version", userAgent.getVersion()) + .put("client_build_number", 222963) + .put("client_event_source", null) + .put("device", "") + .put("os", userAgent.getOs().getName()) + .put("referer", "https://www.midjourney.com") + .put("referrer_current", "") + .put("referring_domain", "www.midjourney.com") + .put("referring_domain_current", "") + .put("release_channel", "stable") + .put("system_locale", "zh-CN"); + JSONObject presence = new JSONObject() + .put("activities", "") + .put("afk", false) + .put("since", 0) + .put("status", "online"); + JSONObject clientState = new JSONObject() + .put("api_code_version", 0) + .put("guild_versions", "") + .put("highest_last_message_id", "0") + .put("private_channels_version", "0") + .put("read_state_version", 0) + .put("user_guild_settings_version", -1) + .put("user_settings_version", -1); + return new JSONObject() + .put("capabilities", 16381) + .put("client_state", clientState) + .put("compress", false) + .put("presence", presence) + .put("properties", connectionProperties) + .put("token", token); + } + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MidjourneyApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyApi.java similarity index 91% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MidjourneyApi.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyApi.java index bf1c89aa4..9aa5edfac 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MidjourneyApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyApi.java @@ -1,10 +1,12 @@ -package cn.iocoder.yudao.framework.ai.Midjourney; +package cn.iocoder.yudao.framework.ai.midjourney; /** * 文档: https://www.xiubbs.com/t-401-1-1.html * * https://github.com/novicezk/midjourney-proxy/blob/main/README_CN.md * + * discord4j、https://github.com/discord-jda/JDA + * */ public class MidjourneyApi { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjCommandEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjCommandEnum.java similarity index 90% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjCommandEnum.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjCommandEnum.java index 9ae051822..7344f424c 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjCommandEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjCommandEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.Midjourney; +package cn.iocoder.yudao.framework.ai.midjourney; import lombok.Getter; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjExecute.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjExecute.java similarity index 81% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjExecute.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjExecute.java index 60eff553e..5945c9212 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/MjExecute.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjExecute.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.Midjourney; +package cn.iocoder.yudao.framework.ai.midjourney; /** * mj 命令 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjHttpExecute.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjHttpExecute.java new file mode 100644 index 000000000..5b5794ae6 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjHttpExecute.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.framework.ai.midjourney; + +import cn.hutool.core.io.FileUtil; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.web.client.RestTemplate; + +import java.nio.charset.Charset; + +public class MjHttpExecute implements MjExecute { + + private static final String URL = "https://discord.com/"; + + @Override + public boolean execute(MjCommandEnum mjCommand, String prompt) { + // 发送的 uri + String uri = "api/v9/interactions"; + // restTemplate 发送post请求 +// String result = restTemplate.postForObject(URL + uri, prompt, String.class); + // 加载当前目录下文件 + return false; + } + + public static void main(String[] args) { + RestTemplate restTemplate = new RestTemplate(); + + String token = "NTY5MDY4NDAxNzEyOTU1Mzky.G4-Fu0.MzD-7ll-ElbXTTgDPHF-WS_UyhMAfbKN3WyyBc"; + String body = FileUtil.readString("/Users/fansili/projects/github/ruoyi-vue-pro/yudao-module-ai" + + "/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney" + + "/interactions_type2.json", Charset.forName("utf-8")); + // 创建HTTP头部 + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); // 设置内容类型为JSON + headers.set("Authorization", token); // 如果需要,设置认证信息(例如JWT令牌) + headers.set("Referer", "https://discord.com/channels/1221445697157468200/1221445862962630706"); // 如果需要,设置认证信息(例如JWT令牌) + headers.set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"); // 如果需要,设置认证信息(例如JWT令牌) + headers.set("Cookie", "__dcfduid=6ca536c0e3fa11eeb7cbe34c31b49caf; __sdcfduid=6ca536c1e3fa11eeb7cbe34c31b49caf52cce5ffd8983d2a052cf6aba75fe5fe566f2c265902e283ce30dbf98b8c9c93; _gcl_au=1.1.245923998.1710853617; _ga=GA1.1.111061823.1710853617; __cfruid=6385bb3f48345a006b25992db7dcf984e395736d-1712124666; _cfuvid=O09la5ms0ypNptiG0iD8A6BKWlTxz1LG0WR7qRStD7o-1712124666575-0.0.1.1-604800000; locale=zh-CN; cf_clearance=l_YGod1_SUtYxpDVeZXiX7DLLPl1DYrquZe8WVltvYs-1712124668-1.0.1.1-Hl2.fToel23EpF2HCu9J20rB4D7OhhCzoajPSdo.9Up.wPxhvq22DP9RHzEBKuIUlKyH.kJLxXJfAt2N.LD5WQ; OptanonConsent=isIABGlobal=false&datestamp=Wed+Apr+03+2024+14%3A11%3A15+GMT%2B0800+(%E4%B8%AD%E5%9B%BD%E6%A0%87%E5%87%86%E6%97%B6%E9%97%B4)&version=6.33.0&hosts=&landingPath=https%3A%2F%2Fdiscord.com%2F&groups=C0001%3A1%2CC0002%3A1%2CC0003%3A1; _ga_Q149DFWHT7=GS1.1.1712124668.4.1.1712124679.0.0.0"); // 如果需要,设置认证信息(例如JWT令牌) + // 封装请求体和头部信息 + HttpEntity requestEntity = new HttpEntity<>(body, headers); + + // 定义请求URL和返回类型 + String uri = "api/v9/interactions"; + String res = restTemplate.postForObject(URL + uri, requestEntity, String.class); + System.err.println("11"); + + // +// MjHttpExecute mjHttpExecute = new MjHttpExecute(); +// mjHttpExecute.execute(null, "童话世界应该是什么样?"); + + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/interactions_type2.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions_type2.json similarity index 89% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/interactions_type2.json rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions_type2.json index da4858dd1..b8a2afef3 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/interactions_type2.json +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions_type2.json @@ -1,8 +1,8 @@ { "type": 2, "application_id": "936929561302675456", - "guild_id": "1224337694918971392", - "channel_id": "1224337694918971396", + "guild_id": "1221445697157468200", + "channel_id": "1221445862962630706", "session_id": "696318caed5180a2210e358e44801449", "data": { "version": "1166847114203123795", @@ -13,7 +13,7 @@ { "type": 3, "name": "prompt", - "value": "中国的是什么样子" + "value": "童话世界应该是什么样?" } ], "application_command": { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/interactions_type3.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions_type3.json similarity index 100% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/Midjourney/interactions_type3.json rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions_type3.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/jad/Constants.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/jad/Constants.java new file mode 100644 index 000000000..7b42bbbe3 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/jad/Constants.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.framework.ai.midjourney.jad; + +import lombok.experimental.UtilityClass; + +@UtilityClass +public final class Constants { + // 任务扩展属性 start + public static final String TASK_PROPERTY_NOTIFY_HOOK = "notifyHook"; + public static final String TASK_PROPERTY_FINAL_PROMPT = "finalPrompt"; + public static final String TASK_PROPERTY_MESSAGE_ID = "messageId"; + public static final String TASK_PROPERTY_MESSAGE_HASH = "messageHash"; + public static final String TASK_PROPERTY_PROGRESS_MESSAGE_ID = "progressMessageId"; + public static final String TASK_PROPERTY_FLAGS = "flags"; + public static final String TASK_PROPERTY_NONCE = "nonce"; + public static final String TASK_PROPERTY_DISCORD_INSTANCE_ID = "discordInstanceId"; + // 任务扩展属性 end + + public static final String API_SECRET_HEADER_NAME = "mj-api-secret"; + public static final String DEFAULT_DISCORD_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36"; + + public static final String MJ_MESSAGE_HANDLED = "mj_proxy_handled"; +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/jad/DiscordAccount.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/jad/DiscordAccount.java new file mode 100644 index 000000000..a67752687 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/jad/DiscordAccount.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.framework.ai.midjourney.jad; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) + +public class DiscordAccount extends DomainObject { + + + private String guildId; + + private String channelId; + + private String userToken; + + private String userAgent = Constants.DEFAULT_DISCORD_USER_AGENT; + + + private boolean enable = true; + + + private int coreSize = 3; + + private int queueSize = 10; + + private int timeoutMinutes = 5; + + @JsonIgnore + public String getDisplay() { + return this.channelId; + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/jad/DomainObject.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/jad/DomainObject.java new file mode 100644 index 000000000..3fae0b346 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/jad/DomainObject.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.framework.ai.midjourney.jad; + + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + + +public class DomainObject implements Serializable { + @Getter + @Setter + protected String id; + + @Setter + protected Map properties; // 扩展属性,仅支持基本类型 + + @JsonIgnore + private final transient Object lock = new Object(); + + public void sleep() throws InterruptedException { + synchronized (this.lock) { + this.lock.wait(); + } + } + + public void awake() { + synchronized (this.lock) { + this.lock.notifyAll(); + } + } + + public DomainObject setProperty(String name, Object value) { + getProperties().put(name, value); + return this; + } + + public DomainObject removeProperty(String name) { + getProperties().remove(name); + return this; + } + + public Object getProperty(String name) { + return getProperties().get(name); + } + + @SuppressWarnings("unchecked") + public T getPropertyGeneric(String name) { + return (T) getProperty(name); + } + + public T getProperty(String name, Class clz) { + return getProperty(name, clz, null); + } + + public T getProperty(String name, Class clz, T defaultValue) { + Object value = getProperty(name); + return value == null ? defaultValue : clz.cast(value); + } + + public Map getProperties() { + if (this.properties == null) { + this.properties = new HashMap<>(); + } + return this.properties; + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/AsyncLockUtils.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/AsyncLockUtils.java new file mode 100644 index 000000000..7309bee89 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/AsyncLockUtils.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.framework.ai.midjourney.wss; + +import cn.hutool.cache.CacheUtil; +import cn.hutool.cache.impl.TimedCache; +import cn.hutool.core.thread.ThreadUtil; +import cn.iocoder.yudao.framework.ai.midjourney.jad.DomainObject; +import lombok.experimental.UtilityClass; + +import java.time.Duration; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +@UtilityClass +public class AsyncLockUtils { + private static final TimedCache LOCK_MAP = CacheUtil.newTimedCache(Duration.ofDays(1).toMillis()); + + public static synchronized LockObject getLock(String key) { + return LOCK_MAP.get(key); + } + + public static LockObject waitForLock(String key, Duration duration) throws TimeoutException { + LockObject lockObject; + synchronized (LOCK_MAP) { + if (LOCK_MAP.containsKey(key)) { + lockObject = LOCK_MAP.get(key); + } else { + lockObject = new LockObject(key); + LOCK_MAP.put(key, lockObject); + } + } + Future future = ThreadUtil.execAsync(() -> { + try { + lockObject.sleep(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }); + try { + future.get(duration.toMillis(), TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } catch (ExecutionException e) { + // do nothing + } catch (TimeoutException e) { + future.cancel(true); + throw new TimeoutException("Wait Timeout"); + } finally { + LOCK_MAP.remove(lockObject.getId()); + } + return lockObject; + } + + public static class LockObject extends DomainObject { + + public LockObject(String id) { + this.id = id; + } + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/DiscordHelper.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/DiscordHelper.java new file mode 100644 index 000000000..3af52647d --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/DiscordHelper.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.framework.ai.midjourney.wss; + +import cn.hutool.core.text.CharSequenceUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class DiscordHelper { + /** + * DISCORD_SERVER_URL. + */ + public static final String DISCORD_SERVER_URL = "https://discord.com"; + /** + * DISCORD_CDN_URL. + */ + public static final String DISCORD_CDN_URL = "https://cdn.discordapp.com"; + /** + * DISCORD_WSS_URL. + */ + public static final String DISCORD_WSS_URL = "wss://gateway.discord.gg"; + /** + * DISCORD_UPLOAD_URL. + */ + public static final String DISCORD_UPLOAD_URL = "https://discord-attachments-uploads-prd.storage.googleapis.com"; + + public String getServer() { + return DISCORD_SERVER_URL; + } + + public String getCdn() { + return DISCORD_CDN_URL; + } + + public String getWss() { + return DISCORD_WSS_URL; + } + + public String getMessageHash(String imageUrl) { + if (CharSequenceUtil.isBlank(imageUrl)) { + return null; + } + if (CharSequenceUtil.endWith(imageUrl, "_grid_0.webp")) { + int hashStartIndex = imageUrl.lastIndexOf("/"); + if (hashStartIndex < 0) { + return null; + } + return CharSequenceUtil.sub(imageUrl, hashStartIndex + 1, imageUrl.length() - "_grid_0.webp".length()); + } + int hashStartIndex = imageUrl.lastIndexOf("_"); + if (hashStartIndex < 0) { + return null; + } + return CharSequenceUtil.subBefore(imageUrl.substring(hashStartIndex + 1), ".", true); + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/Main.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/Main.java new file mode 100644 index 000000000..923a1cb74 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/Main.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.framework.ai.midjourney.wss; + +import cn.iocoder.yudao.framework.ai.midjourney.jad.DiscordAccount; +import cn.iocoder.yudao.framework.ai.midjourney.wss.user.SpringUserWebSocketStarter; +import cn.iocoder.yudao.framework.ai.midjourney.wss.user.UserMessageListener; + +import java.util.Scanner; + +/** + * author: fansili + * time: 2024/4/3 16:40 + */ +public class Main { + + public static void main(String[] args) { + String token = "NTY5MDY4NDAxNzEyOTU1Mzky.G4-Fu0.MzD-7ll-ElbXTTgDPHF-WS_UyhMAfbKN3WyyBc"; + + + DiscordHelper discordHelper = new DiscordHelper(); + DiscordAccount discordAccount = new DiscordAccount(); + discordAccount.setUserToken(token); + discordAccount.setGuildId("1221445697157468200"); + discordAccount.setChannelId("1221445862962630706"); + + + var messageListener = new UserMessageListener(); + var webSocketStarter = new SpringUserWebSocketStarter(discordHelper.getWss(), null, discordAccount, messageListener); + + try { + webSocketStarter.start(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + + Scanner scanner = new Scanner(System.in); + scanner.nextLine(); + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/MessageType.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/MessageType.java new file mode 100644 index 000000000..3beb3a090 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/MessageType.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.framework.ai.midjourney.wss; + + +public enum MessageType { + /** + * 创建. + */ + CREATE, + /** + * 修改. + */ + UPDATE, + /** + * 删除. + */ + DELETE; + + public static MessageType of(String type) { + return switch (type) { + case "MESSAGE_CREATE" -> CREATE; + case "MESSAGE_UPDATE" -> UPDATE; + case "MESSAGE_DELETE" -> DELETE; + default -> null; + }; + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/ReturnCode.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/ReturnCode.java new file mode 100644 index 000000000..84c87452d --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/ReturnCode.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.framework.ai.midjourney.wss; + +import lombok.experimental.UtilityClass; + +@UtilityClass +public final class ReturnCode { + /** + * 成功. + */ + public static final int SUCCESS = 1; + /** + * 数据未找到. + */ + public static final int NOT_FOUND = 3; + /** + * 校验错误. + */ + public static final int VALIDATION_ERROR = 4; + /** + * 系统异常. + */ + public static final int FAILURE = 9; + + /** + * 已存在. + */ + public static final int EXISTED = 21; + /** + * 排队中. + */ + public static final int IN_QUEUE = 22; + /** + * 队列已满. + */ + public static final int QUEUE_REJECTED = 23; + /** + * prompt包含敏感词. + */ + public static final int BANNED_PROMPT = 24; + + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/WebSocketStarter.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/WebSocketStarter.java new file mode 100644 index 000000000..d49b94dbc --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/WebSocketStarter.java @@ -0,0 +1,8 @@ +package cn.iocoder.yudao.framework.ai.midjourney.wss; + + +public interface WebSocketStarter { + + void start() throws Exception; + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/FailureCallback.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/FailureCallback.java new file mode 100644 index 000000000..c4a44aceb --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/FailureCallback.java @@ -0,0 +1,6 @@ +package cn.iocoder.yudao.framework.ai.midjourney.wss.user; + + +public interface FailureCallback { + void onFailure(int code, String reason); +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/SpringUserWebSocketStarter.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/SpringUserWebSocketStarter.java new file mode 100644 index 000000000..d4561794d --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/SpringUserWebSocketStarter.java @@ -0,0 +1,189 @@ +package cn.iocoder.yudao.framework.ai.midjourney.wss.user; + + +import cn.hutool.core.exceptions.ValidateException; +import cn.hutool.core.text.CharSequenceUtil; +import cn.hutool.core.thread.ThreadUtil; +import cn.iocoder.yudao.framework.ai.midjourney.jad.DiscordAccount; +import cn.iocoder.yudao.framework.ai.midjourney.wss.AsyncLockUtils; +import cn.iocoder.yudao.framework.ai.midjourney.wss.ReturnCode; +import cn.iocoder.yudao.framework.ai.midjourney.wss.WebSocketStarter; +import lombok.extern.slf4j.Slf4j; +import org.apache.tomcat.websocket.Constants; +import org.jetbrains.annotations.NotNull; +import org.springframework.util.concurrent.ListenableFutureCallback; +import org.springframework.web.socket.CloseStatus; +import org.springframework.web.socket.WebSocketHttpHeaders; +import org.springframework.web.socket.WebSocketSession; +import org.springframework.web.socket.client.standard.StandardWebSocketClient; + +import java.io.IOException; +import java.net.URI; +import java.time.Duration; +import java.util.concurrent.TimeoutException; + +@Slf4j +public class SpringUserWebSocketStarter implements WebSocketStarter { + private static final int CONNECT_RETRY_LIMIT = 5; + + private final DiscordAccount account; + private final UserMessageListener userMessageListener; + private final String wssServer; + private final String resumeWss; + + private boolean running = false; + + private WebSocketSession webSocketSession = null; + private ResumeData resumeData = null; + + public SpringUserWebSocketStarter(String wssServer, String resumeWss, DiscordAccount account, UserMessageListener userMessageListener) { + this.wssServer = wssServer; + this.resumeWss = resumeWss; + this.account = account; + this.userMessageListener = userMessageListener; + } + + @Override + public void start() throws Exception { + start(false); + } + + private void start(boolean reconnect) { + WebSocketHttpHeaders headers = new WebSocketHttpHeaders(); + headers.add("Accept-Encoding", "gzip, deflate, br"); + headers.add("Accept-Language", "zh-CN,zh;q=0.9"); + headers.add("Cache-Control", "no-cache"); + headers.add("Pragma", "no-cache"); + headers.add("Sec-Websocket-Extensions", "permessage-deflate; client_max_window_bits"); + headers.add("User-Agent", this.account.getUserAgent()); + var handler = new SpringWebSocketHandler(this.account, this.userMessageListener, this::onSocketSuccess, this::onSocketFailure); + String gatewayUrl; + if (reconnect) { + gatewayUrl = getGatewayServer(this.resumeData.resumeGatewayUrl()) + "/?encoding=json&v=9&compress=zlib-stream"; + handler.setSessionId(this.resumeData.sessionId()); + handler.setSequence(this.resumeData.sequence()); + handler.setResumeGatewayUrl(this.resumeData.resumeGatewayUrl()); + } else { + gatewayUrl = getGatewayServer(null) + "/?encoding=json&v=9&compress=zlib-stream"; + } + var webSocketClient = new StandardWebSocketClient(); + webSocketClient.getUserProperties().put(Constants.IO_TIMEOUT_MS_PROPERTY, "10000"); + var socketSessionFuture = webSocketClient.doHandshake(handler, headers, URI.create(gatewayUrl)); + socketSessionFuture.addCallback(new ListenableFutureCallback<>() { + @Override + public void onFailure(@NotNull Throwable e) { + onSocketFailure(SpringWebSocketHandler.CLOSE_CODE_EXCEPTION, e.getMessage()); + } + + @Override + public void onSuccess(WebSocketSession session) { + SpringUserWebSocketStarter.this.webSocketSession = session; + } + }); + } + + private void onSocketSuccess(String sessionId, Object sequence, String resumeGatewayUrl) { + this.resumeData = new ResumeData(sessionId, sequence, resumeGatewayUrl); + this.running = true; + notifyWssLock(ReturnCode.SUCCESS, ""); + } + + private void onSocketFailure(int code, String reason) { + if (code == 1001) { + return; + } + closeSocketSessionWhenIsOpen(); + if (!this.running) { + notifyWssLock(code, reason); + return; + } + this.running = false; + if (code >= 4000) { + log.warn("[wss-{}] Can't reconnect! Account disabled. Closed by {}({}).", this.account.getDisplay(), code, reason); + disableAccount(); + } else if (code == 2001) { + log.warn("[wss-{}] Closed by {}({}). Try reconnect...", this.account.getDisplay(), code, reason); + tryReconnect(); + } else { + log.warn("[wss-{}] Closed by {}({}). Try new connection...", this.account.getDisplay(), code, reason); + tryNewConnect(); + } + } + + private void tryReconnect() { + try { + tryStart(true); + } catch (Exception e) { + if (e instanceof TimeoutException) { + closeSocketSessionWhenIsOpen(); + } + log.warn("[wss-{}] Reconnect fail: {}, Try new connection...", this.account.getDisplay(), e.getMessage()); + ThreadUtil.sleep(1000); + tryNewConnect(); + } + } + + private void tryNewConnect() { + for (int i = 1; i <= CONNECT_RETRY_LIMIT; i++) { + try { + tryStart(false); + return; + } catch (Exception e) { + if (e instanceof TimeoutException) { + closeSocketSessionWhenIsOpen(); + } + log.warn("[wss-{}] New connect fail ({}): {}", this.account.getDisplay(), i, e.getMessage()); + ThreadUtil.sleep(5000); + } + } + log.error("[wss-{}] Account disabled", this.account.getDisplay()); + disableAccount(); + } + + public void tryStart(boolean reconnect) throws Exception { + start(reconnect); + AsyncLockUtils.LockObject lock = AsyncLockUtils.waitForLock("wss:" + this.account.getId(), Duration.ofSeconds(20)); + int code = lock.getProperty("code", Integer.class, 0); + if (code == ReturnCode.SUCCESS) { + log.debug("[wss-{}] {} success.", this.account.getDisplay(), reconnect ? "Reconnect" : "New connect"); + return; + } + throw new ValidateException(lock.getProperty("description", String.class)); + } + + private void notifyWssLock(int code, String reason) { + AsyncLockUtils.LockObject lock = AsyncLockUtils.getLock("wss:" + this.account.getId()); + if (lock != null) { + lock.setProperty("code", code); + lock.setProperty("description", reason); + lock.awake(); + } + } + + private void disableAccount() { + if (Boolean.FALSE.equals(this.account.isEnable())) { + return; + } + this.account.setEnable(false); + } + + private void closeSocketSessionWhenIsOpen() { + try { + if (this.webSocketSession != null && this.webSocketSession.isOpen()) { + this.webSocketSession.close(CloseStatus.GOING_AWAY); + } + } catch (IOException e) { + // do nothing + } + } + + private String getGatewayServer(String resumeGatewayUrl) { + if (CharSequenceUtil.isNotBlank(resumeGatewayUrl)) { + return CharSequenceUtil.isBlank(this.resumeWss) ? resumeGatewayUrl : this.resumeWss; + } + return this.wssServer; + } + + public record ResumeData(String sessionId, Object sequence, String resumeGatewayUrl) { + } +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/SpringWebSocketHandler.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/SpringWebSocketHandler.java new file mode 100644 index 000000000..044ce24d9 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/SpringWebSocketHandler.java @@ -0,0 +1,240 @@ +package cn.iocoder.yudao.framework.ai.midjourney.wss.user; + +import cn.hutool.core.text.CharSequenceUtil; +import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.http.useragent.UserAgent; +import cn.hutool.http.useragent.UserAgentUtil; +import cn.iocoder.yudao.framework.ai.midjourney.jad.DiscordAccount; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.utils.data.DataArray; +import net.dv8tion.jda.api.utils.data.DataObject; +import net.dv8tion.jda.api.utils.data.DataType; +import net.dv8tion.jda.internal.requests.WebSocketCode; +import net.dv8tion.jda.internal.utils.compress.Decompressor; +import net.dv8tion.jda.internal.utils.compress.ZlibDecompressor; +import org.jetbrains.annotations.NotNull; +import org.springframework.web.socket.*; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +@Slf4j +public class SpringWebSocketHandler implements WebSocketHandler { + public static final int CLOSE_CODE_RECONNECT = 2001; + public static final int CLOSE_CODE_INVALIDATE = 1009; + public static final int CLOSE_CODE_EXCEPTION = 1011; + + private final DiscordAccount account; + private final UserMessageListener userMessageListener; + private final SuccessCallback successCallback; + private final FailureCallback failureCallback; + + private final ScheduledExecutorService heartExecutor; + private final DataObject authData; + + @Setter + private String sessionId = null; + @Setter + private Object sequence = null; + @Setter + private String resumeGatewayUrl = null; + + private long interval = 41250; + private boolean heartbeatAck = false; + + private Future heartbeatInterval; + private Future heartbeatTimeout; + + private final Decompressor decompressor = new ZlibDecompressor(2048); + + public SpringWebSocketHandler(DiscordAccount account, UserMessageListener userMessageListener, SuccessCallback successCallback, FailureCallback failureCallback) { + this.account = account; + this.userMessageListener = userMessageListener; + this.successCallback = successCallback; + this.failureCallback = failureCallback; + this.heartExecutor = Executors.newSingleThreadScheduledExecutor(); + this.authData = createAuthData(); + } + + @Override + public void afterConnectionEstablished(@NotNull WebSocketSession session) throws Exception { + // do nothing + } + + @Override + public void handleTransportError(@NotNull WebSocketSession session, @NotNull Throwable e) throws Exception { + log.error("[wss-{}] Transport error", this.account.getDisplay(), e); + onFailure(CLOSE_CODE_EXCEPTION, "transport error"); + } + + @Override + public void afterConnectionClosed(@NotNull WebSocketSession session, @NotNull CloseStatus closeStatus) throws Exception { + onFailure(closeStatus.getCode(), closeStatus.getReason()); + } + + @Override + public boolean supportsPartialMessages() { + return true; + } + + @Override + public void handleMessage(@NotNull WebSocketSession session, WebSocketMessage message) throws Exception { + ByteBuffer buffer = (ByteBuffer) message.getPayload(); + byte[] decompressed = decompressor.decompress(buffer.array()); + if (decompressed == null) { + return; + } + String json = new String(decompressed, StandardCharsets.UTF_8); + DataObject data = DataObject.fromJson(json); + int opCode = data.getInt("op"); + switch (opCode) { + case WebSocketCode.HEARTBEAT -> handleHeartbeat(session); + case WebSocketCode.HEARTBEAT_ACK -> { + this.heartbeatAck = true; + clearHeartbeatTimeout(); + } + case WebSocketCode.HELLO -> { + handleHello(session, data); + doResumeOrIdentify(session); + } + case WebSocketCode.RESUME -> onSuccess(); + case WebSocketCode.RECONNECT -> onFailure(CLOSE_CODE_RECONNECT, "receive server reconnect"); + case WebSocketCode.INVALIDATE_SESSION -> onFailure(CLOSE_CODE_INVALIDATE, "receive session invalid"); + case WebSocketCode.DISPATCH -> handleDispatch(data); + default -> log.debug("[wss-{}] Receive unknown code: {}.", account.getDisplay(), data); + } + } + + private void handleDispatch(DataObject raw) { + this.sequence = raw.opt("s").orElse(null); + if (!raw.isType("d", DataType.OBJECT)) { + return; + } + DataObject content = raw.getObject("d"); + String t = raw.getString("t", null); + if ("READY".equals(t)) { + this.sessionId = content.getString("session_id"); + this.resumeGatewayUrl = content.getString("resume_gateway_url"); + onSuccess(); + } else if ("RESUMED".equals(t)) { + onSuccess(); + } else { + try { + this.userMessageListener.onMessage(raw); + } catch (Exception e) { + log.error("[wss-{}] Handle message error", this.account.getDisplay(), e); + } + } + } + + private void handleHeartbeat(WebSocketSession session) { + sendMessage(session, WebSocketCode.HEARTBEAT, this.sequence); + this.heartbeatTimeout = ThreadUtil.execAsync(() -> { + ThreadUtil.sleep(this.interval); + onFailure(CLOSE_CODE_RECONNECT, "heartbeat has not ack"); + }); + } + + private void handleHello(WebSocketSession session, DataObject data) { + clearHeartbeatInterval(); + this.interval = data.getObject("d").getLong("heartbeat_interval"); + this.heartbeatAck = true; + this.heartbeatInterval = this.heartExecutor.scheduleAtFixedRate(() -> { + if (this.heartbeatAck) { + this.heartbeatAck = false; + sendMessage(session, WebSocketCode.HEARTBEAT, this.sequence); + } else { + onFailure(CLOSE_CODE_RECONNECT, "heartbeat has not ack interval"); + } + }, (long) Math.floor(RandomUtil.randomDouble(0, 1) * this.interval), this.interval, TimeUnit.MILLISECONDS); + } + + private void doResumeOrIdentify(WebSocketSession session) { + if (CharSequenceUtil.isBlank(this.sessionId)) { + sendMessage(session, WebSocketCode.IDENTIFY, this.authData); + } else { + var data = DataObject.empty().put("token", this.account.getUserToken()) + .put("session_id", this.sessionId).put("seq", this.sequence); + sendMessage(session, WebSocketCode.RESUME, data); + } + } + + private void sendMessage(WebSocketSession session, int op, Object d) { + var data = DataObject.empty().put("op", op).put("d", d); + try { + session.sendMessage(new TextMessage(data.toString())); + } catch (IOException e) { + log.error("[wss-{}] Send message error", this.account.getDisplay(), e); + onFailure(CLOSE_CODE_EXCEPTION, "send message error"); + } + } + + private void onSuccess() { + ThreadUtil.execute(() -> this.successCallback.onSuccess(this.sessionId, this.sequence, this.resumeGatewayUrl)); + } + + private void onFailure(int code, String reason) { + clearHeartbeatTimeout(); + clearHeartbeatInterval(); + ThreadUtil.execute(() -> this.failureCallback.onFailure(code, reason)); + } + + private void clearHeartbeatTimeout() { + if (this.heartbeatTimeout != null) { + this.heartbeatTimeout.cancel(true); + this.heartbeatTimeout = null; + } + } + + private void clearHeartbeatInterval() { + if (this.heartbeatInterval != null) { + this.heartbeatInterval.cancel(true); + this.heartbeatInterval = null; + } + } + + private DataObject createAuthData() { + UserAgent userAgent = UserAgentUtil.parse(this.account.getUserAgent()); + DataObject connectionProperties = DataObject.empty() + .put("browser", userAgent.getBrowser().getName()) + .put("browser_user_agent", this.account.getUserAgent()) + .put("browser_version", userAgent.getVersion()) + .put("client_build_number", 222963) + .put("client_event_source", null) + .put("device", "") + .put("os", userAgent.getOs().getName()) + .put("referer", "https://www.midjourney.com") + .put("referrer_current", "") + .put("referring_domain", "www.midjourney.com") + .put("referring_domain_current", "") + .put("release_channel", "stable") + .put("system_locale", "zh-CN"); + DataObject presence = DataObject.empty() + .put("activities", DataArray.empty()) + .put("afk", false) + .put("since", 0) + .put("status", "online"); + DataObject clientState = DataObject.empty() + .put("api_code_version", 0) + .put("guild_versions", DataObject.empty()) + .put("highest_last_message_id", "0") + .put("private_channels_version", "0") + .put("read_state_version", 0) + .put("user_guild_settings_version", -1) + .put("user_settings_version", -1); + return DataObject.empty() + .put("capabilities", 16381) + .put("client_state", clientState) + .put("compress", false) + .put("presence", presence) + .put("properties", connectionProperties) + .put("token", this.account.getUserToken()); + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/SuccessCallback.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/SuccessCallback.java new file mode 100644 index 000000000..e6e0d89d0 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/SuccessCallback.java @@ -0,0 +1,7 @@ +package cn.iocoder.yudao.framework.ai.midjourney.wss.user; + + +public interface SuccessCallback { + + void onSuccess(String sessionId, Object sequence, String resumeGatewayUrl); +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/UserMessageListener.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/UserMessageListener.java new file mode 100644 index 000000000..5bf4d9cf5 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/UserMessageListener.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.framework.ai.midjourney.wss.user; + + +import cn.hutool.core.thread.ThreadUtil; +import cn.iocoder.yudao.framework.ai.midjourney.wss.MessageType; +import com.alibaba.fastjson.JSON; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.utils.data.DataObject; + +@Slf4j +public class UserMessageListener { + + public void onMessage(DataObject raw) { + MessageType messageType = MessageType.of(raw.getString("t")); + if (messageType == null || MessageType.DELETE == messageType) { + return; + } + DataObject data = raw.getObject("d"); + System.err.println(data); + ThreadUtil.sleep(50); +// for (MessageHandler messageHandler : this.messageHandlers) { +// if (data.getBoolean(Constants.MJ_MESSAGE_HANDLED, false)) { +// return; +// } +// messageHandler.handle(this.instance, messageType, data); +// } + } +} From 2f6b9b2ef5bf4679f4d175f363e090e0a059f808 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 3 Apr 2024 17:09:22 +0800 Subject: [PATCH 034/684] =?UTF-8?q?=E7=A7=BB=E5=8A=A8=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/midjourney/{ => demo}/DiscordJadMain.java | 2 +- .../midjourney/{ => demo}/DiscordWebSocketClient.java | 2 +- .../ai/midjourney/{ => demo}/MidjourneyApi.java | 2 +- .../ai/midjourney/{ => demo}/MjCommandEnum.java | 2 +- .../framework/ai/midjourney/{ => demo}/MjExecute.java | 2 +- .../ai/midjourney/{ => demo}/MjHttpExecute.java | 2 +- .../ai/midjourney/{ => demo}/interactions_type2.json | 0 .../ai/midjourney/{ => demo}/interactions_type3.json | 0 .../ai/midjourney/{ => demo}/jad/Constants.java | 2 +- .../ai/midjourney/{ => demo}/jad/DiscordAccount.java | 2 +- .../ai/midjourney/{ => demo}/jad/DomainObject.java | 2 +- .../ai/midjourney/{ => demo}/wss/AsyncLockUtils.java | 4 ++-- .../ai/midjourney/{ => demo}/wss/DiscordHelper.java | 2 +- .../framework/ai/midjourney/{ => demo}/wss/Main.java | 8 ++++---- .../ai/midjourney/{ => demo}/wss/MessageType.java | 2 +- .../ai/midjourney/{ => demo}/wss/ReturnCode.java | 2 +- .../ai/midjourney/{ => demo}/wss/WebSocketStarter.java | 2 +- .../{ => demo}/wss/user/FailureCallback.java | 2 +- .../wss/user/SpringUserWebSocketStarter.java | 10 +++++----- .../{ => demo}/wss/user/SpringWebSocketHandler.java | 4 ++-- .../{ => demo}/wss/user/SuccessCallback.java | 2 +- .../{ => demo}/wss/user/UserMessageListener.java | 5 ++--- .../yudao/framework/ai/midjourney/package-info.java | 5 +++++ 23 files changed, 35 insertions(+), 31 deletions(-) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/DiscordJadMain.java (60%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/DiscordWebSocketClient.java (99%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/MidjourneyApi.java (95%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/MjCommandEnum.java (89%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/MjExecute.java (79%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/MjHttpExecute.java (98%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/interactions_type2.json (100%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/interactions_type3.json (100%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/jad/Constants.java (94%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/jad/DiscordAccount.java (90%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/jad/DomainObject.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/wss/AsyncLockUtils.java (92%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/wss/DiscordHelper.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/wss/Main.java (75%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/wss/MessageType.java (84%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/wss/ReturnCode.java (91%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/wss/WebSocketStarter.java (55%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/wss/user/FailureCallback.java (55%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/wss/user/SpringUserWebSocketStarter.java (94%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/wss/user/SpringWebSocketHandler.java (98%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/wss/user/SuccessCallback.java (64%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{ => demo}/wss/user/UserMessageListener.java (80%) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/package-info.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/DiscordJadMain.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/DiscordJadMain.java similarity index 60% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/DiscordJadMain.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/DiscordJadMain.java index 5da1b667c..d9c9dba17 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/DiscordJadMain.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/DiscordJadMain.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney; +package cn.iocoder.yudao.framework.ai.midjourney.demo; /** * author: fansili diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/DiscordWebSocketClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/DiscordWebSocketClient.java similarity index 99% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/DiscordWebSocketClient.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/DiscordWebSocketClient.java index 6b77be884..df9705095 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/DiscordWebSocketClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/DiscordWebSocketClient.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney; +package cn.iocoder.yudao.framework.ai.midjourney.demo; import cn.hutool.http.useragent.UserAgent; import cn.hutool.http.useragent.UserAgentUtil; import cn.hutool.json.JSONObject; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MidjourneyApi.java similarity index 95% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyApi.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MidjourneyApi.java index 9aa5edfac..1c0cbd480 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MidjourneyApi.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney; +package cn.iocoder.yudao.framework.ai.midjourney.demo; /** * 文档: https://www.xiubbs.com/t-401-1-1.html diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjCommandEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjCommandEnum.java similarity index 89% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjCommandEnum.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjCommandEnum.java index 7344f424c..e65ddf294 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjCommandEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjCommandEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney; +package cn.iocoder.yudao.framework.ai.midjourney.demo; import lombok.Getter; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjExecute.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjExecute.java similarity index 79% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjExecute.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjExecute.java index 5945c9212..887a35e73 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjExecute.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjExecute.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney; +package cn.iocoder.yudao.framework.ai.midjourney.demo; /** * mj 命令 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjHttpExecute.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjHttpExecute.java similarity index 98% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjHttpExecute.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjHttpExecute.java index 5b5794ae6..4c1a8b20f 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjHttpExecute.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjHttpExecute.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney; +package cn.iocoder.yudao.framework.ai.midjourney.demo; import cn.hutool.core.io.FileUtil; import org.springframework.http.HttpEntity; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions_type2.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/interactions_type2.json similarity index 100% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions_type2.json rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/interactions_type2.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions_type3.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/interactions_type3.json similarity index 100% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions_type3.json rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/interactions_type3.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/jad/Constants.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/Constants.java similarity index 94% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/jad/Constants.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/Constants.java index 7b42bbbe3..42e1b2f47 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/jad/Constants.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/Constants.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.jad; +package cn.iocoder.yudao.framework.ai.midjourney.demo.jad; import lombok.experimental.UtilityClass; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/jad/DiscordAccount.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/DiscordAccount.java similarity index 90% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/jad/DiscordAccount.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/DiscordAccount.java index a67752687..8fafa9f59 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/jad/DiscordAccount.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/DiscordAccount.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.jad; +package cn.iocoder.yudao.framework.ai.midjourney.demo.jad; import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Data; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/jad/DomainObject.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/DomainObject.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/jad/DomainObject.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/DomainObject.java index 3fae0b346..e12339edc 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/jad/DomainObject.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/DomainObject.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.jad; +package cn.iocoder.yudao.framework.ai.midjourney.demo.jad; import com.fasterxml.jackson.annotation.JsonIgnore; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/AsyncLockUtils.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/AsyncLockUtils.java similarity index 92% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/AsyncLockUtils.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/AsyncLockUtils.java index 7309bee89..365935a8f 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/AsyncLockUtils.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/AsyncLockUtils.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.framework.ai.midjourney.wss; +package cn.iocoder.yudao.framework.ai.midjourney.demo.wss; import cn.hutool.cache.CacheUtil; import cn.hutool.cache.impl.TimedCache; import cn.hutool.core.thread.ThreadUtil; -import cn.iocoder.yudao.framework.ai.midjourney.jad.DomainObject; +import cn.iocoder.yudao.framework.ai.midjourney.demo.jad.DomainObject; import lombok.experimental.UtilityClass; import java.time.Duration; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/DiscordHelper.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/DiscordHelper.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/DiscordHelper.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/DiscordHelper.java index 3af52647d..7f57fea08 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/DiscordHelper.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/DiscordHelper.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.wss; +package cn.iocoder.yudao.framework.ai.midjourney.demo.wss; import cn.hutool.core.text.CharSequenceUtil; import lombok.RequiredArgsConstructor; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/Main.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/Main.java similarity index 75% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/Main.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/Main.java index 923a1cb74..25a332702 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/Main.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/Main.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.framework.ai.midjourney.wss; +package cn.iocoder.yudao.framework.ai.midjourney.demo.wss; -import cn.iocoder.yudao.framework.ai.midjourney.jad.DiscordAccount; -import cn.iocoder.yudao.framework.ai.midjourney.wss.user.SpringUserWebSocketStarter; -import cn.iocoder.yudao.framework.ai.midjourney.wss.user.UserMessageListener; +import cn.iocoder.yudao.framework.ai.midjourney.demo.jad.DiscordAccount; +import cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user.SpringUserWebSocketStarter; +import cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user.UserMessageListener; import java.util.Scanner; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/MessageType.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/MessageType.java similarity index 84% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/MessageType.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/MessageType.java index 3beb3a090..cc48fe983 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/MessageType.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/MessageType.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.wss; +package cn.iocoder.yudao.framework.ai.midjourney.demo.wss; public enum MessageType { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/ReturnCode.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/ReturnCode.java similarity index 91% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/ReturnCode.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/ReturnCode.java index 84c87452d..0de539035 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/ReturnCode.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/ReturnCode.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.wss; +package cn.iocoder.yudao.framework.ai.midjourney.demo.wss; import lombok.experimental.UtilityClass; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/WebSocketStarter.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/WebSocketStarter.java similarity index 55% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/WebSocketStarter.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/WebSocketStarter.java index d49b94dbc..82874f204 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/WebSocketStarter.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/WebSocketStarter.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.wss; +package cn.iocoder.yudao.framework.ai.midjourney.demo.wss; public interface WebSocketStarter { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/FailureCallback.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/FailureCallback.java similarity index 55% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/FailureCallback.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/FailureCallback.java index c4a44aceb..9600ddab3 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/FailureCallback.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/FailureCallback.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.wss.user; +package cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user; public interface FailureCallback { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/SpringUserWebSocketStarter.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/SpringUserWebSocketStarter.java similarity index 94% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/SpringUserWebSocketStarter.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/SpringUserWebSocketStarter.java index d4561794d..644a36844 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/SpringUserWebSocketStarter.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/SpringUserWebSocketStarter.java @@ -1,13 +1,13 @@ -package cn.iocoder.yudao.framework.ai.midjourney.wss.user; +package cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user; import cn.hutool.core.exceptions.ValidateException; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.thread.ThreadUtil; -import cn.iocoder.yudao.framework.ai.midjourney.jad.DiscordAccount; -import cn.iocoder.yudao.framework.ai.midjourney.wss.AsyncLockUtils; -import cn.iocoder.yudao.framework.ai.midjourney.wss.ReturnCode; -import cn.iocoder.yudao.framework.ai.midjourney.wss.WebSocketStarter; +import cn.iocoder.yudao.framework.ai.midjourney.demo.jad.DiscordAccount; +import cn.iocoder.yudao.framework.ai.midjourney.demo.wss.AsyncLockUtils; +import cn.iocoder.yudao.framework.ai.midjourney.demo.wss.ReturnCode; +import cn.iocoder.yudao.framework.ai.midjourney.demo.wss.WebSocketStarter; import lombok.extern.slf4j.Slf4j; import org.apache.tomcat.websocket.Constants; import org.jetbrains.annotations.NotNull; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/SpringWebSocketHandler.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/SpringWebSocketHandler.java similarity index 98% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/SpringWebSocketHandler.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/SpringWebSocketHandler.java index 044ce24d9..b9d77784d 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/SpringWebSocketHandler.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/SpringWebSocketHandler.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.framework.ai.midjourney.wss.user; +package cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.RandomUtil; import cn.hutool.http.useragent.UserAgent; import cn.hutool.http.useragent.UserAgentUtil; -import cn.iocoder.yudao.framework.ai.midjourney.jad.DiscordAccount; +import cn.iocoder.yudao.framework.ai.midjourney.demo.jad.DiscordAccount; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.utils.data.DataArray; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/SuccessCallback.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/SuccessCallback.java similarity index 64% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/SuccessCallback.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/SuccessCallback.java index e6e0d89d0..7ff2bd3af 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/SuccessCallback.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/SuccessCallback.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.wss.user; +package cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user; public interface SuccessCallback { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/UserMessageListener.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/UserMessageListener.java similarity index 80% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/UserMessageListener.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/UserMessageListener.java index 5bf4d9cf5..ca97b6cae 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/wss/user/UserMessageListener.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/UserMessageListener.java @@ -1,9 +1,8 @@ -package cn.iocoder.yudao.framework.ai.midjourney.wss.user; +package cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user; import cn.hutool.core.thread.ThreadUtil; -import cn.iocoder.yudao.framework.ai.midjourney.wss.MessageType; -import com.alibaba.fastjson.JSON; +import cn.iocoder.yudao.framework.ai.midjourney.demo.wss.MessageType; import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.utils.data.DataObject; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/package-info.java new file mode 100644 index 000000000..2ab112963 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/package-info.java @@ -0,0 +1,5 @@ +/** + * author: fansili + * time: 2024/4/3 17:08 + */ +package cn.iocoder.yudao.framework.ai.midjourney; \ No newline at end of file From 98b4fb7ff0842f9292bc9e05b951f7d590722c3a Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 4 Apr 2024 19:33:55 +0800 Subject: [PATCH 035/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20imagine=20?= =?UTF-8?q?=E5=91=BD=E4=BB=A4=E5=8F=91=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/midjourney/MidjourneyClient.java | 17 +++++ .../ai/midjourney/MidjourneyConfig.java | 67 +++++++++++++++++++ ...m.java => MidjourneyInteractionsEnum.java} | 6 +- .../ai/midjourney/demo/MjExecute.java | 4 +- .../ai/midjourney/demo/MjHttpExecute.java | 6 +- .../ai/midjourney/interactions/MjClient.java | 46 +++++++++++++ .../interactions/MjImagineInteractions.java | 58 ++++++++++++++++ .../interactions/MjInteractions.java | 18 +++++ 8 files changed, 214 insertions(+), 8 deletions(-) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyClient.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyConfig.java rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{demo/MjCommandEnum.java => MidjourneyInteractionsEnum.java} (71%) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyClient.java new file mode 100644 index 000000000..1c99564e7 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyClient.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.framework.ai.midjourney; + +/** + * midjourney + * + * author: fansili + * time: 2024/4/3 17:09 + */ +public class MidjourneyClient { + + + public void imagine() { + + } + + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyConfig.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyConfig.java new file mode 100644 index 000000000..48f43ca60 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyConfig.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.framework.ai.midjourney; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.Map; + +/** + * Midjourney 配置 + * + * author: fansili + * time: 2024/4/3 17:10 + */ +@Data +@Accessors(chain = true) +public class MidjourneyConfig { + + public MidjourneyConfig(String token, String guildId, String channelId, Map requestTemplates) { + this.token = token; + this.guildId = guildId; + this.channelId = channelId; + this.serverUrl = serverUrl; + this.apiInteractions = apiInteractions; + this.userAage = userAage; + this.requestTemplates = requestTemplates; + } + + /** + * token信息 + * + * tip: 登录discard F12找 messages 接口 + */ + private String token; + /** + * 服务器id + */ + private String guildId; + /** + * 频道id + */ + private String channelId; + + // + // api 接口 + + /** + * 服务地址 + */ + private String serverUrl = "https://discord.com/"; + /** + * 发送命令 + */ + private String apiInteractions = "api/v9/interactions"; + + + // + // 浏览器配置 + + private String userAage = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"; + + + // + // 请求 json 文件 + + + private Map requestTemplates; +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjCommandEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsEnum.java similarity index 71% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjCommandEnum.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsEnum.java index e65ddf294..20b70b5f9 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjCommandEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.demo; +package cn.iocoder.yudao.framework.ai.midjourney; import lombok.Getter; @@ -6,7 +6,7 @@ import lombok.Getter; * MJ 命令 */ @Getter -public enum MjCommandEnum { +public enum MidjourneyInteractionsEnum { IMAGINE("imagine", "生成图片"), DESCRIBE("describe", "生成描述"), @@ -17,7 +17,7 @@ public enum MjCommandEnum { ; - MjCommandEnum(String value, String message) { + MidjourneyInteractionsEnum(String value, String message) { this.value =value; this.message =message; } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjExecute.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjExecute.java index 887a35e73..299266c78 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjExecute.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjExecute.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.framework.ai.midjourney.demo; +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyInteractionsEnum; + /** * mj 命令 */ @@ -12,6 +14,6 @@ public interface MjExecute { * @param prompt * @return */ - boolean execute(MjCommandEnum mjCommand, String prompt); + boolean execute(MidjourneyInteractionsEnum mjCommand, String prompt); } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjHttpExecute.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjHttpExecute.java index 4c1a8b20f..34cf4fd7a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjHttpExecute.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjHttpExecute.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.framework.ai.midjourney.demo; import cn.hutool.core.io.FileUtil; +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyInteractionsEnum; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; @@ -13,7 +14,7 @@ public class MjHttpExecute implements MjExecute { private static final String URL = "https://discord.com/"; @Override - public boolean execute(MjCommandEnum mjCommand, String prompt) { + public boolean execute(MidjourneyInteractionsEnum mjCommand, String prompt) { // 发送的 uri String uri = "api/v9/interactions"; // restTemplate 发送post请求 @@ -44,9 +45,6 @@ public class MjHttpExecute implements MjExecute { String res = restTemplate.postForObject(URL + uri, requestEntity, String.class); System.err.println("11"); - // -// MjHttpExecute mjHttpExecute = new MjHttpExecute(); -// mjHttpExecute.execute(null, "童话世界应该是什么样?"); } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java new file mode 100644 index 000000000..17fa16c8b --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.framework.ai.midjourney.interactions; + +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.web.client.RestTemplate; + +import java.util.Map; + +/** + * mj client + *

+ * author: fansili + * time: 2024/4/3 17:37 + */ +public class MjClient { + + private static RestTemplate restTemplate = new RestTemplate(); + private static HttpHeaders headers = new HttpHeaders(); + + static { + headers.setContentType(MediaType.APPLICATION_JSON); // 设置内容类型为JSON +// headers.set("Authorization", token); // 如果需要,设置认证信息(例如JWT令牌) + headers.set("Referer", "https://discord.com/channels/1221445697157468200/1221445862962630706"); // 如果需要,设置认证信息(例如JWT令牌) + headers.set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"); // 如果需要,设置认证信息(例如JWT令牌) + headers.set("Cookie", "__dcfduid=6ca536c0e3fa11eeb7cbe34c31b49caf; __sdcfduid=6ca536c1e3fa11eeb7cbe34c31b49caf52cce5ffd8983d2a052cf6aba75fe5fe566f2c265902e283ce30dbf98b8c9c93; _gcl_au=1.1.245923998.1710853617; _ga=GA1.1.111061823.1710853617; __cfruid=6385bb3f48345a006b25992db7dcf984e395736d-1712124666; _cfuvid=O09la5ms0ypNptiG0iD8A6BKWlTxz1LG0WR7qRStD7o-1712124666575-0.0.1.1-604800000; locale=zh-CN; cf_clearance=l_YGod1_SUtYxpDVeZXiX7DLLPl1DYrquZe8WVltvYs-1712124668-1.0.1.1-Hl2.fToel23EpF2HCu9J20rB4D7OhhCzoajPSdo.9Up.wPxhvq22DP9RHzEBKuIUlKyH.kJLxXJfAt2N.LD5WQ; OptanonConsent=isIABGlobal=false&datestamp=Wed+Apr+03+2024+14%3A11%3A15+GMT%2B0800+(%E4%B8%AD%E5%9B%BD%E6%A0%87%E5%87%86%E6%97%B6%E9%97%B4)&version=6.33.0&hosts=&landingPath=https%3A%2F%2Fdiscord.com%2F&groups=C0001%3A1%2CC0002%3A1%2CC0003%3A1; _ga_Q149DFWHT7=GS1.1.1712124668.4.1.1712124679.0.0.0"); // 如果需要,设置认证信息(例如JWT令牌) + } + + public static String post(String url, String token, String body) { + // 设置token + headers.set("Authorization", token); + // 封装请求体和头部信息 + HttpEntity requestEntity = new HttpEntity<>(body, headers); + // 发送请求 + String result = restTemplate.postForObject(url, requestEntity, String.class); + return result; + } + + + public static String setParams(String requestTemplate, Map requestParams) { + for (Map.Entry entry : requestParams.entrySet()) { + requestTemplate = requestTemplate.replace("$".concat(entry.getKey()), entry.getValue()); + } + return requestTemplate; + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java new file mode 100644 index 000000000..ee05e7287 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.framework.ai.midjourney.interactions; + +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyInteractionsEnum; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Maps; +import lombok.extern.slf4j.Slf4j; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.HashMap; +import java.util.List; +import java.util.UUID; + +/** + * + * + * author: fansili + * time: 2024/4/3 17:36 + */ +@Slf4j +public class MjImagineInteractions implements MjInteractions { + + private MidjourneyConfig midjourneyConfig; + + public MjImagineInteractions(MidjourneyConfig midjourneyConfig) { + this.midjourneyConfig = midjourneyConfig; + } + + @Override + public List supperInteractions() { + return null; + } + + @Override + public Boolean execute(String prompt) { + String url = midjourneyConfig.getServerUrl().concat(midjourneyConfig.getApiInteractions()); + // 获取请求模板 + String requestTemplate = midjourneyConfig.getRequestTemplates().get("imagine"); + // 设置参数 + HashMap requestParams = Maps.newHashMap(); + requestParams.put("guild_id", midjourneyConfig.getGuildId()); + requestParams.put("channel_id", midjourneyConfig.getChannelId()); + requestParams.put("session_id", UUID.randomUUID().toString().replaceAll("-", "")); + requestParams.put("nonce", String.valueOf(IdUtil.getSnowflakeNextId())); + requestParams.put("prompt", prompt); + // 设置参数 + String requestBody = MjClient.setParams(requestTemplate, requestParams); + // 发送请求 + String res = MjClient.post(url, midjourneyConfig.getToken(), requestBody); + // + System.err.println(res); + log.info(res); + // 这个 res 只要不返回值,就是成功! + return StrUtil.isBlank(res); + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java new file mode 100644 index 000000000..9b94abc7a --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.framework.ai.midjourney.interactions; + +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyInteractionsEnum; + +import java.util.List; + +/** + * mj Interactions + * + * author: fansili + * time: 2024/4/3 17:22 + */ +public interface MjInteractions { + + List supperInteractions(); + + Boolean execute(String prompt); +} From f1f003b76dda730e9c76e8fd65781d1155aaea12 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 4 Apr 2024 19:34:41 +0800 Subject: [PATCH 036/684] =?UTF-8?q?imagine=20=E5=8F=91=E9=80=81=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/http-body/imagine.json | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/imagine.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/imagine.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/imagine.json new file mode 100644 index 000000000..f4554cc50 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/imagine.json @@ -0,0 +1,21 @@ +{ + "type": 2, + "guild_id": "$guild_id", + "channel_id": "$channel_id", + "application_id": "936929561302675456", + "session_id": "$session_id", + "nonce": "$nonce", + "data": { + "version": "1166847114203123795", + "id": "938956540159881230", + "name": "imagine", + "type": 1, + "options": [ + { + "type": 3, + "name": "prompt", + "value": "$prompt" + } + ] + } +} \ No newline at end of file From b77e8f16e9e8948a05ee332a59cb433d00f7cf08 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 4 Apr 2024 19:38:03 +0800 Subject: [PATCH 037/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20mj=20Imagine=20?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/framework/ai/image/MjTests.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjTests.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjTests.java new file mode 100644 index 000000000..df8fea90d --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjTests.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.framework.ai.image; + +import cn.hutool.core.io.FileUtil; +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; +import cn.iocoder.yudao.framework.ai.midjourney.interactions.MjImagineInteractions; +import org.junit.Test; + +import java.io.File; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * mj + * + * author: fansili + * time: 2024/4/4 18:59 + */ +public class MjTests { + + @Test + public void mjImage() { + String token = "NTY5MDY4NDAxNzEyOTU1Mzky.G4-Fu0.MzD-7ll-ElbXTTgDPHF-WS_UyhMAfbKN3WyyBc"; + Map requestTemplates = new HashMap<>(); + List files = FileUtil.loopFiles("/Users/fansili/projects/github/ruoyi-vue-pro/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body"); + for (File file : files) { + requestTemplates.put(file.getName().replace(".json", ""), FileUtil.readUtf8String(file)); + } + MidjourneyConfig midjourneyConfig = new MidjourneyConfig( + token, "1221445697157468200", "1221445862962630706", requestTemplates); + MjImagineInteractions mjImagineInteractions = new MjImagineInteractions(midjourneyConfig); + mjImagineInteractions.execute("童话里应该是什么样子?"); + } +} From e6bc5cf06955654c23e4f0399346cc07a5a21661 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 4 Apr 2024 19:40:21 +0800 Subject: [PATCH 038/684] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=B2=A1=E7=94=A8?= =?UTF-8?q?=E7=9A=84=20import?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/midjourney/interactions/MjImagineInteractions.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java index ee05e7287..8b49e55c2 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java @@ -4,10 +4,8 @@ import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyInteractionsEnum; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; -import org.checkerframework.checker.nullness.qual.Nullable; import java.util.HashMap; import java.util.List; From 6adb8d657c840917396c5bba99e7ca38659543db Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 4 Apr 2024 19:43:28 +0800 Subject: [PATCH 039/684] =?UTF-8?q?=E5=A4=84=E7=90=86=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E7=BB=93=E6=9E=9C=EF=BC=8C=E6=97=A5=E5=BF=97=E8=BE=93=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../midjourney/interactions/MjImagineInteractions.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java index 8b49e55c2..5768cbe8d 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java @@ -47,10 +47,12 @@ public class MjImagineInteractions implements MjInteractions { String requestBody = MjClient.setParams(requestTemplate, requestParams); // 发送请求 String res = MjClient.post(url, midjourneyConfig.getToken(), requestBody); - // - System.err.println(res); - log.info(res); // 这个 res 只要不返回值,就是成功! - return StrUtil.isBlank(res); + boolean isSuccess = StrUtil.isBlank(res); + if (isSuccess) { + return true; + } + log.error("请求失败! 请求参数:{} 返回结果! {}", requestBody, res); + return isSuccess; } } From 28b2fad7b612e3b1ff4684da022788ba93a3cd77 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 5 Apr 2024 08:46:41 +0800 Subject: [PATCH 040/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0mj=20web=20socket=20?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/midjourney/demo/wss/Main.java | 39 -------------- .../framework/ai/image/MjWebSocketTests.java | 51 +++++++++++++++++++ 2 files changed, 51 insertions(+), 39 deletions(-) delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/Main.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjWebSocketTests.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/Main.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/Main.java deleted file mode 100644 index 25a332702..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/Main.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.iocoder.yudao.framework.ai.midjourney.demo.wss; - -import cn.iocoder.yudao.framework.ai.midjourney.demo.jad.DiscordAccount; -import cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user.SpringUserWebSocketStarter; -import cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user.UserMessageListener; - -import java.util.Scanner; - -/** - * author: fansili - * time: 2024/4/3 16:40 - */ -public class Main { - - public static void main(String[] args) { - String token = "NTY5MDY4NDAxNzEyOTU1Mzky.G4-Fu0.MzD-7ll-ElbXTTgDPHF-WS_UyhMAfbKN3WyyBc"; - - - DiscordHelper discordHelper = new DiscordHelper(); - DiscordAccount discordAccount = new DiscordAccount(); - discordAccount.setUserToken(token); - discordAccount.setGuildId("1221445697157468200"); - discordAccount.setChannelId("1221445862962630706"); - - - var messageListener = new UserMessageListener(); - var webSocketStarter = new SpringUserWebSocketStarter(discordHelper.getWss(), null, discordAccount, messageListener); - - try { - webSocketStarter.start(); - } catch (Exception e) { - throw new RuntimeException(e); - } - - - Scanner scanner = new Scanner(System.in); - scanner.nextLine(); - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjWebSocketTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjWebSocketTests.java new file mode 100644 index 000000000..177b7c733 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjWebSocketTests.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.framework.ai.image; + +import cn.hutool.core.io.FileUtil; +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; +import cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user.MjMessageListener; +import cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user.MjWebSocketStarter; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Scanner; + +/** + * author: fansili + * time: 2024/4/3 16:40 + */ +public class MjWebSocketTests { + + private MidjourneyConfig midjourneyConfig; + + @Before + public void setup() { + String token = "OTcwNDc3NzQxMjUyMTY5NzI4.GJcVxa.VrzMii8dsHOJAPZn4Mw8GuEo7_nIUJij9JIHD4"; + Map requestTemplates = new HashMap<>(); + List files = FileUtil.loopFiles("/Users/fansili/projects/github/ruoyi-vue-pro/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body"); + for (File file : files) { + requestTemplates.put(file.getName().replace(".json", ""), FileUtil.readUtf8String(file)); + } + this.midjourneyConfig = new MidjourneyConfig(token, "1225414986084388926", "1225414986587832385", requestTemplates); + } + + @Test + public void startSocketTest() { + String wssUrl = "wss://gateway.discord.gg"; + var messageListener = new MjMessageListener(midjourneyConfig); + var webSocketStarter = new MjWebSocketStarter(wssUrl, null, midjourneyConfig, messageListener); + + try { + webSocketStarter.start(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + + Scanner scanner = new Scanner(System.in); + scanner.nextLine(); + } +} From 5044a58118408c98367c7d3eaed440abac4accd5 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 5 Apr 2024 09:27:09 +0800 Subject: [PATCH 041/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0mj=20web=20socket?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/midjourney/constants/MjConstants.java | 8 + .../MjInteractionsEnum.java} | 6 +- .../MjMessageTypeEnum.java} | 6 +- .../MjNotifyCode.java} | 4 +- .../ai/midjourney/demo/DiscordJadMain.java | 10 -- .../demo/DiscordWebSocketClient.java | 141 ------------------ .../ai/midjourney/demo/MidjourneyApi.java | 19 --- .../ai/midjourney/demo/MjExecute.java | 19 --- .../ai/midjourney/demo/MjHttpExecute.java | 50 ------- .../ai/midjourney/demo/jad/Constants.java | 22 --- .../midjourney/demo/jad/DiscordAccount.java | 35 ----- .../ai/midjourney/demo/jad/DomainObject.java | 70 --------- .../midjourney/demo/wss/AsyncLockUtils.java | 61 -------- .../ai/midjourney/demo/wss/DiscordHelper.java | 57 ------- .../demo/wss/user/UserMessageListener.java | 27 ---- .../interactions/MjImagineInteractions.java | 4 +- .../interactions/MjInteractions.java | 4 +- .../framework/ai/midjourney/package-info.java | 5 - .../user => webSocket}/FailureCallback.java | 2 +- .../MjWebSocketStarter.java} | 67 +++------ .../user => webSocket}/SuccessCallback.java | 2 +- .../wss => webSocket}/WebSocketStarter.java | 2 +- .../handler/MjWebSocketHandler.java} | 36 +++-- .../webSocket/listener/MjMessageListener.java | 44 ++++++ .../http-body}/interactions_type2.json | 0 .../http-body}/interactions_type3.json | 0 26 files changed, 110 insertions(+), 591 deletions(-) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjConstants.java rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{MidjourneyInteractionsEnum.java => constants/MjInteractionsEnum.java} (71%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{demo/wss/MessageType.java => constants/MjMessageTypeEnum.java} (64%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{demo/wss/ReturnCode.java => constants/MjNotifyCode.java} (86%) delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/DiscordJadMain.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/DiscordWebSocketClient.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MidjourneyApi.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjExecute.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjHttpExecute.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/Constants.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/DiscordAccount.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/DomainObject.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/AsyncLockUtils.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/DiscordHelper.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/UserMessageListener.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/package-info.java rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{demo/wss/user => webSocket}/FailureCallback.java (55%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{demo/wss/user/SpringUserWebSocketStarter.java => webSocket/MjWebSocketStarter.java} (65%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{demo/wss/user => webSocket}/SuccessCallback.java (64%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{demo/wss => webSocket}/WebSocketStarter.java (55%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{demo/wss/user/SpringWebSocketHandler.java => webSocket/handler/MjWebSocketHandler.java} (84%) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MjMessageListener.java rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/{java/cn/iocoder/yudao/framework/ai/midjourney/demo => resources/http-body}/interactions_type2.json (100%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/{java/cn/iocoder/yudao/framework/ai/midjourney/demo => resources/http-body}/interactions_type3.json (100%) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjConstants.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjConstants.java new file mode 100644 index 000000000..79b5b1b55 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjConstants.java @@ -0,0 +1,8 @@ +package cn.iocoder.yudao.framework.ai.midjourney.constants; + +public final class MjConstants { + + public static final String CHANNEL_ID = "channel_id"; + + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjInteractionsEnum.java similarity index 71% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsEnum.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjInteractionsEnum.java index 20b70b5f9..124bc8332 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjInteractionsEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney; +package cn.iocoder.yudao.framework.ai.midjourney.constants; import lombok.Getter; @@ -6,7 +6,7 @@ import lombok.Getter; * MJ 命令 */ @Getter -public enum MidjourneyInteractionsEnum { +public enum MjInteractionsEnum { IMAGINE("imagine", "生成图片"), DESCRIBE("describe", "生成描述"), @@ -17,7 +17,7 @@ public enum MidjourneyInteractionsEnum { ; - MidjourneyInteractionsEnum(String value, String message) { + MjInteractionsEnum(String value, String message) { this.value =value; this.message =message; } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/MessageType.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjMessageTypeEnum.java similarity index 64% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/MessageType.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjMessageTypeEnum.java index cc48fe983..b47199e91 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/MessageType.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjMessageTypeEnum.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.framework.ai.midjourney.demo.wss; +package cn.iocoder.yudao.framework.ai.midjourney.constants; -public enum MessageType { +public enum MjMessageTypeEnum { /** * 创建. */ @@ -15,7 +15,7 @@ public enum MessageType { */ DELETE; - public static MessageType of(String type) { + public static MjMessageTypeEnum of(String type) { return switch (type) { case "MESSAGE_CREATE" -> CREATE; case "MESSAGE_UPDATE" -> UPDATE; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/ReturnCode.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjNotifyCode.java similarity index 86% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/ReturnCode.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjNotifyCode.java index 0de539035..823d13fc2 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/ReturnCode.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjNotifyCode.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.framework.ai.midjourney.demo.wss; +package cn.iocoder.yudao.framework.ai.midjourney.constants; import lombok.experimental.UtilityClass; @UtilityClass -public final class ReturnCode { +public final class MjNotifyCode { /** * 成功. */ diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/DiscordJadMain.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/DiscordJadMain.java deleted file mode 100644 index d9c9dba17..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/DiscordJadMain.java +++ /dev/null @@ -1,10 +0,0 @@ -package cn.iocoder.yudao.framework.ai.midjourney.demo; - -/** - * author: fansili - * time: 2024/4/3 15:54 - */ -public class DiscordJadMain { - - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/DiscordWebSocketClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/DiscordWebSocketClient.java deleted file mode 100644 index df9705095..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/DiscordWebSocketClient.java +++ /dev/null @@ -1,141 +0,0 @@ -package cn.iocoder.yudao.framework.ai.midjourney.demo; -import cn.hutool.http.useragent.UserAgent; -import cn.hutool.http.useragent.UserAgentUtil; -import cn.hutool.json.JSONObject; -import com.alibaba.fastjson.JSON; -import org.springframework.web.socket.*; -import org.springframework.web.socket.client.standard.StandardWebSocketClient; -import org.springframework.web.socket.handler.TextWebSocketHandler; - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; - -/** - * https://blog.csdn.net/qq_38490457/article/details/125250135 - */ -public class DiscordWebSocketClient { - - private static final String DISCORD_GATEWAY_URL = "wss://gateway.discord.gg/?v=9&encoding=json"; - - public static void main(String[] args) throws InterruptedException, ExecutionException, IOException, URISyntaxException { - StandardWebSocketClient client = new StandardWebSocketClient(); - DiscordWebSocketHandler handler = new DiscordWebSocketHandler(); - - - WebSocketHttpHeaders headers = new WebSocketHttpHeaders(); - headers.add("Accept-Encoding", "gzip, deflate, br"); - headers.add("Accept-Language", "zh-CN,zh;q=0.9"); - headers.add("Cache-Control", "no-cache"); - headers.add("Pragma", "no-cache"); - headers.add("Sec-Websocket-Extensions", "permessage-deflate; client_max_window_bits"); - headers.add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36"); - - Future futureSession = client.doHandshake(handler, headers, new URI(DISCORD_GATEWAY_URL)); - WebSocketSession session = futureSession.get(); // 这会阻塞直到连接建立 - - // 登录过程(你需要替换 TOKEN 为你的 Discord Bot Token) -// String token = "YOUR_DISCORD_BOT_TOKEN"; // 请替换为你的 Bot Token -// String identifyPayload = "{\"op\":2,\"d\":{\"token\":\"" + token + "\",\"properties\":{\"$os\":\"java\",\"$browser\":\"spring-websocket\",\"$device\":\"spring-websocket\"},\"compress\":false,\"large_threshold\":256,\"shard\":[0,1]}}"; -// session.sendMessage(new TextMessage(identifyPayload)); - - // 发送心跳以保持连接活跃 - Thread heartbeatThread = new Thread(() -> { - int interval = 0; // 初始心跳间隔,后续从 Discord 服务器获取 - while (!Thread.currentThread().isInterrupted()) { - try { - Thread.sleep(interval * 1000); // 等待指定的心跳间隔 - session.sendMessage(new TextMessage("{\"op\":1,\"d\":null}")); // 发送心跳包 - } catch (Exception e) { - e.printStackTrace(); - break; - } - } - }); - heartbeatThread.start(); - - // 等待用户输入来保持程序运行(仅用于示例) - System.in.read(); - - // 关闭连接和线程 - session.close(); - heartbeatThread.interrupt(); - } - - private static class DiscordWebSocketHandler implements WebSocketHandler { - - @Override - public void afterConnectionEstablished(WebSocketSession session) throws Exception { - - } - - @Override - public void handleMessage(WebSocketSession session, WebSocketMessage message) throws Exception { - Object payload = message.getPayload(); - - session.sendMessage(new TextMessage(JSON.toJSONString(createAuthData()))); - String a= ""; - } - - @Override - public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { - - } - - @Override - public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { - - } - - @Override - public boolean supportsPartialMessages() { - return false; - } - - - private JSONObject createAuthData() { - String userAgentStr = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36"; - UserAgent userAgent = UserAgentUtil.parse(userAgentStr); - String token = "NTY5MDY4NDAxNzEyOTU1Mzky.G4-Fu0.MzD-7ll-ElbXTTgDPHF-WS_UyhMAfbKN3WyyBc"; - - JSONObject connectionProperties = new JSONObject() - .put("browser", userAgent.getBrowser().getName()) - .put("browser_user_agent", userAgentStr) - .put("browser_version", userAgent.getVersion()) - .put("client_build_number", 222963) - .put("client_event_source", null) - .put("device", "") - .put("os", userAgent.getOs().getName()) - .put("referer", "https://www.midjourney.com") - .put("referrer_current", "") - .put("referring_domain", "www.midjourney.com") - .put("referring_domain_current", "") - .put("release_channel", "stable") - .put("system_locale", "zh-CN"); - JSONObject presence = new JSONObject() - .put("activities", "") - .put("afk", false) - .put("since", 0) - .put("status", "online"); - JSONObject clientState = new JSONObject() - .put("api_code_version", 0) - .put("guild_versions", "") - .put("highest_last_message_id", "0") - .put("private_channels_version", "0") - .put("read_state_version", 0) - .put("user_guild_settings_version", -1) - .put("user_settings_version", -1); - return new JSONObject() - .put("capabilities", 16381) - .put("client_state", clientState) - .put("compress", false) - .put("presence", presence) - .put("properties", connectionProperties) - .put("token", token); - } - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MidjourneyApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MidjourneyApi.java deleted file mode 100644 index 1c0cbd480..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MidjourneyApi.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.framework.ai.midjourney.demo; - -/** - * 文档: https://www.xiubbs.com/t-401-1-1.html - * - * https://github.com/novicezk/midjourney-proxy/blob/main/README_CN.md - * - * discord4j、https://github.com/discord-jda/JDA - * - */ -public class MidjourneyApi { - - -// https://discord.com/api/v9/interactions -// -// payload_json: {"type":2,"application_id":"936929561302675456","guild_id":"1224337694918971392","channel_id":"1224337694918971396","session_id":"696318caed5180a2210e358e44801449","data":{"version":"1166847114203123795","id":"938956540159881230","name":"imagine","type":1,"options":[{"type":3,"name":"prompt","value":"中国的是什么样子"}],"application_command":{"id":"938956540159881230","type":1,"application_id":"936929561302675456","version":"1166847114203123795","name":"imagine","description":"Create images with Midjourney","options":[{"type":3,"name":"prompt","description":"The prompt to imagine","required":true,"description_localized":"The prompt to imagine","name_localized":"prompt"}],"dm_permission":true,"integration_types":[0],"global_popularity_rank":1,"description_localized":"Create images with Midjourney","name_localized":"imagine"},"attachments":[]},"nonce":"1224342266261274624","analytics_location":"slash_ui"} -// - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjExecute.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjExecute.java deleted file mode 100644 index 299266c78..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjExecute.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.framework.ai.midjourney.demo; - -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyInteractionsEnum; - -/** - * mj 命令 - */ -public interface MjExecute { - - /** - * 执行命令 - * - * @param mjCommand - * @param prompt - * @return - */ - boolean execute(MidjourneyInteractionsEnum mjCommand, String prompt); - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjHttpExecute.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjHttpExecute.java deleted file mode 100644 index 34cf4fd7a..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjHttpExecute.java +++ /dev/null @@ -1,50 +0,0 @@ -package cn.iocoder.yudao.framework.ai.midjourney.demo; - -import cn.hutool.core.io.FileUtil; -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyInteractionsEnum; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.web.client.RestTemplate; - -import java.nio.charset.Charset; - -public class MjHttpExecute implements MjExecute { - - private static final String URL = "https://discord.com/"; - - @Override - public boolean execute(MidjourneyInteractionsEnum mjCommand, String prompt) { - // 发送的 uri - String uri = "api/v9/interactions"; - // restTemplate 发送post请求 -// String result = restTemplate.postForObject(URL + uri, prompt, String.class); - // 加载当前目录下文件 - return false; - } - - public static void main(String[] args) { - RestTemplate restTemplate = new RestTemplate(); - - String token = "NTY5MDY4NDAxNzEyOTU1Mzky.G4-Fu0.MzD-7ll-ElbXTTgDPHF-WS_UyhMAfbKN3WyyBc"; - String body = FileUtil.readString("/Users/fansili/projects/github/ruoyi-vue-pro/yudao-module-ai" + - "/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney" + - "/interactions_type2.json", Charset.forName("utf-8")); - // 创建HTTP头部 - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); // 设置内容类型为JSON - headers.set("Authorization", token); // 如果需要,设置认证信息(例如JWT令牌) - headers.set("Referer", "https://discord.com/channels/1221445697157468200/1221445862962630706"); // 如果需要,设置认证信息(例如JWT令牌) - headers.set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"); // 如果需要,设置认证信息(例如JWT令牌) - headers.set("Cookie", "__dcfduid=6ca536c0e3fa11eeb7cbe34c31b49caf; __sdcfduid=6ca536c1e3fa11eeb7cbe34c31b49caf52cce5ffd8983d2a052cf6aba75fe5fe566f2c265902e283ce30dbf98b8c9c93; _gcl_au=1.1.245923998.1710853617; _ga=GA1.1.111061823.1710853617; __cfruid=6385bb3f48345a006b25992db7dcf984e395736d-1712124666; _cfuvid=O09la5ms0ypNptiG0iD8A6BKWlTxz1LG0WR7qRStD7o-1712124666575-0.0.1.1-604800000; locale=zh-CN; cf_clearance=l_YGod1_SUtYxpDVeZXiX7DLLPl1DYrquZe8WVltvYs-1712124668-1.0.1.1-Hl2.fToel23EpF2HCu9J20rB4D7OhhCzoajPSdo.9Up.wPxhvq22DP9RHzEBKuIUlKyH.kJLxXJfAt2N.LD5WQ; OptanonConsent=isIABGlobal=false&datestamp=Wed+Apr+03+2024+14%3A11%3A15+GMT%2B0800+(%E4%B8%AD%E5%9B%BD%E6%A0%87%E5%87%86%E6%97%B6%E9%97%B4)&version=6.33.0&hosts=&landingPath=https%3A%2F%2Fdiscord.com%2F&groups=C0001%3A1%2CC0002%3A1%2CC0003%3A1; _ga_Q149DFWHT7=GS1.1.1712124668.4.1.1712124679.0.0.0"); // 如果需要,设置认证信息(例如JWT令牌) - // 封装请求体和头部信息 - HttpEntity requestEntity = new HttpEntity<>(body, headers); - - // 定义请求URL和返回类型 - String uri = "api/v9/interactions"; - String res = restTemplate.postForObject(URL + uri, requestEntity, String.class); - System.err.println("11"); - - - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/Constants.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/Constants.java deleted file mode 100644 index 42e1b2f47..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/Constants.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.framework.ai.midjourney.demo.jad; - -import lombok.experimental.UtilityClass; - -@UtilityClass -public final class Constants { - // 任务扩展属性 start - public static final String TASK_PROPERTY_NOTIFY_HOOK = "notifyHook"; - public static final String TASK_PROPERTY_FINAL_PROMPT = "finalPrompt"; - public static final String TASK_PROPERTY_MESSAGE_ID = "messageId"; - public static final String TASK_PROPERTY_MESSAGE_HASH = "messageHash"; - public static final String TASK_PROPERTY_PROGRESS_MESSAGE_ID = "progressMessageId"; - public static final String TASK_PROPERTY_FLAGS = "flags"; - public static final String TASK_PROPERTY_NONCE = "nonce"; - public static final String TASK_PROPERTY_DISCORD_INSTANCE_ID = "discordInstanceId"; - // 任务扩展属性 end - - public static final String API_SECRET_HEADER_NAME = "mj-api-secret"; - public static final String DEFAULT_DISCORD_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36"; - - public static final String MJ_MESSAGE_HANDLED = "mj_proxy_handled"; -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/DiscordAccount.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/DiscordAccount.java deleted file mode 100644 index 8fafa9f59..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/DiscordAccount.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.yudao.framework.ai.midjourney.demo.jad; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import lombok.Data; -import lombok.EqualsAndHashCode; - -@Data -@EqualsAndHashCode(callSuper = true) - -public class DiscordAccount extends DomainObject { - - - private String guildId; - - private String channelId; - - private String userToken; - - private String userAgent = Constants.DEFAULT_DISCORD_USER_AGENT; - - - private boolean enable = true; - - - private int coreSize = 3; - - private int queueSize = 10; - - private int timeoutMinutes = 5; - - @JsonIgnore - public String getDisplay() { - return this.channelId; - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/DomainObject.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/DomainObject.java deleted file mode 100644 index e12339edc..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/DomainObject.java +++ /dev/null @@ -1,70 +0,0 @@ -package cn.iocoder.yudao.framework.ai.midjourney.demo.jad; - - -import com.fasterxml.jackson.annotation.JsonIgnore; -import lombok.Getter; -import lombok.Setter; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; - - -public class DomainObject implements Serializable { - @Getter - @Setter - protected String id; - - @Setter - protected Map properties; // 扩展属性,仅支持基本类型 - - @JsonIgnore - private final transient Object lock = new Object(); - - public void sleep() throws InterruptedException { - synchronized (this.lock) { - this.lock.wait(); - } - } - - public void awake() { - synchronized (this.lock) { - this.lock.notifyAll(); - } - } - - public DomainObject setProperty(String name, Object value) { - getProperties().put(name, value); - return this; - } - - public DomainObject removeProperty(String name) { - getProperties().remove(name); - return this; - } - - public Object getProperty(String name) { - return getProperties().get(name); - } - - @SuppressWarnings("unchecked") - public T getPropertyGeneric(String name) { - return (T) getProperty(name); - } - - public T getProperty(String name, Class clz) { - return getProperty(name, clz, null); - } - - public T getProperty(String name, Class clz, T defaultValue) { - Object value = getProperty(name); - return value == null ? defaultValue : clz.cast(value); - } - - public Map getProperties() { - if (this.properties == null) { - this.properties = new HashMap<>(); - } - return this.properties; - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/AsyncLockUtils.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/AsyncLockUtils.java deleted file mode 100644 index 365935a8f..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/AsyncLockUtils.java +++ /dev/null @@ -1,61 +0,0 @@ -package cn.iocoder.yudao.framework.ai.midjourney.demo.wss; - -import cn.hutool.cache.CacheUtil; -import cn.hutool.cache.impl.TimedCache; -import cn.hutool.core.thread.ThreadUtil; -import cn.iocoder.yudao.framework.ai.midjourney.demo.jad.DomainObject; -import lombok.experimental.UtilityClass; - -import java.time.Duration; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -@UtilityClass -public class AsyncLockUtils { - private static final TimedCache LOCK_MAP = CacheUtil.newTimedCache(Duration.ofDays(1).toMillis()); - - public static synchronized LockObject getLock(String key) { - return LOCK_MAP.get(key); - } - - public static LockObject waitForLock(String key, Duration duration) throws TimeoutException { - LockObject lockObject; - synchronized (LOCK_MAP) { - if (LOCK_MAP.containsKey(key)) { - lockObject = LOCK_MAP.get(key); - } else { - lockObject = new LockObject(key); - LOCK_MAP.put(key, lockObject); - } - } - Future future = ThreadUtil.execAsync(() -> { - try { - lockObject.sleep(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - }); - try { - future.get(duration.toMillis(), TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } catch (ExecutionException e) { - // do nothing - } catch (TimeoutException e) { - future.cancel(true); - throw new TimeoutException("Wait Timeout"); - } finally { - LOCK_MAP.remove(lockObject.getId()); - } - return lockObject; - } - - public static class LockObject extends DomainObject { - - public LockObject(String id) { - this.id = id; - } - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/DiscordHelper.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/DiscordHelper.java deleted file mode 100644 index 7f57fea08..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/DiscordHelper.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.iocoder.yudao.framework.ai.midjourney.demo.wss; - -import cn.hutool.core.text.CharSequenceUtil; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; - -@Component -@RequiredArgsConstructor -public class DiscordHelper { - /** - * DISCORD_SERVER_URL. - */ - public static final String DISCORD_SERVER_URL = "https://discord.com"; - /** - * DISCORD_CDN_URL. - */ - public static final String DISCORD_CDN_URL = "https://cdn.discordapp.com"; - /** - * DISCORD_WSS_URL. - */ - public static final String DISCORD_WSS_URL = "wss://gateway.discord.gg"; - /** - * DISCORD_UPLOAD_URL. - */ - public static final String DISCORD_UPLOAD_URL = "https://discord-attachments-uploads-prd.storage.googleapis.com"; - - public String getServer() { - return DISCORD_SERVER_URL; - } - - public String getCdn() { - return DISCORD_CDN_URL; - } - - public String getWss() { - return DISCORD_WSS_URL; - } - - public String getMessageHash(String imageUrl) { - if (CharSequenceUtil.isBlank(imageUrl)) { - return null; - } - if (CharSequenceUtil.endWith(imageUrl, "_grid_0.webp")) { - int hashStartIndex = imageUrl.lastIndexOf("/"); - if (hashStartIndex < 0) { - return null; - } - return CharSequenceUtil.sub(imageUrl, hashStartIndex + 1, imageUrl.length() - "_grid_0.webp".length()); - } - int hashStartIndex = imageUrl.lastIndexOf("_"); - if (hashStartIndex < 0) { - return null; - } - return CharSequenceUtil.subBefore(imageUrl.substring(hashStartIndex + 1), ".", true); - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/UserMessageListener.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/UserMessageListener.java deleted file mode 100644 index ca97b6cae..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/UserMessageListener.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user; - - -import cn.hutool.core.thread.ThreadUtil; -import cn.iocoder.yudao.framework.ai.midjourney.demo.wss.MessageType; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.utils.data.DataObject; - -@Slf4j -public class UserMessageListener { - - public void onMessage(DataObject raw) { - MessageType messageType = MessageType.of(raw.getString("t")); - if (messageType == null || MessageType.DELETE == messageType) { - return; - } - DataObject data = raw.getObject("d"); - System.err.println(data); - ThreadUtil.sleep(50); -// for (MessageHandler messageHandler : this.messageHandlers) { -// if (data.getBoolean(Constants.MJ_MESSAGE_HANDLED, false)) { -// return; -// } -// messageHandler.handle(this.instance, messageType, data); -// } - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java index 5768cbe8d..5e49d6784 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.framework.ai.midjourney.interactions; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyInteractionsEnum; +import cn.iocoder.yudao.framework.ai.midjourney.constants.MjInteractionsEnum; import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; @@ -27,7 +27,7 @@ public class MjImagineInteractions implements MjInteractions { } @Override - public List supperInteractions() { + public List supperInteractions() { return null; } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java index 9b94abc7a..38f58f70f 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.framework.ai.midjourney.interactions; -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyInteractionsEnum; +import cn.iocoder.yudao.framework.ai.midjourney.constants.MjInteractionsEnum; import java.util.List; @@ -12,7 +12,7 @@ import java.util.List; */ public interface MjInteractions { - List supperInteractions(); + List supperInteractions(); Boolean execute(String prompt); } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/package-info.java deleted file mode 100644 index 2ab112963..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -/** - * author: fansili - * time: 2024/4/3 17:08 - */ -package cn.iocoder.yudao.framework.ai.midjourney; \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/FailureCallback.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/FailureCallback.java similarity index 55% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/FailureCallback.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/FailureCallback.java index 9600ddab3..29bdb062c 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/FailureCallback.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/FailureCallback.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user; +package cn.iocoder.yudao.framework.ai.midjourney.webSocket; public interface FailureCallback { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/SpringUserWebSocketStarter.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MjWebSocketStarter.java similarity index 65% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/SpringUserWebSocketStarter.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MjWebSocketStarter.java index 644a36844..e6dcafc1a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/SpringUserWebSocketStarter.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MjWebSocketStarter.java @@ -1,13 +1,12 @@ -package cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user; +package cn.iocoder.yudao.framework.ai.midjourney.webSocket; -import cn.hutool.core.exceptions.ValidateException; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.thread.ThreadUtil; -import cn.iocoder.yudao.framework.ai.midjourney.demo.jad.DiscordAccount; -import cn.iocoder.yudao.framework.ai.midjourney.demo.wss.AsyncLockUtils; -import cn.iocoder.yudao.framework.ai.midjourney.demo.wss.ReturnCode; -import cn.iocoder.yudao.framework.ai.midjourney.demo.wss.WebSocketStarter; +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; +import cn.iocoder.yudao.framework.ai.midjourney.constants.MjNotifyCode; +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.handler.MjWebSocketHandler; +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener.MjMessageListener; import lombok.extern.slf4j.Slf4j; import org.apache.tomcat.websocket.Constants; import org.jetbrains.annotations.NotNull; @@ -19,15 +18,14 @@ import org.springframework.web.socket.client.standard.StandardWebSocketClient; import java.io.IOException; import java.net.URI; -import java.time.Duration; import java.util.concurrent.TimeoutException; @Slf4j -public class SpringUserWebSocketStarter implements WebSocketStarter { +public class MjWebSocketStarter implements WebSocketStarter { private static final int CONNECT_RETRY_LIMIT = 5; - private final DiscordAccount account; - private final UserMessageListener userMessageListener; + private final MidjourneyConfig midjourneyConfig; + private final MjMessageListener userMessageListener; private final String wssServer; private final String resumeWss; @@ -36,10 +34,10 @@ public class SpringUserWebSocketStarter implements WebSocketStarter { private WebSocketSession webSocketSession = null; private ResumeData resumeData = null; - public SpringUserWebSocketStarter(String wssServer, String resumeWss, DiscordAccount account, UserMessageListener userMessageListener) { + public MjWebSocketStarter(String wssServer, String resumeWss, MidjourneyConfig midjourneyConfig, MjMessageListener userMessageListener) { this.wssServer = wssServer; this.resumeWss = resumeWss; - this.account = account; + this.midjourneyConfig = midjourneyConfig; this.userMessageListener = userMessageListener; } @@ -55,8 +53,8 @@ public class SpringUserWebSocketStarter implements WebSocketStarter { headers.add("Cache-Control", "no-cache"); headers.add("Pragma", "no-cache"); headers.add("Sec-Websocket-Extensions", "permessage-deflate; client_max_window_bits"); - headers.add("User-Agent", this.account.getUserAgent()); - var handler = new SpringWebSocketHandler(this.account, this.userMessageListener, this::onSocketSuccess, this::onSocketFailure); + headers.add("User-Agent", this.midjourneyConfig.getUserAage()); + var handler = new MjWebSocketHandler(this.midjourneyConfig, this.userMessageListener, this::onSocketSuccess, this::onSocketFailure); String gatewayUrl; if (reconnect) { gatewayUrl = getGatewayServer(this.resumeData.resumeGatewayUrl()) + "/?encoding=json&v=9&compress=zlib-stream"; @@ -72,12 +70,12 @@ public class SpringUserWebSocketStarter implements WebSocketStarter { socketSessionFuture.addCallback(new ListenableFutureCallback<>() { @Override public void onFailure(@NotNull Throwable e) { - onSocketFailure(SpringWebSocketHandler.CLOSE_CODE_EXCEPTION, e.getMessage()); + onSocketFailure(MjWebSocketHandler.CLOSE_CODE_EXCEPTION, e.getMessage()); } @Override public void onSuccess(WebSocketSession session) { - SpringUserWebSocketStarter.this.webSocketSession = session; + MjWebSocketStarter.this.webSocketSession = session; } }); } @@ -85,7 +83,7 @@ public class SpringUserWebSocketStarter implements WebSocketStarter { private void onSocketSuccess(String sessionId, Object sequence, String resumeGatewayUrl) { this.resumeData = new ResumeData(sessionId, sequence, resumeGatewayUrl); this.running = true; - notifyWssLock(ReturnCode.SUCCESS, ""); + notifyWssLock(MjNotifyCode.SUCCESS, ""); } private void onSocketFailure(int code, String reason) { @@ -99,13 +97,12 @@ public class SpringUserWebSocketStarter implements WebSocketStarter { } this.running = false; if (code >= 4000) { - log.warn("[wss-{}] Can't reconnect! Account disabled. Closed by {}({}).", this.account.getDisplay(), code, reason); - disableAccount(); + log.warn("[wss-{}] Can't reconnect! Account disabled. Closed by {}({}).", this.midjourneyConfig.getChannelId(), code, reason); } else if (code == 2001) { - log.warn("[wss-{}] Closed by {}({}). Try reconnect...", this.account.getDisplay(), code, reason); + log.warn("[wss-{}] Closed by {}({}). Try reconnect...", this.midjourneyConfig.getChannelId(), code, reason); tryReconnect(); } else { - log.warn("[wss-{}] Closed by {}({}). Try new connection...", this.account.getDisplay(), code, reason); + log.warn("[wss-{}] Closed by {}({}). Try new connection...", this.midjourneyConfig.getChannelId(), code, reason); tryNewConnect(); } } @@ -117,7 +114,7 @@ public class SpringUserWebSocketStarter implements WebSocketStarter { if (e instanceof TimeoutException) { closeSocketSessionWhenIsOpen(); } - log.warn("[wss-{}] Reconnect fail: {}, Try new connection...", this.account.getDisplay(), e.getMessage()); + log.warn("[wss-{}] Reconnect fail: {}, Try new connection...", this.midjourneyConfig.getChannelId(), e.getMessage()); ThreadUtil.sleep(1000); tryNewConnect(); } @@ -132,39 +129,19 @@ public class SpringUserWebSocketStarter implements WebSocketStarter { if (e instanceof TimeoutException) { closeSocketSessionWhenIsOpen(); } - log.warn("[wss-{}] New connect fail ({}): {}", this.account.getDisplay(), i, e.getMessage()); + log.warn("[wss-{}] New connect fail ({}): {}", this.midjourneyConfig.getChannelId(), i, e.getMessage()); ThreadUtil.sleep(5000); } } - log.error("[wss-{}] Account disabled", this.account.getDisplay()); - disableAccount(); + log.error("[wss-{}] Account disabled", this.midjourneyConfig.getChannelId()); } public void tryStart(boolean reconnect) throws Exception { start(reconnect); - AsyncLockUtils.LockObject lock = AsyncLockUtils.waitForLock("wss:" + this.account.getId(), Duration.ofSeconds(20)); - int code = lock.getProperty("code", Integer.class, 0); - if (code == ReturnCode.SUCCESS) { - log.debug("[wss-{}] {} success.", this.account.getDisplay(), reconnect ? "Reconnect" : "New connect"); - return; - } - throw new ValidateException(lock.getProperty("description", String.class)); } private void notifyWssLock(int code, String reason) { - AsyncLockUtils.LockObject lock = AsyncLockUtils.getLock("wss:" + this.account.getId()); - if (lock != null) { - lock.setProperty("code", code); - lock.setProperty("description", reason); - lock.awake(); - } - } - - private void disableAccount() { - if (Boolean.FALSE.equals(this.account.isEnable())) { - return; - } - this.account.setEnable(false); + System.err.println("notifyWssLock: " + code + " - " + reason); } private void closeSocketSessionWhenIsOpen() { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/SuccessCallback.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/SuccessCallback.java similarity index 64% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/SuccessCallback.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/SuccessCallback.java index 7ff2bd3af..729498fbc 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/SuccessCallback.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/SuccessCallback.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user; +package cn.iocoder.yudao.framework.ai.midjourney.webSocket; public interface SuccessCallback { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/WebSocketStarter.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/WebSocketStarter.java similarity index 55% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/WebSocketStarter.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/WebSocketStarter.java index 82874f204..88e283244 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/WebSocketStarter.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/WebSocketStarter.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.demo.wss; +package cn.iocoder.yudao.framework.ai.midjourney.webSocket; public interface WebSocketStarter { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/SpringWebSocketHandler.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/handler/MjWebSocketHandler.java similarity index 84% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/SpringWebSocketHandler.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/handler/MjWebSocketHandler.java index b9d77784d..481fa1b0c 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/SpringWebSocketHandler.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/handler/MjWebSocketHandler.java @@ -1,11 +1,14 @@ -package cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user; +package cn.iocoder.yudao.framework.ai.midjourney.webSocket.handler; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.RandomUtil; import cn.hutool.http.useragent.UserAgent; import cn.hutool.http.useragent.UserAgentUtil; -import cn.iocoder.yudao.framework.ai.midjourney.demo.jad.DiscordAccount; +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.FailureCallback; +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.SuccessCallback; +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener.MjMessageListener; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.utils.data.DataArray; @@ -26,13 +29,13 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @Slf4j -public class SpringWebSocketHandler implements WebSocketHandler { +public class MjWebSocketHandler implements WebSocketHandler { public static final int CLOSE_CODE_RECONNECT = 2001; public static final int CLOSE_CODE_INVALIDATE = 1009; public static final int CLOSE_CODE_EXCEPTION = 1011; - private final DiscordAccount account; - private final UserMessageListener userMessageListener; + private final MidjourneyConfig midjourneyConfig; + private final MjMessageListener userMessageListener; private final SuccessCallback successCallback; private final FailureCallback failureCallback; @@ -54,8 +57,11 @@ public class SpringWebSocketHandler implements WebSocketHandler { private final Decompressor decompressor = new ZlibDecompressor(2048); - public SpringWebSocketHandler(DiscordAccount account, UserMessageListener userMessageListener, SuccessCallback successCallback, FailureCallback failureCallback) { - this.account = account; + public MjWebSocketHandler(MidjourneyConfig account, + MjMessageListener userMessageListener, + SuccessCallback successCallback, + FailureCallback failureCallback) { + this.midjourneyConfig = account; this.userMessageListener = userMessageListener; this.successCallback = successCallback; this.failureCallback = failureCallback; @@ -70,7 +76,7 @@ public class SpringWebSocketHandler implements WebSocketHandler { @Override public void handleTransportError(@NotNull WebSocketSession session, @NotNull Throwable e) throws Exception { - log.error("[wss-{}] Transport error", this.account.getDisplay(), e); + log.error("[wss-{}] Transport error", this.midjourneyConfig.getChannelId(), e); onFailure(CLOSE_CODE_EXCEPTION, "transport error"); } @@ -108,7 +114,7 @@ public class SpringWebSocketHandler implements WebSocketHandler { case WebSocketCode.RECONNECT -> onFailure(CLOSE_CODE_RECONNECT, "receive server reconnect"); case WebSocketCode.INVALIDATE_SESSION -> onFailure(CLOSE_CODE_INVALIDATE, "receive session invalid"); case WebSocketCode.DISPATCH -> handleDispatch(data); - default -> log.debug("[wss-{}] Receive unknown code: {}.", account.getDisplay(), data); + default -> log.debug("[wss-{}] Receive unknown code: {}.", midjourneyConfig.getChannelId(), data); } } @@ -129,7 +135,7 @@ public class SpringWebSocketHandler implements WebSocketHandler { try { this.userMessageListener.onMessage(raw); } catch (Exception e) { - log.error("[wss-{}] Handle message error", this.account.getDisplay(), e); + log.error("[wss-{}] Handle message error", this.midjourneyConfig.getChannelId(), e); } } } @@ -160,7 +166,7 @@ public class SpringWebSocketHandler implements WebSocketHandler { if (CharSequenceUtil.isBlank(this.sessionId)) { sendMessage(session, WebSocketCode.IDENTIFY, this.authData); } else { - var data = DataObject.empty().put("token", this.account.getUserToken()) + var data = DataObject.empty().put("token", this.midjourneyConfig.getToken()) .put("session_id", this.sessionId).put("seq", this.sequence); sendMessage(session, WebSocketCode.RESUME, data); } @@ -171,7 +177,7 @@ public class SpringWebSocketHandler implements WebSocketHandler { try { session.sendMessage(new TextMessage(data.toString())); } catch (IOException e) { - log.error("[wss-{}] Send message error", this.account.getDisplay(), e); + log.error("[wss-{}] Send message error", this.midjourneyConfig.getChannelId(), e); onFailure(CLOSE_CODE_EXCEPTION, "send message error"); } } @@ -201,10 +207,10 @@ public class SpringWebSocketHandler implements WebSocketHandler { } private DataObject createAuthData() { - UserAgent userAgent = UserAgentUtil.parse(this.account.getUserAgent()); + UserAgent userAgent = UserAgentUtil.parse(this.midjourneyConfig.getUserAage()); DataObject connectionProperties = DataObject.empty() .put("browser", userAgent.getBrowser().getName()) - .put("browser_user_agent", this.account.getUserAgent()) + .put("browser_user_agent", this.midjourneyConfig.getUserAage()) .put("browser_version", userAgent.getVersion()) .put("client_build_number", 222963) .put("client_event_source", null) @@ -235,6 +241,6 @@ public class SpringWebSocketHandler implements WebSocketHandler { .put("compress", false) .put("presence", presence) .put("properties", connectionProperties) - .put("token", this.account.getUserToken()); + .put("token", this.midjourneyConfig.getToken()); } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MjMessageListener.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MjMessageListener.java new file mode 100644 index 000000000..8e57a46ab --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MjMessageListener.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener; + + +import cn.hutool.core.text.CharSequenceUtil; +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; +import cn.iocoder.yudao.framework.ai.midjourney.constants.MjConstants; +import cn.iocoder.yudao.framework.ai.midjourney.constants.MjMessageTypeEnum; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.utils.data.DataObject; + +@Slf4j +public class MjMessageListener { + + private MidjourneyConfig midjourneyConfig; + + public MjMessageListener(MidjourneyConfig midjourneyConfig) { + this.midjourneyConfig = midjourneyConfig; + } + + public void onMessage(DataObject raw) { + MjMessageTypeEnum messageType = MjMessageTypeEnum.of(raw.getString("t")); + if (messageType == null || MjMessageTypeEnum.DELETE == messageType) { + return; + } + DataObject data = raw.getObject("d"); + if (ignoreAndLogMessage(data, messageType)) { + return; + } + System.err.println(data); +// if (data.getBoolean(Constants.MJ_MESSAGE_HANDLED, false)) { +// return; +// } + } + + private boolean ignoreAndLogMessage(DataObject data, MjMessageTypeEnum messageType) { + String channelId = data.getString(MjConstants.CHANNEL_ID); + if (!CharSequenceUtil.equals(channelId, midjourneyConfig.getChannelId())) { + return true; + } + String authorName = data.optObject("author").map(a -> a.getString("username")).orElse("System"); + log.debug("{} - {} - {}: {}", midjourneyConfig.getChannelId(), messageType.name(), authorName, data.opt("content").orElse("")); + return false; + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/interactions_type2.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/interactions_type2.json similarity index 100% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/interactions_type2.json rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/interactions_type2.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/interactions_type3.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/interactions_type3.json similarity index 100% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/interactions_type3.json rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/interactions_type3.json From 44e44dc4bb1431a293afd2d3cd9c57fccb65258e Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 5 Apr 2024 10:15:59 +0800 Subject: [PATCH 042/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/midjourney/constants/MjNotifyCode.java | 28 ----- .../webSocket/MjWebSocketStarter.java | 101 +++++++++++++----- .../webSocket/handler/MjWebSocketHandler.java | 39 ++++++- 3 files changed, 114 insertions(+), 54 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjNotifyCode.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjNotifyCode.java index 823d13fc2..103bd6fdf 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjNotifyCode.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjNotifyCode.java @@ -8,35 +8,7 @@ public final class MjNotifyCode { * 成功. */ public static final int SUCCESS = 1; - /** - * 数据未找到. - */ - public static final int NOT_FOUND = 3; - /** - * 校验错误. - */ - public static final int VALIDATION_ERROR = 4; - /** - * 系统异常. - */ - public static final int FAILURE = 9; - /** - * 已存在. - */ - public static final int EXISTED = 21; - /** - * 排队中. - */ - public static final int IN_QUEUE = 22; - /** - * 队列已满. - */ - public static final int QUEUE_REJECTED = 23; - /** - * prompt包含敏感词. - */ - public static final int BANNED_PROMPT = 24; } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MjWebSocketStarter.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MjWebSocketStarter.java index e6dcafc1a..0d6a7d0c6 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MjWebSocketStarter.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MjWebSocketStarter.java @@ -7,9 +7,11 @@ import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; import cn.iocoder.yudao.framework.ai.midjourney.constants.MjNotifyCode; import cn.iocoder.yudao.framework.ai.midjourney.webSocket.handler.MjWebSocketHandler; import cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener.MjMessageListener; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.apache.tomcat.websocket.Constants; import org.jetbrains.annotations.NotNull; +import org.springframework.util.concurrent.ListenableFuture; import org.springframework.util.concurrent.ListenableFutureCallback; import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.WebSocketHttpHeaders; @@ -22,19 +24,43 @@ import java.util.concurrent.TimeoutException; @Slf4j public class MjWebSocketStarter implements WebSocketStarter { + /** + * 链接重试次数 + */ private static final int CONNECT_RETRY_LIMIT = 5; - + /** + * mj 配置文件 + */ private final MidjourneyConfig midjourneyConfig; + /** + * mj 监听(所有message 都会 callback到这里) + */ private final MjMessageListener userMessageListener; + /** + * wss 服务器 + */ private final String wssServer; + /** + * + */ private final String resumeWss; - - private boolean running = false; - - private WebSocketSession webSocketSession = null; + /** + * + */ private ResumeData resumeData = null; + /** + * 是否运行成功 + */ + private boolean running = false; + /** + * 链接成功的 session + */ + private WebSocketSession webSocketSession = null; - public MjWebSocketStarter(String wssServer, String resumeWss, MidjourneyConfig midjourneyConfig, MjMessageListener userMessageListener) { + public MjWebSocketStarter(String wssServer, + String resumeWss, + MidjourneyConfig midjourneyConfig, + MjMessageListener userMessageListener) { this.wssServer = wssServer; this.resumeWss = resumeWss; this.midjourneyConfig = midjourneyConfig; @@ -42,11 +68,12 @@ public class MjWebSocketStarter implements WebSocketStarter { } @Override - public void start() throws Exception { + public void start() { start(false); } private void start(boolean reconnect) { + // 设置header WebSocketHttpHeaders headers = new WebSocketHttpHeaders(); headers.add("Accept-Encoding", "gzip, deflate, br"); headers.add("Accept-Language", "zh-CN,zh;q=0.9"); @@ -54,19 +81,26 @@ public class MjWebSocketStarter implements WebSocketStarter { headers.add("Pragma", "no-cache"); headers.add("Sec-Websocket-Extensions", "permessage-deflate; client_max_window_bits"); headers.add("User-Agent", this.midjourneyConfig.getUserAage()); - var handler = new MjWebSocketHandler(this.midjourneyConfig, this.userMessageListener, this::onSocketSuccess, this::onSocketFailure); + // 创建 mjHeader + MjWebSocketHandler mjWebSocketHandler = new MjWebSocketHandler( + this.midjourneyConfig, this.userMessageListener, this::onSocketSuccess, this::onSocketFailure); + // String gatewayUrl; if (reconnect) { - gatewayUrl = getGatewayServer(this.resumeData.resumeGatewayUrl()) + "/?encoding=json&v=9&compress=zlib-stream"; - handler.setSessionId(this.resumeData.sessionId()); - handler.setSequence(this.resumeData.sequence()); - handler.setResumeGatewayUrl(this.resumeData.resumeGatewayUrl()); + gatewayUrl = getGatewayServer(this.resumeData.getResumeGatewayUrl()) + "/?encoding=json&v=9&compress=zlib-stream"; + mjWebSocketHandler.setSessionId(this.resumeData.getSessionId()); + mjWebSocketHandler.setSequence(this.resumeData.getSequence()); + mjWebSocketHandler.setResumeGatewayUrl(this.resumeData.getResumeGatewayUrl()); } else { gatewayUrl = getGatewayServer(null) + "/?encoding=json&v=9&compress=zlib-stream"; } - var webSocketClient = new StandardWebSocketClient(); + // 创建 StandardWebSocketClient + StandardWebSocketClient webSocketClient = new StandardWebSocketClient(); + // 设置 io timeout 时间 webSocketClient.getUserProperties().put(Constants.IO_TIMEOUT_MS_PROPERTY, "10000"); - var socketSessionFuture = webSocketClient.doHandshake(handler, headers, URI.create(gatewayUrl)); + // + ListenableFuture socketSessionFuture = webSocketClient.doHandshake(mjWebSocketHandler, headers, URI.create(gatewayUrl)); + // 添加 callback 进行回调 socketSessionFuture.addCallback(new ListenableFutureCallback<>() { @Override public void onFailure(@NotNull Throwable e) { @@ -87,14 +121,18 @@ public class MjWebSocketStarter implements WebSocketStarter { } private void onSocketFailure(int code, String reason) { + // 1001异常可以忽略 if (code == 1001) { return; } + // 关闭 socket closeSocketSessionWhenIsOpen(); + // 没有运行通知 if (!this.running) { notifyWssLock(code, reason); return; } + // 已经运行先设置为false,发起 this.running = false; if (code >= 4000) { log.warn("[wss-{}] Can't reconnect! Account disabled. Closed by {}({}).", this.midjourneyConfig.getChannelId(), code, reason); @@ -107,36 +145,34 @@ public class MjWebSocketStarter implements WebSocketStarter { } } + /** + * 重连 + */ private void tryReconnect() { try { tryStart(true); } catch (Exception e) { - if (e instanceof TimeoutException) { - closeSocketSessionWhenIsOpen(); - } - log.warn("[wss-{}] Reconnect fail: {}, Try new connection...", this.midjourneyConfig.getChannelId(), e.getMessage()); + log.warn("[wss-{}] Reconnect fail: {}, Try new connection...", this.midjourneyConfig.getChannelId(), e.getMessage()); ThreadUtil.sleep(1000); tryNewConnect(); } } private void tryNewConnect() { + // 链接重试次数5 for (int i = 1; i <= CONNECT_RETRY_LIMIT; i++) { try { tryStart(false); return; } catch (Exception e) { - if (e instanceof TimeoutException) { - closeSocketSessionWhenIsOpen(); - } - log.warn("[wss-{}] New connect fail ({}): {}", this.midjourneyConfig.getChannelId(), i, e.getMessage()); + log.warn("[wss-{}] New connect fail ({}): {}", this.midjourneyConfig.getChannelId(), i, e.getMessage()); ThreadUtil.sleep(5000); } } log.error("[wss-{}] Account disabled", this.midjourneyConfig.getChannelId()); } - public void tryStart(boolean reconnect) throws Exception { + public void tryStart(boolean reconnect) { start(reconnect); } @@ -144,6 +180,9 @@ public class MjWebSocketStarter implements WebSocketStarter { System.err.println("notifyWssLock: " + code + " - " + reason); } + /** + * 关闭 socket session + */ private void closeSocketSessionWhenIsOpen() { try { if (this.webSocketSession != null && this.webSocketSession.isOpen()) { @@ -161,6 +200,20 @@ public class MjWebSocketStarter implements WebSocketStarter { return this.wssServer; } - public record ResumeData(String sessionId, Object sequence, String resumeGatewayUrl) { + @Getter + public static class ResumeData { + + public ResumeData(String sessionId, Object sequence, String resumeGatewayUrl) { + this.sessionId = sessionId; + this.sequence = sequence; + this.resumeGatewayUrl = resumeGatewayUrl; + } + + /** + * socket session + */ + private final String sessionId; + private final Object sequence; + private final String resumeGatewayUrl; } } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/handler/MjWebSocketHandler.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/handler/MjWebSocketHandler.java index 481fa1b0c..55fc7e4bc 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/handler/MjWebSocketHandler.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/handler/MjWebSocketHandler.java @@ -30,16 +30,41 @@ import java.util.concurrent.TimeUnit; @Slf4j public class MjWebSocketHandler implements WebSocketHandler { + /** + * close 错误码:重连 + */ public static final int CLOSE_CODE_RECONNECT = 2001; + /** + * close 错误码:无效、作废 + */ public static final int CLOSE_CODE_INVALIDATE = 1009; + /** + * close 错误码:异常 + */ public static final int CLOSE_CODE_EXCEPTION = 1011; - + /** + * mj配置文件 + */ private final MidjourneyConfig midjourneyConfig; + /** + * mj 消息监听 + */ private final MjMessageListener userMessageListener; + /** + * 成功回调 + */ private final SuccessCallback successCallback; + /** + * 失败回调 + */ private final FailureCallback failureCallback; - + /** + * 心跳执行器 + */ private final ScheduledExecutorService heartExecutor; + /** + * auth数据 + */ private final DataObject authData; @Setter @@ -55,6 +80,9 @@ public class MjWebSocketHandler implements WebSocketHandler { private Future heartbeatInterval; private Future heartbeatTimeout; + /** + * 处理 message 消息的 Decompressor + */ private final Decompressor decompressor = new ZlibDecompressor(2048); public MjWebSocketHandler(MidjourneyConfig account, @@ -77,11 +105,13 @@ public class MjWebSocketHandler implements WebSocketHandler { @Override public void handleTransportError(@NotNull WebSocketSession session, @NotNull Throwable e) throws Exception { log.error("[wss-{}] Transport error", this.midjourneyConfig.getChannelId(), e); + // 通知链接异常 onFailure(CLOSE_CODE_EXCEPTION, "transport error"); } @Override public void afterConnectionClosed(@NotNull WebSocketSession session, @NotNull CloseStatus closeStatus) throws Exception { + // 链接关闭 onFailure(closeStatus.getCode(), closeStatus.getReason()); } @@ -92,13 +122,18 @@ public class MjWebSocketHandler implements WebSocketHandler { @Override public void handleMessage(@NotNull WebSocketSession session, WebSocketMessage message) throws Exception { + // 获取 message 消息 ByteBuffer buffer = (ByteBuffer) message.getPayload(); + // 解析 message byte[] decompressed = decompressor.decompress(buffer.array()); if (decompressed == null) { return; } + // 转换 json String json = new String(decompressed, StandardCharsets.UTF_8); + // 转换 jda 自带的 dataObject(和json object 差不多) DataObject data = DataObject.fromJson(json); + // 获取消息类型 int opCode = data.getInt("op"); switch (opCode) { case WebSocketCode.HEARTBEAT -> handleHeartbeat(session); From dfbd75b53c529f50a6a33ff498a623c2539a8baa Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 5 Apr 2024 10:16:46 +0800 Subject: [PATCH 043/684] =?UTF-8?q?=E4=BF=AE=E6=94=B9test=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0before=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iocoder/yudao/framework/ai/image/MjTests.java | 15 ++++++++++----- .../framework/ai/image/MjWebSocketTests.java | 8 ++++---- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjTests.java index df8fea90d..b5c434a94 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjTests.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.ai.image; import cn.hutool.core.io.FileUtil; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; import cn.iocoder.yudao.framework.ai.midjourney.interactions.MjImagineInteractions; +import org.junit.Before; import org.junit.Test; import java.io.File; @@ -18,16 +19,20 @@ import java.util.Map; */ public class MjTests { - @Test - public void mjImage() { - String token = "NTY5MDY4NDAxNzEyOTU1Mzky.G4-Fu0.MzD-7ll-ElbXTTgDPHF-WS_UyhMAfbKN3WyyBc"; + private MidjourneyConfig midjourneyConfig; + @Before + public void setup() { + String token = "OTcwNDc3NzQxMjUyMTY5NzI4.GJcVxa.VrzMii8dsHOJAPZn4Mw8GuEo7_nIUJij9JIHD4"; Map requestTemplates = new HashMap<>(); List files = FileUtil.loopFiles("/Users/fansili/projects/github/ruoyi-vue-pro/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body"); for (File file : files) { requestTemplates.put(file.getName().replace(".json", ""), FileUtil.readUtf8String(file)); } - MidjourneyConfig midjourneyConfig = new MidjourneyConfig( - token, "1221445697157468200", "1221445862962630706", requestTemplates); + this.midjourneyConfig = new MidjourneyConfig(token, "1225414986084388926", "1225414986587832385", requestTemplates); + } + + @Test + public void mjImage() { MjImagineInteractions mjImagineInteractions = new MjImagineInteractions(midjourneyConfig); mjImagineInteractions.execute("童话里应该是什么样子?"); } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjWebSocketTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjWebSocketTests.java index 177b7c733..786eb6570 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjWebSocketTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjWebSocketTests.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.framework.ai.image; import cn.hutool.core.io.FileUtil; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; -import cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user.MjMessageListener; -import cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user.MjWebSocketStarter; +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener.MjMessageListener; +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MjWebSocketStarter; import org.junit.Before; import org.junit.Test; @@ -23,13 +23,13 @@ public class MjWebSocketTests { @Before public void setup() { - String token = "OTcwNDc3NzQxMjUyMTY5NzI4.GJcVxa.VrzMii8dsHOJAPZn4Mw8GuEo7_nIUJij9JIHD4"; + String token = "OTcyNzIxMzA0ODkxNDUzNDUw.G_vMOz.BO_Q0sXAD80u5ZKIHPNYDTRX_FgeKL3cKFc53I"; Map requestTemplates = new HashMap<>(); List files = FileUtil.loopFiles("/Users/fansili/projects/github/ruoyi-vue-pro/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body"); for (File file : files) { requestTemplates.put(file.getName().replace(".json", ""), FileUtil.readUtf8String(file)); } - this.midjourneyConfig = new MidjourneyConfig(token, "1225414986084388926", "1225414986587832385", requestTemplates); + this.midjourneyConfig = new MidjourneyConfig(token, "1225608134878302329", "1225608134878302332", requestTemplates); } @Test From 1b02733c10e70e6ce04da0b462f23e1fdd6fdaaf Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 5 Apr 2024 10:23:35 +0800 Subject: [PATCH 044/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E7=94=9F=E6=88=90=20socket=20=E6=8E=A5=E6=94=B6=E5=88=B0?= =?UTF-8?q?=E7=9A=84=E6=B6=88=E6=81=AF=E7=B1=BB=E5=9E=8B=E3=80=81=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E8=BF=87=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/图片消息过程/1.json | 41 +++++ .../src/main/resources/图片消息过程/10.json | 115 ++++++++++++++ .../src/main/resources/图片消息过程/11.json | 115 ++++++++++++++ .../src/main/resources/图片消息过程/12.json | 145 ++++++++++++++++++ .../src/main/resources/图片消息过程/2.json | 103 +++++++++++++ .../src/main/resources/图片消息过程/3.json | 102 ++++++++++++ .../src/main/resources/图片消息过程/4.json | 102 ++++++++++++ .../src/main/resources/图片消息过程/5.json | 102 ++++++++++++ .../src/main/resources/图片消息过程/6.json | 102 ++++++++++++ .../src/main/resources/图片消息过程/7.json | 102 ++++++++++++ .../src/main/resources/图片消息过程/8.json | 102 ++++++++++++ .../src/main/resources/图片消息过程/9.json | 115 ++++++++++++++ 12 files changed, 1246 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/1.json create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/10.json create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/11.json create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/12.json create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/2.json create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/3.json create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/4.json create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/5.json create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/6.json create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/7.json create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/8.json create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/9.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/1.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/1.json new file mode 100644 index 000000000..156a89e68 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/1.json @@ -0,0 +1,41 @@ +{ + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [], + "author": { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + }, + "flags": 0, + "type": 0, + "mention_roles": [], + "nonce": "1225630680067604480", + "edited_timestamp": null, + "content": "南极应该是什么样子?", + "tts": false, + "referenced_message": null, + "mentions": [], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "guild_id": "1225608134878302329", + "id": "1225630681556586556", + "embeds": [], + "channel_id": "1225608134878302332", + "timestamp": "2024-04-05T02:18:45.600000+00:00" +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/10.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/10.json new file mode 100644 index 000000000..e17f83fea --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/10.json @@ -0,0 +1,115 @@ +{ + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [ + { + "filename": "8f23f288-6028-468b-8056-1e4adef73985_grid_0.webp", + "size": 34624, + "content_type": "image/webp", + "width": 512, + "placeholder_version": 1, + "proxy_url": "https://media.discordapp.net/attachments/1225608134878302332/1225630835240210442/8f23f288-6028-468b-8056-1e4adef73985_grid_0.webp?ex=6621d4aa&is=660f5faa&hm=f58106ba5fa0ddf51abe68493cf460ccd70eb7ef379d2d3865d4b45e230c3037&", + "placeholder": "4CcODwJ/hotGl2iHd2iYd3h3d/kJyLQA", + "id": "1225630835240210442", + "url": "https://cdn.discordapp.com/attachments/1225608134878302332/1225630835240210442/8f23f288-6028-468b-8056-1e4adef73985_grid_0.webp?ex=6621d4aa&is=660f5faa&hm=f58106ba5fa0ddf51abe68493cf460ccd70eb7ef379d2d3865d4b45e230c3037&", + "height": 512 + } + ], + "interaction_metadata": { + "user_id": "972721304891453450", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1225608134878302329" + }, + "id": "1225630717426274377", + "type": 2 + }, + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 20, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-05T02:19:22.200320+00:00", + "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (55%) (fast, stealth)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:35.840941+00:00", + "communication_disabled_until": null, + "roles": [ + "1225608242688819214" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "interaction": { + "name": "imagine", + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "id": "1225630717426274377", + "type": 2, + "user": { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + }, + "guild_id": "1225608134878302329", + "position": 0, + "id": "1225630724431024259", + "embeds": [], + "channel_id": "1225608134878302332", + "timestamp": "2024-04-05T02:18:55.822000+00:00" +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/11.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/11.json new file mode 100644 index 000000000..837c89123 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/11.json @@ -0,0 +1,115 @@ +{ + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [ + { + "filename": "8f23f288-6028-468b-8056-1e4adef73985_grid_0.webp", + "size": 46376, + "content_type": "image/webp", + "width": 512, + "placeholder_version": 1, + "proxy_url": "https://media.discordapp.net/attachments/1225608134878302332/1225630846317498469/8f23f288-6028-468b-8056-1e4adef73985_grid_0.webp?ex=6621d4ac&is=660f5fac&hm=efe167b852efc37fe4690253697cee2b8fd350d0b724b3a99004ad36baa09c1f&", + "placeholder": "oSgOFwRvtYxVlnl2d1iIh4h3aPdnmC8F", + "id": "1225630846317498469", + "url": "https://cdn.discordapp.com/attachments/1225608134878302332/1225630846317498469/8f23f288-6028-468b-8056-1e4adef73985_grid_0.webp?ex=6621d4ac&is=660f5fac&hm=efe167b852efc37fe4690253697cee2b8fd350d0b724b3a99004ad36baa09c1f&", + "height": 512 + } + ], + "interaction_metadata": { + "user_id": "972721304891453450", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1225608134878302329" + }, + "id": "1225630717426274377", + "type": 2 + }, + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 20, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-05T02:19:24.805512+00:00", + "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (75%) (fast, stealth)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:35.840941+00:00", + "communication_disabled_until": null, + "roles": [ + "1225608242688819214" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "interaction": { + "name": "imagine", + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "id": "1225630717426274377", + "type": 2, + "user": { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + }, + "guild_id": "1225608134878302329", + "position": 0, + "id": "1225630724431024259", + "embeds": [], + "channel_id": "1225608134878302332", + "timestamp": "2024-04-05T02:18:55.822000+00:00" +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/12.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/12.json new file mode 100644 index 000000000..890297b55 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/12.json @@ -0,0 +1,145 @@ +{ + "mention_everyone": false, + "pinned": false, + "components": [ + { + "components": [ + { + "custom_id": "MJ::JOB::upsample::1::8f23f288-6028-468b-8056-1e4adef73985", + "style": 2, + "label": "U1", + "type": 2 + }, + { + "custom_id": "MJ::JOB::upsample::2::8f23f288-6028-468b-8056-1e4adef73985", + "style": 2, + "label": "U2", + "type": 2 + }, + { + "custom_id": "MJ::JOB::upsample::3::8f23f288-6028-468b-8056-1e4adef73985", + "style": 2, + "label": "U3", + "type": 2 + }, + { + "custom_id": "MJ::JOB::upsample::4::8f23f288-6028-468b-8056-1e4adef73985", + "style": 2, + "label": "U4", + "type": 2 + }, + { + "emoji": { + "name": "🔄" + }, + "custom_id": "MJ::JOB::reroll::0::8f23f288-6028-468b-8056-1e4adef73985::SOLO", + "style": 2, + "type": 2 + } + ], + "type": 1 + }, + { + "components": [ + { + "custom_id": "MJ::JOB::variation::1::8f23f288-6028-468b-8056-1e4adef73985", + "style": 2, + "label": "V1", + "type": 2 + }, + { + "custom_id": "MJ::JOB::variation::2::8f23f288-6028-468b-8056-1e4adef73985", + "style": 2, + "label": "V2", + "type": 2 + }, + { + "custom_id": "MJ::JOB::variation::3::8f23f288-6028-468b-8056-1e4adef73985", + "style": 2, + "label": "V3", + "type": 2 + }, + { + "custom_id": "MJ::JOB::variation::4::8f23f288-6028-468b-8056-1e4adef73985", + "style": 2, + "label": "V4", + "type": 2 + } + ], + "type": 1 + } + ], + "attachments": [ + { + "filename": "jverbalu4990__8f23f288-6028-468b-8056-1e4adef73985.png", + "size": 7092878, + "content_type": "image/png", + "width": 2048, + "placeholder_version": 1, + "proxy_url": "https://media.discordapp.net/attachments/1225608134878302332/1225630861899333652/jverbalu4990__8f23f288-6028-468b-8056-1e4adef73985.png?ex=6621d4b0&is=660f5fb0&hm=658c7766ac3df7e484ccf2e1a30b0afc266ec38e5b2da6c95f12cb7f9c204886&", + "placeholder": "YRgODwJvpY1XlXl2h0iYh4iIePkQqgkB", + "id": "1225630861899333652", + "url": "https://cdn.discordapp.com/attachments/1225608134878302332/1225630861899333652/jverbalu4990__8f23f288-6028-468b-8056-1e4adef73985.png?ex=6621d4b0&is=660f5fb0&hm=658c7766ac3df7e484ccf2e1a30b0afc266ec38e5b2da6c95f12cb7f9c204886&", + "height": 2048 + } + ], + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 0, + "mention_roles": [], + "edited_timestamp": null, + "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (fast, stealth)", + "tts": false, + "referenced_message": null, + "mentions": [ + { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:35.840941+00:00", + "communication_disabled_until": null, + "roles": [ + "1225608242688819214" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "guild_id": "1225608134878302329", + "id": "1225630862393999442", + "embeds": [], + "channel_id": "1225608134878302332", + "timestamp": "2024-04-05T02:19:28.715000+00:00" +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/2.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/2.json new file mode 100644 index 000000000..2643136a2 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/2.json @@ -0,0 +1,103 @@ +{ + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [], + "interaction_metadata": { + "user_id": "972721304891453450", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1225608134878302329" + }, + "id": "1225630717426274377", + "type": 2 + }, + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 20, + "mention_roles": [], + "nonce": "1225630715874377728", + "application_id": "936929561302675456", + "edited_timestamp": null, + "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (Waiting to start)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:35.840941+00:00", + "communication_disabled_until": null, + "roles": [ + "1225608242688819214" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "interaction": { + "name": "imagine", + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "id": "1225630717426274377", + "type": 2, + "user": { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + }, + "guild_id": "1225608134878302329", + "position": 0, + "id": "1225630724431024259", + "embeds": [], + "channel_id": "1225608134878302332", + "timestamp": "2024-04-05T02:18:55.822000+00:00" +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/3.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/3.json new file mode 100644 index 000000000..0f6d35cc1 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/3.json @@ -0,0 +1,102 @@ +{ + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [], + "interaction_metadata": { + "user_id": "972721304891453450", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1225608134878302329" + }, + "id": "1225630717426274377", + "type": 2 + }, + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 20, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-05T02:18:59.141254+00:00", + "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (0%) (fast, stealth)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:35.840941+00:00", + "communication_disabled_until": null, + "roles": [ + "1225608242688819214" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "interaction": { + "name": "imagine", + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "id": "1225630717426274377", + "type": 2, + "user": { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + }, + "guild_id": "1225608134878302329", + "position": 0, + "id": "1225630724431024259", + "embeds": [], + "channel_id": "1225608134878302332", + "timestamp": "2024-04-05T02:18:55.822000+00:00" +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/4.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/4.json new file mode 100644 index 000000000..d41eb22c2 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/4.json @@ -0,0 +1,102 @@ +{ + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [], + "interaction_metadata": { + "user_id": "972721304891453450", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1225608134878302329" + }, + "id": "1225630717426274377", + "type": 2 + }, + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 20, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-05T02:19:02.665459+00:00", + "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (10%) (fast, stealth)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:35.840941+00:00", + "communication_disabled_until": null, + "roles": [ + "1225608242688819214" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "interaction": { + "name": "imagine", + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "id": "1225630717426274377", + "type": 2, + "user": { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + }, + "guild_id": "1225608134878302329", + "position": 0, + "id": "1225630724431024259", + "embeds": [], + "channel_id": "1225608134878302332", + "timestamp": "2024-04-05T02:18:55.822000+00:00" +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/5.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/5.json new file mode 100644 index 000000000..7503abd10 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/5.json @@ -0,0 +1,102 @@ +{ + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [], + "interaction_metadata": { + "user_id": "972721304891453450", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1225608134878302329" + }, + "id": "1225630717426274377", + "type": 2 + }, + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 20, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-05T02:19:05.339248+00:00", + "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (17%) (fast, stealth)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:35.840941+00:00", + "communication_disabled_until": null, + "roles": [ + "1225608242688819214" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "interaction": { + "name": "imagine", + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "id": "1225630717426274377", + "type": 2, + "user": { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + }, + "guild_id": "1225608134878302329", + "position": 0, + "id": "1225630724431024259", + "embeds": [], + "channel_id": "1225608134878302332", + "timestamp": "2024-04-05T02:18:55.822000+00:00" +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/6.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/6.json new file mode 100644 index 000000000..61dad1272 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/6.json @@ -0,0 +1,102 @@ +{ + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [], + "interaction_metadata": { + "user_id": "972721304891453450", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1225608134878302329" + }, + "id": "1225630717426274377", + "type": 2 + }, + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 20, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-05T02:19:08.810399+00:00", + "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (25%) (fast, stealth)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:35.840941+00:00", + "communication_disabled_until": null, + "roles": [ + "1225608242688819214" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "interaction": { + "name": "imagine", + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "id": "1225630717426274377", + "type": 2, + "user": { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + }, + "guild_id": "1225608134878302329", + "position": 0, + "id": "1225630724431024259", + "embeds": [], + "channel_id": "1225608134878302332", + "timestamp": "2024-04-05T02:18:55.822000+00:00" +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/7.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/7.json new file mode 100644 index 000000000..a21f527aa --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/7.json @@ -0,0 +1,102 @@ +{ + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [], + "interaction_metadata": { + "user_id": "972721304891453450", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1225608134878302329" + }, + "id": "1225630717426274377", + "type": 2 + }, + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 20, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-05T02:19:12.017944+00:00", + "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (32%) (fast, stealth)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:35.840941+00:00", + "communication_disabled_until": null, + "roles": [ + "1225608242688819214" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "interaction": { + "name": "imagine", + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "id": "1225630717426274377", + "type": 2, + "user": { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + }, + "guild_id": "1225608134878302329", + "position": 0, + "id": "1225630724431024259", + "embeds": [], + "channel_id": "1225608134878302332", + "timestamp": "2024-04-05T02:18:55.822000+00:00" +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/8.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/8.json new file mode 100644 index 000000000..48decf5f6 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/8.json @@ -0,0 +1,102 @@ +{ + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [], + "interaction_metadata": { + "user_id": "972721304891453450", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1225608134878302329" + }, + "id": "1225630717426274377", + "type": 2 + }, + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 20, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-05T02:19:15.043965+00:00", + "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (35%) (fast, stealth)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:35.840941+00:00", + "communication_disabled_until": null, + "roles": [ + "1225608242688819214" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "interaction": { + "name": "imagine", + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "id": "1225630717426274377", + "type": 2, + "user": { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + }, + "guild_id": "1225608134878302329", + "position": 0, + "id": "1225630724431024259", + "embeds": [], + "channel_id": "1225608134878302332", + "timestamp": "2024-04-05T02:18:55.822000+00:00" +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/9.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/9.json new file mode 100644 index 000000000..10a28991d --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/9.json @@ -0,0 +1,115 @@ +{ + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [ + { + "filename": "8f23f288-6028-468b-8056-1e4adef73985_grid_0.webp", + "size": 30752, + "content_type": "image/webp", + "width": 512, + "placeholder_version": 1, + "proxy_url": "https://media.discordapp.net/attachments/1225608134878302332/1225630819515764806/8f23f288-6028-468b-8056-1e4adef73985_grid_0.webp?ex=6621d4a6&is=660f5fa6&hm=d46f487fce290539acae4e83322345b35f658c2ec40fb6f015a698dac9e84bb7&", + "placeholder": "HBgSFwJ/hYpEl3iGd3iId3h3R/k0gF4E", + "id": "1225630819515764806", + "url": "https://cdn.discordapp.com/attachments/1225608134878302332/1225630819515764806/8f23f288-6028-468b-8056-1e4adef73985_grid_0.webp?ex=6621d4a6&is=660f5fa6&hm=d46f487fce290539acae4e83322345b35f658c2ec40fb6f015a698dac9e84bb7&", + "height": 512 + } + ], + "interaction_metadata": { + "user_id": "972721304891453450", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1225608134878302329" + }, + "id": "1225630717426274377", + "type": 2 + }, + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 20, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-05T02:19:18.460823+00:00", + "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (45%) (fast, stealth)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:35.840941+00:00", + "communication_disabled_until": null, + "roles": [ + "1225608242688819214" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "interaction": { + "name": "imagine", + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-05T00:49:10.062000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "id": "1225630717426274377", + "type": 2, + "user": { + "global_name": "JVerbalu", + "avatar_decoration_data": null, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + }, + "guild_id": "1225608134878302329", + "position": 0, + "id": "1225630724431024259", + "embeds": [], + "channel_id": "1225608134878302332", + "timestamp": "2024-04-05T02:18:55.822000+00:00" +} \ No newline at end of file From b38c94847e2f14f62f86e242de3b907506db0bb0 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 6 Apr 2024 20:32:08 +0800 Subject: [PATCH 045/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0contentparse=20?= =?UTF-8?q?=E5=B7=A5=E5=85=B7=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ai/midjourney/util/MjUtil.java | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java new file mode 100644 index 000000000..19ad63184 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java @@ -0,0 +1,68 @@ +package cn.iocoder.yudao.framework.ai.midjourney.util; + +import cn.hutool.core.text.CharSequenceUtil; +import cn.iocoder.yudao.framework.ai.midjourney.MjMessage; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * author: fansili + * time: 2024/4/6 19:00 + */ +public class MjUtil { + /** + * content正则匹配prompt和进度. + */ + public static final String CONTENT_REGEX = ".*?\\*\\*(.*?)\\*\\*.+<@\\d+> \\((.*?)\\)"; + public static final String CONTENT_PROGRESS_REGEX = "\\(([^)]*)\\)"; + + + public static MjMessage.Content parseContent(String content) { + // "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (32%) (fast, stealth)", + // "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (fast, stealth)" + MjMessage.Content mjContent = new MjMessage.Content(); + if (CharSequenceUtil.isBlank(content)) { + return null; + } + if (!content.contains("raw**")) { + return mjContent.setPrompt(content); + } + int rawIndex = content.indexOf("raw**") + 5; + String prompt = content.substring(0, rawIndex).trim(); + String contentTail = content.substring(rawIndex).trim(); + // 检查是否存在进度条 + Pattern pattern = Pattern.compile(CONTENT_PROGRESS_REGEX); + Matcher matcher = pattern.matcher(contentTail); + + if (contentTail.contains("%")) { + if (matcher.find()) { + // 获取第一个(也是此处唯一的)捕获组的内容 + String progress = matcher.group(1); + mjContent.setProgress(progress); + } + if (matcher.find()) { + String status = matcher.group(1); + mjContent.setStatus(status); + } + } else { + if (matcher.find()) { + // 获取第一个(也是此处唯一的)捕获组的内容 + String status = matcher.group(1); + mjContent.setStatus(status); + } + } + mjContent.setPrompt(prompt); + // tip:contentArray + return mjContent; + } + + public static void main(String[] args) { + String content1 = "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (32%) (fast, stealth)"; + String content2 = "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (fast, stealth)"; + + System.err.println(parseContent(content1));; + System.err.println(parseContent(content2));; + } + +} From b09fc5579c86a8a7c53be889e7bac55b3a989d62 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 6 Apr 2024 21:04:53 +0800 Subject: [PATCH 046/684] =?UTF-8?q?=E5=A4=84=E7=90=86=E8=A1=A8=E6=83=85?= =?UTF-8?q?=E7=AC=A6=E5=8F=B7=EF=BC=8Ccontent=E8=A7=A3=E6=9E=90=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java index 19ad63184..bc7ee5504 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java @@ -25,10 +25,10 @@ public class MjUtil { if (CharSequenceUtil.isBlank(content)) { return null; } - if (!content.contains("raw**")) { + if (!content.contains("<@")) { return mjContent.setPrompt(content); } - int rawIndex = content.indexOf("raw**") + 5; + int rawIndex = content.indexOf("<@") - 3; String prompt = content.substring(0, rawIndex).trim(); String contentTail = content.substring(rawIndex).trim(); // 检查是否存在进度条 From f2b9c14819c750ac43dcb190b0a56b6edcc5a341 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 6 Apr 2024 21:20:10 +0800 Subject: [PATCH 047/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0mj=20=E5=9B=BE?= =?UTF-8?q?=E7=89=87=E7=94=9F=E6=88=90=E6=B6=88=E6=81=AF=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ai/midjourney/MjMessage.java | 124 ++++++++++++++++++ .../constants/MjGennerateStatusEnum.java | 29 ++++ .../webSocket/listener/MjMessageListener.java | 93 +++++++++---- 3 files changed, 219 insertions(+), 27 deletions(-) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjMessage.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjGennerateStatusEnum.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjMessage.java new file mode 100644 index 000000000..f4cf47d5d --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjMessage.java @@ -0,0 +1,124 @@ +package cn.iocoder.yudao.framework.ai.midjourney; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; + +@Data +@Accessors(chain = true) +public class MjMessage { + + /** + * id是一个重要的字段,在同时生成多个的时候,可以区分生成信息 + */ + private String id; + /** + * 现在已知: + * 0:我们发送的消息,和指令 + * 20: mj生成图片发送过程中 + */ + private Integer type; + /** + * content + */ + private Content content; + /** + * 图片生成完成才有 + */ + private List components; + /** + * 生成过程中如果有,预展示图片,这里会有 + */ + private List attachments; + /** + * 原始数据(discard 返回的原始数据) + */ + private String rawData; + /** + * 生成状态(用于区分生成状态) + * 1、等待 + * 2、进行中 + * 3、完成 + * {@link cn.iocoder.yudao.framework.ai.midjourney.constants.MjGennerateStatusEnum} + */ + private String generateStatus; + + @Data + @Accessors(chain = true) + public static class ComponentType { + + private int type; + + private List components; + } + + @Data + @Accessors(chain = true) + public static class Component { + /** + * 自定义ID,用于唯一标识特定交互动作及其上下文信息。 + */ + private String customId; + + /** + * 样式编号,用于确定按钮的样式外观。 + * 在某些应用中,例如Discord,2可能表示一种特定的颜色或形状的按钮。 + */ + private int style; + + /** + * 按钮的标签文本,用户可见的内容。 + */ + private String label; + + /** + * 组件类型,此处为2可能表示这是一种特定类型的交互组件, + * 如在Discord API中,类型2对应的是一个可点击的按钮组件。 + */ + private int type; + + } + + @Data + @Accessors(chain = true) + public static class Attachment { + // 文件名 + private String filename; + + // 附件大小(字节) + private int size; + + // 内容类型(例如:image/webp) + private String contentType; + + // 图像宽度(像素) + private int width; + + // 占位符版本号 + private int placeholderVersion; + + // 代理URL,用于访问附件资源 + private String proxyUrl; + + // 占位符标识符 + private String placeholder; + + // 附件ID + private String id; + + // 直接访问附件资源的URL + private String url; + + // 图像高度(像素) + private int height; + } + + @Data + @Accessors(chain = true) + public static class Content { + private String prompt; + private String progress; + private String status; + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjGennerateStatusEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjGennerateStatusEnum.java new file mode 100644 index 000000000..bbe682c5f --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjGennerateStatusEnum.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.framework.ai.midjourney.constants; + +import lombok.Getter; + +/** + * mj 生成状态 + * + * author: fansili + * time: 2024/4/6 21:07 + */ +@Getter +public enum MjGennerateStatusEnum { + + + WAITING("waiting", "等待..."), + IN_PROGRESS("in_progress", "进行中"), + COMPLETED("completed", "完成"), + + ; + + MjGennerateStatusEnum(String value, String message) { + this.value = value; + this.message = message; + } + + private String value; + + private String message; +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MjMessageListener.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MjMessageListener.java index 8e57a46ab..ae18ee930 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MjMessageListener.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MjMessageListener.java @@ -1,44 +1,83 @@ package cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.text.CharSequenceUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; +import cn.iocoder.yudao.framework.ai.midjourney.MjMessage; import cn.iocoder.yudao.framework.ai.midjourney.constants.MjConstants; +import cn.iocoder.yudao.framework.ai.midjourney.constants.MjGennerateStatusEnum; import cn.iocoder.yudao.framework.ai.midjourney.constants.MjMessageTypeEnum; +import cn.iocoder.yudao.framework.ai.midjourney.util.MjUtil; +import com.alibaba.fastjson.JSON; +import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.utils.data.DataObject; +import java.io.UnsupportedEncodingException; +import java.util.Arrays; +import java.util.List; + @Slf4j public class MjMessageListener { - private MidjourneyConfig midjourneyConfig; + private MidjourneyConfig midjourneyConfig; - public MjMessageListener(MidjourneyConfig midjourneyConfig) { - this.midjourneyConfig = midjourneyConfig; - } + public MjMessageListener(MidjourneyConfig midjourneyConfig) { + this.midjourneyConfig = midjourneyConfig; + } - public void onMessage(DataObject raw) { - MjMessageTypeEnum messageType = MjMessageTypeEnum.of(raw.getString("t")); - if (messageType == null || MjMessageTypeEnum.DELETE == messageType) { - return; - } - DataObject data = raw.getObject("d"); - if (ignoreAndLogMessage(data, messageType)) { - return; - } - System.err.println(data); -// if (data.getBoolean(Constants.MJ_MESSAGE_HANDLED, false)) { -// return; -// } - } + public void onMessage(DataObject raw) { + MjMessageTypeEnum messageType = MjMessageTypeEnum.of(raw.getString("t")); + if (messageType == null || MjMessageTypeEnum.DELETE == messageType) { + return; + } + DataObject data = raw.getObject("d"); + if (ignoreAndLogMessage(data, messageType)) { + return; + } - private boolean ignoreAndLogMessage(DataObject data, MjMessageTypeEnum messageType) { - String channelId = data.getString(MjConstants.CHANNEL_ID); - if (!CharSequenceUtil.equals(channelId, midjourneyConfig.getChannelId())) { - return true; - } - String authorName = data.optObject("author").map(a -> a.getString("username")).orElse("System"); - log.debug("{} - {} - {}: {}", midjourneyConfig.getChannelId(), messageType.name(), authorName, data.opt("content").orElse("")); - return false; - } + MjMessage mjMessage = new MjMessage(); + mjMessage.setId(data.getString("id")); + mjMessage.setType(data.getInt("type")); + mjMessage.setRawData(StrUtil.str(raw.toJson(), "UTF-8")); + mjMessage.setContent(MjUtil.parseContent(data.getString("content"))); + + if (!data.getArray("components").isEmpty()) { + String componentsJson = StrUtil.str(data.getArray("components").toJson(), "UTF-8"); + List components = JSON.parseArray(componentsJson, MjMessage.ComponentType.class); + mjMessage.setComponents(components); + } + if (!data.getArray("attachments").isEmpty()) { + String attachmentsJson = StrUtil.str(data.getArray("attachments").toJson(), "UTF-8"); + List attachments = JSON.parseArray(attachmentsJson, MjMessage.Attachment.class); + mjMessage.setAttachments(attachments); + } + + // 转换状态 + convertGenerateStatus(mjMessage); + System.err.println(JSONUtil.toJsonPrettyStr(mjMessage)); + } + + private void convertGenerateStatus(MjMessage mjMessage) { + if (mjMessage.getType() == 20 && mjMessage.getContent().getStatus().contains("Waiting")) { + mjMessage.setGenerateStatus(MjGennerateStatusEnum.WAITING.getValue()); + } else if (mjMessage.getType() == 20 && !StrUtil.isBlank(mjMessage.getContent().getProgress())) { + mjMessage.setGenerateStatus(MjGennerateStatusEnum.IN_PROGRESS.getValue()); + } else if (mjMessage.getType() == 0 && !CollUtil.isEmpty(mjMessage.getComponents())) { + mjMessage.setGenerateStatus(MjGennerateStatusEnum.COMPLETED.getValue()); + } + } + + private boolean ignoreAndLogMessage(DataObject data, MjMessageTypeEnum messageType) { + String channelId = data.getString(MjConstants.CHANNEL_ID); + if (!CharSequenceUtil.equals(channelId, midjourneyConfig.getChannelId())) { + return true; + } + String authorName = data.optObject("author").map(a -> a.getString("username")).orElse("System"); + log.debug("{} - {} - {}: {}", midjourneyConfig.getChannelId(), messageType.name(), authorName, data.opt("content").orElse("")); + return false; + } } From b1158fb1a7e26985ab5041a84340a576915f1cfe Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 6 Apr 2024 21:53:22 +0800 Subject: [PATCH 048/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E9=80=89=E6=8B=A9=EF=BC=8C=E5=92=8C=E5=9B=BE=E7=89=87=E6=94=BE?= =?UTF-8?q?=E5=A4=A7=E7=9B=B8=E5=85=B3=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/midjourney/MidjourneyConfig.java | 30 +++++++++++------ .../framework/ai/midjourney/MjMessage.java | 1 + .../ai/midjourney/interactions/MjClient.java | 3 +- .../interactions/MjImagineInteractions.java | 33 +++++++++++++++++-- .../framework/ai/midjourney/vo/ReRoll.java | 16 +++++++++ .../src/main/resources/http-body/reroll.json | 14 ++++++++ 6 files changed, 82 insertions(+), 15 deletions(-) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/ReRoll.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/reroll.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyConfig.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyConfig.java index 48f43ca60..dd8a599c6 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyConfig.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyConfig.java @@ -4,6 +4,7 @@ import lombok.Data; import lombok.experimental.Accessors; import java.util.Map; +import java.util.UUID; /** * Midjourney 配置 @@ -15,16 +16,6 @@ import java.util.Map; @Accessors(chain = true) public class MidjourneyConfig { - public MidjourneyConfig(String token, String guildId, String channelId, Map requestTemplates) { - this.token = token; - this.guildId = guildId; - this.channelId = channelId; - this.serverUrl = serverUrl; - this.apiInteractions = apiInteractions; - this.userAage = userAage; - this.requestTemplates = requestTemplates; - } - /** * token信息 * @@ -64,4 +55,23 @@ public class MidjourneyConfig { private Map requestTemplates; + + // + // + + private String sessionId; + + public MidjourneyConfig(String token, String guildId, String channelId, Map requestTemplates) { + this.token = token; + this.guildId = guildId; + this.channelId = channelId; + this.serverUrl = serverUrl; + this.apiInteractions = apiInteractions; + this.userAage = userAage; + this.requestTemplates = requestTemplates; + + // 生成 session id + sessionId = UUID.randomUUID().toString().replaceAll("-", ""); + } + } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjMessage.java index f4cf47d5d..2160e8e14 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjMessage.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjMessage.java @@ -17,6 +17,7 @@ public class MjMessage { * 现在已知: * 0:我们发送的消息,和指令 * 20: mj生成图片发送过程中 + * 19: 选择了某一张图片后的通知 */ private Integer type; /** diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java index 17fa16c8b..c2ffb0f0f 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java @@ -32,8 +32,7 @@ public class MjClient { // 封装请求体和头部信息 HttpEntity requestEntity = new HttpEntity<>(body, headers); // 发送请求 - String result = restTemplate.postForObject(url, requestEntity, String.class); - return result; + return restTemplate.postForObject(url, requestEntity, String.class); } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java index 5e49d6784..4ffceba15 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java @@ -4,6 +4,8 @@ import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; import cn.iocoder.yudao.framework.ai.midjourney.constants.MjInteractionsEnum; +import cn.iocoder.yudao.framework.ai.midjourney.vo.ReRoll; +import com.google.common.collect.Lists; import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; @@ -12,7 +14,7 @@ import java.util.List; import java.util.UUID; /** - * + * 图片生成 * * author: fansili * time: 2024/4/3 17:36 @@ -28,7 +30,7 @@ public class MjImagineInteractions implements MjInteractions { @Override public List supperInteractions() { - return null; + return Lists.newArrayList(MjInteractionsEnum.IMAGINE); } @Override @@ -40,7 +42,7 @@ public class MjImagineInteractions implements MjInteractions { HashMap requestParams = Maps.newHashMap(); requestParams.put("guild_id", midjourneyConfig.getGuildId()); requestParams.put("channel_id", midjourneyConfig.getChannelId()); - requestParams.put("session_id", UUID.randomUUID().toString().replaceAll("-", "")); + requestParams.put("session_id", midjourneyConfig.getSessionId()); requestParams.put("nonce", String.valueOf(IdUtil.getSnowflakeNextId())); requestParams.put("prompt", prompt); // 设置参数 @@ -55,4 +57,29 @@ public class MjImagineInteractions implements MjInteractions { log.error("请求失败! 请求参数:{} 返回结果! {}", requestBody, res); return isSuccess; } + + public Boolean reRoll(ReRoll reRoll) { + String url = midjourneyConfig.getServerUrl().concat(midjourneyConfig.getApiInteractions()); + // 获取请求模板 + String requestTemplate = midjourneyConfig.getRequestTemplates().get("reroll"); + // 设置参数 + HashMap requestParams = Maps.newHashMap(); + requestParams.put("guild_id", midjourneyConfig.getGuildId()); + requestParams.put("channel_id", midjourneyConfig.getChannelId()); + requestParams.put("session_id", midjourneyConfig.getSessionId()); + requestParams.put("nonce", String.valueOf(IdUtil.getSnowflakeNextId())); + requestParams.put("custom_id", reRoll.getCustomId()); + requestParams.put("message_id", reRoll.getMessageId()); + // 设置参数 + String requestBody = MjClient.setParams(requestTemplate, requestParams); + // 发送请求 + String res = MjClient.post(url, midjourneyConfig.getToken(), requestBody); + // 这个 res 只要不返回值,就是成功! + boolean isSuccess = StrUtil.isBlank(res); + if (isSuccess) { + return true; + } + log.error("请求失败! 请求参数:{} 返回结果! {}", requestBody, res); + return isSuccess; + } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/ReRoll.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/ReRoll.java new file mode 100644 index 000000000..2d39ba1df --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/ReRoll.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.framework.ai.midjourney.vo; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * author: fansili + * time: 2024/4/6 21:33 + */ +@Data +@Accessors(chain = true) +public class ReRoll { + + private String messageId; + private String customId; +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/reroll.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/reroll.json new file mode 100644 index 000000000..9bc425cde --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/reroll.json @@ -0,0 +1,14 @@ +{ + "type": 3, + "guild_id": "$guild_id", + "channel_id": "$channel_id", + "message_id": "$message_id", + "application_id": "936929561302675456", + "session_id": "$session_id", + "nonce": "$nonce", + "message_flags": 0, + "data": { + "component_type": 2, + "custom_id": "$custom_id" + } +} \ No newline at end of file From 0c42d6175e35f2d63873efd44ad1ab6b0616d5ff Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 6 Apr 2024 21:59:57 +0800 Subject: [PATCH 049/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0mjutil=20=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ai/midjourney/util/MjUtil.java | 10 ++------- .../yudao/framework/ai/mj/MjUtilTests.java | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjUtilTests.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java index bc7ee5504..e119b100f 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java @@ -7,6 +7,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; /** + * mj util + * * author: fansili * time: 2024/4/6 19:00 */ @@ -57,12 +59,4 @@ public class MjUtil { return mjContent; } - public static void main(String[] args) { - String content1 = "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (32%) (fast, stealth)"; - String content2 = "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (fast, stealth)"; - - System.err.println(parseContent(content1));; - System.err.println(parseContent(content2));; - } - } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjUtilTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjUtilTests.java new file mode 100644 index 000000000..521e9b5ab --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjUtilTests.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.framework.ai.mj; + +import cn.iocoder.yudao.framework.ai.midjourney.util.MjUtil; +import org.junit.Test; + +/** + * mj util + * + * author: fansili + * time: 2024/4/6 21:57 + */ +public class MjUtilTests { + + @Test + public void parseContentTest() { + String content1 = "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (32%) (fast, stealth)"; + String content2 = "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (fast, stealth)"; + + System.err.println(MjUtil.parseContent(content1)); + System.err.println(MjUtil.parseContent(content2)); + } +} From 21b6e9f996100f1f22203f54f0804f13af75e0cb Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 6 Apr 2024 22:00:56 +0800 Subject: [PATCH 050/684] =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MjInteractionsTests.java} | 26 +++++++++++++------ .../ai/{image => mj}/MjWebSocketTests.java | 2 +- .../OpenAiImageClientTests.java | 4 ++- 3 files changed, 22 insertions(+), 10 deletions(-) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/{image/MjTests.java => mj/MjInteractionsTests.java} (53%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/{image => mj}/MjWebSocketTests.java (97%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/{image => openAiImage}/OpenAiImageClientTests.java (93%) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjInteractionsTests.java similarity index 53% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjTests.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjInteractionsTests.java index b5c434a94..3108b31be 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjInteractionsTests.java @@ -1,8 +1,9 @@ -package cn.iocoder.yudao.framework.ai.image; +package cn.iocoder.yudao.framework.ai.mj; import cn.hutool.core.io.FileUtil; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; -import cn.iocoder.yudao.framework.ai.midjourney.interactions.MjImagineInteractions; +import cn.iocoder.yudao.framework.ai.midjourney.interactions.MjInteractions; +import cn.iocoder.yudao.framework.ai.midjourney.vo.ReRoll; import org.junit.Before; import org.junit.Test; @@ -17,23 +18,32 @@ import java.util.Map; * author: fansili * time: 2024/4/4 18:59 */ -public class MjTests { +public class MjInteractionsTests { private MidjourneyConfig midjourneyConfig; @Before public void setup() { - String token = "OTcwNDc3NzQxMjUyMTY5NzI4.GJcVxa.VrzMii8dsHOJAPZn4Mw8GuEo7_nIUJij9JIHD4"; + String token = "OTcyNzIxMzA0ODkxNDUzNDUw.G_vMOz.BO_Q0sXAD80u5ZKIHPNYDTRX_FgeKL3cKFc53I"; Map requestTemplates = new HashMap<>(); List files = FileUtil.loopFiles("/Users/fansili/projects/github/ruoyi-vue-pro/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body"); for (File file : files) { requestTemplates.put(file.getName().replace(".json", ""), FileUtil.readUtf8String(file)); } - this.midjourneyConfig = new MidjourneyConfig(token, "1225414986084388926", "1225414986587832385", requestTemplates); + this.midjourneyConfig = new MidjourneyConfig(token, "1225608134878302329", "1225608134878302332", requestTemplates); } @Test - public void mjImage() { - MjImagineInteractions mjImagineInteractions = new MjImagineInteractions(midjourneyConfig); - mjImagineInteractions.execute("童话里应该是什么样子?"); + public void mjImageTest() { + MjInteractions mjImagineInteractions = new MjInteractions(midjourneyConfig); + mjImagineInteractions.imagine("童话里应该是什么样子?"); + } + + + @Test + public void reRollTest() { + MjInteractions mjImagineInteractions = new MjInteractions(midjourneyConfig); + mjImagineInteractions.reRoll(new ReRoll() + .setMessageId("1226165117448753243") + .setCustomId("MJ::JOB::upsample::3::2aeefbef-43e2-4057-bcf1-43b5f39ab6f7")); } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjWebSocketTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjWebSocketTests.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjWebSocketTests.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjWebSocketTests.java index 786eb6570..9076923b4 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/MjWebSocketTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjWebSocketTests.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.image; +package cn.iocoder.yudao.framework.ai.mj; import cn.hutool.core.io.FileUtil; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/OpenAiImageClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java similarity index 93% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/OpenAiImageClientTests.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java index 8a6fb5f23..389106397 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/OpenAiImageClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java @@ -1,8 +1,10 @@ -package cn.iocoder.yudao.framework.ai.image; +package cn.iocoder.yudao.framework.ai.openAiImage; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageApi; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageClient; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageOptions; +import cn.iocoder.yudao.framework.ai.mj.ImagePrompt; +import cn.iocoder.yudao.framework.ai.mj.ImageResponse; import org.junit.Before; import org.junit.Test; From 8b980d1e11fc9c3c23f9502158fb56db444fe6ab Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 6 Apr 2024 22:02:08 +0800 Subject: [PATCH 051/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20reRoll=EF=BC=8C?= =?UTF-8?q?=E5=9B=BE=E7=89=87=E9=80=89=E6=8B=A9=E3=80=81=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E6=94=BE=E5=A4=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/midjourney/interactions/MjClient.java | 7 +- .../interactions/MjImagineInteractions.java | 85 ------------------- .../interactions/MjInteractions.java | 72 ++++++++++++++-- 3 files changed, 68 insertions(+), 96 deletions(-) delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java index c2ffb0f0f..87b68b909 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java @@ -20,10 +20,9 @@ public class MjClient { static { headers.setContentType(MediaType.APPLICATION_JSON); // 设置内容类型为JSON -// headers.set("Authorization", token); // 如果需要,设置认证信息(例如JWT令牌) - headers.set("Referer", "https://discord.com/channels/1221445697157468200/1221445862962630706"); // 如果需要,设置认证信息(例如JWT令牌) - headers.set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"); // 如果需要,设置认证信息(例如JWT令牌) - headers.set("Cookie", "__dcfduid=6ca536c0e3fa11eeb7cbe34c31b49caf; __sdcfduid=6ca536c1e3fa11eeb7cbe34c31b49caf52cce5ffd8983d2a052cf6aba75fe5fe566f2c265902e283ce30dbf98b8c9c93; _gcl_au=1.1.245923998.1710853617; _ga=GA1.1.111061823.1710853617; __cfruid=6385bb3f48345a006b25992db7dcf984e395736d-1712124666; _cfuvid=O09la5ms0ypNptiG0iD8A6BKWlTxz1LG0WR7qRStD7o-1712124666575-0.0.1.1-604800000; locale=zh-CN; cf_clearance=l_YGod1_SUtYxpDVeZXiX7DLLPl1DYrquZe8WVltvYs-1712124668-1.0.1.1-Hl2.fToel23EpF2HCu9J20rB4D7OhhCzoajPSdo.9Up.wPxhvq22DP9RHzEBKuIUlKyH.kJLxXJfAt2N.LD5WQ; OptanonConsent=isIABGlobal=false&datestamp=Wed+Apr+03+2024+14%3A11%3A15+GMT%2B0800+(%E4%B8%AD%E5%9B%BD%E6%A0%87%E5%87%86%E6%97%B6%E9%97%B4)&version=6.33.0&hosts=&landingPath=https%3A%2F%2Fdiscord.com%2F&groups=C0001%3A1%2CC0002%3A1%2CC0003%3A1; _ga_Q149DFWHT7=GS1.1.1712124668.4.1.1712124679.0.0.0"); // 如果需要,设置认证信息(例如JWT令牌) + headers.set("Referer", "https://discord.com/channels/1221445697157468200/1221445862962630706"); + headers.set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"); + headers.set("Cookie", "__dcfduid=6ca536c0e3fa11eeb7cbe34c31b49caf; __sdcfduid=6ca536c1e3fa11eeb7cbe34c31b49caf52cce5ffd8983d2a052cf6aba75fe5fe566f2c265902e283ce30dbf98b8c9c93; _gcl_au=1.1.245923998.1710853617; _ga=GA1.1.111061823.1710853617; __cfruid=6385bb3f48345a006b25992db7dcf984e395736d-1712124666; _cfuvid=O09la5ms0ypNptiG0iD8A6BKWlTxz1LG0WR7qRStD7o-1712124666575-0.0.1.1-604800000; locale=zh-CN; cf_clearance=l_YGod1_SUtYxpDVeZXiX7DLLPl1DYrquZe8WVltvYs-1712124668-1.0.1.1-Hl2.fToel23EpF2HCu9J20rB4D7OhhCzoajPSdo.9Up.wPxhvq22DP9RHzEBKuIUlKyH.kJLxXJfAt2N.LD5WQ; OptanonConsent=isIABGlobal=false&datestamp=Wed+Apr+03+2024+14%3A11%3A15+GMT%2B0800+(%E4%B8%AD%E5%9B%BD%E6%A0%87%E5%87%86%E6%97%B6%E9%97%B4)&version=6.33.0&hosts=&landingPath=https%3A%2F%2Fdiscord.com%2F&groups=C0001%3A1%2CC0002%3A1%2CC0003%3A1; _ga_Q149DFWHT7=GS1.1.1712124668.4.1.1712124679.0.0.0"); } public static String post(String url, String token, String body) { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java deleted file mode 100644 index 4ffceba15..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java +++ /dev/null @@ -1,85 +0,0 @@ -package cn.iocoder.yudao.framework.ai.midjourney.interactions; - -import cn.hutool.core.util.IdUtil; -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; -import cn.iocoder.yudao.framework.ai.midjourney.constants.MjInteractionsEnum; -import cn.iocoder.yudao.framework.ai.midjourney.vo.ReRoll; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import lombok.extern.slf4j.Slf4j; - -import java.util.HashMap; -import java.util.List; -import java.util.UUID; - -/** - * 图片生成 - * - * author: fansili - * time: 2024/4/3 17:36 - */ -@Slf4j -public class MjImagineInteractions implements MjInteractions { - - private MidjourneyConfig midjourneyConfig; - - public MjImagineInteractions(MidjourneyConfig midjourneyConfig) { - this.midjourneyConfig = midjourneyConfig; - } - - @Override - public List supperInteractions() { - return Lists.newArrayList(MjInteractionsEnum.IMAGINE); - } - - @Override - public Boolean execute(String prompt) { - String url = midjourneyConfig.getServerUrl().concat(midjourneyConfig.getApiInteractions()); - // 获取请求模板 - String requestTemplate = midjourneyConfig.getRequestTemplates().get("imagine"); - // 设置参数 - HashMap requestParams = Maps.newHashMap(); - requestParams.put("guild_id", midjourneyConfig.getGuildId()); - requestParams.put("channel_id", midjourneyConfig.getChannelId()); - requestParams.put("session_id", midjourneyConfig.getSessionId()); - requestParams.put("nonce", String.valueOf(IdUtil.getSnowflakeNextId())); - requestParams.put("prompt", prompt); - // 设置参数 - String requestBody = MjClient.setParams(requestTemplate, requestParams); - // 发送请求 - String res = MjClient.post(url, midjourneyConfig.getToken(), requestBody); - // 这个 res 只要不返回值,就是成功! - boolean isSuccess = StrUtil.isBlank(res); - if (isSuccess) { - return true; - } - log.error("请求失败! 请求参数:{} 返回结果! {}", requestBody, res); - return isSuccess; - } - - public Boolean reRoll(ReRoll reRoll) { - String url = midjourneyConfig.getServerUrl().concat(midjourneyConfig.getApiInteractions()); - // 获取请求模板 - String requestTemplate = midjourneyConfig.getRequestTemplates().get("reroll"); - // 设置参数 - HashMap requestParams = Maps.newHashMap(); - requestParams.put("guild_id", midjourneyConfig.getGuildId()); - requestParams.put("channel_id", midjourneyConfig.getChannelId()); - requestParams.put("session_id", midjourneyConfig.getSessionId()); - requestParams.put("nonce", String.valueOf(IdUtil.getSnowflakeNextId())); - requestParams.put("custom_id", reRoll.getCustomId()); - requestParams.put("message_id", reRoll.getMessageId()); - // 设置参数 - String requestBody = MjClient.setParams(requestTemplate, requestParams); - // 发送请求 - String res = MjClient.post(url, midjourneyConfig.getToken(), requestBody); - // 这个 res 只要不返回值,就是成功! - boolean isSuccess = StrUtil.isBlank(res); - if (isSuccess) { - return true; - } - log.error("请求失败! 请求参数:{} 返回结果! {}", requestBody, res); - return isSuccess; - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java index 38f58f70f..81bb749cd 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java @@ -1,18 +1,76 @@ package cn.iocoder.yudao.framework.ai.midjourney.interactions; -import cn.iocoder.yudao.framework.ai.midjourney.constants.MjInteractionsEnum; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; +import cn.iocoder.yudao.framework.ai.midjourney.vo.ReRoll; +import com.google.common.collect.Maps; +import lombok.extern.slf4j.Slf4j; -import java.util.List; +import java.util.HashMap; /** - * mj Interactions + * 图片生成 * * author: fansili - * time: 2024/4/3 17:22 + * time: 2024/4/3 17:36 */ -public interface MjInteractions { +@Slf4j +public class MjInteractions { - List supperInteractions(); + private MidjourneyConfig midjourneyConfig; - Boolean execute(String prompt); + private String url; + + public MjInteractions(MidjourneyConfig midjourneyConfig) { + this.midjourneyConfig = midjourneyConfig; + this.url = midjourneyConfig.getServerUrl().concat(midjourneyConfig.getApiInteractions()); + } + + public Boolean imagine(String prompt) { + // 获取请求模板 + String requestTemplate = midjourneyConfig.getRequestTemplates().get("imagine"); + // 设置参数 + HashMap requestParams = Maps.newHashMap(); + requestParams.put("guild_id", midjourneyConfig.getGuildId()); + requestParams.put("channel_id", midjourneyConfig.getChannelId()); + requestParams.put("session_id", midjourneyConfig.getSessionId()); + requestParams.put("nonce", String.valueOf(IdUtil.getSnowflakeNextId())); + requestParams.put("prompt", prompt); + // 设置参数 + String requestBody = MjClient.setParams(requestTemplate, requestParams); + // 发送请求 + String res = MjClient.post(url, midjourneyConfig.getToken(), requestBody); + // 这个 res 只要不返回值,就是成功! + boolean isSuccess = StrUtil.isBlank(res); + if (isSuccess) { + return true; + } + log.error("请求失败! 请求参数:{} 返回结果! {}", requestBody, res); + return isSuccess; + } + + public Boolean reRoll(ReRoll reRoll) { + // 获取请求模板 + String requestTemplate = midjourneyConfig.getRequestTemplates().get("reroll"); + // 设置参数 + HashMap requestParams = Maps.newHashMap(); + requestParams.put("guild_id", midjourneyConfig.getGuildId()); + requestParams.put("channel_id", midjourneyConfig.getChannelId()); + requestParams.put("session_id", midjourneyConfig.getSessionId()); + requestParams.put("nonce", String.valueOf(IdUtil.getSnowflakeNextId())); + requestParams.put("custom_id", reRoll.getCustomId()); + requestParams.put("message_id", reRoll.getMessageId()); + // 设置参数 + String requestBody = MjClient.setParams(requestTemplate, requestParams); + // 发送请求 + String res = MjClient.post(url, midjourneyConfig.getToken(), requestBody); + // 这个 res 只要不返回值,就是成功! + boolean isSuccess = StrUtil.isBlank(res); + if (isSuccess) { + return true; + } + log.error("请求失败! 请求参数:{} 返回结果! {}", requestBody, res); + return isSuccess; + } } From 3364b8bfc52ccb9eb8ade07c778fb97c3624942c Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 6 Apr 2024 22:03:51 +0800 Subject: [PATCH 052/684] =?UTF-8?q?=E4=BF=AE=E6=94=B9package?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ai/openAiImage/OpenAiImageClientTests.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java index 389106397..c5861f57b 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.framework.ai.openAiImage; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageApi; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageClient; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageOptions; -import cn.iocoder.yudao.framework.ai.mj.ImagePrompt; -import cn.iocoder.yudao.framework.ai.mj.ImageResponse; +import cn.iocoder.yudao.framework.ai.image.ImagePrompt; +import cn.iocoder.yudao.framework.ai.image.ImageResponse; import org.junit.Before; import org.junit.Test; From 2c21f71327a91d715daba1e430eab366f186d242 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 7 Apr 2024 09:29:27 +0800 Subject: [PATCH 053/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20parseContent=20?= =?UTF-8?q?=E5=A4=87=E6=B3=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java index e119b100f..4e04e69dc 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java @@ -21,8 +21,10 @@ public class MjUtil { public static MjMessage.Content parseContent(String content) { + // 有三种格式。 + // 南极应该是什么样子? // "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (32%) (fast, stealth)", - // "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (fast, stealth)" + // "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (fast, stealth)" MjMessage.Content mjContent = new MjMessage.Content(); if (CharSequenceUtil.isBlank(content)) { return null; From defe628026b35bd46c5a275f19b89272a1e4f303 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 7 Apr 2024 09:35:58 +0800 Subject: [PATCH 054/684] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=AF=B7=E6=B1=82=20?= =?UTF-8?q?header=20=E4=B8=AD=20Referer=20=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/midjourney/interactions/MjClient.java | 11 +++++++---- .../ai/midjourney/interactions/MjInteractions.java | 4 ++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java index 87b68b909..67ce684f2 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.ai.midjourney.interactions; +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; @@ -18,16 +19,18 @@ public class MjClient { private static RestTemplate restTemplate = new RestTemplate(); private static HttpHeaders headers = new HttpHeaders(); + private static final String HEADER_REFERER = "https://discord.com/channels/%s/%s"; + static { headers.setContentType(MediaType.APPLICATION_JSON); // 设置内容类型为JSON - headers.set("Referer", "https://discord.com/channels/1221445697157468200/1221445862962630706"); headers.set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"); headers.set("Cookie", "__dcfduid=6ca536c0e3fa11eeb7cbe34c31b49caf; __sdcfduid=6ca536c1e3fa11eeb7cbe34c31b49caf52cce5ffd8983d2a052cf6aba75fe5fe566f2c265902e283ce30dbf98b8c9c93; _gcl_au=1.1.245923998.1710853617; _ga=GA1.1.111061823.1710853617; __cfruid=6385bb3f48345a006b25992db7dcf984e395736d-1712124666; _cfuvid=O09la5ms0ypNptiG0iD8A6BKWlTxz1LG0WR7qRStD7o-1712124666575-0.0.1.1-604800000; locale=zh-CN; cf_clearance=l_YGod1_SUtYxpDVeZXiX7DLLPl1DYrquZe8WVltvYs-1712124668-1.0.1.1-Hl2.fToel23EpF2HCu9J20rB4D7OhhCzoajPSdo.9Up.wPxhvq22DP9RHzEBKuIUlKyH.kJLxXJfAt2N.LD5WQ; OptanonConsent=isIABGlobal=false&datestamp=Wed+Apr+03+2024+14%3A11%3A15+GMT%2B0800+(%E4%B8%AD%E5%9B%BD%E6%A0%87%E5%87%86%E6%97%B6%E9%97%B4)&version=6.33.0&hosts=&landingPath=https%3A%2F%2Fdiscord.com%2F&groups=C0001%3A1%2CC0002%3A1%2CC0003%3A1; _ga_Q149DFWHT7=GS1.1.1712124668.4.1.1712124679.0.0.0"); } - public static String post(String url, String token, String body) { - // 设置token - headers.set("Authorization", token); + public static String post(String url, MidjourneyConfig config, String body) { + // 设置 header + headers.set("Referer", String.format(HEADER_REFERER, config.getGuildId(), config.getChannelId())); + headers.set("Authorization", config.getToken()); // 封装请求体和头部信息 HttpEntity requestEntity = new HttpEntity<>(body, headers); // 发送请求 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java index 81bb749cd..1a4d0d817 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java @@ -40,7 +40,7 @@ public class MjInteractions { // 设置参数 String requestBody = MjClient.setParams(requestTemplate, requestParams); // 发送请求 - String res = MjClient.post(url, midjourneyConfig.getToken(), requestBody); + String res = MjClient.post(url, midjourneyConfig, requestBody); // 这个 res 只要不返回值,就是成功! boolean isSuccess = StrUtil.isBlank(res); if (isSuccess) { @@ -64,7 +64,7 @@ public class MjInteractions { // 设置参数 String requestBody = MjClient.setParams(requestTemplate, requestParams); // 发送请求 - String res = MjClient.post(url, midjourneyConfig.getToken(), requestBody); + String res = MjClient.post(url, midjourneyConfig, requestBody); // 这个 res 只要不返回值,就是成功! boolean isSuccess = StrUtil.isBlank(res); if (isSuccess) { From 3fe04ac98e899864642e96efc9d1dd1892361862 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 7 Apr 2024 09:43:05 +0800 Subject: [PATCH 055/684] =?UTF-8?q?=E6=8A=BD=E7=A6=BB=20=E5=B8=B8=E7=94=A8?= =?UTF-8?q?key=E5=88=B0=20mj=20constants=20=E9=87=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/midjourney/constants/MjConstants.java | 31 ++++++++++++++++++- .../webSocket/listener/MjMessageListener.java | 26 ++++++++-------- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjConstants.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjConstants.java index 79b5b1b55..884f2626c 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjConstants.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjConstants.java @@ -2,7 +2,36 @@ package cn.iocoder.yudao.framework.ai.midjourney.constants; public final class MjConstants { - public static final String CHANNEL_ID = "channel_id"; + /** + * 消息 - 编号 + */ + public static final String MSG_ID = "id"; + /** + * 消息 - 类型 + * 现在已知: + * 0:我们发送的消息,和指令 + * 20: mj生成图片发送过程中 + * 19: 选择了某一张图片后的通知 + */ + public static final String MSG_TYPE = "type"; + /** + * 平道id + */ + public static final String MSG_CHANNEL_ID = "channel_id"; + /** + * 内容 + * + * "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (32%) (fast, stealth)", + */ + public static final String MSG_CONTENT = "content"; + /** + * 组件(图片生成好之后才有) + */ + public static final String MSG_COMPONENTS = "components"; + /** + * 附件(生成中比较模糊的图片) + */ + public static final String MSG_ATTACHMENTS = "attachments"; } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MjMessageListener.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MjMessageListener.java index ae18ee930..4893e7b37 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MjMessageListener.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MjMessageListener.java @@ -12,12 +12,9 @@ import cn.iocoder.yudao.framework.ai.midjourney.constants.MjGennerateStatusEnum; import cn.iocoder.yudao.framework.ai.midjourney.constants.MjMessageTypeEnum; import cn.iocoder.yudao.framework.ai.midjourney.util.MjUtil; import com.alibaba.fastjson.JSON; -import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.utils.data.DataObject; -import java.io.UnsupportedEncodingException; -import java.util.Arrays; import java.util.List; @Slf4j @@ -39,25 +36,28 @@ public class MjMessageListener { return; } + // 转换几个重要的信息 MjMessage mjMessage = new MjMessage(); - mjMessage.setId(data.getString("id")); - mjMessage.setType(data.getInt("type")); + mjMessage.setId(data.getString(MjConstants.MSG_ID)); + mjMessage.setType(data.getInt(MjConstants.MSG_TYPE)); mjMessage.setRawData(StrUtil.str(raw.toJson(), "UTF-8")); - mjMessage.setContent(MjUtil.parseContent(data.getString("content"))); - - if (!data.getArray("components").isEmpty()) { - String componentsJson = StrUtil.str(data.getArray("components").toJson(), "UTF-8"); + mjMessage.setContent(MjUtil.parseContent(data.getString(MjConstants.MSG_CONTENT))); + // 转换 components + if (!data.getArray(MjConstants.MSG_COMPONENTS).isEmpty()) { + String componentsJson = StrUtil.str(data.getArray(MjConstants.MSG_COMPONENTS).toJson(), "UTF-8"); List components = JSON.parseArray(componentsJson, MjMessage.ComponentType.class); mjMessage.setComponents(components); } - if (!data.getArray("attachments").isEmpty()) { - String attachmentsJson = StrUtil.str(data.getArray("attachments").toJson(), "UTF-8"); + // 转换附件 + if (!data.getArray(MjConstants.MSG_ATTACHMENTS).isEmpty()) { + String attachmentsJson = StrUtil.str(data.getArray(MjConstants.MSG_ATTACHMENTS).toJson(), "UTF-8"); List attachments = JSON.parseArray(attachmentsJson, MjMessage.Attachment.class); mjMessage.setAttachments(attachments); } - // 转换状态 convertGenerateStatus(mjMessage); + // + log.info("message 信息 {}", JSONUtil.toJsonPrettyStr(mjMessage)); System.err.println(JSONUtil.toJsonPrettyStr(mjMessage)); } @@ -72,7 +72,7 @@ public class MjMessageListener { } private boolean ignoreAndLogMessage(DataObject data, MjMessageTypeEnum messageType) { - String channelId = data.getString(MjConstants.CHANNEL_ID); + String channelId = data.getString(MjConstants.MSG_CHANNEL_ID); if (!CharSequenceUtil.equals(channelId, midjourneyConfig.getChannelId())) { return true; } From ed1841e69cc09edcb6bc6a19e89be60c8aea1bec Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 7 Apr 2024 20:24:35 +0800 Subject: [PATCH 056/684] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=B2=A1=E7=94=A8?= =?UTF-8?q?=E7=9A=84=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/midjourney/MidjourneyClient.java | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyClient.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyClient.java deleted file mode 100644 index 1c99564e7..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyClient.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.yudao.framework.ai.midjourney; - -/** - * midjourney - * - * author: fansili - * time: 2024/4/3 17:09 - */ -public class MidjourneyClient { - - - public void imagine() { - - } - - -} From 56c802c01e40b62f5aaab6c14e877303e503f41d Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 8 Apr 2024 09:36:57 +0800 Subject: [PATCH 057/684] =?UTF-8?q?=E6=8F=90=E4=BA=A4pom=20=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao-spring-boot-starter-ai/pom.xml | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml index a4e1deae2..6e3f2b2f1 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml @@ -120,6 +120,35 @@ 4.5.14 compile + + org.springframework.boot + spring-boot-starter-websocket + + + + com.fasterxml.jackson.core + jackson-databind + + + + com.squareup.okhttp3 + okhttp + + + com.google.guava + guava + + + net.dv8tion + JDA + 5.0.0-beta.21 + + + + + + + \ No newline at end of file From 316d2db484ffc2f22d698483f1f7486d5b843e3d Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 8 Apr 2024 14:34:24 +0800 Subject: [PATCH 058/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0mj=E7=94=9F=E6=88=90?= =?UTF-8?q?=E6=8F=8F=E8=BF=B0=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/midjourney/MidjourneyConfig.java | 13 +- .../ai/midjourney/constants/MjConstants.java | 4 + .../ai/midjourney/interactions/MjClient.java | 47 ------- .../interactions/MjInteractions.java | 126 +++++++++++++++++- .../framework/ai/midjourney/util/MjUtil.java | 21 ++- .../ai/midjourney/vo/Attachments.java | 22 +++ .../framework/ai/midjourney/vo/Describe.java | 26 ++++ .../framework/ai/midjourney/vo/ReRoll.java | 6 + .../midjourney/vo/UploadAttachmentsRes.java | 36 +++++ .../framework/ai/mj/MjInteractionsTests.java | 24 ++++ 10 files changed, 265 insertions(+), 60 deletions(-) delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/Attachments.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/Describe.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/UploadAttachmentsRes.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyConfig.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyConfig.java index dd8a599c6..8f749baf4 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyConfig.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyConfig.java @@ -42,14 +42,20 @@ public class MidjourneyConfig { * 发送命令 */ private String apiInteractions = "api/v9/interactions"; - + /** + * 附件 + */ + private String apiAttachments = "/api/v9/channels/%s/attachments"; + /** + * 文件上传 + */ + private String apiAttachmentsUpload = "https://discord-attachments-uploads-prd.storage.googleapis.com/"; // // 浏览器配置 private String userAage = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"; - // // 请求 json 文件 @@ -65,9 +71,6 @@ public class MidjourneyConfig { this.token = token; this.guildId = guildId; this.channelId = channelId; - this.serverUrl = serverUrl; - this.apiInteractions = apiInteractions; - this.userAage = userAage; this.requestTemplates = requestTemplates; // 生成 session id diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjConstants.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjConstants.java index 884f2626c..751652b08 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjConstants.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjConstants.java @@ -34,4 +34,8 @@ public final class MjConstants { public static final String MSG_ATTACHMENTS = "attachments"; + // + // + + public static final String HTTP_COOKIE = "__dcfduid=6ca536c0e3fa11eeb7cbe34c31b49caf; __sdcfduid=6ca536c1e3fa11eeb7cbe34c31b49caf52cce5ffd8983d2a052cf6aba75fe5fe566f2c265902e283ce30dbf98b8c9c93; _gcl_au=1.1.245923998.1710853617; _ga=GA1.1.111061823.1710853617; __cfruid=6385bb3f48345a006b25992db7dcf984e395736d-1712124666; _cfuvid=O09la5ms0ypNptiG0iD8A6BKWlTxz1LG0WR7qRStD7o-1712124666575-0.0.1.1-604800000; locale=zh-CN; cf_clearance=l_YGod1_SUtYxpDVeZXiX7DLLPl1DYrquZe8WVltvYs-1712124668-1.0.1.1-Hl2.fToel23EpF2HCu9J20rB4D7OhhCzoajPSdo.9Up.wPxhvq22DP9RHzEBKuIUlKyH.kJLxXJfAt2N.LD5WQ; OptanonConsent=isIABGlobal=false&datestamp=Wed+Apr+03+2024+14%3A11%3A15+GMT%2B0800+(%E4%B8%AD%E5%9B%BD%E6%A0%87%E5%87%86%E6%97%B6%E9%97%B4)&version=6.33.0&hosts=&landingPath=https%3A%2F%2Fdiscord.com%2F&groups=C0001%3A1%2CC0002%3A1%2CC0003%3A1; _ga_Q149DFWHT7=GS1.1.1712124668.4.1.1712124679.0.0.0"; } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java deleted file mode 100644 index 67ce684f2..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java +++ /dev/null @@ -1,47 +0,0 @@ -package cn.iocoder.yudao.framework.ai.midjourney.interactions; - -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.web.client.RestTemplate; - -import java.util.Map; - -/** - * mj client - *

- * author: fansili - * time: 2024/4/3 17:37 - */ -public class MjClient { - - private static RestTemplate restTemplate = new RestTemplate(); - private static HttpHeaders headers = new HttpHeaders(); - - private static final String HEADER_REFERER = "https://discord.com/channels/%s/%s"; - - static { - headers.setContentType(MediaType.APPLICATION_JSON); // 设置内容类型为JSON - headers.set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"); - headers.set("Cookie", "__dcfduid=6ca536c0e3fa11eeb7cbe34c31b49caf; __sdcfduid=6ca536c1e3fa11eeb7cbe34c31b49caf52cce5ffd8983d2a052cf6aba75fe5fe566f2c265902e283ce30dbf98b8c9c93; _gcl_au=1.1.245923998.1710853617; _ga=GA1.1.111061823.1710853617; __cfruid=6385bb3f48345a006b25992db7dcf984e395736d-1712124666; _cfuvid=O09la5ms0ypNptiG0iD8A6BKWlTxz1LG0WR7qRStD7o-1712124666575-0.0.1.1-604800000; locale=zh-CN; cf_clearance=l_YGod1_SUtYxpDVeZXiX7DLLPl1DYrquZe8WVltvYs-1712124668-1.0.1.1-Hl2.fToel23EpF2HCu9J20rB4D7OhhCzoajPSdo.9Up.wPxhvq22DP9RHzEBKuIUlKyH.kJLxXJfAt2N.LD5WQ; OptanonConsent=isIABGlobal=false&datestamp=Wed+Apr+03+2024+14%3A11%3A15+GMT%2B0800+(%E4%B8%AD%E5%9B%BD%E6%A0%87%E5%87%86%E6%97%B6%E9%97%B4)&version=6.33.0&hosts=&landingPath=https%3A%2F%2Fdiscord.com%2F&groups=C0001%3A1%2CC0002%3A1%2CC0003%3A1; _ga_Q149DFWHT7=GS1.1.1712124668.4.1.1712124679.0.0.0"); - } - - public static String post(String url, MidjourneyConfig config, String body) { - // 设置 header - headers.set("Referer", String.format(HEADER_REFERER, config.getGuildId(), config.getChannelId())); - headers.set("Authorization", config.getToken()); - // 封装请求体和头部信息 - HttpEntity requestEntity = new HttpEntity<>(body, headers); - // 发送请求 - return restTemplate.postForObject(url, requestEntity, String.class); - } - - - public static String setParams(String requestTemplate, Map requestParams) { - for (Map.Entry entry : requestParams.entrySet()) { - requestTemplate = requestTemplate.replace("$".concat(entry.getKey()), entry.getValue()); - } - return requestTemplate; - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java index 1a4d0d817..07827e978 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java @@ -3,10 +3,25 @@ package cn.iocoder.yudao.framework.ai.midjourney.interactions; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; +import cn.iocoder.yudao.framework.ai.midjourney.constants.MjConstants; +import cn.iocoder.yudao.framework.ai.midjourney.util.MjUtil; +import cn.iocoder.yudao.framework.ai.midjourney.vo.Attachments; +import cn.iocoder.yudao.framework.ai.midjourney.vo.Describe; import cn.iocoder.yudao.framework.ai.midjourney.vo.ReRoll; +import cn.iocoder.yudao.framework.ai.midjourney.vo.UploadAttachmentsRes; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.google.common.collect.Lists; import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; +import org.springframework.core.io.FileSystemResource; +import org.springframework.http.*; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; +import java.io.IOException; import java.util.HashMap; /** @@ -18,9 +33,12 @@ import java.util.HashMap; @Slf4j public class MjInteractions { - private MidjourneyConfig midjourneyConfig; - private String url; + private final String url; + private final MidjourneyConfig midjourneyConfig; + private final RestTemplate restTemplate = new RestTemplate(); + private static final String HEADER_REFERER = "https://discord.com/channels/%s/%s"; + public MjInteractions(MidjourneyConfig midjourneyConfig) { this.midjourneyConfig = midjourneyConfig; @@ -37,10 +55,13 @@ public class MjInteractions { requestParams.put("session_id", midjourneyConfig.getSessionId()); requestParams.put("nonce", String.valueOf(IdUtil.getSnowflakeNextId())); requestParams.put("prompt", prompt); - // 设置参数 - String requestBody = MjClient.setParams(requestTemplate, requestParams); + // 解析 template 参数占位符 + String requestBody = MjUtil.parseTemplate(requestTemplate, requestParams); + // 获取 header + HttpHeaders httpHeaders = getHttpHeaders(); // 发送请求 - String res = MjClient.post(url, midjourneyConfig, requestBody); + HttpEntity requestEntity = new HttpEntity<>(requestBody, httpHeaders); + String res = restTemplate.postForObject(url, requestEntity, String.class); // 这个 res 只要不返回值,就是成功! boolean isSuccess = StrUtil.isBlank(res); if (isSuccess) { @@ -50,6 +71,8 @@ public class MjInteractions { return isSuccess; } + + public Boolean reRoll(ReRoll reRoll) { // 获取请求模板 String requestTemplate = midjourneyConfig.getRequestTemplates().get("reroll"); @@ -61,10 +84,13 @@ public class MjInteractions { requestParams.put("nonce", String.valueOf(IdUtil.getSnowflakeNextId())); requestParams.put("custom_id", reRoll.getCustomId()); requestParams.put("message_id", reRoll.getMessageId()); + // 获取 header + HttpHeaders httpHeaders = getHttpHeaders(); // 设置参数 - String requestBody = MjClient.setParams(requestTemplate, requestParams); + String requestBody = MjUtil.parseTemplate(requestTemplate, requestParams); // 发送请求 - String res = MjClient.post(url, midjourneyConfig, requestBody); + HttpEntity requestEntity = new HttpEntity<>(requestBody, httpHeaders); + String res = restTemplate.postForObject(url, requestEntity, String.class); // 这个 res 只要不返回值,就是成功! boolean isSuccess = StrUtil.isBlank(res); if (isSuccess) { @@ -73,4 +99,90 @@ public class MjInteractions { log.error("请求失败! 请求参数:{} 返回结果! {}", requestBody, res); return isSuccess; } + + + public UploadAttachmentsRes uploadAttachments(Attachments attachments) { + // file + JSONObject fileObj = new JSONObject(); + fileObj.put("id", "0"); + fileObj.put("filename", attachments.getFileSystemResource().getFilename()); + try { + fileObj.put("file_size", attachments.getFileSystemResource().contentLength()); + } catch (IOException e) { + throw new RuntimeException(e); + } + // 创建用于存放表单数据的MultiValueMap + MultiValueMap multipartRequest = new LinkedMultiValueMap<>(); + multipartRequest.put("files", Lists.newArrayList(fileObj)); + // 设置header值 + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setContentType(MediaType.APPLICATION_JSON); + httpHeaders.set("Authorization", midjourneyConfig.getToken()); + httpHeaders.set("User-Agent", midjourneyConfig.getUserAage()); + httpHeaders.set("Cookie", MjConstants.HTTP_COOKIE); + httpHeaders.set("Referer", String.format(HEADER_REFERER, midjourneyConfig.getGuildId(), midjourneyConfig.getChannelId())); + // 创建HttpEntity对象,包含表单数据和头部信息 + HttpEntity> multiValueMapHttpEntity = new HttpEntity<>(multipartRequest, httpHeaders); + // 发送POST请求并接收响应 + String uri = String.format(midjourneyConfig.getApiAttachments(), midjourneyConfig.getChannelId()); + String response = restTemplate.postForObject(midjourneyConfig.getServerUrl().concat(uri), multiValueMapHttpEntity, String.class); + UploadAttachmentsRes uploadAttachmentsRes = JSON.parseObject(response, UploadAttachmentsRes.class); + + + // + // 上传文件 + String uploadUrl = uploadAttachmentsRes.getAttachments().getFirst().getUploadUrl(); + String uploadAttachmentsUrl = midjourneyConfig.getApiAttachmentsUpload().concat(uploadUrl); + httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); + HttpEntity fileSystemResourceHttpEntity = new HttpEntity<>(attachments.getFileSystemResource(), httpHeaders); + ResponseEntity exchange = restTemplate.exchange(uploadUrl, HttpMethod.PUT, fileSystemResourceHttpEntity, String.class); + String uploadRes = exchange.getBody(); + + return uploadAttachmentsRes; + } + + public Boolean describe(Describe describe) { + // 获取请求模板 + String requestTemplate = midjourneyConfig.getRequestTemplates().get("describe"); + // 设置参数 + HashMap requestParams = Maps.newHashMap(); + requestParams.put("guild_id", midjourneyConfig.getGuildId()); + requestParams.put("channel_id", midjourneyConfig.getChannelId()); + requestParams.put("session_id", midjourneyConfig.getSessionId()); + requestParams.put("nonce", String.valueOf(IdUtil.getSnowflakeNextId())); + requestParams.put("file_name", describe.getFileName()); + requestParams.put("final_file_name", describe.getFinalFileName()); + // 设置 header + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); // 设置内容类型为JSON + httpHeaders.set("Authorization", midjourneyConfig.getToken()); + httpHeaders.set("User-Agent", midjourneyConfig.getUserAage()); + httpHeaders.set("Cookie", MjConstants.HTTP_COOKIE); + httpHeaders.set("Referer", String.format(HEADER_REFERER, midjourneyConfig.getGuildId(), midjourneyConfig.getChannelId())); + String requestBody = MjUtil.parseTemplate(requestTemplate, requestParams); + // 创建表单数据 + MultiValueMap formData = new LinkedMultiValueMap<>(); + formData.add("payload_json", requestBody); + // 发送请求 + HttpEntity> multiValueMapHttpEntity = new HttpEntity<>(formData, httpHeaders); + String res = restTemplate.postForObject(url, multiValueMapHttpEntity, String.class); + // 这个 res 只要不返回值,就是成功! + boolean isSuccess = StrUtil.isBlank(res); + if (isSuccess) { + return true; + } + log.error("请求失败! 请求参数:{} 返回结果! {}", requestBody, res); + return isSuccess; + } + + @NotNull + private HttpHeaders getHttpHeaders() { + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setContentType(MediaType.APPLICATION_JSON); // 设置内容类型为JSON + httpHeaders.set("Authorization", midjourneyConfig.getToken()); + httpHeaders.set("User-Agent", midjourneyConfig.getUserAage()); + httpHeaders.set("Cookie", MjConstants.HTTP_COOKIE); + httpHeaders.set("Referer", String.format(HEADER_REFERER, midjourneyConfig.getGuildId(), midjourneyConfig.getChannelId())); + return httpHeaders; + } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java index 4e04e69dc..751a79b04 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.ai.midjourney.util; import cn.hutool.core.text.CharSequenceUtil; import cn.iocoder.yudao.framework.ai.midjourney.MjMessage; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -19,7 +20,12 @@ public class MjUtil { public static final String CONTENT_REGEX = ".*?\\*\\*(.*?)\\*\\*.+<@\\d+> \\((.*?)\\)"; public static final String CONTENT_PROGRESS_REGEX = "\\(([^)]*)\\)"; - + /** + * 解析 content 参数 + * + * @param content + * @return + */ public static MjMessage.Content parseContent(String content) { // 有三种格式。 // 南极应该是什么样子? @@ -61,4 +67,17 @@ public class MjUtil { return mjContent; } + /** + * 设置 params + * + * @param requestTemplate + * @param requestParams + * @return + */ + public static String parseTemplate(String requestTemplate, Map requestParams) { + for (Map.Entry entry : requestParams.entrySet()) { + requestTemplate = requestTemplate.replace("$".concat(entry.getKey()), entry.getValue()); + } + return requestTemplate; + } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/Attachments.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/Attachments.java new file mode 100644 index 000000000..133a7031f --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/Attachments.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.framework.ai.midjourney.vo; + +import lombok.Data; +import lombok.experimental.Accessors; +import org.springframework.core.io.FileSystemResource; + +/** + * 附件 + *

+ * author: fansili + * time: 2024/4/7 17:18 + */ +@Data +@Accessors(chain = true) +public class Attachments { + + /** + * 创建文件系统资源对象 + */ + private FileSystemResource fileSystemResource; + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/Describe.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/Describe.java new file mode 100644 index 000000000..6517f7b86 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/Describe.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.framework.ai.midjourney.vo; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.File; + +/** + * describe + * + * author: fansili + * time: 2024/4/7 12:30 + */ +@Data +@Accessors(chain = true) +public class Describe { + + /** + * 文件名字 + */ + private String fileName; + /** + * UploadAttachmentsRes 里面的 finalFileName + */ + private String finalFileName; +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/ReRoll.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/ReRoll.java index 2d39ba1df..a28517419 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/ReRoll.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/ReRoll.java @@ -11,6 +11,12 @@ import lombok.experimental.Accessors; @Accessors(chain = true) public class ReRoll { + /** + * socket 消息里面收到的 messageId + */ private String messageId; + /** + * socket 消息里面的,操作按钮id(MJ::JOB::upsample::3::2aeefbef-43e2-4057-bcf1-43b5f39ab6f7) + */ private String customId; } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/UploadAttachmentsRes.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/UploadAttachmentsRes.java new file mode 100644 index 000000000..b06c1c318 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/UploadAttachmentsRes.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.framework.ai.midjourney.vo; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; + +/** + * 上传附件 - res + * + * author: fansili + * time: 2024/4/8 13:32 + */ +@Data +@Accessors(chain = true) +public class UploadAttachmentsRes { + + private List attachments; + + @Data + @Accessors(chain = true) + public static class Attachment { + /** + * 附件的ID。 + */ + private int id; + /** + * 附件的上传URL。 + */ + private String uploadUrl; + /** + * 上传到服务器的文件名。 + */ + private String uploadFilename; + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjInteractionsTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjInteractionsTests.java index 3108b31be..636e9d2d4 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjInteractionsTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjInteractionsTests.java @@ -3,9 +3,14 @@ package cn.iocoder.yudao.framework.ai.mj; import cn.hutool.core.io.FileUtil; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; import cn.iocoder.yudao.framework.ai.midjourney.interactions.MjInteractions; +import cn.iocoder.yudao.framework.ai.midjourney.vo.Attachments; +import cn.iocoder.yudao.framework.ai.midjourney.vo.Describe; import cn.iocoder.yudao.framework.ai.midjourney.vo.ReRoll; +import cn.iocoder.yudao.framework.ai.midjourney.vo.UploadAttachmentsRes; +import com.alibaba.fastjson.JSON; import org.junit.Before; import org.junit.Test; +import org.springframework.core.io.FileSystemResource; import java.io.File; import java.util.HashMap; @@ -46,4 +51,23 @@ public class MjInteractionsTests { .setMessageId("1226165117448753243") .setCustomId("MJ::JOB::upsample::3::2aeefbef-43e2-4057-bcf1-43b5f39ab6f7")); } + + @Test + public void uploadAttachmentsTest() { + MjInteractions mjImagineInteractions = new MjInteractions(midjourneyConfig); + UploadAttachmentsRes res = mjImagineInteractions.uploadAttachments( + new Attachments().setFileSystemResource( + new FileSystemResource(new File("/Users/fansili/Downloads/DSC01402.JPG"))) + ); + System.err.println(JSON.toJSONString(res)); + } + + @Test + public void describeTest() { + MjInteractions mjImagineInteractions = new MjInteractions(midjourneyConfig); + mjImagineInteractions.describe(new Describe() + .setFileName("DSC01402.JPG") + .setFinalFileName("16826931-2873-45ec-8cfb-0ad81f1a075f/DSC01402.JPG") + ); + } } From dabe491cde69e8abb8dc96101a5a1d21e9185dcd Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 8 Apr 2024 14:34:40 +0800 Subject: [PATCH 059/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20describe=20?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E6=A8=A1=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/resources/http-body/describe.json | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/describe.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/describe.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/describe.json new file mode 100644 index 000000000..6d1f534ab --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/describe.json @@ -0,0 +1,28 @@ +{ + "type": 2, + "guild_id": "$guild_id", + "channel_id": "$channel_id", + "application_id": "936929561302675456", + "session_id": "$session_id", + "nonce": "$nonce", + "data": { + "version": "1204231436023111690", + "id": "1092492867185950852", + "name": "describe", + "type": 1, + "options": [ + { + "type": 11, + "name": "image", + "value": 0 + } + ], + "attachments": [ + { + "id": "0", + "filename": "$file_name", + "uploaded_filename": "$final_file_name" + } + ] + } +} \ No newline at end of file From 29dc77fc0d0c215e991a412ddbc32f5280bd52ea Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 8 Apr 2024 14:36:26 +0800 Subject: [PATCH 060/684] =?UTF-8?q?=E8=B0=83=E6=95=B4=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../imageGenerationProcess}/1.json | 0 .../imageGenerationProcess}/10.json | 0 .../imageGenerationProcess}/11.json | 0 .../imageGenerationProcess}/12.json | 0 .../imageGenerationProcess}/2.json | 0 .../imageGenerationProcess}/3.json | 0 .../imageGenerationProcess}/4.json | 0 .../imageGenerationProcess}/5.json | 0 .../imageGenerationProcess}/6.json | 0 .../imageGenerationProcess}/7.json | 0 .../imageGenerationProcess}/8.json | 0 .../imageGenerationProcess}/9.json | 0 .../{http-body => requestTestJson}/interactions_type2.json | 0 .../{http-body => requestTestJson}/interactions_type3.json | 0 14 files changed, 0 insertions(+), 0 deletions(-) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/{图片消息过程 => requestTestJson/imageGenerationProcess}/1.json (100%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/{图片消息过程 => requestTestJson/imageGenerationProcess}/10.json (100%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/{图片消息过程 => requestTestJson/imageGenerationProcess}/11.json (100%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/{图片消息过程 => requestTestJson/imageGenerationProcess}/12.json (100%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/{图片消息过程 => requestTestJson/imageGenerationProcess}/2.json (100%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/{图片消息过程 => requestTestJson/imageGenerationProcess}/3.json (100%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/{图片消息过程 => requestTestJson/imageGenerationProcess}/4.json (100%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/{图片消息过程 => requestTestJson/imageGenerationProcess}/5.json (100%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/{图片消息过程 => requestTestJson/imageGenerationProcess}/6.json (100%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/{图片消息过程 => requestTestJson/imageGenerationProcess}/7.json (100%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/{图片消息过程 => requestTestJson/imageGenerationProcess}/8.json (100%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/{图片消息过程 => requestTestJson/imageGenerationProcess}/9.json (100%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/{http-body => requestTestJson}/interactions_type2.json (100%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/{http-body => requestTestJson}/interactions_type3.json (100%) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/1.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/1.json similarity index 100% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/1.json rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/1.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/10.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/10.json similarity index 100% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/10.json rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/10.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/11.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/11.json similarity index 100% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/11.json rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/11.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/12.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/12.json similarity index 100% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/12.json rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/12.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/2.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/2.json similarity index 100% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/2.json rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/2.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/3.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/3.json similarity index 100% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/3.json rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/3.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/4.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/4.json similarity index 100% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/4.json rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/4.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/5.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/5.json similarity index 100% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/5.json rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/5.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/6.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/6.json similarity index 100% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/6.json rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/6.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/7.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/7.json similarity index 100% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/7.json rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/7.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/8.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/8.json similarity index 100% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/8.json rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/8.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/9.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/9.json similarity index 100% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/9.json rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/9.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/interactions_type2.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/interactions_type2.json similarity index 100% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/interactions_type2.json rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/interactions_type2.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/interactions_type3.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/interactions_type3.json similarity index 100% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/interactions_type3.json rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/interactions_type3.json From a44628e436b0bb3d9df60587617da81ec204aad0 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 9 Apr 2024 00:10:36 +0800 Subject: [PATCH 061/684] =?UTF-8?q?AI=EF=BC=9Acode=20review=20chat=20?= =?UTF-8?q?=E9=83=A8=E5=88=86=E7=9A=84=E4=BB=A3=E7=A0=81=EF=BC=88qianwen?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/iocoder/yudao/module/ai/ErrorCodeConstants.java | 1 + .../cn/iocoder/yudao/module/ai/enums/AiModelEnum.java | 3 +++ .../yudao/module/ai/controller/admin/ChatController.java | 1 + .../yudao/module/ai/controller/admin/vo/AiChatReqVO.java | 1 + .../src/main/resources/application.properties | 2 +- .../yudao/framework/ai/chatqianwen/QianWenApi.java | 1 + .../yudao/framework/ai/chatqianwen/QianWenChatClient.java | 3 ++- .../java/cn/iocoder/yudao/framework/ai/package-info.java | 8 ++++++++ 8 files changed, 18 insertions(+), 2 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index 69795ead2..9ca5f09ad 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -11,6 +11,7 @@ public interface ErrorCodeConstants { // ========== 模块 ai 错误码区间 [1-022-000-000 ~ 1-023-000-000) ========== + // TODO @fansili:1)类注释不太对;2)中英文之间,有个空格;例如说 AI 模型 ErrorCode AI_MODULE_NOT_SUPPORTED = new ErrorCode(1_022_000_000, "AI模型暂不支持!"); } diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiModelEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiModelEnum.java index ff1889fe7..7eac2b61f 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiModelEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiModelEnum.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.enums; import lombok.Getter; +// TODO @fansili:1)类注释要加下;2)author 和 time 用 javadoc,@author 和 @since;3)@AllArgsConstructor 使用这个注解,去掉构造方法;4)value 改成 model 字段,然后注释都写下哈;5)message 改成 name,然后注释都写下哈 /** * author: fansili * time: 2024/3/4 12:36 @@ -19,7 +20,9 @@ public enum AiModelEnum { this.message = message; } + // TODO @fan private String value; private String message; + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java index eb97f92e5..a6300a5c2 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java @@ -26,6 +26,7 @@ import reactor.core.publisher.Flux; import java.util.Scanner; import java.util.function.Consumer; +// TODO @fansili:有了 swagger 注释,就不用类注释了 /** * AI模块 * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/vo/AiChatReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/vo/AiChatReqVO.java index 43b29d283..187f51741 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/vo/AiChatReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/vo/AiChatReqVO.java @@ -5,6 +5,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +// TODO @fansili 1)swagger 注释不太对;2)有了 swagger 注释,就不用类注释了 /** * ai 聊天 req * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.properties b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.properties index e53f358d0..6ec2672e6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.properties +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.properties @@ -1,4 +1,4 @@ -# open ai +# open ai TODO @fansili?????????????? # openAI https://openai.com/ spring.ai.openai.api-key=${OPEN_AI_KEY} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java index aefabc62a..77d4411f3 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java @@ -9,6 +9,7 @@ import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; import reactor.core.publisher.Flux; +// TODO @fansili:是不是挪到 api 包里?按照 spring ai 的结构;根目录只放 client 和 options /** * 阿里 通义千问 * diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java index 60b533559..62c982095 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java @@ -29,7 +29,7 @@ import java.util.stream.Collectors; * time: 2024/3/13 21:06 */ @Slf4j -public class QianWenChatClient implements ChatClient, StreamingChatClient { +public class QianWenChatClient implements ChatClient, StreamingChatClient { private QianWenApi qianWenApi; @@ -44,6 +44,7 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient { this.qianWenOptions = qianWenOptions; } + // TODO @fansili:看看咋公用出来,允许传入类似异常之类的参数; public final RetryTemplate retryTemplate = RetryTemplate.builder() // 最大重试次数 10 .maxAttempts(10) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java index de43c748b..6e60edaa4 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java @@ -1,5 +1,13 @@ /** * author: fansili * time: 2024/3/12 20:29 + * + * 1. org.springframework.ai:包括 chat、image、model、parser、util 部分 + * + * 2. yudao.framework.models + * \qianwen 通义千问 + * \yiyan 文心一言 + * \xinghuo 星火 + * \midjourney */ package cn.iocoder.yudao.framework.ai; \ No newline at end of file From 337ae045519b8c83cb4ff53aa57cf9426b5fd5ff Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 9 Apr 2024 09:31:56 +0800 Subject: [PATCH 062/684] =?UTF-8?q?AI=EF=BC=9Acode=20review=20chat=20?= =?UTF-8?q?=E9=83=A8=E5=88=86=E7=9A=84=E4=BB=A3=E7=A0=81=EF=BC=88mj?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 1 + .../constants/MjGennerateStatusEnum.java | 1 + .../midjourney/interactions/MjInteractions.java | 17 +++++++++++------ .../webSocket/MjWebSocketStarter.java | 1 + .../yudao/framework/ai/package-info.java | 2 ++ .../yudao/framework/ai/util/JacksonUtil.java | 1 + 6 files changed, 17 insertions(+), 6 deletions(-) diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 6b4f135ab..7a3ee3e0a 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -629,6 +629,7 @@ ${ureport2.version} + org.springframework.ai diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjGennerateStatusEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjGennerateStatusEnum.java index bbe682c5f..1e8bc6f53 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjGennerateStatusEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjGennerateStatusEnum.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.ai.midjourney.constants; import lombok.Getter; +// TODO @fansili:1)Mj 缩写,还是搞成全称。。虽然长一点,但是感觉会相对清晰一些哈;2)lombok 相关的注解,可以用用哈;3)value 改 status; /** * mj 生成状态 * diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java index 07827e978..f0bd74daa 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java @@ -24,6 +24,7 @@ import org.springframework.web.client.RestTemplate; import java.io.IOException; import java.util.HashMap; +// TODO @fansili:按照 spring ai 的封装习惯,这个类是不是 MidjourneyApi /** * 图片生成 * @@ -33,13 +34,12 @@ import java.util.HashMap; @Slf4j public class MjInteractions { - private final String url; private final MidjourneyConfig midjourneyConfig; - private final RestTemplate restTemplate = new RestTemplate(); + private final RestTemplate restTemplate = new RestTemplate(); // TODO @fansili:优先级低:后续搞到统一的管理 + // TODO @fansili:静态变量,放在最前面哈; private static final String HEADER_REFERER = "https://discord.com/channels/%s/%s"; - public MjInteractions(MidjourneyConfig midjourneyConfig) { this.midjourneyConfig = midjourneyConfig; this.url = midjourneyConfig.getServerUrl().concat(midjourneyConfig.getApiInteractions()); @@ -50,10 +50,11 @@ public class MjInteractions { String requestTemplate = midjourneyConfig.getRequestTemplates().get("imagine"); // 设置参数 HashMap requestParams = Maps.newHashMap(); + // TODO @fansili:感觉参数的组装,可以搞成一个公用的方法;就是 config + 入参的感觉; requestParams.put("guild_id", midjourneyConfig.getGuildId()); requestParams.put("channel_id", midjourneyConfig.getChannelId()); requestParams.put("session_id", midjourneyConfig.getSessionId()); - requestParams.put("nonce", String.valueOf(IdUtil.getSnowflakeNextId())); + requestParams.put("nonce", String.valueOf(IdUtil.getSnowflakeNextId())); // TODO @fansili:建议用 uuid 之类的;nextId 跨进程未必合适哈; requestParams.put("prompt", prompt); // 解析 template 参数占位符 String requestBody = MjUtil.parseTemplate(requestTemplate, requestParams); @@ -63,6 +64,7 @@ public class MjInteractions { HttpEntity requestEntity = new HttpEntity<>(requestBody, httpHeaders); String res = restTemplate.postForObject(url, requestEntity, String.class); // 这个 res 只要不返回值,就是成功! + // TODO @fansili:可以直接 if (StrUtil.isBlank(res)) boolean isSuccess = StrUtil.isBlank(res); if (isSuccess) { return true; @@ -70,7 +72,7 @@ public class MjInteractions { log.error("请求失败! 请求参数:{} 返回结果! {}", requestBody, res); return isSuccess; } - + // TODO @fansili:方法和方法之间,空一行哈; public Boolean reRoll(ReRoll reRoll) { @@ -100,12 +102,13 @@ public class MjInteractions { return isSuccess; } - + // TODO @fansili:搞成私有方法,可能会好点; public UploadAttachmentsRes uploadAttachments(Attachments attachments) { // file JSONObject fileObj = new JSONObject(); fileObj.put("id", "0"); fileObj.put("filename", attachments.getFileSystemResource().getFilename()); + // TODO @fansili:这块用 lombok 哪个异常处理,简化下代码; try { fileObj.put("file_size", attachments.getFileSystemResource().contentLength()); } catch (IOException e) { @@ -116,6 +119,7 @@ public class MjInteractions { multipartRequest.put("files", Lists.newArrayList(fileObj)); // 设置header值 HttpHeaders httpHeaders = new HttpHeaders(); + // TODO @fansili:通用的 header 构建,抽一个方法哈; httpHeaders.setContentType(MediaType.APPLICATION_JSON); httpHeaders.set("Authorization", midjourneyConfig.getToken()); httpHeaders.set("User-Agent", midjourneyConfig.getUserAage()); @@ -185,4 +189,5 @@ public class MjInteractions { httpHeaders.set("Referer", String.format(HEADER_REFERER, midjourneyConfig.getGuildId(), midjourneyConfig.getChannelId())); return httpHeaders; } + } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MjWebSocketStarter.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MjWebSocketStarter.java index 0d6a7d0c6..b01c4adfe 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MjWebSocketStarter.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MjWebSocketStarter.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.net.URI; import java.util.concurrent.TimeoutException; +// TODO @fansili:mj 这块 websocket 有点小复杂,虽然代码量 400 多行;感觉可以考虑,有没第三方 sdk,通过它透明接入 mj @Slf4j public class MjWebSocketStarter implements WebSocketStarter { /** diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java index 6e60edaa4..ffd2ac933 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java @@ -2,6 +2,8 @@ * author: fansili * time: 2024/3/12 20:29 * + * TODO @fansili:包的想法,需要重点看看 + * * 1. org.springframework.ai:包括 chat、image、model、parser、util 部分 * * 2. yudao.framework.models diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/util/JacksonUtil.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/util/JacksonUtil.java index 046a481dc..b5c96c992 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/util/JacksonUtil.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/util/JacksonUtil.java @@ -9,6 +9,7 @@ import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import java.io.IOException; +// TODO @fansili:看看能不能用 JsonUtils /** * Jackson工具类 * From 32bc632947783ac18dd8618d57e216ac6174892c Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 9 Apr 2024 20:12:41 +0800 Subject: [PATCH 063/684] =?UTF-8?q?=E5=A4=84=E7=90=86todo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/enums/AiModelEnum.java | 28 ------- .../module/ai/enums/OpenAiModelEnum.java | 35 ++++++++ .../ai/controller/admin/ChatController.java | 41 ++------- .../ai/controller/admin/vo/AiChatReqVO.java | 20 ++--- .../yudao-spring-boot-starter-ai/pom.xml | 4 + .../ai/chatqianwen/QianWenChatClient.java | 1 + .../ai/chatqianwen/{ => api}/QianWenApi.java | 4 +- .../ai/imageopenai/OpenAiImageApi.java | 3 +- ...{MjMessage.java => MidjourneyMessage.java} | 5 +- ...onstants.java => MidjourneyConstants.java} | 2 +- .../MidjourneyGennerateStatusEnum.java | 31 +++++++ ...m.java => MidjourneyInteractionsEnum.java} | 4 +- ...um.java => MidjourneyMessageTypeEnum.java} | 4 +- ...ifyCode.java => MidjourneyNotifyCode.java} | 2 +- .../constants/MjGennerateStatusEnum.java | 30 ------- ...tions.java => MidjourneyInteractions.java} | 39 +++++---- .../util/{MjUtil.java => MidjourneyUtil.java} | 8 +- ...r.java => MidjourneyWebSocketStarter.java} | 27 +++--- ...r.java => MidjourneyWebSocketHandler.java} | 14 ++-- .../listener/MidjourneyMessageListener.java | 83 +++++++++++++++++++ .../webSocket/listener/MjMessageListener.java | 83 ------------------- .../yudao/framework/ai/util/JacksonUtil.java | 80 ------------------ .../ai/chat/QianWenChatClientTests.java | 3 +- .../MidjourneyInteractionsTests.java} | 15 ++-- .../MidjourneyUtilTests.java} | 10 +-- .../MidjourneyWebSocketTests.java} | 13 ++- 26 files changed, 243 insertions(+), 346 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiModelEnum.java create mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/OpenAiModelEnum.java rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/{ => api}/QianWenApi.java (92%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{MjMessage.java => MidjourneyMessage.java} (93%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/{MjConstants.java => MidjourneyConstants.java} (97%) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyGennerateStatusEnum.java rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/{MjInteractionsEnum.java => MidjourneyInteractionsEnum.java} (81%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/{MjMessageTypeEnum.java => MidjourneyMessageTypeEnum.java} (76%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/{MjNotifyCode.java => MidjourneyNotifyCode.java} (81%) delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjGennerateStatusEnum.java rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/{MjInteractions.java => MidjourneyInteractions.java} (89%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/{MjUtil.java => MidjourneyUtil.java} (91%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/{MjWebSocketStarter.java => MidjourneyWebSocketStarter.java} (89%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/handler/{MjWebSocketHandler.java => MidjourneyWebSocketHandler.java} (96%) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MjMessageListener.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/util/JacksonUtil.java rename yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/{mj/MjInteractionsTests.java => midjourney/MidjourneyInteractionsTests.java} (79%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/{mj/MjUtilTests.java => midjourney/MidjourneyUtilTests.java} (58%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/{mj/MjWebSocketTests.java => midjourney/MidjourneyWebSocketTests.java} (76%) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiModelEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiModelEnum.java deleted file mode 100644 index 7eac2b61f..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiModelEnum.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums; - -import lombok.Getter; - -// TODO @fansili:1)类注释要加下;2)author 和 time 用 javadoc,@author 和 @since;3)@AllArgsConstructor 使用这个注解,去掉构造方法;4)value 改成 model 字段,然后注释都写下哈;5)message 改成 name,然后注释都写下哈 -/** - * author: fansili - * time: 2024/3/4 12:36 - */ -@Getter -public enum AiModelEnum { - - OPEN_AI_GPT_3_5("gpt-3.5-turbo", "GPT3.5"), - OPEN_AI_GPT_4("gpt-4-turbo", "GPT4") - - ; - - AiModelEnum(String value, String message) { - this.value = value; - this.message = message; - } - - // TODO @fan - private String value; - - private String message; - -} diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/OpenAiModelEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/OpenAiModelEnum.java new file mode 100644 index 000000000..3daa3f57b --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/OpenAiModelEnum.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.ai.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +// TODO done @fansili:1)类注释要加下;2)author 和 time 用 javadoc,@author 和 @since;3)@AllArgsConstructor 使用这个注解,去掉构造方法;4)value 改成 model 字段,然后注释都写下哈;5)message 改成 name,然后注释都写下哈 +/** + * @author: fansili + * @time: 2024/3/4 12:36 + */ +@Getter +@AllArgsConstructor +public enum OpenAiModelEnum { + + /** + * open ai 3.5模型 + */ + OPEN_AI_GPT_3_5("gpt-3.5-turbo", "GPT3.5"), + /** + * open ai 4.0 收费模型 + */ + OPEN_AI_GPT_4("gpt-4-turbo", "GPT4") + + ; + + /** + * 模型 - 用于参数传递 + */ + private String model; + /** + * 模型名字 - 用于展示 + */ + private String name; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java index a6300a5c2..e9f8ab6b5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.controller.admin.vo.AiChatReqVO; -import cn.iocoder.yudao.module.ai.enums.AiModelEnum; +import cn.iocoder.yudao.module.ai.enums.OpenAiModelEnum; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletResponse; @@ -13,7 +13,6 @@ import org.springframework.ai.chat.ChatClient; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.openai.OpenAiChatClient; -import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.validation.annotation.Validated; @@ -23,16 +22,9 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Flux; -import java.util.Scanner; import java.util.function.Consumer; -// TODO @fansili:有了 swagger 注释,就不用类注释了 -/** - * AI模块 - * - * author: fansili - * time: 2024/3/3 20:28 - */ +// TODO done @fansili:有了 swagger 注释,就不用类注释了 @Tag(name = "AI模块") @RestController @RequestMapping("/ai-api") @@ -48,7 +40,7 @@ public class ChatController { ChatClient chatClient = getChatClient(reqVO.getAiModel()); String res; try { - res = chatClient.call(reqVO.getInputText()); + res = chatClient.call(reqVO.getPrompt()); } catch (Exception e) { res = e.getMessage(); } @@ -59,33 +51,14 @@ public class ChatController { @Operation(summary = "对话聊天chatStream", description = "简单的ai聊天") public CommonResult chatStream(HttpServletResponse response, @RequestBody @Validated AiChatReqVO reqVO) throws InterruptedException { OpenAiChatClient chatClient = applicationContext.getBean(OpenAiChatClient.class); - Flux chatResponse = chatClient.stream(new Prompt(reqVO.getInputText())); + Flux chatResponse = chatClient.stream(new Prompt(reqVO.getPrompt())); chatResponse.subscribe(new Consumer() { @Override public void accept(ChatResponse chatResponse) { System.err.println(chatResponse.getResults().get(0).getOutput().getContent()); } }); - return CommonResult.success("1"); - } - - public static void main(String[] args) { - OpenAiChatClient openAiChatClient = new OpenAiChatClient(new OpenAiApi("openkey")); - Flux responseFlux = openAiChatClient.stream(new Prompt("最好的编程语言!")); - long now = System.currentTimeMillis(); - responseFlux.subscribe(new Consumer() { - @Override - public void accept(ChatResponse chatResponse) { - if (chatResponse.getResults().get(0).getOutput() == null) { - return; - } - System.err.println(chatResponse.getResults().get(0).getOutput().getContent()); - } - }); - - // 阻止退出 - Scanner scanner = new Scanner(System.in); - scanner.nextLine(); + return CommonResult.success(null); } /** @@ -94,8 +67,8 @@ public class ChatController { * @param aiModelEnum * @return */ - private ChatClient getChatClient(AiModelEnum aiModelEnum) { - if (AiModelEnum.OPEN_AI_GPT_3_5 == aiModelEnum) { + private ChatClient getChatClient(OpenAiModelEnum aiModelEnum) { + if (OpenAiModelEnum.OPEN_AI_GPT_3_5 == aiModelEnum) { return applicationContext.getBean(OpenAiChatClient.class); } // AI模型暂不支持 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/vo/AiChatReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/vo/AiChatReqVO.java index 187f51741..643b6600d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/vo/AiChatReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/vo/AiChatReqVO.java @@ -1,27 +1,21 @@ package cn.iocoder.yudao.module.ai.controller.admin.vo; -import cn.iocoder.yudao.module.ai.enums.AiModelEnum; +import cn.iocoder.yudao.module.ai.enums.OpenAiModelEnum; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; -// TODO @fansili 1)swagger 注释不太对;2)有了 swagger 注释,就不用类注释了 -/** - * ai 聊天 req - * - * author: fansili - * time: 2024/3/4 12:33 - */ -@Schema(description = "用户 App - 上传文件 Request VO") +// TODO done @fansili 1)swagger 注释不太对;2)有了 swagger 注释,就不用类注释了 @Data +@Schema(description = "用户 App - 上传文件 Request VO") public class AiChatReqVO { - @Schema(description = "输入内容", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "输入内容不能为空") - private String inputText; + @Schema(description = "提示词", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "提示词不能为空!") + private String prompt; @Schema(description = "AI模型", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "AI模型不能为空") - private AiModelEnum aiModel; + private OpenAiModelEnum aiModel; } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml index 6e3f2b2f1..81d303ab6 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml @@ -149,6 +149,10 @@ + + cn.iocoder.boot + yudao-common + \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java index 62c982095..a8fb9105f 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.ai.chat.*; import cn.iocoder.yudao.framework.ai.chat.messages.MessageType; import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; +import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenApi; import cn.iocoder.yudao.framework.ai.chatyiyan.exception.YiYanApiException; import com.aliyun.broadscope.bailian.sdk.models.*; import lombok.extern.slf4j.Slf4j; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenApi.java similarity index 92% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenApi.java index 77d4411f3..c8170af0f 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenApi.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.chatqianwen; +package cn.iocoder.yudao.framework.ai.chatqianwen.api; import com.aliyun.broadscope.bailian.sdk.AccessTokenClient; import com.aliyun.broadscope.bailian.sdk.ApplicationClient; @@ -9,7 +9,7 @@ import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; import reactor.core.publisher.Flux; -// TODO @fansili:是不是挪到 api 包里?按照 spring ai 的结构;根目录只放 client 和 options +// TODO done @fansili:是不是挪到 api 包里?按照 spring ai 的结构;根目录只放 client 和 options /** * 阿里 通义千问 * diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageApi.java index 0f651ac09..6c5c8dba3 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageApi.java @@ -4,6 +4,7 @@ import cn.hutool.json.JSONUtil; import cn.iocoder.yudao.framework.ai.imageopenai.api.OpenAiImageRequest; import cn.iocoder.yudao.framework.ai.imageopenai.api.OpenAiImageResponse; import cn.iocoder.yudao.framework.ai.util.JacksonUtil; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import io.netty.channel.ChannelOption; import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpEntity; @@ -55,7 +56,7 @@ public class OpenAiImageApi { httpPost.setURI(URI.create(DEFAULT_BASE_URL.concat("/v1/images/generations"))); httpPost.setHeader("Content-Type", "application/json"); httpPost.setHeader("Authorization", "Bearer " + apiKey); - httpPost.setEntity(new StringEntity(JacksonUtil.toJson(request), "UTF-8")); + httpPost.setEntity(new StringEntity(JsonUtils.toJsonString(request), "UTF-8")); CloseableHttpResponse response= null; try { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyMessage.java similarity index 93% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjMessage.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyMessage.java index 2160e8e14..f52ba9337 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MjMessage.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyMessage.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.ai.midjourney; +import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyGennerateStatusEnum; import lombok.Data; import lombok.experimental.Accessors; @@ -7,7 +8,7 @@ import java.util.List; @Data @Accessors(chain = true) -public class MjMessage { +public class MidjourneyMessage { /** * id是一个重要的字段,在同时生成多个的时候,可以区分生成信息 @@ -41,7 +42,7 @@ public class MjMessage { * 1、等待 * 2、进行中 * 3、完成 - * {@link cn.iocoder.yudao.framework.ai.midjourney.constants.MjGennerateStatusEnum} + * {@link MidjourneyGennerateStatusEnum} */ private String generateStatus; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjConstants.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyConstants.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjConstants.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyConstants.java index 751652b08..ee180a0f4 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjConstants.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyConstants.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.framework.ai.midjourney.constants; -public final class MjConstants { +public final class MidjourneyConstants { /** * 消息 - 编号 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyGennerateStatusEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyGennerateStatusEnum.java new file mode 100644 index 000000000..ef7147beb --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyGennerateStatusEnum.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.framework.ai.midjourney.constants; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +// TODO done @fansili:1)Mj 缩写,还是搞成全称。。虽然长一点,但是感觉会相对清晰一些哈;2)lombok 相关的注解,可以用用哈;3)value 改 status; +/** + * mj 生成状态 + * + * author: fansili + * time: 2024/4/6 21:07 + */ +@Getter +@AllArgsConstructor +public enum MidjourneyGennerateStatusEnum { + + WAITING("waiting", "等待..."), + IN_PROGRESS("in_progress", "进行中"), + COMPLETED("completed", "完成"), + + ; + + /** + * 状态 + */ + private String status; + /** + * 状态信息 + */ + private String message; +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjInteractionsEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyInteractionsEnum.java similarity index 81% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjInteractionsEnum.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyInteractionsEnum.java index 124bc8332..08832e78b 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjInteractionsEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyInteractionsEnum.java @@ -6,7 +6,7 @@ import lombok.Getter; * MJ 命令 */ @Getter -public enum MjInteractionsEnum { +public enum MidjourneyInteractionsEnum { IMAGINE("imagine", "生成图片"), DESCRIBE("describe", "生成描述"), @@ -17,7 +17,7 @@ public enum MjInteractionsEnum { ; - MjInteractionsEnum(String value, String message) { + MidjourneyInteractionsEnum(String value, String message) { this.value =value; this.message =message; } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjMessageTypeEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyMessageTypeEnum.java similarity index 76% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjMessageTypeEnum.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyMessageTypeEnum.java index b47199e91..9c8eb9ed5 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjMessageTypeEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyMessageTypeEnum.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.framework.ai.midjourney.constants; -public enum MjMessageTypeEnum { +public enum MidjourneyMessageTypeEnum { /** * 创建. */ @@ -15,7 +15,7 @@ public enum MjMessageTypeEnum { */ DELETE; - public static MjMessageTypeEnum of(String type) { + public static MidjourneyMessageTypeEnum of(String type) { return switch (type) { case "MESSAGE_CREATE" -> CREATE; case "MESSAGE_UPDATE" -> UPDATE; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjNotifyCode.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyNotifyCode.java similarity index 81% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjNotifyCode.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyNotifyCode.java index 103bd6fdf..1dccb8a41 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjNotifyCode.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyNotifyCode.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.framework.ai.midjourney.constants; import lombok.experimental.UtilityClass; @UtilityClass -public final class MjNotifyCode { +public final class MidjourneyNotifyCode { /** * 成功. */ diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjGennerateStatusEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjGennerateStatusEnum.java deleted file mode 100644 index 1e8bc6f53..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjGennerateStatusEnum.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.framework.ai.midjourney.constants; - -import lombok.Getter; - -// TODO @fansili:1)Mj 缩写,还是搞成全称。。虽然长一点,但是感觉会相对清晰一些哈;2)lombok 相关的注解,可以用用哈;3)value 改 status; -/** - * mj 生成状态 - * - * author: fansili - * time: 2024/4/6 21:07 - */ -@Getter -public enum MjGennerateStatusEnum { - - - WAITING("waiting", "等待..."), - IN_PROGRESS("in_progress", "进行中"), - COMPLETED("completed", "完成"), - - ; - - MjGennerateStatusEnum(String value, String message) { - this.value = value; - this.message = message; - } - - private String value; - - private String message; -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MidjourneyInteractions.java similarity index 89% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MidjourneyInteractions.java index f0bd74daa..104e1dd2c 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MidjourneyInteractions.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.framework.ai.midjourney.interactions; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; -import cn.iocoder.yudao.framework.ai.midjourney.constants.MjConstants; -import cn.iocoder.yudao.framework.ai.midjourney.util.MjUtil; +import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyConstants; +import cn.iocoder.yudao.framework.ai.midjourney.util.MidjourneyUtil; import cn.iocoder.yudao.framework.ai.midjourney.vo.Attachments; import cn.iocoder.yudao.framework.ai.midjourney.vo.Describe; import cn.iocoder.yudao.framework.ai.midjourney.vo.ReRoll; @@ -32,15 +32,17 @@ import java.util.HashMap; * time: 2024/4/3 17:36 */ @Slf4j -public class MjInteractions { +public class MidjourneyInteractions { + + // TODO done @fansili:静态变量,放在最前面哈; + private static final String HEADER_REFERER = "https://discord.com/channels/%s/%s"; private final String url; private final MidjourneyConfig midjourneyConfig; private final RestTemplate restTemplate = new RestTemplate(); // TODO @fansili:优先级低:后续搞到统一的管理 - // TODO @fansili:静态变量,放在最前面哈; - private static final String HEADER_REFERER = "https://discord.com/channels/%s/%s"; - public MjInteractions(MidjourneyConfig midjourneyConfig) { + + public MidjourneyInteractions(MidjourneyConfig midjourneyConfig) { this.midjourneyConfig = midjourneyConfig; this.url = midjourneyConfig.getServerUrl().concat(midjourneyConfig.getApiInteractions()); } @@ -57,7 +59,7 @@ public class MjInteractions { requestParams.put("nonce", String.valueOf(IdUtil.getSnowflakeNextId())); // TODO @fansili:建议用 uuid 之类的;nextId 跨进程未必合适哈; requestParams.put("prompt", prompt); // 解析 template 参数占位符 - String requestBody = MjUtil.parseTemplate(requestTemplate, requestParams); + String requestBody = MidjourneyUtil.parseTemplate(requestTemplate, requestParams); // 获取 header HttpHeaders httpHeaders = getHttpHeaders(); // 发送请求 @@ -65,14 +67,14 @@ public class MjInteractions { String res = restTemplate.postForObject(url, requestEntity, String.class); // 这个 res 只要不返回值,就是成功! // TODO @fansili:可以直接 if (StrUtil.isBlank(res)) - boolean isSuccess = StrUtil.isBlank(res); - if (isSuccess) { + if (StrUtil.isBlank(res)) { return true; + } else { + log.error("请求失败! 请求参数:{} 返回结果! {}", requestBody, res); + return false; } - log.error("请求失败! 请求参数:{} 返回结果! {}", requestBody, res); - return isSuccess; } - // TODO @fansili:方法和方法之间,空一行哈; + // TODO done @fansili:方法和方法之间,空一行哈; public Boolean reRoll(ReRoll reRoll) { @@ -89,7 +91,7 @@ public class MjInteractions { // 获取 header HttpHeaders httpHeaders = getHttpHeaders(); // 设置参数 - String requestBody = MjUtil.parseTemplate(requestTemplate, requestParams); + String requestBody = MidjourneyUtil.parseTemplate(requestTemplate, requestParams); // 发送请求 HttpEntity requestEntity = new HttpEntity<>(requestBody, httpHeaders); String res = restTemplate.postForObject(url, requestEntity, String.class); @@ -123,7 +125,7 @@ public class MjInteractions { httpHeaders.setContentType(MediaType.APPLICATION_JSON); httpHeaders.set("Authorization", midjourneyConfig.getToken()); httpHeaders.set("User-Agent", midjourneyConfig.getUserAage()); - httpHeaders.set("Cookie", MjConstants.HTTP_COOKIE); + httpHeaders.set("Cookie", MidjourneyConstants.HTTP_COOKIE); httpHeaders.set("Referer", String.format(HEADER_REFERER, midjourneyConfig.getGuildId(), midjourneyConfig.getChannelId())); // 创建HttpEntity对象,包含表单数据和头部信息 HttpEntity> multiValueMapHttpEntity = new HttpEntity<>(multipartRequest, httpHeaders); @@ -132,16 +134,13 @@ public class MjInteractions { String response = restTemplate.postForObject(midjourneyConfig.getServerUrl().concat(uri), multiValueMapHttpEntity, String.class); UploadAttachmentsRes uploadAttachmentsRes = JSON.parseObject(response, UploadAttachmentsRes.class); - // // 上传文件 String uploadUrl = uploadAttachmentsRes.getAttachments().getFirst().getUploadUrl(); - String uploadAttachmentsUrl = midjourneyConfig.getApiAttachmentsUpload().concat(uploadUrl); httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); HttpEntity fileSystemResourceHttpEntity = new HttpEntity<>(attachments.getFileSystemResource(), httpHeaders); ResponseEntity exchange = restTemplate.exchange(uploadUrl, HttpMethod.PUT, fileSystemResourceHttpEntity, String.class); String uploadRes = exchange.getBody(); - return uploadAttachmentsRes; } @@ -161,9 +160,9 @@ public class MjInteractions { httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); // 设置内容类型为JSON httpHeaders.set("Authorization", midjourneyConfig.getToken()); httpHeaders.set("User-Agent", midjourneyConfig.getUserAage()); - httpHeaders.set("Cookie", MjConstants.HTTP_COOKIE); + httpHeaders.set("Cookie", MidjourneyConstants.HTTP_COOKIE); httpHeaders.set("Referer", String.format(HEADER_REFERER, midjourneyConfig.getGuildId(), midjourneyConfig.getChannelId())); - String requestBody = MjUtil.parseTemplate(requestTemplate, requestParams); + String requestBody = MidjourneyUtil.parseTemplate(requestTemplate, requestParams); // 创建表单数据 MultiValueMap formData = new LinkedMultiValueMap<>(); formData.add("payload_json", requestBody); @@ -185,7 +184,7 @@ public class MjInteractions { httpHeaders.setContentType(MediaType.APPLICATION_JSON); // 设置内容类型为JSON httpHeaders.set("Authorization", midjourneyConfig.getToken()); httpHeaders.set("User-Agent", midjourneyConfig.getUserAage()); - httpHeaders.set("Cookie", MjConstants.HTTP_COOKIE); + httpHeaders.set("Cookie", MidjourneyConstants.HTTP_COOKIE); httpHeaders.set("Referer", String.format(HEADER_REFERER, midjourneyConfig.getGuildId(), midjourneyConfig.getChannelId())); return httpHeaders; } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MidjourneyUtil.java similarity index 91% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MidjourneyUtil.java index 751a79b04..92c7d42e0 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MidjourneyUtil.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.framework.ai.midjourney.util; import cn.hutool.core.text.CharSequenceUtil; -import cn.iocoder.yudao.framework.ai.midjourney.MjMessage; +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyMessage; import java.util.Map; import java.util.regex.Matcher; @@ -13,7 +13,7 @@ import java.util.regex.Pattern; * author: fansili * time: 2024/4/6 19:00 */ -public class MjUtil { +public class MidjourneyUtil { /** * content正则匹配prompt和进度. */ @@ -26,12 +26,12 @@ public class MjUtil { * @param content * @return */ - public static MjMessage.Content parseContent(String content) { + public static MidjourneyMessage.Content parseContent(String content) { // 有三种格式。 // 南极应该是什么样子? // "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (32%) (fast, stealth)", // "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (fast, stealth)" - MjMessage.Content mjContent = new MjMessage.Content(); + MidjourneyMessage.Content mjContent = new MidjourneyMessage.Content(); if (CharSequenceUtil.isBlank(content)) { return null; } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MjWebSocketStarter.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MidjourneyWebSocketStarter.java similarity index 89% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MjWebSocketStarter.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MidjourneyWebSocketStarter.java index b01c4adfe..e7ff41cc5 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MjWebSocketStarter.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MidjourneyWebSocketStarter.java @@ -4,9 +4,9 @@ package cn.iocoder.yudao.framework.ai.midjourney.webSocket; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.thread.ThreadUtil; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; -import cn.iocoder.yudao.framework.ai.midjourney.constants.MjNotifyCode; -import cn.iocoder.yudao.framework.ai.midjourney.webSocket.handler.MjWebSocketHandler; -import cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener.MjMessageListener; +import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyNotifyCode; +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.handler.MidjourneyWebSocketHandler; +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener.MidjourneyMessageListener; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.apache.tomcat.websocket.Constants; @@ -20,11 +20,10 @@ import org.springframework.web.socket.client.standard.StandardWebSocketClient; import java.io.IOException; import java.net.URI; -import java.util.concurrent.TimeoutException; // TODO @fansili:mj 这块 websocket 有点小复杂,虽然代码量 400 多行;感觉可以考虑,有没第三方 sdk,通过它透明接入 mj @Slf4j -public class MjWebSocketStarter implements WebSocketStarter { +public class MidjourneyWebSocketStarter implements WebSocketStarter { /** * 链接重试次数 */ @@ -36,7 +35,7 @@ public class MjWebSocketStarter implements WebSocketStarter { /** * mj 监听(所有message 都会 callback到这里) */ - private final MjMessageListener userMessageListener; + private final MidjourneyMessageListener userMessageListener; /** * wss 服务器 */ @@ -58,10 +57,10 @@ public class MjWebSocketStarter implements WebSocketStarter { */ private WebSocketSession webSocketSession = null; - public MjWebSocketStarter(String wssServer, - String resumeWss, - MidjourneyConfig midjourneyConfig, - MjMessageListener userMessageListener) { + public MidjourneyWebSocketStarter(String wssServer, + String resumeWss, + MidjourneyConfig midjourneyConfig, + MidjourneyMessageListener userMessageListener) { this.wssServer = wssServer; this.resumeWss = resumeWss; this.midjourneyConfig = midjourneyConfig; @@ -83,7 +82,7 @@ public class MjWebSocketStarter implements WebSocketStarter { headers.add("Sec-Websocket-Extensions", "permessage-deflate; client_max_window_bits"); headers.add("User-Agent", this.midjourneyConfig.getUserAage()); // 创建 mjHeader - MjWebSocketHandler mjWebSocketHandler = new MjWebSocketHandler( + MidjourneyWebSocketHandler mjWebSocketHandler = new MidjourneyWebSocketHandler( this.midjourneyConfig, this.userMessageListener, this::onSocketSuccess, this::onSocketFailure); // String gatewayUrl; @@ -105,12 +104,12 @@ public class MjWebSocketStarter implements WebSocketStarter { socketSessionFuture.addCallback(new ListenableFutureCallback<>() { @Override public void onFailure(@NotNull Throwable e) { - onSocketFailure(MjWebSocketHandler.CLOSE_CODE_EXCEPTION, e.getMessage()); + onSocketFailure(MidjourneyWebSocketHandler.CLOSE_CODE_EXCEPTION, e.getMessage()); } @Override public void onSuccess(WebSocketSession session) { - MjWebSocketStarter.this.webSocketSession = session; + MidjourneyWebSocketStarter.this.webSocketSession = session; } }); } @@ -118,7 +117,7 @@ public class MjWebSocketStarter implements WebSocketStarter { private void onSocketSuccess(String sessionId, Object sequence, String resumeGatewayUrl) { this.resumeData = new ResumeData(sessionId, sequence, resumeGatewayUrl); this.running = true; - notifyWssLock(MjNotifyCode.SUCCESS, ""); + notifyWssLock(MidjourneyNotifyCode.SUCCESS, ""); } private void onSocketFailure(int code, String reason) { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/handler/MjWebSocketHandler.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/handler/MidjourneyWebSocketHandler.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/handler/MjWebSocketHandler.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/handler/MidjourneyWebSocketHandler.java index 55fc7e4bc..b6fbf5c21 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/handler/MjWebSocketHandler.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/handler/MidjourneyWebSocketHandler.java @@ -8,7 +8,7 @@ import cn.hutool.http.useragent.UserAgentUtil; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; import cn.iocoder.yudao.framework.ai.midjourney.webSocket.FailureCallback; import cn.iocoder.yudao.framework.ai.midjourney.webSocket.SuccessCallback; -import cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener.MjMessageListener; +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener.MidjourneyMessageListener; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.utils.data.DataArray; @@ -29,7 +29,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @Slf4j -public class MjWebSocketHandler implements WebSocketHandler { +public class MidjourneyWebSocketHandler implements WebSocketHandler { /** * close 错误码:重连 */ @@ -49,7 +49,7 @@ public class MjWebSocketHandler implements WebSocketHandler { /** * mj 消息监听 */ - private final MjMessageListener userMessageListener; + private final MidjourneyMessageListener userMessageListener; /** * 成功回调 */ @@ -85,10 +85,10 @@ public class MjWebSocketHandler implements WebSocketHandler { */ private final Decompressor decompressor = new ZlibDecompressor(2048); - public MjWebSocketHandler(MidjourneyConfig account, - MjMessageListener userMessageListener, - SuccessCallback successCallback, - FailureCallback failureCallback) { + public MidjourneyWebSocketHandler(MidjourneyConfig account, + MidjourneyMessageListener userMessageListener, + SuccessCallback successCallback, + FailureCallback failureCallback) { this.midjourneyConfig = account; this.userMessageListener = userMessageListener; this.successCallback = successCallback; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java new file mode 100644 index 000000000..31bbe0a97 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener; + + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.text.CharSequenceUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyMessage; +import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyConstants; +import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyGennerateStatusEnum; +import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyMessageTypeEnum; +import cn.iocoder.yudao.framework.ai.midjourney.util.MidjourneyUtil; +import com.alibaba.fastjson.JSON; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.utils.data.DataObject; + +import java.util.List; + +@Slf4j +public class MidjourneyMessageListener { + + private MidjourneyConfig midjourneyConfig; + + public MidjourneyMessageListener(MidjourneyConfig midjourneyConfig) { + this.midjourneyConfig = midjourneyConfig; + } + + public void onMessage(DataObject raw) { + MidjourneyMessageTypeEnum messageType = MidjourneyMessageTypeEnum.of(raw.getString("t")); + if (messageType == null || MidjourneyMessageTypeEnum.DELETE == messageType) { + return; + } + DataObject data = raw.getObject("d"); + if (ignoreAndLogMessage(data, messageType)) { + return; + } + + // 转换几个重要的信息 + MidjourneyMessage mjMessage = new MidjourneyMessage(); + mjMessage.setId(data.getString(MidjourneyConstants.MSG_ID)); + mjMessage.setType(data.getInt(MidjourneyConstants.MSG_TYPE)); + mjMessage.setRawData(StrUtil.str(raw.toJson(), "UTF-8")); + mjMessage.setContent(MidjourneyUtil.parseContent(data.getString(MidjourneyConstants.MSG_CONTENT))); + // 转换 components + if (!data.getArray(MidjourneyConstants.MSG_COMPONENTS).isEmpty()) { + String componentsJson = StrUtil.str(data.getArray(MidjourneyConstants.MSG_COMPONENTS).toJson(), "UTF-8"); + List components = JSON.parseArray(componentsJson, MidjourneyMessage.ComponentType.class); + mjMessage.setComponents(components); + } + // 转换附件 + if (!data.getArray(MidjourneyConstants.MSG_ATTACHMENTS).isEmpty()) { + String attachmentsJson = StrUtil.str(data.getArray(MidjourneyConstants.MSG_ATTACHMENTS).toJson(), "UTF-8"); + List attachments = JSON.parseArray(attachmentsJson, MidjourneyMessage.Attachment.class); + mjMessage.setAttachments(attachments); + } + // 转换状态 + convertGenerateStatus(mjMessage); + // + log.info("message 信息 {}", JSONUtil.toJsonPrettyStr(mjMessage)); + System.err.println(JSONUtil.toJsonPrettyStr(mjMessage)); + } + + private void convertGenerateStatus(MidjourneyMessage mjMessage) { + if (mjMessage.getType() == 20 && mjMessage.getContent().getStatus().contains("Waiting")) { + mjMessage.setGenerateStatus(MidjourneyGennerateStatusEnum.WAITING.getValue()); + } else if (mjMessage.getType() == 20 && !StrUtil.isBlank(mjMessage.getContent().getProgress())) { + mjMessage.setGenerateStatus(MidjourneyGennerateStatusEnum.IN_PROGRESS.getValue()); + } else if (mjMessage.getType() == 0 && !CollUtil.isEmpty(mjMessage.getComponents())) { + mjMessage.setGenerateStatus(MidjourneyGennerateStatusEnum.COMPLETED.getValue()); + } + } + + private boolean ignoreAndLogMessage(DataObject data, MidjourneyMessageTypeEnum messageType) { + String channelId = data.getString(MidjourneyConstants.MSG_CHANNEL_ID); + if (!CharSequenceUtil.equals(channelId, midjourneyConfig.getChannelId())) { + return true; + } + String authorName = data.optObject("author").map(a -> a.getString("username")).orElse("System"); + log.debug("{} - {} - {}: {}", midjourneyConfig.getChannelId(), messageType.name(), authorName, data.opt("content").orElse("")); + return false; + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MjMessageListener.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MjMessageListener.java deleted file mode 100644 index 4893e7b37..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MjMessageListener.java +++ /dev/null @@ -1,83 +0,0 @@ -package cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener; - - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.text.CharSequenceUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.json.JSONUtil; -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; -import cn.iocoder.yudao.framework.ai.midjourney.MjMessage; -import cn.iocoder.yudao.framework.ai.midjourney.constants.MjConstants; -import cn.iocoder.yudao.framework.ai.midjourney.constants.MjGennerateStatusEnum; -import cn.iocoder.yudao.framework.ai.midjourney.constants.MjMessageTypeEnum; -import cn.iocoder.yudao.framework.ai.midjourney.util.MjUtil; -import com.alibaba.fastjson.JSON; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.utils.data.DataObject; - -import java.util.List; - -@Slf4j -public class MjMessageListener { - - private MidjourneyConfig midjourneyConfig; - - public MjMessageListener(MidjourneyConfig midjourneyConfig) { - this.midjourneyConfig = midjourneyConfig; - } - - public void onMessage(DataObject raw) { - MjMessageTypeEnum messageType = MjMessageTypeEnum.of(raw.getString("t")); - if (messageType == null || MjMessageTypeEnum.DELETE == messageType) { - return; - } - DataObject data = raw.getObject("d"); - if (ignoreAndLogMessage(data, messageType)) { - return; - } - - // 转换几个重要的信息 - MjMessage mjMessage = new MjMessage(); - mjMessage.setId(data.getString(MjConstants.MSG_ID)); - mjMessage.setType(data.getInt(MjConstants.MSG_TYPE)); - mjMessage.setRawData(StrUtil.str(raw.toJson(), "UTF-8")); - mjMessage.setContent(MjUtil.parseContent(data.getString(MjConstants.MSG_CONTENT))); - // 转换 components - if (!data.getArray(MjConstants.MSG_COMPONENTS).isEmpty()) { - String componentsJson = StrUtil.str(data.getArray(MjConstants.MSG_COMPONENTS).toJson(), "UTF-8"); - List components = JSON.parseArray(componentsJson, MjMessage.ComponentType.class); - mjMessage.setComponents(components); - } - // 转换附件 - if (!data.getArray(MjConstants.MSG_ATTACHMENTS).isEmpty()) { - String attachmentsJson = StrUtil.str(data.getArray(MjConstants.MSG_ATTACHMENTS).toJson(), "UTF-8"); - List attachments = JSON.parseArray(attachmentsJson, MjMessage.Attachment.class); - mjMessage.setAttachments(attachments); - } - // 转换状态 - convertGenerateStatus(mjMessage); - // - log.info("message 信息 {}", JSONUtil.toJsonPrettyStr(mjMessage)); - System.err.println(JSONUtil.toJsonPrettyStr(mjMessage)); - } - - private void convertGenerateStatus(MjMessage mjMessage) { - if (mjMessage.getType() == 20 && mjMessage.getContent().getStatus().contains("Waiting")) { - mjMessage.setGenerateStatus(MjGennerateStatusEnum.WAITING.getValue()); - } else if (mjMessage.getType() == 20 && !StrUtil.isBlank(mjMessage.getContent().getProgress())) { - mjMessage.setGenerateStatus(MjGennerateStatusEnum.IN_PROGRESS.getValue()); - } else if (mjMessage.getType() == 0 && !CollUtil.isEmpty(mjMessage.getComponents())) { - mjMessage.setGenerateStatus(MjGennerateStatusEnum.COMPLETED.getValue()); - } - } - - private boolean ignoreAndLogMessage(DataObject data, MjMessageTypeEnum messageType) { - String channelId = data.getString(MjConstants.MSG_CHANNEL_ID); - if (!CharSequenceUtil.equals(channelId, midjourneyConfig.getChannelId())) { - return true; - } - String authorName = data.optObject("author").map(a -> a.getString("username")).orElse("System"); - log.debug("{} - {} - {}: {}", midjourneyConfig.getChannelId(), messageType.name(), authorName, data.opt("content").orElse("")); - return false; - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/util/JacksonUtil.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/util/JacksonUtil.java deleted file mode 100644 index b5c96c992..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/util/JacksonUtil.java +++ /dev/null @@ -1,80 +0,0 @@ -package cn.iocoder.yudao.framework.ai.util; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.databind.module.SimpleModule; -import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; - -import java.io.IOException; - -// TODO @fansili:看看能不能用 JsonUtils -/** - * Jackson工具类 - * - * author: fansili - * time: 2024/3/17 10:13 - */ -public class JacksonUtil { - - private static final ObjectMapper objectMapper = new ObjectMapper(); - - /** - * 初始化 ObjectMapper 以美化输出(即格式化JSON内容) - */ - static { - // 美化输出(缩进) - objectMapper.enable(SerializationFeature.INDENT_OUTPUT); - // 忽略值为 null 的属性 - objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - // 配置一个模块来将 Long 类型转换为 String 类型 - SimpleModule module = new SimpleModule(); - module.addSerializer(Long.class, ToStringSerializer.instance); - objectMapper.registerModule(module); - } - - /** - * 将对象转换为 JSON 字符串 - * - * @param obj 需要序列化的Java对象 - * @return 序列化后的 JSON 字符串 - * @throws JsonProcessingException 当 JSON 序列化过程中出现错误时抛出异常 - */ - public static String toJson(Object obj) { - try { - return objectMapper.writeValueAsString(obj); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } - - /** - * 将 JSON 字符串反序列化为指定类型的对象 - * - * @param json JSON 字符串 - * @param clazz 目标类型 Class 对象 - * @param 泛型类型参数 - * @return 反序列化后的 Java 对象 - * @throws IOException 当 JSON 解析过程中出现错误时抛出异常 - */ - public static T fromJson(String json, Class clazz) { - try { - return objectMapper.readValue(json, clazz); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } - - /** - * 将对象转换为格式化的 JSON 字符串(已启用 INDENT_OUTPUT 功能,所以所有方法都会返回格式化后的 JSON) - * - * @param obj 需要序列化的Java对象 - * @return 格式化后的 JSON 字符串 - * @throws JsonProcessingException 当 JSON 序列化过程中出现错误时抛出异常 - */ - public static String toFormattedJson(Object obj) { - // 已在类初始化时设置了 SerializationFeature.INDENT_OUTPUT,此处无需额外操作 - return toJson(obj); - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java index 14b839747..0a748667b 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java @@ -1,10 +1,9 @@ package cn.iocoder.yudao.framework.ai.chat; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; -import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenApi; +import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenApi; import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient; import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenOptions; -import com.aliyun.broadscope.bailian.sdk.models.CompletionsRequest; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjInteractionsTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java similarity index 79% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjInteractionsTests.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java index 636e9d2d4..10c9a0923 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjInteractionsTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java @@ -1,8 +1,7 @@ -package cn.iocoder.yudao.framework.ai.mj; +package cn.iocoder.yudao.framework.ai.midjourney; import cn.hutool.core.io.FileUtil; -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; -import cn.iocoder.yudao.framework.ai.midjourney.interactions.MjInteractions; +import cn.iocoder.yudao.framework.ai.midjourney.interactions.MidjourneyInteractions; import cn.iocoder.yudao.framework.ai.midjourney.vo.Attachments; import cn.iocoder.yudao.framework.ai.midjourney.vo.Describe; import cn.iocoder.yudao.framework.ai.midjourney.vo.ReRoll; @@ -23,7 +22,7 @@ import java.util.Map; * author: fansili * time: 2024/4/4 18:59 */ -public class MjInteractionsTests { +public class MidjourneyInteractionsTests { private MidjourneyConfig midjourneyConfig; @Before @@ -39,14 +38,14 @@ public class MjInteractionsTests { @Test public void mjImageTest() { - MjInteractions mjImagineInteractions = new MjInteractions(midjourneyConfig); + MidjourneyInteractions mjImagineInteractions = new MidjourneyInteractions(midjourneyConfig); mjImagineInteractions.imagine("童话里应该是什么样子?"); } @Test public void reRollTest() { - MjInteractions mjImagineInteractions = new MjInteractions(midjourneyConfig); + MidjourneyInteractions mjImagineInteractions = new MidjourneyInteractions(midjourneyConfig); mjImagineInteractions.reRoll(new ReRoll() .setMessageId("1226165117448753243") .setCustomId("MJ::JOB::upsample::3::2aeefbef-43e2-4057-bcf1-43b5f39ab6f7")); @@ -54,7 +53,7 @@ public class MjInteractionsTests { @Test public void uploadAttachmentsTest() { - MjInteractions mjImagineInteractions = new MjInteractions(midjourneyConfig); + MidjourneyInteractions mjImagineInteractions = new MidjourneyInteractions(midjourneyConfig); UploadAttachmentsRes res = mjImagineInteractions.uploadAttachments( new Attachments().setFileSystemResource( new FileSystemResource(new File("/Users/fansili/Downloads/DSC01402.JPG"))) @@ -64,7 +63,7 @@ public class MjInteractionsTests { @Test public void describeTest() { - MjInteractions mjImagineInteractions = new MjInteractions(midjourneyConfig); + MidjourneyInteractions mjImagineInteractions = new MidjourneyInteractions(midjourneyConfig); mjImagineInteractions.describe(new Describe() .setFileName("DSC01402.JPG") .setFinalFileName("16826931-2873-45ec-8cfb-0ad81f1a075f/DSC01402.JPG") diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjUtilTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyUtilTests.java similarity index 58% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjUtilTests.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyUtilTests.java index 521e9b5ab..39d64931f 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjUtilTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyUtilTests.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.framework.ai.mj; +package cn.iocoder.yudao.framework.ai.midjourney; -import cn.iocoder.yudao.framework.ai.midjourney.util.MjUtil; +import cn.iocoder.yudao.framework.ai.midjourney.util.MidjourneyUtil; import org.junit.Test; /** @@ -9,14 +9,14 @@ import org.junit.Test; * author: fansili * time: 2024/4/6 21:57 */ -public class MjUtilTests { +public class MidjourneyUtilTests { @Test public void parseContentTest() { String content1 = "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (32%) (fast, stealth)"; String content2 = "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (fast, stealth)"; - System.err.println(MjUtil.parseContent(content1)); - System.err.println(MjUtil.parseContent(content2)); + System.err.println(MidjourneyUtil.parseContent(content1)); + System.err.println(MidjourneyUtil.parseContent(content2)); } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjWebSocketTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyWebSocketTests.java similarity index 76% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjWebSocketTests.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyWebSocketTests.java index 9076923b4..a0d672873 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjWebSocketTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyWebSocketTests.java @@ -1,9 +1,8 @@ -package cn.iocoder.yudao.framework.ai.mj; +package cn.iocoder.yudao.framework.ai.midjourney; import cn.hutool.core.io.FileUtil; -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; -import cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener.MjMessageListener; -import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MjWebSocketStarter; +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener.MidjourneyMessageListener; +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyWebSocketStarter; import org.junit.Before; import org.junit.Test; @@ -17,7 +16,7 @@ import java.util.Scanner; * author: fansili * time: 2024/4/3 16:40 */ -public class MjWebSocketTests { +public class MidjourneyWebSocketTests { private MidjourneyConfig midjourneyConfig; @@ -35,8 +34,8 @@ public class MjWebSocketTests { @Test public void startSocketTest() { String wssUrl = "wss://gateway.discord.gg"; - var messageListener = new MjMessageListener(midjourneyConfig); - var webSocketStarter = new MjWebSocketStarter(wssUrl, null, midjourneyConfig, messageListener); + var messageListener = new MidjourneyMessageListener(midjourneyConfig); + var webSocketStarter = new MidjourneyWebSocketStarter(wssUrl, null, midjourneyConfig, messageListener); try { webSocketStarter.start(); From 8f2ce2faae8818542bd806cc8a07fdb630381028 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 10 Apr 2024 19:42:29 +0800 Subject: [PATCH 064/684] =?UTF-8?q?=E4=BF=AE=E6=94=B9mj=20message=20type?= =?UTF-8?q?=20=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../webSocket/listener/MidjourneyMessageListener.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java index 31bbe0a97..5e63b079c 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java @@ -63,11 +63,11 @@ public class MidjourneyMessageListener { private void convertGenerateStatus(MidjourneyMessage mjMessage) { if (mjMessage.getType() == 20 && mjMessage.getContent().getStatus().contains("Waiting")) { - mjMessage.setGenerateStatus(MidjourneyGennerateStatusEnum.WAITING.getValue()); + mjMessage.setGenerateStatus(MidjourneyGennerateStatusEnum.WAITING.getStatus()); } else if (mjMessage.getType() == 20 && !StrUtil.isBlank(mjMessage.getContent().getProgress())) { - mjMessage.setGenerateStatus(MidjourneyGennerateStatusEnum.IN_PROGRESS.getValue()); + mjMessage.setGenerateStatus(MidjourneyGennerateStatusEnum.IN_PROGRESS.getStatus()); } else if (mjMessage.getType() == 0 && !CollUtil.isEmpty(mjMessage.getComponents())) { - mjMessage.setGenerateStatus(MidjourneyGennerateStatusEnum.COMPLETED.getValue()); + mjMessage.setGenerateStatus(MidjourneyGennerateStatusEnum.COMPLETED.getStatus()); } } From a9e0bc51e9d051bcf67f22ed6387bda8bb218720 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 10 Apr 2024 19:42:42 +0800 Subject: [PATCH 065/684] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=B2=A1=E7=94=A8?= =?UTF-8?q?=E7=9A=84=20jsonUtils?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iocoder/yudao/framework/ai/imageopenai/OpenAiImageApi.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageApi.java index 6c5c8dba3..efc15a3ba 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageApi.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.framework.ai.imageopenai; import cn.hutool.json.JSONUtil; import cn.iocoder.yudao.framework.ai.imageopenai.api.OpenAiImageRequest; import cn.iocoder.yudao.framework.ai.imageopenai.api.OpenAiImageResponse; -import cn.iocoder.yudao.framework.ai.util.JacksonUtil; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import io.netty.channel.ChannelOption; import lombok.extern.slf4j.Slf4j; @@ -15,7 +14,6 @@ import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.springframework.http.client.reactive.ReactorClientHttpConnector; -import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.WebClient; import reactor.netty.http.client.HttpClient; From 0e277b71e10aee439e31df294620626e4a271f70 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 10 Apr 2024 20:01:05 +0800 Subject: [PATCH 066/684] =?UTF-8?q?=E5=88=A0=E9=99=A4=20spring-ai-bom=20?= =?UTF-8?q?=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 7a3ee3e0a..8924245e9 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -628,16 +628,6 @@ ureport2-console ${ureport2.version} - - - - - org.springframework.ai - spring-ai-bom - ${spring-ai-bom.version} - pom - import - From 03f124a82b5e2a083c06b39ea44be9c0373e3d36 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 10 Apr 2024 20:02:06 +0800 Subject: [PATCH 067/684] =?UTF-8?q?1=E3=80=81=E8=AF=B7=E6=B1=82=E5=85=AC?= =?UTF-8?q?=E5=85=B1=E9=83=A8=E5=88=86=E6=8A=BD=E7=A6=BB=202=E3=80=81?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=BAapi=E5=92=8Cspring=20ai=E7=BB=93?= =?UTF-8?q?=E6=9E=84=E4=BF=9D=E6=8C=81=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/MidjourneyInteractions.java | 83 +++++++++++++++++++ .../MidjourneyInteractionsApi.java} | 80 ++++-------------- 2 files changed, 101 insertions(+), 62 deletions(-) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractions.java rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{interactions/MidjourneyInteractions.java => api/MidjourneyInteractionsApi.java} (59%) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractions.java new file mode 100644 index 000000000..4077912a5 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractions.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.framework.ai.midjourney.api; + +import cn.hutool.core.util.IdUtil; +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; +import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyConstants; +import com.google.common.collect.Maps; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; + +import java.util.HashMap; + +// TODO @fansili:按照 spring ai 的封装习惯,这个类是不是 MidjourneyApi + +/** + * 图片生成 + * + * author: fansili + * time: 2024/4/3 17:36 + */ +@Slf4j +public abstract class MidjourneyInteractions { + + // TODO done @fansili:静态变量,放在最前面哈; + /** + * header - referer 头信息 + */ + private static final String HEADER_REFERER = "https://discord.com/channels/%s/%s"; + /** + * mj配置文件 + */ + protected final MidjourneyConfig midjourneyConfig; + + protected MidjourneyInteractions(MidjourneyConfig midjourneyConfig) { + this.midjourneyConfig = midjourneyConfig; + } + + /** + * 获取headers - application json + * + * @return + */ + protected HttpHeaders getHeadersOfAppJson() { + // 设置header值 + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setContentType(MediaType.APPLICATION_JSON); + httpHeaders.set("Authorization", midjourneyConfig.getToken()); + httpHeaders.set("User-Agent", midjourneyConfig.getUserAage()); + httpHeaders.set("Cookie", MidjourneyConstants.HTTP_COOKIE); + httpHeaders.set("Referer", String.format(HEADER_REFERER, midjourneyConfig.getGuildId(), midjourneyConfig.getChannelId())); + return httpHeaders; + } + + /** + * 获取headers - http form data + * + * @return + */ + protected HttpHeaders getHeadersOfFormData() { + // 设置header值 + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); + httpHeaders.set("Authorization", midjourneyConfig.getToken()); + httpHeaders.set("User-Agent", midjourneyConfig.getUserAage()); + httpHeaders.set("Cookie", MidjourneyConstants.HTTP_COOKIE); + httpHeaders.set("Referer", String.format(HEADER_REFERER, midjourneyConfig.getGuildId(), midjourneyConfig.getChannelId())); + return httpHeaders; + } + + /** + * 获取 - 默认参数 + * @return + */ + protected HashMap getDefaultParams() { + HashMap requestParams = Maps.newHashMap(); + // TODO @fansili:感觉参数的组装,可以搞成一个公用的方法;就是 config + 入参的感觉; + requestParams.put("guild_id", midjourneyConfig.getGuildId()); + requestParams.put("channel_id", midjourneyConfig.getChannelId()); + requestParams.put("session_id", midjourneyConfig.getSessionId()); + requestParams.put("nonce", String.valueOf(IdUtil.getSnowflakeNextId())); // TODO @fansili:建议用 uuid 之类的;nextId 跨进程未必合适哈; + return requestParams; + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MidjourneyInteractions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractionsApi.java similarity index 59% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MidjourneyInteractions.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractionsApi.java index 104e1dd2c..f71a81667 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MidjourneyInteractions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractionsApi.java @@ -1,20 +1,16 @@ -package cn.iocoder.yudao.framework.ai.midjourney.interactions; +package cn.iocoder.yudao.framework.ai.midjourney.api; -import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; -import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyConstants; import cn.iocoder.yudao.framework.ai.midjourney.util.MidjourneyUtil; -import cn.iocoder.yudao.framework.ai.midjourney.vo.Attachments; -import cn.iocoder.yudao.framework.ai.midjourney.vo.Describe; -import cn.iocoder.yudao.framework.ai.midjourney.vo.ReRoll; -import cn.iocoder.yudao.framework.ai.midjourney.vo.UploadAttachmentsRes; +import cn.iocoder.yudao.framework.ai.midjourney.api.req.AttachmentsReq; +import cn.iocoder.yudao.framework.ai.midjourney.api.req.DescribeReq; +import cn.iocoder.yudao.framework.ai.midjourney.api.req.ReRollReq; +import cn.iocoder.yudao.framework.ai.midjourney.api.res.UploadAttachmentsRes; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.google.common.collect.Lists; -import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; -import org.jetbrains.annotations.NotNull; import org.springframework.core.io.FileSystemResource; import org.springframework.http.*; import org.springframework.util.LinkedMultiValueMap; @@ -32,18 +28,13 @@ import java.util.HashMap; * time: 2024/4/3 17:36 */ @Slf4j -public class MidjourneyInteractions { - - // TODO done @fansili:静态变量,放在最前面哈; - private static final String HEADER_REFERER = "https://discord.com/channels/%s/%s"; +public class MidjourneyInteractionsApi extends MidjourneyInteractions { private final String url; - private final MidjourneyConfig midjourneyConfig; private final RestTemplate restTemplate = new RestTemplate(); // TODO @fansili:优先级低:后续搞到统一的管理 - - public MidjourneyInteractions(MidjourneyConfig midjourneyConfig) { - this.midjourneyConfig = midjourneyConfig; + public MidjourneyInteractionsApi(MidjourneyConfig midjourneyConfig) { + super(midjourneyConfig); this.url = midjourneyConfig.getServerUrl().concat(midjourneyConfig.getApiInteractions()); } @@ -51,17 +42,12 @@ public class MidjourneyInteractions { // 获取请求模板 String requestTemplate = midjourneyConfig.getRequestTemplates().get("imagine"); // 设置参数 - HashMap requestParams = Maps.newHashMap(); - // TODO @fansili:感觉参数的组装,可以搞成一个公用的方法;就是 config + 入参的感觉; - requestParams.put("guild_id", midjourneyConfig.getGuildId()); - requestParams.put("channel_id", midjourneyConfig.getChannelId()); - requestParams.put("session_id", midjourneyConfig.getSessionId()); - requestParams.put("nonce", String.valueOf(IdUtil.getSnowflakeNextId())); // TODO @fansili:建议用 uuid 之类的;nextId 跨进程未必合适哈; + HashMap requestParams = getDefaultParams(); requestParams.put("prompt", prompt); // 解析 template 参数占位符 String requestBody = MidjourneyUtil.parseTemplate(requestTemplate, requestParams); // 获取 header - HttpHeaders httpHeaders = getHttpHeaders(); + HttpHeaders httpHeaders = getHeadersOfAppJson(); // 发送请求 HttpEntity requestEntity = new HttpEntity<>(requestBody, httpHeaders); String res = restTemplate.postForObject(url, requestEntity, String.class); @@ -77,19 +63,15 @@ public class MidjourneyInteractions { // TODO done @fansili:方法和方法之间,空一行哈; - public Boolean reRoll(ReRoll reRoll) { + public Boolean reRoll(ReRollReq reRoll) { // 获取请求模板 String requestTemplate = midjourneyConfig.getRequestTemplates().get("reroll"); // 设置参数 - HashMap requestParams = Maps.newHashMap(); - requestParams.put("guild_id", midjourneyConfig.getGuildId()); - requestParams.put("channel_id", midjourneyConfig.getChannelId()); - requestParams.put("session_id", midjourneyConfig.getSessionId()); - requestParams.put("nonce", String.valueOf(IdUtil.getSnowflakeNextId())); + HashMap requestParams = getDefaultParams(); requestParams.put("custom_id", reRoll.getCustomId()); requestParams.put("message_id", reRoll.getMessageId()); // 获取 header - HttpHeaders httpHeaders = getHttpHeaders(); + HttpHeaders httpHeaders = getHeadersOfAppJson(); // 设置参数 String requestBody = MidjourneyUtil.parseTemplate(requestTemplate, requestParams); // 发送请求 @@ -105,7 +87,7 @@ public class MidjourneyInteractions { } // TODO @fansili:搞成私有方法,可能会好点; - public UploadAttachmentsRes uploadAttachments(Attachments attachments) { + public UploadAttachmentsRes uploadAttachments(AttachmentsReq attachments) { // file JSONObject fileObj = new JSONObject(); fileObj.put("id", "0"); @@ -120,13 +102,7 @@ public class MidjourneyInteractions { MultiValueMap multipartRequest = new LinkedMultiValueMap<>(); multipartRequest.put("files", Lists.newArrayList(fileObj)); // 设置header值 - HttpHeaders httpHeaders = new HttpHeaders(); - // TODO @fansili:通用的 header 构建,抽一个方法哈; - httpHeaders.setContentType(MediaType.APPLICATION_JSON); - httpHeaders.set("Authorization", midjourneyConfig.getToken()); - httpHeaders.set("User-Agent", midjourneyConfig.getUserAage()); - httpHeaders.set("Cookie", MidjourneyConstants.HTTP_COOKIE); - httpHeaders.set("Referer", String.format(HEADER_REFERER, midjourneyConfig.getGuildId(), midjourneyConfig.getChannelId())); + HttpHeaders httpHeaders = getHeadersOfAppJson(); // 创建HttpEntity对象,包含表单数据和头部信息 HttpEntity> multiValueMapHttpEntity = new HttpEntity<>(multipartRequest, httpHeaders); // 发送POST请求并接收响应 @@ -144,24 +120,15 @@ public class MidjourneyInteractions { return uploadAttachmentsRes; } - public Boolean describe(Describe describe) { + public Boolean describe(DescribeReq describe) { // 获取请求模板 String requestTemplate = midjourneyConfig.getRequestTemplates().get("describe"); // 设置参数 - HashMap requestParams = Maps.newHashMap(); - requestParams.put("guild_id", midjourneyConfig.getGuildId()); - requestParams.put("channel_id", midjourneyConfig.getChannelId()); - requestParams.put("session_id", midjourneyConfig.getSessionId()); - requestParams.put("nonce", String.valueOf(IdUtil.getSnowflakeNextId())); + HashMap requestParams = getDefaultParams(); requestParams.put("file_name", describe.getFileName()); requestParams.put("final_file_name", describe.getFinalFileName()); // 设置 header - HttpHeaders httpHeaders = new HttpHeaders(); - httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); // 设置内容类型为JSON - httpHeaders.set("Authorization", midjourneyConfig.getToken()); - httpHeaders.set("User-Agent", midjourneyConfig.getUserAage()); - httpHeaders.set("Cookie", MidjourneyConstants.HTTP_COOKIE); - httpHeaders.set("Referer", String.format(HEADER_REFERER, midjourneyConfig.getGuildId(), midjourneyConfig.getChannelId())); + HttpHeaders httpHeaders = getHeadersOfFormData(); String requestBody = MidjourneyUtil.parseTemplate(requestTemplate, requestParams); // 创建表单数据 MultiValueMap formData = new LinkedMultiValueMap<>(); @@ -178,15 +145,4 @@ public class MidjourneyInteractions { return isSuccess; } - @NotNull - private HttpHeaders getHttpHeaders() { - HttpHeaders httpHeaders = new HttpHeaders(); - httpHeaders.setContentType(MediaType.APPLICATION_JSON); // 设置内容类型为JSON - httpHeaders.set("Authorization", midjourneyConfig.getToken()); - httpHeaders.set("User-Agent", midjourneyConfig.getUserAage()); - httpHeaders.set("Cookie", MidjourneyConstants.HTTP_COOKIE); - httpHeaders.set("Referer", String.format(HEADER_REFERER, midjourneyConfig.getGuildId(), midjourneyConfig.getChannelId())); - return httpHeaders; - } - } From 9476a05949bc5039b3bc19b822a58acf84027523 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 10 Apr 2024 20:02:33 +0800 Subject: [PATCH 068/684] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=90=8D=E7=A7=B0?= =?UTF-8?q?=EF=BC=8C=E8=AF=B7=E6=B1=82=E5=A2=9E=E5=8A=A0=20req=20res=20?= =?UTF-8?q?=E5=90=8E=E7=BC=80=EF=BC=8C=E7=A7=BB=E5=8A=A8=E5=88=B0api?= =?UTF-8?q?=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{vo/Attachments.java => api/req/AttachmentsReq.java} | 4 ++-- .../{vo/Describe.java => api/req/DescribeReq.java} | 6 ++---- .../midjourney/{vo/ReRoll.java => api/req/ReRollReq.java} | 4 ++-- .../ai/midjourney/{vo => api/res}/UploadAttachmentsRes.java | 2 +- 4 files changed, 7 insertions(+), 9 deletions(-) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{vo/Attachments.java => api/req/AttachmentsReq.java} (78%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{vo/Describe.java => api/req/DescribeReq.java} (76%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{vo/ReRoll.java => api/req/ReRollReq.java} (82%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/{vo => api/res}/UploadAttachmentsRes.java (91%) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/Attachments.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/req/AttachmentsReq.java similarity index 78% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/Attachments.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/req/AttachmentsReq.java index 133a7031f..ed18a4834 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/Attachments.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/req/AttachmentsReq.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.vo; +package cn.iocoder.yudao.framework.ai.midjourney.api.req; import lombok.Data; import lombok.experimental.Accessors; @@ -12,7 +12,7 @@ import org.springframework.core.io.FileSystemResource; */ @Data @Accessors(chain = true) -public class Attachments { +public class AttachmentsReq { /** * 创建文件系统资源对象 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/Describe.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/req/DescribeReq.java similarity index 76% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/Describe.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/req/DescribeReq.java index 6517f7b86..49a4ab31a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/Describe.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/req/DescribeReq.java @@ -1,10 +1,8 @@ -package cn.iocoder.yudao.framework.ai.midjourney.vo; +package cn.iocoder.yudao.framework.ai.midjourney.api.req; import lombok.Data; import lombok.experimental.Accessors; -import java.io.File; - /** * describe * @@ -13,7 +11,7 @@ import java.io.File; */ @Data @Accessors(chain = true) -public class Describe { +public class DescribeReq { /** * 文件名字 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/ReRoll.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/req/ReRollReq.java similarity index 82% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/ReRoll.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/req/ReRollReq.java index a28517419..0d8368987 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/ReRoll.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/req/ReRollReq.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.vo; +package cn.iocoder.yudao.framework.ai.midjourney.api.req; import lombok.Data; import lombok.experimental.Accessors; @@ -9,7 +9,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class ReRoll { +public class ReRollReq { /** * socket 消息里面收到的 messageId diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/UploadAttachmentsRes.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/res/UploadAttachmentsRes.java similarity index 91% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/UploadAttachmentsRes.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/res/UploadAttachmentsRes.java index b06c1c318..cba21c974 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/UploadAttachmentsRes.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/res/UploadAttachmentsRes.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.vo; +package cn.iocoder.yudao.framework.ai.midjourney.api.res; import lombok.Data; import lombok.experimental.Accessors; From c8a2c8369fdb7bfd992c64b6fbbe2aa83ccede73 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 10 Apr 2024 20:02:50 +0800 Subject: [PATCH 069/684] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MidjourneyInteractionsTests.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java index 10c9a0923..1ed3afc1d 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.framework.ai.midjourney; import cn.hutool.core.io.FileUtil; -import cn.iocoder.yudao.framework.ai.midjourney.interactions.MidjourneyInteractions; -import cn.iocoder.yudao.framework.ai.midjourney.vo.Attachments; -import cn.iocoder.yudao.framework.ai.midjourney.vo.Describe; -import cn.iocoder.yudao.framework.ai.midjourney.vo.ReRoll; -import cn.iocoder.yudao.framework.ai.midjourney.vo.UploadAttachmentsRes; +import cn.iocoder.yudao.framework.ai.midjourney.api.MidjourneyInteractionsApi; +import cn.iocoder.yudao.framework.ai.midjourney.api.req.AttachmentsReq; +import cn.iocoder.yudao.framework.ai.midjourney.api.req.DescribeReq; +import cn.iocoder.yudao.framework.ai.midjourney.api.req.ReRollReq; +import cn.iocoder.yudao.framework.ai.midjourney.api.res.UploadAttachmentsRes; import com.alibaba.fastjson.JSON; import org.junit.Before; import org.junit.Test; @@ -38,24 +38,24 @@ public class MidjourneyInteractionsTests { @Test public void mjImageTest() { - MidjourneyInteractions mjImagineInteractions = new MidjourneyInteractions(midjourneyConfig); + MidjourneyInteractionsApi mjImagineInteractions = new MidjourneyInteractionsApi(midjourneyConfig); mjImagineInteractions.imagine("童话里应该是什么样子?"); } @Test public void reRollTest() { - MidjourneyInteractions mjImagineInteractions = new MidjourneyInteractions(midjourneyConfig); - mjImagineInteractions.reRoll(new ReRoll() + MidjourneyInteractionsApi mjImagineInteractions = new MidjourneyInteractionsApi(midjourneyConfig); + mjImagineInteractions.reRoll(new ReRollReq() .setMessageId("1226165117448753243") .setCustomId("MJ::JOB::upsample::3::2aeefbef-43e2-4057-bcf1-43b5f39ab6f7")); } @Test public void uploadAttachmentsTest() { - MidjourneyInteractions mjImagineInteractions = new MidjourneyInteractions(midjourneyConfig); + MidjourneyInteractionsApi mjImagineInteractions = new MidjourneyInteractionsApi(midjourneyConfig); UploadAttachmentsRes res = mjImagineInteractions.uploadAttachments( - new Attachments().setFileSystemResource( + new AttachmentsReq().setFileSystemResource( new FileSystemResource(new File("/Users/fansili/Downloads/DSC01402.JPG"))) ); System.err.println(JSON.toJSONString(res)); @@ -63,8 +63,8 @@ public class MidjourneyInteractionsTests { @Test public void describeTest() { - MidjourneyInteractions mjImagineInteractions = new MidjourneyInteractions(midjourneyConfig); - mjImagineInteractions.describe(new Describe() + MidjourneyInteractionsApi mjImagineInteractions = new MidjourneyInteractionsApi(midjourneyConfig); + mjImagineInteractions.describe(new DescribeReq() .setFileName("DSC01402.JPG") .setFinalFileName("16826931-2873-45ec-8cfb-0ad81f1a075f/DSC01402.JPG") ); From e1d3e90565bd0e969b0d15e64b52bfb1ca7ee81c Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 11 Apr 2024 20:44:47 +0800 Subject: [PATCH 070/684] job message --- .../requestTestJson/job-message.json | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/job-message.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/job-message.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/job-message.json new file mode 100644 index 000000000..46f77310f --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/job-message.json @@ -0,0 +1,70 @@ +{ + "op": 0, + "s": 10, + "t": "MESSAGE_CREATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [], + "interaction_metadata": { + "user_id": "972721304891453450", + "name": "blend", + "authorizing_integration_owners": { + "0": "1225608134878302329" + }, + "id": "1226901083708723310", + "type": 2 + }, + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 64, + "type": 20, + "mention_roles": [], + "nonce": "1226901080604934144", + "application_id": "936929561302675456", + "edited_timestamp": null, + "content": "", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [], + "interaction": { + "name": "blend", + "id": "1226901083708723310", + "type": 2, + "user": { + "global_name": "tiger", + "avatar_decoration_data": null, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + }, + "position": 0, + "id": "1226901087286591558", + "embeds": [ + { + "content_scan_version": 0, + "color": 16239475, + "footer": { + "text": "/imagine https://cdn.discordapp.com/ephemeral-attachments/1062880104792997970/1226901079514419221/srchttp___c-ssl.duitang.com_uploads_item_202001_20_20200120152231_lncpq.thumb.1000_0.jpgreferhttp___c-ssl.duitang.webp?ex=662673ac&is=6613feac&hm=bf9a400940c747fa869b8e4bf2a38238639b67b4b5e799ce1ef2c1f42bab178f& https://cdn.discordapp.com/ephemeral-attachments/1062880104792997970/1226901080970100736/xiyangyang20151021171455974.png?ex=662673ac&is=6613feac&hm=9c8f42ad2dfb1963a9e424c1942c59568544faed4d38f94b678bfcaa60f47b04& --v 5.2 --s 250" + }, + "description": "You have reached the maximum allowed number of concurrent jobs. Don't worry, this job will start as soon as another one finishes!", + "type": "rich", + "title": "Job queued" + } + ], + "channel_id": "1225608134878302332", + "timestamp": "2024-04-08T14:26:53.929000+00:00" + } +} From 4267686d7b87f55acb6dda827fe5447ef9b2ca45 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 11 Apr 2024 21:50:14 +0800 Subject: [PATCH 071/684] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20message=20DO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/dataobject/AiChatMessage.java | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatMessage.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatMessage.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatMessage.java new file mode 100644 index 000000000..e4968b91b --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatMessage.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.ai.dataobject; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.Date; + +/** + * ai 聊天 message + * + * @fansili + * @since v1.0 + */ +@Data +@Accessors(chain = true) +public class AiChatMessage { + + /** + * 编号,作为每条聊天记录的唯一标识符 + */ + private Long id; + + /** + * 聊天ID,关联到特定的会话或对话 + */ + private Long chatId; + + /** + * 角色ID,用于标识发送消息的用户或系统的身份 + */ + private String userId; + + /** + * 消息具体内容,存储用户的发言或者系统响应的文字信息 + */ + private String message; + + /** + * 消息类型,枚举值可能包括'system'(系统消息)、'user'(用户消息)和'assistant'(助手消息) + */ + private Double messageType; + + /** + * 在生成消息时采用的Top-K采样大小, + * 表示模型生成回复时考虑的候选项集合的大小 + */ + private Double topK; + + /** + * Top-P核采样方法的概率阈值, + * 在语言模型生成过程中控制采样的过滤标准 + */ + private Double topP; + + /** + * 温度参数,用于调整生成回复的随机性和多样性程度, + * 较低的温度值会使输出更收敛于高频词汇,较高的则增加多样性 + */ + private Double temperature; + + /** + * 创建该记录的操作员ID + */ + private Long createdBy; + + /** + * 记录创建的时间戳 + */ + private Date createdTime; + + /** + * 最后更新该记录的操作员ID + */ + private Long updatedBy; + + /** + * 记录最后更新的时间戳 + */ + private Date updatedTime; +} From 632b21991da902275b806aaa5baa99720b211903 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 11 Apr 2024 21:50:25 +0800 Subject: [PATCH 072/684] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20chat=20role=20DO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/dataobject/AiChatRole.java | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatRole.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatRole.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatRole.java new file mode 100644 index 000000000..04ebfe0cf --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatRole.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.ai.dataobject; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * ai 聊天角色 + * + * @fansili + * @since v1.0 + */ +@Data +@Accessors(chain = true) +public class AiChatRole extends BaseDO { + /** + * 编号,表示聊天角色在数据库中的唯一标识符 + */ + private Long id; + + /** + * 用户ID,关联到使用该聊天角色的用户 + */ + private Long userId; + + /** + * 模型编号,关联到角色使用的特定模型 + */ + private String modelId; + + /** + * 角色名,角色的显示名称 + */ + private String roleName; + + /** + * 角色介绍,详细描述角色的功能或用途 + */ + private String roleIntroduce; + + /** + * 角色来源,如 system(系统预置)、customer(用户自定义) + */ + private String roleSource; + + /** + * 分类,角色所属的类别,如娱乐、创作等 + */ + private String classify; + + /** + * 发布状态,0表示仅自己可见,1表示公开,2表示禁用 + */ + private String visibility; + + /** + * 生成时的Top-K采样候选集大小 + */ + private Double topK; + + /** + * 生成时使用的核采样方法的概率阈值 + */ + private Double topP; + + /** + * 用于控制随机性和多样性的温度参数 + */ + private Double temperature; + + /** + * 角色的使用次数统计 + */ + private Integer useCount; + +} From c273da8934fe046b0d1156037ed6bd0316c55243 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 11 Apr 2024 21:50:44 +0800 Subject: [PATCH 073/684] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20chat.sql(=E5=8F=AA?= =?UTF-8?q?=E4=BD=9C=E4=B8=BA=E5=8F=82=E8=80=83=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/chat.sql | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/resources/chat.sql diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/chat.sql b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/chat.sql new file mode 100644 index 000000000..e06f3e9bc --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/chat.sql @@ -0,0 +1,79 @@ +DROP TABLE IF EXISTS chat_role; +CREATE TABLE chat_role( + `id` bigint COMMENT '编号' , + `user_id` bigint COMMENT '用户id' , + `model_id` VARCHAR(255) COMMENT '模型编号' , + `role_name` VARCHAR(32) COMMENT '角色名' , + `role_introduce` VARCHAR(255) COMMENT '介绍' , + `role_source` VARCHAR(32) COMMENT '角色来源(system、customer)' , + `classify` VARCHAR(32) COMMENT '分类(娱乐、创作)' , + `publish` tinyint COMMENT '发布(0、自己可见 1、公开 2、禁用)' , + `top_k` DECIMAL(4,2) COMMENT '生成时,采样候选集的大小' , + `top_p` DECIMAL(24,6) COMMENT '生成时,核采样方法的概率阈值。' , + `temperature` DECIMAL(24,6) COMMENT '用于控制随机性和多样性的程度' , + `use_count` INT COMMENT '使用次数' , + `CREATED_BY` bigint COMMENT '创建人' , + `CREATED_TIME` DATETIME COMMENT '创建时间' , + `UPDATED_BY` bigint COMMENT '更新人' , + `UPDATED_TIME` DATETIME COMMENT '更新时间' +) COMMENT = 'chat角色;'; + +DROP TABLE IF EXISTS chat_history; +CREATE TABLE chat_history( + `id` bigint COMMENT '编号' , + `chat_id` bigint COMMENT '聊天id' , + `user_id` VARCHAR(32) COMMENT '角色名' , + `message` TEXT COMMENT '消息' , + `message_type` DECIMAL(4,2) COMMENT 'system、user、assistant' , + `top_k` DECIMAL(4,2) COMMENT '生成时,采样候选集的大小' , + `top_p` DECIMAL(24,6) COMMENT '生成时,核采样方法的概率阈值。' , + `temperature` DECIMAL(24,6) COMMENT '用于控制随机性和多样性的程度' , + `CREATED_BY` bigint COMMENT '创建人' , + `CREATED_TIME` DATETIME COMMENT '创建时间' , + `UPDATED_BY` bigint COMMENT '更新人' , + `UPDATED_TIME` DATETIME COMMENT '更新时间' +) COMMENT = '聊天记录;'; + +DROP TABLE IF EXISTS user; +CREATE TABLE user( + `id` bigint COMMENT '编号' , + `username` VARCHAR(32) COMMENT '用户名' , + `nickname` VARCHAR(32) COMMENT '昵称' , + `mobile` VARCHAR(32) COMMENT '手机号' , + `avatar_url` VARCHAR(128) COMMENT '头像' , + `password` VARCHAR(32) COMMENT '密码' , + `publish` tinyint COMMENT '发布(0、未发布 1、已发布)' , + `disable` VARCHAR(255) COMMENT '禁用(0、正常 1、禁用)' , + `CREATED_BY` bigint COMMENT '创建人' , + `CREATED_TIME` DATETIME COMMENT '创建时间' , + `UPDATED_BY` bigint COMMENT '更新人' , + `UPDATED_TIME` DATETIME COMMENT '更新时间' +) COMMENT = '用户;'; + +DROP TABLE IF EXISTS chat; +CREATE TABLE chat( + `id` bigint COMMENT '编号' , + `user_id` bigint COMMENT '用户id' , + `chat_role_id` VARCHAR(255) COMMENT '模型id' , + `chat_title` VARCHAR(128) COMMENT '聊天标题' , + `chat_count` INT COMMENT '聊天次数' , + `CREATED_BY` bigint COMMENT '创建人' , + `CREATED_TIME` DATETIME COMMENT '创建时间' , + `UPDATED_BY` bigint COMMENT '更人' , + `UPDATED_TIME` DATETIME COMMENT '更新时间' +) COMMENT = '聊天;'; + +DROP TABLE IF EXISTS chat_model; +CREATE TABLE chat_model( + `id` bigint COMMENT '编号' , + `model_name` bigint COMMENT '模型名字' , + `model_type` VARCHAR(32) COMMENT '模型类型(qianwen、yiyan、xinghuo、openai)' , + `model_config` TEXT(128) COMMENT '模型配置JSON' , + `model_image` VARCHAR(255) COMMENT '模型图片' , + `disable` tinyint COMMENT '禁用 0、正常 1、禁用' , + `CREATED_BY` bigint COMMENT '创建人' , + `CREATED_TIME` DATETIME COMMENT '创建时间' , + `UPDATED_BY` bigint COMMENT '更新人' , + `UPDATED_TIME` DATETIME COMMENT '更新时间' +) COMMENT = '聊天模型;'; + From d494c313025b42d027acc901e8fdd9f7bb3c40a7 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 11 Apr 2024 21:51:09 +0800 Subject: [PATCH 074/684] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20chat.sql(=E5=8F=AA?= =?UTF-8?q?=E4=BD=9C=E4=B8=BA=E5=8F=82=E8=80=83=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-module-ai/yudao-module-ai-biz/pom.xml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/pom.xml b/yudao-module-ai/yudao-module-ai-biz/pom.xml index 0281c9ece..264641296 100644 --- a/yudao-module-ai/yudao-module-ai-biz/pom.xml +++ b/yudao-module-ai/yudao-module-ai-biz/pom.xml @@ -30,15 +30,14 @@ - - org.springframework.ai - spring-ai-openai-spring-boot-starter - - cn.iocoder.boot yudao-spring-boot-starter-security + + cn.iocoder.boot + yudao-spring-boot-starter-mybatis + From 238ef898263c0bb72cea2e0e4c7090bdbfae413e Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 11 Apr 2024 21:51:30 +0800 Subject: [PATCH 075/684] =?UTF-8?q?=E5=AE=9A=E4=B9=89=20message=20?= =?UTF-8?q?=E5=92=8C=20role=20mapper=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/mapper/AiChatMessageMapper.java | 17 +++++++++++++++++ .../module/ai/mapper/AiChatRoleMapper.java | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatRoleMapper.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java new file mode 100644 index 000000000..91526ab79 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.ai.mapper; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.ai.dataobject.AiChatMessage; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Repository; + +/** + * message mapper + * + * @fansili + * @since v1.0 + */ +@Repository +@Mapper +public interface AiChatMessageMapper extends BaseMapperX { +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatRoleMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatRoleMapper.java new file mode 100644 index 000000000..09a662fe7 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatRoleMapper.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.ai.mapper; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.ai.dataobject.AiChatRole; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Repository; + +/** + * role mapper + * + * @fansili + * @since v1.0 + */ +@Repository +@Mapper +public interface AiChatRoleMapper extends BaseMapperX { +} From 1ea94d9245c33e4f21bcbbf8511375836df980df Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 11 Apr 2024 21:51:54 +0800 Subject: [PATCH 076/684] =?UTF-8?q?=E6=B3=A8=E9=87=8A=20chat=20controller?= =?UTF-8?q?=EF=BC=8C=E7=8E=B0=E5=9C=A8=E6=B2=A1=E7=94=A8=E4=BA=86=EF=BC=8C?= =?UTF-8?q?=E9=9C=80=E8=A6=81=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/admin/ChatController.java | 154 +++++++++--------- 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java index e9f8ab6b5..49fae6b62 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java @@ -1,77 +1,77 @@ -package cn.iocoder.yudao.module.ai.controller.admin; - -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.ai.ErrorCodeConstants; -import cn.iocoder.yudao.module.ai.controller.admin.vo.AiChatReqVO; -import cn.iocoder.yudao.module.ai.enums.OpenAiModelEnum; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.ai.chat.ChatClient; -import org.springframework.ai.chat.ChatResponse; -import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.openai.OpenAiChatClient; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import reactor.core.publisher.Flux; - -import java.util.function.Consumer; - -// TODO done @fansili:有了 swagger 注释,就不用类注释了 -@Tag(name = "AI模块") -@RestController -@RequestMapping("/ai-api") -@Slf4j -public class ChatController { - - @Autowired - private ApplicationContext applicationContext; - - @PostMapping("/chat") - @Operation(summary = "对话聊天", description = "简单的ai聊天") - public CommonResult chat(@RequestBody @Validated AiChatReqVO reqVO) { - ChatClient chatClient = getChatClient(reqVO.getAiModel()); - String res; - try { - res = chatClient.call(reqVO.getPrompt()); - } catch (Exception e) { - res = e.getMessage(); - } - return CommonResult.success(res); - } - - @PostMapping("/chatStream") - @Operation(summary = "对话聊天chatStream", description = "简单的ai聊天") - public CommonResult chatStream(HttpServletResponse response, @RequestBody @Validated AiChatReqVO reqVO) throws InterruptedException { - OpenAiChatClient chatClient = applicationContext.getBean(OpenAiChatClient.class); - Flux chatResponse = chatClient.stream(new Prompt(reqVO.getPrompt())); - chatResponse.subscribe(new Consumer() { - @Override - public void accept(ChatResponse chatResponse) { - System.err.println(chatResponse.getResults().get(0).getOutput().getContent()); - } - }); - return CommonResult.success(null); - } - - /** - * 根据 ai模型 获取对于的 模型实现类 - * - * @param aiModelEnum - * @return - */ - private ChatClient getChatClient(OpenAiModelEnum aiModelEnum) { - if (OpenAiModelEnum.OPEN_AI_GPT_3_5 == aiModelEnum) { - return applicationContext.getBean(OpenAiChatClient.class); - } - // AI模型暂不支持 - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODULE_NOT_SUPPORTED); - } -} +//package cn.iocoder.yudao.module.ai.controller.admin; +// +//import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; +//import cn.iocoder.yudao.framework.common.pojo.CommonResult; +//import cn.iocoder.yudao.module.ai.ErrorCodeConstants; +//import cn.iocoder.yudao.module.ai.controller.admin.vo.AiChatReqVO; +//import cn.iocoder.yudao.module.ai.enums.OpenAiModelEnum; +//import io.swagger.v3.oas.annotations.Operation; +//import io.swagger.v3.oas.annotations.tags.Tag; +//import jakarta.servlet.http.HttpServletResponse; +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.ai.chat.ChatClient; +//import org.springframework.ai.chat.ChatResponse; +//import org.springframework.ai.chat.prompt.Prompt; +//import org.springframework.ai.openai.OpenAiChatClient; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.context.ApplicationContext; +//import org.springframework.validation.annotation.Validated; +//import org.springframework.web.bind.annotation.PostMapping; +//import org.springframework.web.bind.annotation.RequestBody; +//import org.springframework.web.bind.annotation.RequestMapping; +//import org.springframework.web.bind.annotation.RestController; +//import reactor.core.publisher.Flux; +// +//import java.util.function.Consumer; +// +//// TODO done @fansili:有了 swagger 注释,就不用类注释了 +//@Tag(name = "AI模块") +//@RestController +//@RequestMapping("/ai-api") +//@Slf4j +//public class ChatController { +// +// @Autowired +// private ApplicationContext applicationContext; +// +// @PostMapping("/chat") +// @Operation(summary = "对话聊天", description = "简单的ai聊天") +// public CommonResult chat(@RequestBody @Validated AiChatReqVO reqVO) { +// ChatClient chatClient = getChatClient(reqVO.getAiModel()); +// String res; +// try { +// res = chatClient.call(reqVO.getPrompt()); +// } catch (Exception e) { +// res = e.getMessage(); +// } +// return CommonResult.success(res); +// } +// +// @PostMapping("/chatStream") +// @Operation(summary = "对话聊天chatStream", description = "简单的ai聊天") +// public CommonResult chatStream(HttpServletResponse response, @RequestBody @Validated AiChatReqVO reqVO) throws InterruptedException { +// OpenAiChatClient chatClient = applicationContext.getBean(OpenAiChatClient.class); +// Flux chatResponse = chatClient.stream(new Prompt(reqVO.getPrompt())); +// chatResponse.subscribe(new Consumer() { +// @Override +// public void accept(ChatResponse chatResponse) { +// System.err.println(chatResponse.getResults().get(0).getOutput().getContent()); +// } +// }); +// return CommonResult.success(null); +// } +// +// /** +// * 根据 ai模型 获取对于的 模型实现类 +// * +// * @param aiModelEnum +// * @return +// */ +// private ChatClient getChatClient(OpenAiModelEnum aiModelEnum) { +// if (OpenAiModelEnum.OPEN_AI_GPT_3_5 == aiModelEnum) { +// return applicationContext.getBean(OpenAiChatClient.class); +// } +// // AI模型暂不支持 +// throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODULE_NOT_SUPPORTED); +// } +//} From 687eef95b64d27a5582d6de4aa7d9febea573233 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 11 Apr 2024 21:52:14 +0800 Subject: [PATCH 077/684] =?UTF-8?q?=E5=AE=9A=E4=B9=89chat=20role=20?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/app/AiChatRoleController.java | 57 +++++++++++++++++++ .../ai/controller/app/vo/ChatRoleAddReq.java | 20 +++++++ .../ai/controller/app/vo/ChatRoleListReq.java | 20 +++++++ .../ai/controller/app/vo/ChatRoleListRes.java | 15 +++++ .../controller/app/vo/ChatRoleUpdateReq.java | 20 +++++++ .../app/vo/ChatRoleUpdateVisibilityReq.java | 20 +++++++ .../module/ai/service/ChatRoleService.java | 52 +++++++++++++++++ .../ai/service/ChatRoleServiceImpl.java | 45 +++++++++++++++ 8 files changed, 249 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/AiChatRoleController.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleAddReq.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleListReq.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleListRes.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleUpdateReq.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleUpdateVisibilityReq.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleServiceImpl.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/AiChatRoleController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/AiChatRoleController.java new file mode 100644 index 000000000..7103e3702 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/AiChatRoleController.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.ai.controller.app; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.ai.controller.app.vo.*; +import cn.iocoder.yudao.module.ai.service.ChatRoleService; +import io.swagger.v3.oas.annotations.Operation; +import lombok.AllArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * ai chat 角色 + * + * @fansili + * @since v1.0 + */ +@RestController +@RequestMapping("/chat-role") +@AllArgsConstructor +public class AiChatRoleController { + + private final ChatRoleService chatRoleService; + + @Operation(summary = "chat角色 - 角色列表") + @GetMapping("/list") + public CommonResult list(@Validated @ModelAttribute ChatRoleListReq req) { + return chatRoleService.list(req); + } + + @Operation(summary = "chat角色 - 添加") + @PutMapping("/add") + public CommonResult add(@Validated @RequestBody ChatRoleAddReq req) { + chatRoleService.add(req); + return CommonResult.success(null); + } + + @Operation(summary = "chat角色 - 修改") + @PostMapping("/update") + public CommonResult update(@Validated @RequestBody ChatRoleUpdateReq req) { + chatRoleService.update(req); + return CommonResult.success(null); + } + + @Operation(summary = "chat角色 - 修改可见性") + @PostMapping("/update-visibility") + public CommonResult updateVisibility(@Validated @RequestBody ChatRoleUpdateVisibilityReq req) { + chatRoleService.updateVisibility(req); + return CommonResult.success(null); + } + + @Operation(summary = "chat角色 - 修改可见性") + @DeleteMapping("/delete") + public CommonResult delete(@RequestParam("chatRoleId") Long chatRoleId) { + chatRoleService.delete(chatRoleId); + return CommonResult.success(null); + } +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleAddReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleAddReq.java new file mode 100644 index 000000000..b3957fafd --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleAddReq.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.ai.controller.app.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * chat 角色列表 + * + * @fansili + * @since v1.0 + */ +@Data +@Accessors(chain = true) +public class ChatRoleAddReq extends PageParam { + + @Schema(description = "查询") + private String search; +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleListReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleListReq.java new file mode 100644 index 000000000..355f00cf6 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleListReq.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.ai.controller.app.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * chat 角色列表 + * + * @fansili + * @since v1.0 + */ +@Data +@Accessors(chain = true) +public class ChatRoleListReq extends PageParam { + + @Schema(description = "查询") + private String search; +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleListRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleListRes.java new file mode 100644 index 000000000..d788e7876 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleListRes.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.ai.controller.app.vo; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * chat 角色列表 + * + * @fansili + * @since v1.0 + */ +@Data +@Accessors(chain = true) +public class ChatRoleListRes { +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleUpdateReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleUpdateReq.java new file mode 100644 index 000000000..f5a894881 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleUpdateReq.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.ai.controller.app.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * chat 角色 - 更新 + * + * @fansili + * @since v1.0 + */ +@Data +@Accessors(chain = true) +public class ChatRoleUpdateReq extends PageParam { + + @Schema(description = "查询") + private String search; +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleUpdateVisibilityReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleUpdateVisibilityReq.java new file mode 100644 index 000000000..bd1836b5e --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleUpdateVisibilityReq.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.ai.controller.app.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * chat 角色 - 修改可见性 + * + * @fansili + * @since v1.0 + */ +@Data +@Accessors(chain = true) +public class ChatRoleUpdateVisibilityReq extends PageParam { + + @Schema(description = "查询") + private String search; +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java new file mode 100644 index 000000000..725ce7779 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.ai.service; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.ai.controller.app.vo.*; + +/** + * chat 角色 + * + * @fansili + * @since v1.0 + */ +public interface ChatRoleService { + + /** + * 获取聊天角色列表 + * + * @param req + * @return + */ + CommonResult list(ChatRoleListReq req); + + /** + * chat角色 - 添加 + * + * @param req + * @return + */ + ChatRoleListRes add(ChatRoleAddReq req); + + /** + * chat角色 - 修改 + * + * @param req + */ + void update(ChatRoleUpdateReq req); + + + /** + * chat角色 - 修改可见性 + * + * @param req + */ + void updateVisibility(ChatRoleUpdateVisibilityReq req); + + /** + * chat角色 - 删除 + * + * @param chatRoleId + */ + void delete(Long chatRoleId); + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleServiceImpl.java new file mode 100644 index 000000000..7b930218a --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleServiceImpl.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.ai.service; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.ai.controller.app.vo.*; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * chat 角色 + * + * @fansili + * @since v1.0 + */ +@Service +@AllArgsConstructor +@Slf4j +public class ChatRoleServiceImpl implements ChatRoleService { + + + @Override + public CommonResult list(ChatRoleListReq req) { + return null; + } + + @Override + public ChatRoleListRes add(ChatRoleAddReq req) { + return null; + } + + @Override + public void update(ChatRoleUpdateReq req) { + + } + + @Override + public void updateVisibility(ChatRoleUpdateVisibilityReq req) { + + } + + @Override + public void delete(Long chatRoleId) { + + } +} From d60cfcd54bc9580d5a7bd663854936c6e2a600f6 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 11 Apr 2024 21:52:32 +0800 Subject: [PATCH 078/684] =?UTF-8?q?=E7=A7=BB=E5=8A=A8=20package=20-=20info?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/iocoder/yudao/module/ai/{ => service}/package-info.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{ => service}/package-info.java (54%) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/package-info.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/package-info.java similarity index 54% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/package-info.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/package-info.java index 6fa1f167a..671d5534f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/package-info.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/package-info.java @@ -2,4 +2,4 @@ * author: fansili * time: 2024/3/3 18:14 */ -package cn.iocoder.yudao.module.ai; \ No newline at end of file +package cn.iocoder.yudao.module.ai.service; \ No newline at end of file From 733c416500f56380015a417d39fe893284d1da83 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 13 Apr 2024 16:00:39 +0800 Subject: [PATCH 079/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20yudao=20ai=20boot?= =?UTF-8?q?=20starter=20=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-module-ai/yudao-module-ai-biz/pom.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/pom.xml b/yudao-module-ai/yudao-module-ai-biz/pom.xml index 264641296..d5e12e512 100644 --- a/yudao-module-ai/yudao-module-ai-biz/pom.xml +++ b/yudao-module-ai/yudao-module-ai-biz/pom.xml @@ -29,14 +29,15 @@ yudao-common - + cn.iocoder.boot - yudao-spring-boot-starter-security + yudao-spring-boot-starter-ai + ${revision} cn.iocoder.boot - yudao-spring-boot-starter-mybatis + yudao-spring-boot-starter-test From ec6ad9da7482ce43227828f1a33a672dabe83c67 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 13 Apr 2024 16:01:42 +0800 Subject: [PATCH 080/684] =?UTF-8?q?api=E7=A7=BB=E5=8A=A8=E5=88=B0api?= =?UTF-8?q?=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/framework/ai/chatxinghuo/{ => api}/XingHuoApi.java | 3 ++- .../yudao/framework/ai/chatyiyan/{ => api}/YiYanApi.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/{ => api}/XingHuoApi.java (98%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/{ => api}/YiYanApi.java (97%) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoApi.java similarity index 98% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoApi.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoApi.java index 323b8a7b7..e2a85779e 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoApi.java @@ -1,7 +1,8 @@ -package cn.iocoder.yudao.framework.ai.chatxinghuo; +package cn.iocoder.yudao.framework.ai.chatxinghuo.api; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONUtil; +import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel; import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletion; import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletionRequest; import lombok.Data; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanApi.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanApi.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanApi.java index d22e8ffc9..ad1059b1a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanApi.java @@ -1,5 +1,6 @@ -package cn.iocoder.yudao.framework.ai.chatyiyan; +package cn.iocoder.yudao.framework.ai.chatyiyan.api; +import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel; import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanAuthRes; import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletion; import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletionRequest; From 17f7970259d3e3456fce1235fbdfaebf64268403 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 13 Apr 2024 16:08:47 +0800 Subject: [PATCH 081/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/config/YudaoAiAutoConfiguration.java | 32 +++++++ .../ai/config/YudaoAiProperties.java | 85 +++++++++++++++++++ ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../src/main/resources/application-local.yaml | 37 ++++++-- 4 files changed, 146 insertions(+), 9 deletions(-) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java new file mode 100644 index 000000000..2725c9a33 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.framework.ai.config; + +import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatClient; +import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoOptions; +import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoApi; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; + +/** + * ai 自动配置 + * + * @author fansili + * @time 2024/4/12 16:29 + * @since 1.0 + */ +@AutoConfiguration +@EnableConfigurationProperties(YudaoAiProperties.class) +public class YudaoAiAutoConfiguration { + + @Bean + public XingHuoChatClient xingHuoChatClient(YudaoAiProperties yudaoAiProperties) { + return new XingHuoChatClient( + new XingHuoApi( + yudaoAiProperties.getXingHuo().getAppId(), + yudaoAiProperties.getXingHuo().getAppKey(), + yudaoAiProperties.getXingHuo().getSecretKey() + ), + new XingHuoOptions().setChatModel(yudaoAiProperties.getXingHuo().getChatModel()) + ); + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java new file mode 100644 index 000000000..2e7bff5c5 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.framework.ai.config; + +import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel; +import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel; +import lombok.Data; +import lombok.experimental.Accessors; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * ai 自动配置 + * + * @author fansili + * @time 2024/4/12 16:29 + * @since 1.0 + */ +@Data +@ConfigurationProperties(prefix = "yudao.ai") +public class YudaoAiProperties { + + private QianWenProperties qianWen; + private XingHuoProperties xingHuo; + private YiYanProperties yiYan; + + @Data + @Accessors(chain = true) + public static class ChatProperties { + + private Float temperature; + + private Float topP; + + private Integer topK; + } + + @Data + @Accessors(chain = true) + public static class QianWenProperties extends ChatProperties { + /** + * 阿里云:服务器接入点 + */ + private String endpoint = "bailian.cn-beijing.aliyuncs.com"; + /** + * 阿里云:权限 accessKeyId + */ + private String accessKeyId; + /** + * 阿里云:权限 accessKeySecret + */ + private String accessKeySecret; + /** + * 阿里云:agentKey(相当于应用id) + */ + private String agentKey; + } + + @Data + @Accessors(chain = true) + public static class XingHuoProperties extends ChatProperties { + private String appId; + private String appKey; + private String secretKey; + private XingHuoChatModel chatModel; + } + + @Data + @Accessors(chain = true) + public static class YiYanProperties extends ChatProperties { + /** + * appKey + */ + private String appKey; + /** + * secretKey + */ + private String secretKey; + /** + * 模型 + */ + private YiYanChatModel chatModel = YiYanChatModel.ERNIE4_3_5_8K; + /** + * token 刷新时间(默认 86400 = 24小时) + */ + private int refreshTokenSecondTime = 86400; + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..6eedc9cc8 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +cn.iocoder.yudao.framework.ai.config.YudaoAiAutoConfiguration diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index cddf42014..59f1d0098 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -54,7 +54,7 @@ spring: # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.master.name} # SQLServer 连接的示例 # url: jdbc:dm://10.211.55.4:5236?schema=RUOYI_VUE_PRO # DM 连接的示例 username: root - password: 123456 + password: root # username: sa # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W # username: SYSDBA # DM 连接的示例 @@ -68,7 +68,7 @@ spring: # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.slave.name} # SQLServer 连接的示例 username: root - password: 123456 + password: root # username: sa # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W @@ -196,12 +196,12 @@ debug: false --- #################### 微信公众号、小程序相关配置 #################### wx: mp: # 公众号配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md 文档 -# app-id: wx041349c6f39b268b # 测试号(牛希尧提供的) -# secret: 5abee519483bc9f8cb37ce280e814bd0 + # app-id: wx041349c6f39b268b # 测试号(牛希尧提供的) + # secret: 5abee519483bc9f8cb37ce280e814bd0 app-id: wx5b23ba7a5589ecbb # 测试号(自己的) secret: 2a7b3b20c537e52e74afd395eb85f61f -# app-id: wxa69ab825b163be19 # 测试号(Kongdy 提供的) -# secret: bd4f9fab889591b62aeac0d7b8d8b4a0 + # app-id: wxa69ab825b163be19 # 测试号(Kongdy 提供的) + # secret: bd4f9fab889591b62aeac0d7b8d8b4a0 # 存储配置,解决 AccessToken 的跨节点的共享 config-storage: type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 @@ -212,8 +212,8 @@ wx: # secret: 333ae72f41552af1e998fe1f54e1584a appid: wx63c280fe3248a3e7 # wenhualian的接口测试号 secret: 6f270509224a7ae1296bbf1c8cb97aed -# appid: wxc4598c446f8a9cb3 # 测试号(Kongdy 提供的) -# secret: 4a1a04e07f6a4a0751b39c3064a92c8b + # appid: wxc4598c446f8a9cb3 # 测试号(Kongdy 提供的) + # secret: 4a1a04e07f6a4a0751b39c3064a92c8b config-storage: type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 key-prefix: wa # Redis Key 的前缀 @@ -223,6 +223,25 @@ wx: # 芋道配置项,设置当前项目所有自定义的配置 yudao: + ai: + temperature: 1 + topP: 1 + topK: 1 + qianWen: + endpoint: bailian.cn-beijing.aliyuncs.com + accessKeyId: LTAI5tNTVhXW4fLKUjMrr98z + accessKeySecret: ZJ0JQeyjzxxm5CfeTV6k1wNE9UsvZP + agentKey: f0c1088824594f589c8f10567ccd929f_p_efm + xingHuo: + appId: 13c8cca6 + appKey: cb6415c19d6162cda07b47316fcb0416 + secretKey: Y2JiYTIxZjA3MDMxMjNjZjQzYzVmNzdh + chatModel: XING_HUO_3_5 + yiYan: + appKey: x0cuLZ7XsaTCU08vuJWO87Lg + secretKey: R9mYF9dl9KASgi5RUq0FQt3wRisSnOcK + refreshTokenSecondTime: 86400 + chatModel: ERNIE4_3_5_8K captcha: enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试; security: @@ -235,6 +254,7 @@ yudao: pay: order-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/order # 支付渠道的【支付】回调地址 refund-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/refund # 支付渠道的【退款】回调地址 + access-log: # 访问日志的配置项 enable: false error-code: # 错误码相关配置项 @@ -267,7 +287,6 @@ justauth: type: REDIS prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE:: timeout: 24h # 超时时长,目前只对 Redis 缓存生效,默认 3 分钟 - # TODO 赤焰:这个配置的目的是? #ureport配置 #ureport: From 1875a49ba39e05740b935061a3b0c96b071d8e15 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 13 Apr 2024 16:09:16 +0800 Subject: [PATCH 082/684] =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D=20modal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/framework/ai/chatxinghuo/XingHuoChatClient.java | 7 ++++--- .../yudao/framework/ai/chatxinghuo/XingHuoOptions.java | 2 +- .../yudao/framework/ai/chat/XingHuoChatClientTests.java | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java index eef59cac0..849a70d75 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java @@ -5,6 +5,7 @@ import cn.hutool.core.exceptions.ExceptionUtil; import cn.iocoder.yudao.framework.ai.chat.*; import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; +import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoApi; import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletion; import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletionRequest; import lombok.extern.slf4j.Slf4j; @@ -69,7 +70,7 @@ public class XingHuoChatClient implements ChatClient, StreamingChatClient { // 创建 request 请求,stream模式需要供应商支持 XingHuoChatCompletionRequest request = this.createRequest(prompt, chatOptions); // 调用 callWithFunctionSupport 发送请求 - ResponseEntity response = xingHuoApi.chatCompletionEntity(request, chatOptions.getDomain()); + ResponseEntity response = xingHuoApi.chatCompletionEntity(request, chatOptions.getChatModel()); // 获取结果封装 ChatResponse return new ChatResponse(List.of(new Generation(response.getBody().getPayload().getChoices().getText().get(0).getContent()))); }); @@ -82,7 +83,7 @@ public class XingHuoChatClient implements ChatClient, StreamingChatClient { // 创建 request 请求,stream模式需要供应商支持 XingHuoChatCompletionRequest request = this.createRequest(prompt, chatOptions); // 发送请求 - Flux response = this.xingHuoApi.chatCompletionStream(request, chatOptions.getDomain()); + Flux response = this.xingHuoApi.chatCompletionStream(request, chatOptions.getChatModel()); return response.map(res -> { String content = res.getPayload().getChoices().getText().stream() .map(item -> item.getContent()).collect(Collectors.joining()); @@ -113,7 +114,7 @@ public class XingHuoChatClient implements ChatClient, StreamingChatClient { // 创建 params XingHuoChatCompletionRequest.Parameter.Chat chatParameter = new XingHuoChatCompletionRequest.Parameter.Chat(); BeanUtil.copyProperties(xingHuoOptions, chatParameter); - chatParameter.setDomain(xingHuoOptions.getDomain().getValue()); + chatParameter.setDomain(xingHuoOptions.getChatModel().getValue()); XingHuoChatCompletionRequest.Parameter parameter = new XingHuoChatCompletionRequest.Parameter().setChat(chatParameter); // 创建 payload text 信息 XingHuoChatCompletionRequest.Payload.Message.Text text = new XingHuoChatCompletionRequest.Payload.Message.Text(); diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoOptions.java index 5c539d491..dd839403e 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoOptions.java @@ -24,7 +24,7 @@ public class XingHuoOptions implements ChatOptions { * generalv3.5指向V3.5版本; * 注意:不同的取值对应的url也不一样! */ - private XingHuoChatModel domain = XingHuoChatModel.XING_HUO_3_5; + private XingHuoChatModel chatModel = XingHuoChatModel.XING_HUO_3_5; /** * 取值范围 (0,1] ,默认值0.5 */ diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java index 4a4b06b81..2340ad9a3 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.framework.ai.chat; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; -import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoApi; import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatClient; import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel; import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoOptions; +import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoApi; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; @@ -31,7 +31,7 @@ public class XingHuoChatClientTests { "cb6415c19d6162cda07b47316fcb0416", "Y2JiYTIxZjA3MDMxMjNjZjQzYzVmNzdh" ), - new XingHuoOptions().setDomain(XingHuoChatModel.XING_HUO_3_5) + new XingHuoOptions().setChatModel(XingHuoChatModel.XING_HUO_3_5) ); } From 02ac6f30cf18cd195b67fe9f69663a760bf68c26 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 13 Apr 2024 16:09:47 +0800 Subject: [PATCH 083/684] =?UTF-8?q?yiyan=20api=E7=A7=BB=E5=8A=A8=E5=88=B0a?= =?UTF-8?q?pi=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java | 1 + .../java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java index c38dae493..c4be256da 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java @@ -4,6 +4,7 @@ import cn.hutool.core.bean.BeanUtil; import cn.iocoder.yudao.framework.ai.chat.*; import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; +import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanApi; import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletion; import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletionRequest; import cn.iocoder.yudao.framework.ai.chatyiyan.exception.YiYanApiException; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java index cff4caa17..326f52552 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.framework.ai.chat; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; -import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanApi; import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatClient; import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel; import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanOptions; +import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanApi; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; From ac0de5d485d5447d8eb8ad062d455b6105c2d3a0 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 13 Apr 2024 18:20:28 +0800 Subject: [PATCH 084/684] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E6=B3=A8=E5=85=A5=EF=BC=8C=E5=8F=AF=E4=BB=A5=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E5=A4=9A=E4=B8=AA=20client?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/admin/ChatController.java | 103 ++++--------- .../controller/admin/OldChatController.java | 77 ++++++++++ .../yudao/framework/ai/AiPlatformEnum.java | 38 +++++ .../ai/config/YudaoAiAutoConfiguration.java | 141 ++++++++++++++++-- .../ai/config/YudaoAiProperties.java | 21 ++- .../framework/ai/exception/AiException.java | 15 ++ .../src/main/resources/application-local.yaml | 16 +- 7 files changed, 320 insertions(+), 91 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/OldChatController.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/exception/AiException.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java index 49fae6b62..8fbc6d9e6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java @@ -1,77 +1,34 @@ -//package cn.iocoder.yudao.module.ai.controller.admin; -// -//import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; -//import cn.iocoder.yudao.framework.common.pojo.CommonResult; -//import cn.iocoder.yudao.module.ai.ErrorCodeConstants; -//import cn.iocoder.yudao.module.ai.controller.admin.vo.AiChatReqVO; -//import cn.iocoder.yudao.module.ai.enums.OpenAiModelEnum; -//import io.swagger.v3.oas.annotations.Operation; -//import io.swagger.v3.oas.annotations.tags.Tag; -//import jakarta.servlet.http.HttpServletResponse; -//import lombok.extern.slf4j.Slf4j; -//import org.springframework.ai.chat.ChatClient; -//import org.springframework.ai.chat.ChatResponse; -//import org.springframework.ai.chat.prompt.Prompt; -//import org.springframework.ai.openai.OpenAiChatClient; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.context.ApplicationContext; -//import org.springframework.validation.annotation.Validated; -//import org.springframework.web.bind.annotation.PostMapping; -//import org.springframework.web.bind.annotation.RequestBody; -//import org.springframework.web.bind.annotation.RequestMapping; -//import org.springframework.web.bind.annotation.RestController; -//import reactor.core.publisher.Flux; -// -//import java.util.function.Consumer; -// -//// TODO done @fansili:有了 swagger 注释,就不用类注释了 -//@Tag(name = "AI模块") -//@RestController -//@RequestMapping("/ai-api") -//@Slf4j -//public class ChatController { +package cn.iocoder.yudao.module.ai.controller.admin; + +import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author fansili + * @since 1.0 + * @time 2024/4/13 17:44 + */ +@Tag(name = "AI模块") +@RestController +@RequestMapping("/ai-api") +@Slf4j +@AllArgsConstructor +public class ChatController { + // // @Autowired -// private ApplicationContext applicationContext; +// private QianWenChatClient qianWenChatClient; // -// @PostMapping("/chat") -// @Operation(summary = "对话聊天", description = "简单的ai聊天") -// public CommonResult chat(@RequestBody @Validated AiChatReqVO reqVO) { -// ChatClient chatClient = getChatClient(reqVO.getAiModel()); -// String res; -// try { -// res = chatClient.call(reqVO.getPrompt()); -// } catch (Exception e) { -// res = e.getMessage(); -// } -// return CommonResult.success(res); +// @GetMapping("/chat") +// public String chat(@RequestParam("prompt") String prompt) { +// return qianWenChatClient.call(prompt); // } -// -// @PostMapping("/chatStream") -// @Operation(summary = "对话聊天chatStream", description = "简单的ai聊天") -// public CommonResult chatStream(HttpServletResponse response, @RequestBody @Validated AiChatReqVO reqVO) throws InterruptedException { -// OpenAiChatClient chatClient = applicationContext.getBean(OpenAiChatClient.class); -// Flux chatResponse = chatClient.stream(new Prompt(reqVO.getPrompt())); -// chatResponse.subscribe(new Consumer() { -// @Override -// public void accept(ChatResponse chatResponse) { -// System.err.println(chatResponse.getResults().get(0).getOutput().getContent()); -// } -// }); -// return CommonResult.success(null); -// } -// -// /** -// * 根据 ai模型 获取对于的 模型实现类 -// * -// * @param aiModelEnum -// * @return -// */ -// private ChatClient getChatClient(OpenAiModelEnum aiModelEnum) { -// if (OpenAiModelEnum.OPEN_AI_GPT_3_5 == aiModelEnum) { -// return applicationContext.getBean(OpenAiChatClient.class); -// } -// // AI模型暂不支持 -// throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODULE_NOT_SUPPORTED); -// } -//} + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/OldChatController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/OldChatController.java new file mode 100644 index 000000000..49fae6b62 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/OldChatController.java @@ -0,0 +1,77 @@ +//package cn.iocoder.yudao.module.ai.controller.admin; +// +//import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; +//import cn.iocoder.yudao.framework.common.pojo.CommonResult; +//import cn.iocoder.yudao.module.ai.ErrorCodeConstants; +//import cn.iocoder.yudao.module.ai.controller.admin.vo.AiChatReqVO; +//import cn.iocoder.yudao.module.ai.enums.OpenAiModelEnum; +//import io.swagger.v3.oas.annotations.Operation; +//import io.swagger.v3.oas.annotations.tags.Tag; +//import jakarta.servlet.http.HttpServletResponse; +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.ai.chat.ChatClient; +//import org.springframework.ai.chat.ChatResponse; +//import org.springframework.ai.chat.prompt.Prompt; +//import org.springframework.ai.openai.OpenAiChatClient; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.context.ApplicationContext; +//import org.springframework.validation.annotation.Validated; +//import org.springframework.web.bind.annotation.PostMapping; +//import org.springframework.web.bind.annotation.RequestBody; +//import org.springframework.web.bind.annotation.RequestMapping; +//import org.springframework.web.bind.annotation.RestController; +//import reactor.core.publisher.Flux; +// +//import java.util.function.Consumer; +// +//// TODO done @fansili:有了 swagger 注释,就不用类注释了 +//@Tag(name = "AI模块") +//@RestController +//@RequestMapping("/ai-api") +//@Slf4j +//public class ChatController { +// +// @Autowired +// private ApplicationContext applicationContext; +// +// @PostMapping("/chat") +// @Operation(summary = "对话聊天", description = "简单的ai聊天") +// public CommonResult chat(@RequestBody @Validated AiChatReqVO reqVO) { +// ChatClient chatClient = getChatClient(reqVO.getAiModel()); +// String res; +// try { +// res = chatClient.call(reqVO.getPrompt()); +// } catch (Exception e) { +// res = e.getMessage(); +// } +// return CommonResult.success(res); +// } +// +// @PostMapping("/chatStream") +// @Operation(summary = "对话聊天chatStream", description = "简单的ai聊天") +// public CommonResult chatStream(HttpServletResponse response, @RequestBody @Validated AiChatReqVO reqVO) throws InterruptedException { +// OpenAiChatClient chatClient = applicationContext.getBean(OpenAiChatClient.class); +// Flux chatResponse = chatClient.stream(new Prompt(reqVO.getPrompt())); +// chatResponse.subscribe(new Consumer() { +// @Override +// public void accept(ChatResponse chatResponse) { +// System.err.println(chatResponse.getResults().get(0).getOutput().getContent()); +// } +// }); +// return CommonResult.success(null); +// } +// +// /** +// * 根据 ai模型 获取对于的 模型实现类 +// * +// * @param aiModelEnum +// * @return +// */ +// private ChatClient getChatClient(OpenAiModelEnum aiModelEnum) { +// if (OpenAiModelEnum.OPEN_AI_GPT_3_5 == aiModelEnum) { +// return applicationContext.getBean(OpenAiChatClient.class); +// } +// // AI模型暂不支持 +// throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODULE_NOT_SUPPORTED); +// } +//} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java new file mode 100644 index 000000000..8a11dac7f --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.framework.ai; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 讯飞星火 模型 + * + * 文档地址:https://www.xfyun.cn/doc/spark/Web.html#_1-%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E + * + * 1tokens 约等于1.5个中文汉字 或者 0.8个英文单词 + * 星火V1.5支持[搜索]内置插件;星火V2.0、V3.0和V3.5支持[搜索]、[天气]、[日期]、[诗词]、[字词]、[股票]六个内置插件 + * 星火V3.5 现已支持system、Function Call 功能。 + * + * author: fansili + * time: 2024/3/11 10:12 + */ +@Getter +@AllArgsConstructor +public enum AiPlatformEnum { + + + YI_YAN("yiyan"), + QIAN_WEN("qianwen"), + XING_HUO("xinghuo"), + + ; + + public static final Map mapValues + = Arrays.stream(values()).collect(Collectors.toMap(AiPlatformEnum::name, o -> o)); + + private String value; + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index 2725c9a33..751b9df06 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -1,11 +1,29 @@ package cn.iocoder.yudao.framework.ai.config; +import cn.hutool.core.bean.BeanUtil; +import cn.iocoder.yudao.framework.ai.AiPlatformEnum; +import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient; +import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenOptions; +import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenApi; import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatClient; import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoOptions; import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoApi; +import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatClient; +import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanOptions; +import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanApi; +import cn.iocoder.yudao.framework.ai.exception.AiException; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Bean; +import org.springframework.context.support.GenericApplicationContext; + +import java.util.Map; /** * ai 自动配置 @@ -18,15 +36,118 @@ import org.springframework.context.annotation.Bean; @EnableConfigurationProperties(YudaoAiProperties.class) public class YudaoAiAutoConfiguration { + // TODO @芋艿:我看sharding jdbc 差不多这么玩的 @Bean - public XingHuoChatClient xingHuoChatClient(YudaoAiProperties yudaoAiProperties) { - return new XingHuoChatClient( - new XingHuoApi( - yudaoAiProperties.getXingHuo().getAppId(), - yudaoAiProperties.getXingHuo().getAppKey(), - yudaoAiProperties.getXingHuo().getSecretKey() - ), - new XingHuoOptions().setChatModel(yudaoAiProperties.getXingHuo().getChatModel()) - ); + @ConditionalOnMissingBean(value = InitChatClient.class) + public InitChatClient initChatClient(YudaoAiProperties yudaoAiProperties) { + return new InitChatClient(yudaoAiProperties); } -} + + public static class InitChatClient implements InitializingBean, ApplicationContextAware { + + private GenericApplicationContext applicationContext; + private YudaoAiProperties yudaoAiProperties; + + public InitChatClient(YudaoAiProperties yudaoAiProperties) { + this.yudaoAiProperties = yudaoAiProperties; + } + + @Override + public void afterPropertiesSet() throws Exception { + for (Map.Entry> properties : yudaoAiProperties.entrySet()) { + String beanName = properties.getKey(); + Map aiPlatformMap = properties.getValue(); + + // 检查平台类型是否正确 + String aiPlatform = String.valueOf(aiPlatformMap.get("aiPlatform")); + if (!AiPlatformEnum.mapValues.containsKey(aiPlatform)) { + throw new AiException("AI平台名称错误! 可以参考 AiPlatformEnum 类!"); + } + // 获取平台类型 + AiPlatformEnum aiPlatformEnum = AiPlatformEnum.mapValues.get(aiPlatform); + // 获取 chat properties + YudaoAiProperties.ChatProperties chatProperties = getChatProperties(aiPlatformEnum, aiPlatformMap); + // 创建客户端 + registerChatClient(applicationContext, chatProperties, beanName); +// applicationContext.refresh(); + + + } + + System.err.println(applicationContext.getBean("qianWen")); + System.err.println(applicationContext.getBean("yiYan")); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = (GenericApplicationContext) applicationContext; + } + } + + private static void registerChatClient(GenericApplicationContext applicationContext, YudaoAiProperties.ChatProperties chatProperties, String beanName) { + ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory(); + Object wrapperBean = null; + if (AiPlatformEnum.XING_HUO == chatProperties.getAiPlatform()) { + YudaoAiProperties.XingHuoProperties xingHuoProperties = (YudaoAiProperties.XingHuoProperties) chatProperties; + wrapperBean = beanFactory.initializeBean( + new XingHuoChatClient( + new XingHuoApi( + xingHuoProperties.getAppId(), + xingHuoProperties.getAppKey(), + xingHuoProperties.getSecretKey() + ), + new XingHuoOptions().setChatModel(xingHuoProperties.getChatModel()) + ), + beanName + ); + } else if (AiPlatformEnum.QIAN_WEN == chatProperties.getAiPlatform()) { + YudaoAiProperties.QianWenProperties qianWenProperties = (YudaoAiProperties.QianWenProperties) chatProperties; + wrapperBean = beanFactory.initializeBean(new QianWenChatClient( + new QianWenApi( + qianWenProperties.getAccessKeyId(), + qianWenProperties.getAccessKeySecret(), + qianWenProperties.getAgentKey(), + qianWenProperties.getEndpoint() + ), + new QianWenOptions() + .setAppId(qianWenProperties.getAppId()) + ), + beanName + ); + } else if (AiPlatformEnum.YI_YAN == chatProperties.getAiPlatform()) { + YudaoAiProperties.YiYanProperties yiYanProperties = (YudaoAiProperties.YiYanProperties) chatProperties; + + wrapperBean = beanFactory.initializeBean(new YiYanChatClient( + new YiYanApi( + yiYanProperties.getAppKey(), + yiYanProperties.getSecretKey(), + yiYanProperties.getChatModel(), + yiYanProperties.getRefreshTokenSecondTime() + ), + new YiYanOptions().setMax_output_tokens(2048)), + beanName + ); + } + if (wrapperBean != null) { + beanFactory.registerSingleton(beanName, wrapperBean); + } + } + + + private static YudaoAiProperties.ChatProperties getChatProperties(AiPlatformEnum aiPlatformEnum, Map aiPlatformMap) { + if (AiPlatformEnum.XING_HUO == aiPlatformEnum) { + YudaoAiProperties.XingHuoProperties xingHuoProperties = new YudaoAiProperties.XingHuoProperties(); + BeanUtil.fillBeanWithMap(aiPlatformMap, xingHuoProperties, true); + return xingHuoProperties; + } else if (AiPlatformEnum.YI_YAN == aiPlatformEnum) { + YudaoAiProperties.YiYanProperties yiYanProperties = new YudaoAiProperties.YiYanProperties(); + BeanUtil.fillBeanWithMap(aiPlatformMap, yiYanProperties, true); + return yiYanProperties; + } else if (AiPlatformEnum.QIAN_WEN == aiPlatformEnum) { + YudaoAiProperties.QianWenProperties qianWenProperties = new YudaoAiProperties.QianWenProperties(); + BeanUtil.fillBeanWithMap(aiPlatformMap, qianWenProperties, true); + return qianWenProperties; + } + throw new AiException("不支持的Ai类型!"); + } +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java index 2e7bff5c5..58d08af3e 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java @@ -1,11 +1,15 @@ package cn.iocoder.yudao.framework.ai.config; +import cn.iocoder.yudao.framework.ai.AiPlatformEnum; import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel; import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel; import lombok.Data; import lombok.experimental.Accessors; import org.springframework.boot.context.properties.ConfigurationProperties; +import java.util.LinkedHashMap; +import java.util.Map; + /** * ai 自动配置 * @@ -15,16 +19,18 @@ import org.springframework.boot.context.properties.ConfigurationProperties; */ @Data @ConfigurationProperties(prefix = "yudao.ai") -public class YudaoAiProperties { +public class YudaoAiProperties extends LinkedHashMap> { - private QianWenProperties qianWen; - private XingHuoProperties xingHuo; - private YiYanProperties yiYan; +// private QianWenProperties qianWen; +// private XingHuoProperties xingHuo; +// private YiYanProperties yiYan; @Data @Accessors(chain = true) public static class ChatProperties { + private AiPlatformEnum aiPlatform; + private Float temperature; private Float topP; @@ -48,9 +54,14 @@ public class YudaoAiProperties { */ private String accessKeySecret; /** - * 阿里云:agentKey(相当于应用id) + * 阿里云:agentKey */ private String agentKey; + /** + * 阿里云:agentKey(相当于应用id) + */ + private String appId; + } @Data diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/exception/AiException.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/exception/AiException.java new file mode 100644 index 000000000..d98b7afc2 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/exception/AiException.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.framework.ai.exception; + +/** + * ai 异常 + * + * @author fansili + * @time 2024/4/13 17:05 + * @since 1.0 + */ +public class AiException extends RuntimeException { + + public AiException(String message) { + super(message); + } +} diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 59f1d0098..fc3f358f1 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -224,20 +224,30 @@ wx: # 芋道配置项,设置当前项目所有自定义的配置 yudao: ai: - temperature: 1 - topP: 1 - topK: 1 qianWen: + aiPlatform: QIAN_WEN + temperature: 1 + topP: 1 + topK: 1 endpoint: bailian.cn-beijing.aliyuncs.com accessKeyId: LTAI5tNTVhXW4fLKUjMrr98z accessKeySecret: ZJ0JQeyjzxxm5CfeTV6k1wNE9UsvZP agentKey: f0c1088824594f589c8f10567ccd929f_p_efm + appId: 5f14955f201a44eb8dbe0c57250a32ce xingHuo: + aiPlatform: XING_HUO + temperature: 1 + topP: 1 + topK: 1 appId: 13c8cca6 appKey: cb6415c19d6162cda07b47316fcb0416 secretKey: Y2JiYTIxZjA3MDMxMjNjZjQzYzVmNzdh chatModel: XING_HUO_3_5 yiYan: + aiPlatform: YI_YAN + temperature: 1 + topP: 1 + topK: 1 appKey: x0cuLZ7XsaTCU08vuJWO87Lg secretKey: R9mYF9dl9KASgi5RUq0FQt3wRisSnOcK refreshTokenSecondTime: 86400 From 98319f68c32ce899bd90cbb6caf36da981297599 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 14 Apr 2024 09:38:29 +0800 Subject: [PATCH 085/684] =?UTF-8?q?1=E3=80=81=E5=A2=9E=E5=8A=A0openapi=20?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=E3=80=81mybatis=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-module-ai/yudao-module-ai-biz/pom.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/pom.xml b/yudao-module-ai/yudao-module-ai-biz/pom.xml index d5e12e512..406c05c14 100644 --- a/yudao-module-ai/yudao-module-ai-biz/pom.xml +++ b/yudao-module-ai/yudao-module-ai-biz/pom.xml @@ -39,7 +39,14 @@ cn.iocoder.boot yudao-spring-boot-starter-test - + + cn.iocoder.boot + yudao-spring-boot-starter-mybatis + + + cn.iocoder.boot + yudao-spring-boot-starter-web + From 3c371dd4db625c22d63ce8cc34ac75162fb5a35a Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 14 Apr 2024 13:37:16 +0800 Subject: [PATCH 086/684] =?UTF-8?q?=E7=A7=BB=E5=8A=A8=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/admin/ChatController.java | 34 ------------------- .../controller/admin/chat/ChatController.java | 34 +++++++++++++++++++ .../app/{ => chat}/vo/ChatRoleAddReq.java | 2 +- .../app/{ => chat}/vo/ChatRoleListReq.java | 2 +- .../app/{ => chat}/vo/ChatRoleListRes.java | 2 +- 5 files changed, 37 insertions(+), 37 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/ChatController.java rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/{ => chat}/vo/ChatRoleAddReq.java (86%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/{ => chat}/vo/ChatRoleListReq.java (86%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/{ => chat}/vo/ChatRoleListRes.java (75%) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java deleted file mode 100644 index 8fbc6d9e6..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/ChatController.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin; - -import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author fansili - * @since 1.0 - * @time 2024/4/13 17:44 - */ -@Tag(name = "AI模块") -@RestController -@RequestMapping("/ai-api") -@Slf4j -@AllArgsConstructor -public class ChatController { - -// -// @Autowired -// private QianWenChatClient qianWenChatClient; -// -// @GetMapping("/chat") -// public String chat(@RequestParam("prompt") String prompt) { -// return qianWenChatClient.call(prompt); -// } - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/ChatController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/ChatController.java new file mode 100644 index 000000000..90710a3dd --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/ChatController.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.ai.controller.admin.chat; + +import cn.iocoder.yudao.framework.ai.chat.ChatResponse; +import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; +import cn.iocoder.yudao.framework.ai.config.AiClient; +import cn.iocoder.yudao.framework.ai.config.YudaoAiClient; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + * @author fansili + * @since 1.0 + * @time 2024/4/13 17:44 + */ +@Tag(name = "AI模块") +@RestController +@RequestMapping("/admin-api/ai") +@Slf4j +@AllArgsConstructor +public class ChatController { + + private final AiClient aiClient; + + @PostMapping("/chat") + public CommonResult chat(@RequestParam("prompt") String prompt) { + ChatResponse callRes = aiClient.call(new Prompt(prompt), "qianWen"); + return CommonResult.success(callRes.getResult().getOutput().getContent()); + } + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleAddReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleAddReq.java similarity index 86% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleAddReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleAddReq.java index b3957fafd..b1c08e286 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleAddReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleAddReq.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.controller.app.vo; +package cn.iocoder.yudao.module.ai.controller.app.chat.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleListReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleListReq.java similarity index 86% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleListReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleListReq.java index 355f00cf6..18f3d46c0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleListReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleListReq.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.controller.app.vo; +package cn.iocoder.yudao.module.ai.controller.app.chat.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleListRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleListRes.java similarity index 75% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleListRes.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleListRes.java index d788e7876..6480296f2 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleListRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleListRes.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.controller.app.vo; +package cn.iocoder.yudao.module.ai.controller.app.chat.vo; import lombok.Data; import lombok.experimental.Accessors; From 652a8f96332c5a59169b5e07ca0a5166dae910aa Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 14 Apr 2024 13:38:31 +0800 Subject: [PATCH 087/684] =?UTF-8?q?=E8=B0=83=E6=95=B4=20chat=20role=20?= =?UTF-8?q?=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/admin/OldChatController.java | 77 ------------------- .../ai/controller/admin/package-info.java | 5 ++ .../app/{ => chat}/vo/ChatRoleUpdateReq.java | 2 +- .../vo/ChatRoleUpdateVisibilityReq.java | 2 +- .../ai/controller/{ => app}/package-info.java | 2 +- 5 files changed, 8 insertions(+), 80 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/OldChatController.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/package-info.java rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/{ => chat}/vo/ChatRoleUpdateReq.java (86%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/{ => chat}/vo/ChatRoleUpdateVisibilityReq.java (87%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/{ => app}/package-info.java (50%) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/OldChatController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/OldChatController.java deleted file mode 100644 index 49fae6b62..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/OldChatController.java +++ /dev/null @@ -1,77 +0,0 @@ -//package cn.iocoder.yudao.module.ai.controller.admin; -// -//import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; -//import cn.iocoder.yudao.framework.common.pojo.CommonResult; -//import cn.iocoder.yudao.module.ai.ErrorCodeConstants; -//import cn.iocoder.yudao.module.ai.controller.admin.vo.AiChatReqVO; -//import cn.iocoder.yudao.module.ai.enums.OpenAiModelEnum; -//import io.swagger.v3.oas.annotations.Operation; -//import io.swagger.v3.oas.annotations.tags.Tag; -//import jakarta.servlet.http.HttpServletResponse; -//import lombok.extern.slf4j.Slf4j; -//import org.springframework.ai.chat.ChatClient; -//import org.springframework.ai.chat.ChatResponse; -//import org.springframework.ai.chat.prompt.Prompt; -//import org.springframework.ai.openai.OpenAiChatClient; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.context.ApplicationContext; -//import org.springframework.validation.annotation.Validated; -//import org.springframework.web.bind.annotation.PostMapping; -//import org.springframework.web.bind.annotation.RequestBody; -//import org.springframework.web.bind.annotation.RequestMapping; -//import org.springframework.web.bind.annotation.RestController; -//import reactor.core.publisher.Flux; -// -//import java.util.function.Consumer; -// -//// TODO done @fansili:有了 swagger 注释,就不用类注释了 -//@Tag(name = "AI模块") -//@RestController -//@RequestMapping("/ai-api") -//@Slf4j -//public class ChatController { -// -// @Autowired -// private ApplicationContext applicationContext; -// -// @PostMapping("/chat") -// @Operation(summary = "对话聊天", description = "简单的ai聊天") -// public CommonResult chat(@RequestBody @Validated AiChatReqVO reqVO) { -// ChatClient chatClient = getChatClient(reqVO.getAiModel()); -// String res; -// try { -// res = chatClient.call(reqVO.getPrompt()); -// } catch (Exception e) { -// res = e.getMessage(); -// } -// return CommonResult.success(res); -// } -// -// @PostMapping("/chatStream") -// @Operation(summary = "对话聊天chatStream", description = "简单的ai聊天") -// public CommonResult chatStream(HttpServletResponse response, @RequestBody @Validated AiChatReqVO reqVO) throws InterruptedException { -// OpenAiChatClient chatClient = applicationContext.getBean(OpenAiChatClient.class); -// Flux chatResponse = chatClient.stream(new Prompt(reqVO.getPrompt())); -// chatResponse.subscribe(new Consumer() { -// @Override -// public void accept(ChatResponse chatResponse) { -// System.err.println(chatResponse.getResults().get(0).getOutput().getContent()); -// } -// }); -// return CommonResult.success(null); -// } -// -// /** -// * 根据 ai模型 获取对于的 模型实现类 -// * -// * @param aiModelEnum -// * @return -// */ -// private ChatClient getChatClient(OpenAiModelEnum aiModelEnum) { -// if (OpenAiModelEnum.OPEN_AI_GPT_3_5 == aiModelEnum) { -// return applicationContext.getBean(OpenAiChatClient.class); -// } -// // AI模型暂不支持 -// throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODULE_NOT_SUPPORTED); -// } -//} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/package-info.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/package-info.java new file mode 100644 index 000000000..81fe7e4bb --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/package-info.java @@ -0,0 +1,5 @@ +/** + * author: fansili + * time: 2024/3/4 13:08 + */ +package cn.iocoder.yudao.module.ai.controller.admin; \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleUpdateReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleUpdateReq.java similarity index 86% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleUpdateReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleUpdateReq.java index f5a894881..0874fd691 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleUpdateReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleUpdateReq.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.controller.app.vo; +package cn.iocoder.yudao.module.ai.controller.app.chat.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleUpdateVisibilityReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleUpdateVisibilityReq.java similarity index 87% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleUpdateVisibilityReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleUpdateVisibilityReq.java index bd1836b5e..fc76b5d4c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/vo/ChatRoleUpdateVisibilityReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleUpdateVisibilityReq.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.controller.app.vo; +package cn.iocoder.yudao.module.ai.controller.app.chat.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/package-info.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/package-info.java similarity index 50% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/package-info.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/package-info.java index f15447172..a7675c99b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/package-info.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/package-info.java @@ -2,4 +2,4 @@ * author: fansili * time: 2024/3/4 13:08 */ -package cn.iocoder.yudao.module.ai.controller; \ No newline at end of file +package cn.iocoder.yudao.module.ai.controller.app; \ No newline at end of file From 97df2755f985fa7d9d92613a3236e4933d0480ad Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 14 Apr 2024 13:39:09 +0800 Subject: [PATCH 088/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0yudao=20ai=20client?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/chatqianwen/QianWenChatClient.java | 2 + .../yudao/framework/ai/config/AiClient.java | 19 +++ .../ai/config/YudaoAiAutoConfiguration.java | 112 ++++++++---------- .../framework/ai/config/YudaoAiClient.java | 44 +++++++ 4 files changed, 117 insertions(+), 60 deletions(-) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/AiClient.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiClient.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java index a8fb9105f..7bab37586 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java @@ -36,6 +36,8 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient { private QianWenOptions qianWenOptions; + + public QianWenChatClient() {} public QianWenChatClient(QianWenApi qianWenApi) { this.qianWenApi = qianWenApi; } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/AiClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/AiClient.java new file mode 100644 index 000000000..f976dcfbf --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/AiClient.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.framework.ai.config; + +import cn.iocoder.yudao.framework.ai.chat.ChatResponse; +import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; +import reactor.core.publisher.Flux; + +/** + * ai client传入 + * + * @author fansili + * @time 2024/4/14 10:27 + * @since 1.0 + */ +public interface AiClient { + + ChatResponse call(Prompt prompt, String clientName); + + Flux stream(Prompt prompt, String clientName); +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index 751b9df06..7e734cd2a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -14,7 +14,6 @@ import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanApi; import cn.iocoder.yudao.framework.ai.exception.AiException; import org.springframework.beans.BeansException; import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -23,6 +22,7 @@ import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Bean; import org.springframework.context.support.GenericApplicationContext; +import java.util.HashMap; import java.util.Map; /** @@ -36,11 +36,33 @@ import java.util.Map; @EnableConfigurationProperties(YudaoAiProperties.class) public class YudaoAiAutoConfiguration { - // TODO @芋艿:我看sharding jdbc 差不多这么玩的 @Bean - @ConditionalOnMissingBean(value = InitChatClient.class) - public InitChatClient initChatClient(YudaoAiProperties yudaoAiProperties) { - return new InitChatClient(yudaoAiProperties); + @ConditionalOnMissingBean(value = AiClient.class) + public AiClient aiClient(YudaoAiProperties yudaoAiProperties) { + Map chatClientMap = buildChatClientMap(yudaoAiProperties); + return new YudaoAiClient(chatClientMap); + } + + public Map buildChatClientMap(YudaoAiProperties yudaoAiProperties) { + Map chatMap = new HashMap<>(); + for (Map.Entry> properties : yudaoAiProperties.entrySet()) { + String beanName = properties.getKey(); + Map aiPlatformMap = properties.getValue(); + + // 检查平台类型是否正确 + String aiPlatform = String.valueOf(aiPlatformMap.get("aiPlatform")); + if (!AiPlatformEnum.mapValues.containsKey(aiPlatform)) { + throw new AiException("AI平台名称错误! 可以参考 AiPlatformEnum 类!"); + } + // 获取平台类型 + AiPlatformEnum aiPlatformEnum = AiPlatformEnum.mapValues.get(aiPlatform); + // 获取 chat properties + YudaoAiProperties.ChatProperties chatProperties = getChatProperties(aiPlatformEnum, aiPlatformMap); + // 创建客户端 + Object chatClient = createChatClient(chatProperties); + chatMap.put(beanName, chatClient); + } + return chatMap; } public static class InitChatClient implements InitializingBean, ApplicationContextAware { @@ -53,26 +75,8 @@ public class YudaoAiAutoConfiguration { } @Override - public void afterPropertiesSet() throws Exception { - for (Map.Entry> properties : yudaoAiProperties.entrySet()) { - String beanName = properties.getKey(); - Map aiPlatformMap = properties.getValue(); + public void afterPropertiesSet() { - // 检查平台类型是否正确 - String aiPlatform = String.valueOf(aiPlatformMap.get("aiPlatform")); - if (!AiPlatformEnum.mapValues.containsKey(aiPlatform)) { - throw new AiException("AI平台名称错误! 可以参考 AiPlatformEnum 类!"); - } - // 获取平台类型 - AiPlatformEnum aiPlatformEnum = AiPlatformEnum.mapValues.get(aiPlatform); - // 获取 chat properties - YudaoAiProperties.ChatProperties chatProperties = getChatProperties(aiPlatformEnum, aiPlatformMap); - // 创建客户端 - registerChatClient(applicationContext, chatProperties, beanName); -// applicationContext.refresh(); - - - } System.err.println(applicationContext.getBean("qianWen")); System.err.println(applicationContext.getBean("yiYan")); @@ -84,53 +88,41 @@ public class YudaoAiAutoConfiguration { } } - private static void registerChatClient(GenericApplicationContext applicationContext, YudaoAiProperties.ChatProperties chatProperties, String beanName) { - ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory(); - Object wrapperBean = null; + private static Object createChatClient(YudaoAiProperties.ChatProperties chatProperties) { if (AiPlatformEnum.XING_HUO == chatProperties.getAiPlatform()) { YudaoAiProperties.XingHuoProperties xingHuoProperties = (YudaoAiProperties.XingHuoProperties) chatProperties; - wrapperBean = beanFactory.initializeBean( - new XingHuoChatClient( - new XingHuoApi( - xingHuoProperties.getAppId(), - xingHuoProperties.getAppKey(), - xingHuoProperties.getSecretKey() - ), - new XingHuoOptions().setChatModel(xingHuoProperties.getChatModel()) + return new XingHuoChatClient( + new XingHuoApi( + xingHuoProperties.getAppId(), + xingHuoProperties.getAppKey(), + xingHuoProperties.getSecretKey() ), - beanName + new XingHuoOptions().setChatModel(xingHuoProperties.getChatModel()) ); } else if (AiPlatformEnum.QIAN_WEN == chatProperties.getAiPlatform()) { YudaoAiProperties.QianWenProperties qianWenProperties = (YudaoAiProperties.QianWenProperties) chatProperties; - wrapperBean = beanFactory.initializeBean(new QianWenChatClient( - new QianWenApi( - qianWenProperties.getAccessKeyId(), - qianWenProperties.getAccessKeySecret(), - qianWenProperties.getAgentKey(), - qianWenProperties.getEndpoint() - ), - new QianWenOptions() - .setAppId(qianWenProperties.getAppId()) + return new QianWenChatClient( + new QianWenApi( + qianWenProperties.getAccessKeyId(), + qianWenProperties.getAccessKeySecret(), + qianWenProperties.getAgentKey(), + qianWenProperties.getEndpoint() ), - beanName + new QianWenOptions() + .setAppId(qianWenProperties.getAppId()) ); } else if (AiPlatformEnum.YI_YAN == chatProperties.getAiPlatform()) { YudaoAiProperties.YiYanProperties yiYanProperties = (YudaoAiProperties.YiYanProperties) chatProperties; - - wrapperBean = beanFactory.initializeBean(new YiYanChatClient( - new YiYanApi( - yiYanProperties.getAppKey(), - yiYanProperties.getSecretKey(), - yiYanProperties.getChatModel(), - yiYanProperties.getRefreshTokenSecondTime() - ), - new YiYanOptions().setMax_output_tokens(2048)), - beanName - ); - } - if (wrapperBean != null) { - beanFactory.registerSingleton(beanName, wrapperBean); + return new YiYanChatClient( + new YiYanApi( + yiYanProperties.getAppKey(), + yiYanProperties.getSecretKey(), + yiYanProperties.getChatModel(), + yiYanProperties.getRefreshTokenSecondTime() + ), + new YiYanOptions().setMax_output_tokens(2048)); } + throw new AiException("不支持的Ai类型!"); } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiClient.java new file mode 100644 index 000000000..2f584c40a --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiClient.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.framework.ai.config; + +import cn.iocoder.yudao.framework.ai.chat.ChatClient; +import cn.iocoder.yudao.framework.ai.chat.ChatResponse; +import cn.iocoder.yudao.framework.ai.chat.StreamingChatClient; +import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; +import cn.iocoder.yudao.framework.ai.exception.AiException; +import reactor.core.publisher.Flux; + +import java.util.Map; + +/** + * yudao ai client + * + * @author fansili + * @time 2024/4/14 10:27 + * @since 1.0 + */ +public class YudaoAiClient implements AiClient{ + + protected Map chatClientMap; + + public YudaoAiClient(Map chatClientMap) { + this.chatClientMap = chatClientMap; + } + + @Override + public ChatResponse call(Prompt prompt, String clientName) { + if (!chatClientMap.containsKey(clientName)) { + throw new AiException("clientName不存在!"); + } + ChatClient chatClient = (ChatClient) chatClientMap.get(clientName); + return chatClient.call(prompt); + } + + @Override + public Flux stream(Prompt prompt, String clientName) { + if (!chatClientMap.containsKey(clientName)) { + throw new AiException("clientName不存在!"); + } + StreamingChatClient streamingChatClient = (StreamingChatClient) chatClientMap.get(clientName); + return streamingChatClient.stream(prompt); + } +} From 239bc21f02809f33787163e63eb6d472a605bd39 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 14 Apr 2024 13:39:37 +0800 Subject: [PATCH 089/684] =?UTF-8?q?=E8=B0=83=E6=95=B4=20chat=20role=20?= =?UTF-8?q?=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/controller/admin/{ => chat}/vo/AiChatReqVO.java | 2 +- .../ai/controller/app/{ => chat}/AiChatRoleController.java | 3 ++- .../cn/iocoder/yudao/module/ai/service/ChatRoleService.java | 1 + .../iocoder/yudao/module/ai/service/ChatRoleServiceImpl.java | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/{ => chat}/vo/AiChatReqVO.java (92%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/{ => chat}/AiChatRoleController.java (94%) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/vo/AiChatReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/AiChatReqVO.java similarity index 92% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/vo/AiChatReqVO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/AiChatReqVO.java index 643b6600d..881982a57 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/vo/AiChatReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/AiChatReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.controller.admin.vo; +package cn.iocoder.yudao.module.ai.controller.admin.chat.vo; import cn.iocoder.yudao.module.ai.enums.OpenAiModelEnum; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/AiChatRoleController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/AiChatRoleController.java similarity index 94% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/AiChatRoleController.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/AiChatRoleController.java index 7103e3702..e59ae9b5d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/AiChatRoleController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/AiChatRoleController.java @@ -1,6 +1,7 @@ -package cn.iocoder.yudao.module.ai.controller.app; +package cn.iocoder.yudao.module.ai.controller.app.chat; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.ai.controller.app.chat.vo.*; import cn.iocoder.yudao.module.ai.controller.app.vo.*; import cn.iocoder.yudao.module.ai.service.ChatRoleService; import io.swagger.v3.oas.annotations.Operation; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java index 725ce7779..ac922939c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.ai.controller.app.chat.vo.*; import cn.iocoder.yudao.module.ai.controller.app.vo.*; /** diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleServiceImpl.java index 7b930218a..c386fb468 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.ai.controller.app.chat.vo.*; import cn.iocoder.yudao.module.ai.controller.app.vo.*; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; From 330faf7b97b831ac7a1a3589a2f94cdfefb0963b Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 14 Apr 2024 13:40:14 +0800 Subject: [PATCH 090/684] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=B2=A1=E7=94=A8?= =?UTF-8?q?=E7=9A=84package?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/controller/app/chat/AiChatRoleController.java | 1 - .../java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java | 1 - .../cn/iocoder/yudao/module/ai/service/ChatRoleServiceImpl.java | 1 - 3 files changed, 3 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/AiChatRoleController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/AiChatRoleController.java index e59ae9b5d..785abdc12 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/AiChatRoleController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/AiChatRoleController.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.ai.controller.app.chat; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.ai.controller.app.chat.vo.*; -import cn.iocoder.yudao.module.ai.controller.app.vo.*; import cn.iocoder.yudao.module.ai.service.ChatRoleService; import io.swagger.v3.oas.annotations.Operation; import lombok.AllArgsConstructor; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java index ac922939c..e91429715 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.ai.controller.app.chat.vo.*; -import cn.iocoder.yudao.module.ai.controller.app.vo.*; /** * chat 角色 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleServiceImpl.java index c386fb468..dc839c4b3 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleServiceImpl.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.ai.controller.app.chat.vo.*; -import cn.iocoder.yudao.module.ai.controller.app.vo.*; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; From 73f334e2b4a64a8de7782e3fbb87a9b58b5d690c Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 14 Apr 2024 13:40:42 +0800 Subject: [PATCH 091/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-module-ai/yudao-module-ai-biz/pom.xml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/pom.xml b/yudao-module-ai/yudao-module-ai-biz/pom.xml index 406c05c14..cb13949c0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/pom.xml +++ b/yudao-module-ai/yudao-module-ai-biz/pom.xml @@ -24,28 +24,28 @@ yudao-module-ai-api ${revision} - - cn.iocoder.boot - yudao-common - - - cn.iocoder.boot yudao-spring-boot-starter-ai ${revision} + cn.iocoder.boot - yudao-spring-boot-starter-test + yudao-common + + + cn.iocoder.boot + yudao-spring-boot-starter-web cn.iocoder.boot yudao-spring-boot-starter-mybatis + cn.iocoder.boot - yudao-spring-boot-starter-web + yudao-spring-boot-starter-test From 8b310c1dcef593d4ddd6fff0a3de00dea465484c Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 14 Apr 2024 13:40:54 +0800 Subject: [PATCH 092/684] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20chat=20http?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/http/chat.http | 39 +++++++++++++++++++ .../main/resources/http/http-client.env.json | 6 +++ 2 files changed, 45 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http new file mode 100644 index 000000000..03c829b85 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http @@ -0,0 +1,39 @@ + + +### 登录 + +POST {{baseUrl}}/admin-api/system/auth/login +Content-Type: application/json +tenant-id: 1 + +{ + "username": "admin", + "password": "123456", + "captchaVerification": "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==", + "socialCode": "1024", + "socialState": "9b2ffbc1-7425-4155-9894-9d5c08541d62", + "socialCodeValid": true +} + +### chat call +POST {{baseUrl}}/admin-api/ai/chat?prompt=中国怎么样 +tenant-id: 1 +Authorization: {{token}} + + +### chat call +POST {{baseUrl}}/ai-api/chat +tenant-id: 1 +Authorization: {{token}} + + +### chat call +GET {{baseUrl}}/chat-role/list +tenant-id: 1 +Authorization: {{token}} + + + + + + diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json new file mode 100644 index 000000000..5fd488f50 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json @@ -0,0 +1,6 @@ +{ + "dev": { + "baseUrl": "http://127.0.0.1:48080", + "token": "Bearer 07390ff2824a4798bcfd7f9395092181" + } +} \ No newline at end of file From 4b5910f97272fdeea053fddfa795eb9e00d17d14 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 14 Apr 2024 15:51:57 +0800 Subject: [PATCH 093/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20Utf8SseEmitter=20?= =?UTF-8?q?=E5=A4=84=E7=90=86=20=E4=B8=AD=E6=96=87=E4=B9=B1=E7=A0=81?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/controller/Utf8SseEmitter.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/Utf8SseEmitter.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/Utf8SseEmitter.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/Utf8SseEmitter.java new file mode 100644 index 000000000..d23f4e9b1 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/Utf8SseEmitter.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.ai.controller; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; + +import java.nio.charset.StandardCharsets; + +/** + * 解决中文乱码 + * + * @author fansili + * @time 2024/4/14 15:13 + * @since 1.0 + */ +public class Utf8SseEmitter extends SseEmitter { + + @Override + protected void extendResponse(ServerHttpResponse outputMessage) { + super.extendResponse(outputMessage); + + HttpHeaders headers = outputMessage.getHeaders(); + headers.setContentType(new MediaType(MediaType.TEXT_EVENT_STREAM, StandardCharsets.UTF_8)); + } +} From a3530555ca82d259fc4cde2f84ece4467a39553f Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 14 Apr 2024 15:52:35 +0800 Subject: [PATCH 094/684] =?UTF-8?q?1=E3=80=81=E5=A2=9E=E5=8A=A0=20chat=20?= =?UTF-8?q?=E5=92=8C=20chatStream?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{app/chat => }/AiChatRoleController.java | 4 +- .../module/ai/controller/ChatController.java | 76 +++++++++++++++++++ .../controller/admin/chat/ChatController.java | 34 --------- .../ai/controller/admin/package-info.java | 5 -- .../ai/controller/app/package-info.java | 5 -- .../module/ai/service/ChatRoleService.java | 2 +- .../{ => impl}/ChatRoleServiceImpl.java | 5 +- .../yudao/module/ai/service/package-info.java | 5 -- .../admin/chat => }/vo/AiChatReqVO.java | 2 +- .../app/chat => }/vo/ChatRoleAddReq.java | 2 +- .../app/chat => }/vo/ChatRoleListReq.java | 2 +- .../app/chat => }/vo/ChatRoleListRes.java | 2 +- .../app/chat => }/vo/ChatRoleUpdateReq.java | 2 +- .../vo/ChatRoleUpdateVisibilityReq.java | 2 +- .../src/main/resources/http/chat.http | 13 +--- .../main/resources/http/http-client.env.json | 2 +- .../ai/chatyiyan/YiYanChatClient.java | 6 ++ 17 files changed, 98 insertions(+), 71 deletions(-) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/{app/chat => }/AiChatRoleController.java (93%) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/ChatController.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/package-info.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/package-info.java rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/{ => impl}/ChatRoleServiceImpl.java (83%) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/package-info.java rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{controller/admin/chat => }/vo/AiChatReqVO.java (92%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{controller/app/chat => }/vo/ChatRoleAddReq.java (86%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{controller/app/chat => }/vo/ChatRoleListReq.java (86%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{controller/app/chat => }/vo/ChatRoleListRes.java (75%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{controller/app/chat => }/vo/ChatRoleUpdateReq.java (86%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{controller/app/chat => }/vo/ChatRoleUpdateVisibilityReq.java (87%) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/AiChatRoleController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatRoleController.java similarity index 93% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/AiChatRoleController.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatRoleController.java index 785abdc12..543754e91 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/AiChatRoleController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatRoleController.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.module.ai.controller.app.chat; +package cn.iocoder.yudao.module.ai.controller; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.ai.controller.app.chat.vo.*; import cn.iocoder.yudao.module.ai.service.ChatRoleService; +import cn.iocoder.yudao.module.ai.vo.*; import io.swagger.v3.oas.annotations.Operation; import lombok.AllArgsConstructor; import org.springframework.validation.annotation.Validated; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java new file mode 100644 index 000000000..a46574046 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.ai.controller; + +import cn.hutool.core.exceptions.ExceptionUtil; +import cn.iocoder.yudao.framework.ai.chat.ChatResponse; +import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; +import cn.iocoder.yudao.framework.ai.config.AiClient; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; +import reactor.core.publisher.Flux; + +import java.io.IOException; +import java.util.function.Consumer; + +/** + * @author fansili + * @time 2024/4/13 17:44 + * @since 1.0 + */ +@Tag(name = "AI模块") +@RestController +@RequestMapping("/ai") +@Slf4j +@AllArgsConstructor +public class ChatController { + + + + @Autowired + private AiClient aiClient; + + @GetMapping("/chat") + public CommonResult chat(@RequestParam("prompt") String prompt) { + ChatResponse callRes = aiClient.call(new Prompt(prompt), "qianWen"); + return CommonResult.success(callRes.getResult().getOutput().getContent()); + } + + // TODO @芋艿:调用这个方法异常,Unable to handle the Spring Security Exception because the response is already committed. + @GetMapping(value = "/chatStream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) + public SseEmitter chatStream(@RequestParam("prompt") String prompt) { + Utf8SseEmitter sseEmitter = new Utf8SseEmitter(); + Flux streamResponse = aiClient.stream(new Prompt(prompt), "qianWen"); + streamResponse.subscribe( + new Consumer() { + @Override + public void accept(ChatResponse chatResponse) { + String content = chatResponse.getResults().get(0).getOutput().getContent(); + try { + sseEmitter.send(content, MediaType.APPLICATION_JSON); + } catch (IOException e) { + log.error("发送异常{}", ExceptionUtil.getMessage(e)); + // 如果不是因为关闭而抛出异常,则重新连接 + sseEmitter.completeWithError(e); + } + } + }, + error -> { + // + log.error("subscribe错误 {}", ExceptionUtil.getMessage(error)); + }, + () -> { + log.info("发送完成!"); + sseEmitter.complete(); + } + ); + return sseEmitter; + } +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/ChatController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/ChatController.java deleted file mode 100644 index 90710a3dd..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/ChatController.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat; - -import cn.iocoder.yudao.framework.ai.chat.ChatResponse; -import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; -import cn.iocoder.yudao.framework.ai.config.AiClient; -import cn.iocoder.yudao.framework.ai.config.YudaoAiClient; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; - -/** - * @author fansili - * @since 1.0 - * @time 2024/4/13 17:44 - */ -@Tag(name = "AI模块") -@RestController -@RequestMapping("/admin-api/ai") -@Slf4j -@AllArgsConstructor -public class ChatController { - - private final AiClient aiClient; - - @PostMapping("/chat") - public CommonResult chat(@RequestParam("prompt") String prompt) { - ChatResponse callRes = aiClient.call(new Prompt(prompt), "qianWen"); - return CommonResult.success(callRes.getResult().getOutput().getContent()); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/package-info.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/package-info.java deleted file mode 100644 index 81fe7e4bb..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -/** - * author: fansili - * time: 2024/3/4 13:08 - */ -package cn.iocoder.yudao.module.ai.controller.admin; \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/package-info.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/package-info.java deleted file mode 100644 index a7675c99b..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -/** - * author: fansili - * time: 2024/3/4 13:08 - */ -package cn.iocoder.yudao.module.ai.controller.app; \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java index e91429715..c4c46a5ef 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.ai.controller.app.chat.vo.*; +import cn.iocoder.yudao.module.ai.vo.*; /** * chat 角色 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java similarity index 83% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleServiceImpl.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java index dc839c4b3..310e8f766 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java @@ -1,7 +1,8 @@ -package cn.iocoder.yudao.module.ai.service; +package cn.iocoder.yudao.module.ai.service.impl; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.ai.controller.app.chat.vo.*; +import cn.iocoder.yudao.module.ai.service.ChatRoleService; +import cn.iocoder.yudao.module.ai.vo.*; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/package-info.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/package-info.java deleted file mode 100644 index 671d5534f..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -/** - * author: fansili - * time: 2024/3/3 18:14 - */ -package cn.iocoder.yudao.module.ai.service; \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/AiChatReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatReqVO.java similarity index 92% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/AiChatReqVO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatReqVO.java index 881982a57..eafbecda5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/AiChatReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo; +package cn.iocoder.yudao.module.ai.vo; import cn.iocoder.yudao.module.ai.enums.OpenAiModelEnum; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleAddReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleAddReq.java similarity index 86% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleAddReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleAddReq.java index b1c08e286..2c2dfcbff 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleAddReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleAddReq.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.controller.app.chat.vo; +package cn.iocoder.yudao.module.ai.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleListReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleListReq.java similarity index 86% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleListReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleListReq.java index 18f3d46c0..32a028b94 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleListReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleListReq.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.controller.app.chat.vo; +package cn.iocoder.yudao.module.ai.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleListRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleListRes.java similarity index 75% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleListRes.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleListRes.java index 6480296f2..8423c66b9 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleListRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleListRes.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.controller.app.chat.vo; +package cn.iocoder.yudao.module.ai.vo; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleUpdateReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateReq.java similarity index 86% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleUpdateReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateReq.java index 0874fd691..2f98e4f79 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleUpdateReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateReq.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.controller.app.chat.vo; +package cn.iocoder.yudao.module.ai.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleUpdateVisibilityReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateVisibilityReq.java similarity index 87% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleUpdateVisibilityReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateVisibilityReq.java index fc76b5d4c..3ae25f4ab 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/chat/vo/ChatRoleUpdateVisibilityReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateVisibilityReq.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.controller.app.chat.vo; +package cn.iocoder.yudao.module.ai.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http index 03c829b85..95a928480 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http @@ -16,24 +16,17 @@ tenant-id: 1 } ### chat call -POST {{baseUrl}}/admin-api/ai/chat?prompt=中国怎么样 +GET {{baseUrl}}/ai/chat?prompt=中国怎么样 tenant-id: 1 Authorization: {{token}} + ### chat call -POST {{baseUrl}}/ai-api/chat -tenant-id: 1 -Authorization: {{token}} - - -### chat call -GET {{baseUrl}}/chat-role/list +GET {{baseUrl}}/ai/chatStream?prompt=苹果是什么颜色? tenant-id: 1 Authorization: {{token}} - - diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json index 5fd488f50..5beca6fd1 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json @@ -1,6 +1,6 @@ { "dev": { "baseUrl": "http://127.0.0.1:48080", - "token": "Bearer 07390ff2824a4798bcfd7f9395092181" + "token": "Bearer cff0ce99ddb14ea89c62ff4de1c31180" } } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java index c4be256da..fae550da8 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java @@ -82,6 +82,12 @@ public class YiYanChatClient implements ChatClient, StreamingChatClient { YiYanChatCompletionRequest request = this.createRequest(prompt, true); // 调用 callWithFunctionSupport 发送请求 Flux response = this.yiYanApi.chatCompletionStream(request); + response.doOnComplete(new Runnable() { + @Override + public void run() { + String a = ";"; + } + }); return response.map(res -> new ChatResponse(List.of(new Generation(res.getResult())))); } From 009914ed73f125a21f6e07793a53b53595b81b9d Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 14 Apr 2024 15:55:08 +0800 Subject: [PATCH 095/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20swagger=20?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iocoder/yudao/module/ai/controller/ChatController.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java index a46574046..26d1d9922 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.ai.chat.ChatResponse; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.ai.config.AiClient; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -32,11 +33,10 @@ import java.util.function.Consumer; @AllArgsConstructor public class ChatController { - - @Autowired private AiClient aiClient; + @Operation(summary = "聊天-chat", description = "这个一般等待时间比较久,需要全部完成才会返回!") @GetMapping("/chat") public CommonResult chat(@RequestParam("prompt") String prompt) { ChatResponse callRes = aiClient.call(new Prompt(prompt), "qianWen"); @@ -44,6 +44,7 @@ public class ChatController { } // TODO @芋艿:调用这个方法异常,Unable to handle the Spring Security Exception because the response is already committed. + @Operation(summary = "聊天-stream", description = "这里跟通义千问一样采用的是 Server-Sent Events (SSE) 通讯模式") @GetMapping(value = "/chatStream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public SseEmitter chatStream(@RequestParam("prompt") String prompt) { Utf8SseEmitter sseEmitter = new Utf8SseEmitter(); From 7024c5ab608832e69da3321f7f05f4516a6cd565 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 14 Apr 2024 16:05:29 +0800 Subject: [PATCH 096/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20client=20name=20?= =?UTF-8?q?=E6=9E=9A=E4=B8=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/enums/AiClientNameEnum.java | 28 +++++++++++++++++++ .../module/ai/controller/ChatController.java | 9 ++++-- 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiClientNameEnum.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiClientNameEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiClientNameEnum.java new file mode 100644 index 000000000..8e1418e62 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiClientNameEnum.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.ai.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * ai client 名字 + * + * 这个需要根据配置文件起的来决定 + * + * @author fansili + * @time 2024/4/14 16:02 + * @since 1.0 + */ +@AllArgsConstructor +@Getter +public enum AiClientNameEnum { + + QIAN_WEN("qianWen", "千问模型!"), + YI_YAN("yiYan", "一言模型!"), + XING_HUO("xingHuo", "星火模型!"), + + ; + + private String name; + + private String message; +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java index 26d1d9922..f873d6c52 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java @@ -5,6 +5,8 @@ import cn.iocoder.yudao.framework.ai.chat.ChatResponse; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.ai.config.AiClient; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.ai.enums.AiClientNameEnum; +import cn.iocoder.yudao.module.ai.service.ChatService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; @@ -22,6 +24,8 @@ import java.io.IOException; import java.util.function.Consumer; /** + * ia 模块 + * * @author fansili * @time 2024/4/13 17:44 * @since 1.0 @@ -35,11 +39,12 @@ public class ChatController { @Autowired private AiClient aiClient; + private final ChatService chatService; @Operation(summary = "聊天-chat", description = "这个一般等待时间比较久,需要全部完成才会返回!") @GetMapping("/chat") public CommonResult chat(@RequestParam("prompt") String prompt) { - ChatResponse callRes = aiClient.call(new Prompt(prompt), "qianWen"); + ChatResponse callRes = aiClient.call(new Prompt(prompt), AiClientNameEnum.QIAN_WEN.getName()); return CommonResult.success(callRes.getResult().getOutput().getContent()); } @@ -48,7 +53,7 @@ public class ChatController { @GetMapping(value = "/chatStream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public SseEmitter chatStream(@RequestParam("prompt") String prompt) { Utf8SseEmitter sseEmitter = new Utf8SseEmitter(); - Flux streamResponse = aiClient.stream(new Prompt(prompt), "qianWen"); + Flux streamResponse = aiClient.stream(new Prompt(prompt), AiClientNameEnum.QIAN_WEN.getName()); streamResponse.subscribe( new Consumer() { @Override From ef701167b76fd2757da5e0d23b08b02a1b7af057 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 14 Apr 2024 17:24:02 +0800 Subject: [PATCH 097/684] =?UTF-8?q?1=E3=80=81=E5=A2=9E=E5=8A=A0=20chat=20s?= =?UTF-8?q?ervice=202=E3=80=81=E5=8F=AF=E5=8A=A8=E6=80=81=E4=BC=A0?= =?UTF-8?q?=E5=85=A5=20modal=EF=BC=8C=E9=80=89=E6=8B=A9=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/enums/AiClientNameEnum.java | 9 +++ .../module/ai/controller/ChatController.java | 15 +++-- ...ontroller.java => ChatRoleController.java} | 2 +- .../yudao/module/ai/service/ChatService.java | 33 ++++++++++ .../ai/service/impl/ChatServiceImpl.java | 62 +++++++++++++++++++ .../iocoder/yudao/module/ai/vo/ChatReq.java | 42 +++++++++++++ 6 files changed, 154 insertions(+), 9 deletions(-) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/{AiChatRoleController.java => ChatRoleController.java} (98%) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatService.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiClientNameEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiClientNameEnum.java index 8e1418e62..13c06bdd3 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiClientNameEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiClientNameEnum.java @@ -25,4 +25,13 @@ public enum AiClientNameEnum { private String name; private String message; + + public static AiClientNameEnum valueOfName(String name) { + for (AiClientNameEnum nameEnum : AiClientNameEnum.values()) { + if (nameEnum.getName().equals(name)) { + return nameEnum; + } + } + throw new IllegalArgumentException("Invalid MessageType value: " + name); + } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java index f873d6c52..3a71c5434 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java @@ -2,20 +2,20 @@ package cn.iocoder.yudao.module.ai.controller; import cn.hutool.core.exceptions.ExceptionUtil; import cn.iocoder.yudao.framework.ai.chat.ChatResponse; -import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.ai.config.AiClient; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.ai.enums.AiClientNameEnum; import cn.iocoder.yudao.module.ai.service.ChatService; +import cn.iocoder.yudao.module.ai.vo.ChatReq; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import reactor.core.publisher.Flux; @@ -43,17 +43,16 @@ public class ChatController { @Operation(summary = "聊天-chat", description = "这个一般等待时间比较久,需要全部完成才会返回!") @GetMapping("/chat") - public CommonResult chat(@RequestParam("prompt") String prompt) { - ChatResponse callRes = aiClient.call(new Prompt(prompt), AiClientNameEnum.QIAN_WEN.getName()); - return CommonResult.success(callRes.getResult().getOutput().getContent()); + public CommonResult chat(@Validated @ModelAttribute ChatReq req) { + return CommonResult.success(chatService.chat(req)); } // TODO @芋艿:调用这个方法异常,Unable to handle the Spring Security Exception because the response is already committed. @Operation(summary = "聊天-stream", description = "这里跟通义千问一样采用的是 Server-Sent Events (SSE) 通讯模式") @GetMapping(value = "/chatStream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) - public SseEmitter chatStream(@RequestParam("prompt") String prompt) { + public SseEmitter chatStream(@Validated @ModelAttribute ChatReq req) { Utf8SseEmitter sseEmitter = new Utf8SseEmitter(); - Flux streamResponse = aiClient.stream(new Prompt(prompt), AiClientNameEnum.QIAN_WEN.getName()); + Flux streamResponse = chatService.chatStream(req); streamResponse.subscribe( new Consumer() { @Override diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatRoleController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatRoleController.java similarity index 98% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatRoleController.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatRoleController.java index 543754e91..4b3e61c09 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatRoleController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatRoleController.java @@ -17,7 +17,7 @@ import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/chat-role") @AllArgsConstructor -public class AiChatRoleController { +public class ChatRoleController { private final ChatRoleService chatRoleService; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatService.java new file mode 100644 index 000000000..aa1c54fb0 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatService.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.ai.service; + +import cn.iocoder.yudao.framework.ai.chat.ChatResponse; +import cn.iocoder.yudao.module.ai.enums.AiClientNameEnum; +import cn.iocoder.yudao.module.ai.vo.ChatReq; +import reactor.core.publisher.Flux; + +/** + * 聊天 chat + * + * @author fansili + * @time 2024/4/14 15:55 + * @since 1.0 + */ +public interface ChatService { + + /** + * chat + * + * @param req + * @return + */ + String chat(ChatReq req); + + /** + * chat stream + * + * @param req + * @param clientNameEnum + * @return + */ + Flux chatStream(ChatReq req); +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java new file mode 100644 index 000000000..8531594db --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.ai.service.impl; + +import cn.iocoder.yudao.framework.ai.chat.ChatResponse; +import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; +import cn.iocoder.yudao.framework.ai.config.AiClient; +import cn.iocoder.yudao.module.ai.enums.AiClientNameEnum; +import cn.iocoder.yudao.module.ai.service.ChatService; +import cn.iocoder.yudao.module.ai.vo.ChatReq; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; + +/** + * 聊天 service + * + * @author fansili + * @time 2024/4/14 15:55 + * @since 1.0 + */ +@Slf4j +@Service +@AllArgsConstructor +public class ChatServiceImpl implements ChatService { + + private final AiClient aiClient; + + /** + * chat + * + * @param req + * @return + */ + public String chat(ChatReq req) { + AiClientNameEnum clientNameEnum = AiClientNameEnum.valueOfName(req.getModal()); + // 创建 chat 需要的 Prompt + Prompt prompt = new Prompt(req.getPrompt()); + req.setTopK(req.getTopK()); + req.setTopP(req.getTopP()); + req.setTemperature(req.getTemperature()); + // 发送 call 调用 + ChatResponse call = aiClient.call(prompt, clientNameEnum.getName()); + return call.getResult().getOutput().getContent(); + } + + /** + * chat stream + * + * @param req + * @return + */ + @Override + public Flux chatStream(ChatReq req) { + AiClientNameEnum clientNameEnum = AiClientNameEnum.valueOfName(req.getModal()); + // 创建 chat 需要的 Prompt + Prompt prompt = new Prompt(req.getPrompt()); + req.setTopK(req.getTopK()); + req.setTopP(req.getTopP()); + req.setTemperature(req.getTemperature()); + return aiClient.stream(prompt, clientNameEnum.getName()); + } +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java new file mode 100644 index 000000000..754cb0572 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.ai.vo; + +import cn.iocoder.yudao.module.ai.enums.AiClientNameEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * chat req + * + * @author fansili + * @time 2024/4/14 16:12 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class ChatReq { + + + @NotNull(message = "提示词不能为空!") + @Size(max = 3000, message = "提示词最大3000个字符!") + @Schema(description = "填入固定值,1 issues, 2 pr") + private String prompt; + + @Schema(description = "用于控制随机性和多样性的温度参数") + private Float temperature; + + @Schema(description = "生成时,核采样方法的概率阈值。例如,取值为0.8时,仅保留累计概率之和大于等于0.8的概率分布中的token,\n" + + " * 作为随机采样的候选集。取值范围为(0,1.0),取值越大,生成的随机性越高;取值越低,生成的随机性越低。\n" + + " * 默认值为0.8。注意,取值不要大于等于1\n") + private Float topP; + + @Schema(description = "在生成消息时采用的Top-K采样大小,表示模型生成回复时考虑的候选项集合的大小") + private Integer topK; + + @Schema(description = "ai模型(查看 AiClientNameEnum)") + @NotNull(message = "模型不能为空!") + @Size(max = 30, message = "模型字符最大30个字符!") + private String modal; +} From 15b76c1d1a43fff26cf917e7bde164020b4e842a Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 14 Apr 2024 17:24:43 +0800 Subject: [PATCH 098/684] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/iocoder/yudao/module/ai/service/ChatService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatService.java index aa1c54fb0..f72c52493 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatService.java @@ -26,7 +26,6 @@ public interface ChatService { * chat stream * * @param req - * @param clientNameEnum * @return */ Flux chatStream(ChatReq req); From 7c8ec404dbdfea597aa2c8aaf59219fc48c75c0d Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 14 Apr 2024 17:31:54 +0800 Subject: [PATCH 099/684] =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E6=A8=A1=E5=9E=8B=E7=89=88=E6=9C=AC=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/iocoder/yudao/module/ai/enums/AiClientNameEnum.java | 2 +- yudao-server/src/main/resources/application-local.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiClientNameEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiClientNameEnum.java index 13c06bdd3..9dc5149e7 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiClientNameEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiClientNameEnum.java @@ -17,7 +17,7 @@ import lombok.Getter; public enum AiClientNameEnum { QIAN_WEN("qianWen", "千问模型!"), - YI_YAN("yiYan", "一言模型!"), + YI_YAN_3_5_8K("yiYan3_5_8k", "文心一言(3.5-8k)"), XING_HUO("xingHuo", "星火模型!"), ; diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index fc3f358f1..87b40adb2 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -243,7 +243,7 @@ yudao: appKey: cb6415c19d6162cda07b47316fcb0416 secretKey: Y2JiYTIxZjA3MDMxMjNjZjQzYzVmNzdh chatModel: XING_HUO_3_5 - yiYan: + yiYan3_5_8k: aiPlatform: YI_YAN temperature: 1 topP: 1 From bff0ad65dcbf15e5fa683fd864b9a43a8ce224d7 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 14 Apr 2024 17:39:30 +0800 Subject: [PATCH 100/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0do=E5=90=8E=E7=BC=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dataobject/{AiChatMessage.java => AiChatMessageDO.java} | 2 +- .../ai/dataobject/{AiChatRole.java => AiChatRoleDO.java} | 2 +- .../iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java | 4 ++-- .../cn/iocoder/yudao/module/ai/mapper/AiChatRoleMapper.java | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/{AiChatMessage.java => AiChatMessageDO.java} (98%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/{AiChatRole.java => AiChatRoleDO.java} (97%) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatMessage.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatMessageDO.java similarity index 98% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatMessage.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatMessageDO.java index e4968b91b..416b3f0f9 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatMessage.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatMessageDO.java @@ -13,7 +13,7 @@ import java.util.Date; */ @Data @Accessors(chain = true) -public class AiChatMessage { +public class AiChatMessageDO { /** * 编号,作为每条聊天记录的唯一标识符 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatRole.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatRoleDO.java similarity index 97% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatRole.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatRoleDO.java index 04ebfe0cf..a049e3cfc 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatRole.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatRoleDO.java @@ -12,7 +12,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class AiChatRole extends BaseDO { +public class AiChatRoleDO extends BaseDO { /** * 编号,表示聊天角色在数据库中的唯一标识符 */ diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java index 91526ab79..0545a7e2f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.ai.mapper; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.module.ai.dataobject.AiChatMessage; +import cn.iocoder.yudao.module.ai.dataobject.AiChatMessageDO; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; @@ -13,5 +13,5 @@ import org.springframework.stereotype.Repository; */ @Repository @Mapper -public interface AiChatMessageMapper extends BaseMapperX { +public interface AiChatMessageMapper extends BaseMapperX { } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatRoleMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatRoleMapper.java index 09a662fe7..32393c409 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatRoleMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatRoleMapper.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.ai.mapper; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.module.ai.dataobject.AiChatRole; +import cn.iocoder.yudao.module.ai.dataobject.AiChatRoleDO; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; @@ -13,5 +13,5 @@ import org.springframework.stereotype.Repository; */ @Repository @Mapper -public interface AiChatRoleMapper extends BaseMapperX { +public interface AiChatRoleMapper extends BaseMapperX { } From be0c81458d7d0e9a11fec8a5c1ba615fb61ed261 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 14 Apr 2024 18:38:06 +0800 Subject: [PATCH 101/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AF=B9=E8=AF=9D?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=EF=BC=8Cnew=E8=BF=98=E6=98=AF=E7=BB=A7?= =?UTF-8?q?=E7=BB=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/enums/ChatConversationTypeEnum.java | 36 ++++++++++++++++ .../ai/dataobject/AiChatConversationDO.java | 42 +++++++++++++++++++ .../ai/mapper/AiChatConversationMapper.java | 24 +++++++++++ 3 files changed, 102 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatConversationTypeEnum.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatConversationDO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatConversationTypeEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatConversationTypeEnum.java new file mode 100644 index 000000000..4a699618d --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatConversationTypeEnum.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.ai.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 对话类型 + * 创建对话、继续对话 + * + * @author fansili + * @time 2024/4/14 18:15 + * @since 1.0 + */ +@AllArgsConstructor +@Getter +public enum ChatConversationTypeEnum { + + NEW("new", "新建对话"), + CONTINUE("continue", "继续对话"), + + ; + + private String type; + + private String name; + + public static ChatConversationTypeEnum valueOfType(String type) { + for (ChatConversationTypeEnum itemEnum : ChatConversationTypeEnum.values()) { + if (itemEnum.getType().equals(type)) { + return itemEnum; + } + } + throw new IllegalArgumentException("Invalid MessageType value: " + type); + } + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatConversationDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatConversationDO.java new file mode 100644 index 000000000..8f1956392 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatConversationDO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.ai.dataobject; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * chat 交谈 + * + * @author fansili + * @time 2024/4/14 17:35 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +@TableName("ai_chat_conversation") +public class AiChatConversationDO extends BaseDO { + + @Schema(description = "id") + private Long id; + + @Schema(description = "用户id") + private Long userId; + + @Schema(description = "chat角色Id") + private Long chatRoleId; + + @Schema(description = "chat角色名称") + private String chatRoleName; + + @Schema(description = "对话标题(有程序自动生成)") + private String chatTitle; + + @Schema(description = "对话标题(有程序自动生成)") + private Integer chatCount; + + @Schema(description = "对话类型(roleChat、userChat)") + private String chatType; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java new file mode 100644 index 000000000..6e018a892 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.ai.mapper; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.ai.dataobject.AiChatConversationDO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; +import org.springframework.stereotype.Repository; + +/** + * message mapper + * + * @fansili + * @since v1.0 + */ +@Repository +@Mapper +public interface AiChatConversationMapper extends BaseMapperX { + + + @Update("update ai_chat_conversation set chat_count = chat_count + 1 where id = #{id}") + void updateIncrChatCount(@Param("id") Long id); + +} From a2bd9b710e95bf1def28a9955cbf8b4cc69ee119 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 14 Apr 2024 18:39:30 +0800 Subject: [PATCH 102/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20=E5=AF=B9=E8=AF=9D?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E3=80=81role=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index 9ca5f09ad..d4ecf4df8 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -14,4 +14,6 @@ public interface ErrorCodeConstants { // TODO @fansili:1)类注释不太对;2)中英文之间,有个空格;例如说 AI 模型 ErrorCode AI_MODULE_NOT_SUPPORTED = new ErrorCode(1_022_000_000, "AI模型暂不支持!"); + ErrorCode AI_CHAT_ROLE_NOT_EXISTENT = new ErrorCode(1_022_000_001, "AI Role 不存在!");; + ErrorCode AI_CHAT_CONTINUE_CONVERSATION_ID_NOT_NULL = new ErrorCode(1_022_000_002, "chat 继续对话,对话id不能为空!");; } From 779499222507f20c2a4fe1157fabde3881f280e0 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 14 Apr 2024 18:40:42 +0800 Subject: [PATCH 103/684] =?UTF-8?q?=E8=81=8A=E5=A4=A9=E5=AF=B9=E8=AF=9D?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0=20=E5=88=9B=E5=BB=BA=E5=AF=B9?= =?UTF-8?q?=E8=AF=9D=E3=80=81=E8=BF=98=E6=98=AF=E7=BB=A7=E7=BB=AD=E5=AF=B9?= =?UTF-8?q?=E8=AF=9D=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/enums/ChatTypeEnum.java | 34 ++++++ .../module/ai/dataobject/AiChatMessageDO.java | 6 +- .../ai/service/impl/ChatServiceImpl.java | 102 ++++++++++++++++-- .../iocoder/yudao/module/ai/vo/ChatReq.java | 16 ++- .../ai/chat/messages/AbstractMessage.java | 2 +- 5 files changed, 145 insertions(+), 15 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatTypeEnum.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatTypeEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatTypeEnum.java new file mode 100644 index 000000000..cdf7c3ba0 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatTypeEnum.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.ai.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 聊天类型 + * + * @author fansili + * @time 2024/4/14 17:58 + * @since 1.0 + */ +@AllArgsConstructor +@Getter +public enum ChatTypeEnum { + + ROLE_CHAT("roleChat", "角色模板聊天"), + USER_CHAT("userChat", "用户普通聊天"), + + ; + + private String type; + + private String name; + + public static ChatTypeEnum valueOfType(String type) { + for (ChatTypeEnum itemEnum : ChatTypeEnum.values()) { + if (itemEnum.getType().equals(type)) { + return itemEnum; + } + } + throw new IllegalArgumentException("Invalid MessageType value: " + type); + } +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatMessageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatMessageDO.java index 416b3f0f9..9047180ec 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatMessageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatMessageDO.java @@ -23,12 +23,12 @@ public class AiChatMessageDO { /** * 聊天ID,关联到特定的会话或对话 */ - private Long chatId; + private Long chatConversationId; /** * 角色ID,用于标识发送消息的用户或系统的身份 */ - private String userId; + private Long userId; /** * 消息具体内容,存储用户的发言或者系统响应的文字信息 @@ -38,7 +38,7 @@ public class AiChatMessageDO { /** * 消息类型,枚举值可能包括'system'(系统消息)、'user'(用户消息)和'assistant'(助手消息) */ - private Double messageType; + private String messageType; /** * 在生成消息时采用的Top-K采样大小, diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java index 8531594db..6fe226181 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java @@ -1,14 +1,28 @@ package cn.iocoder.yudao.module.ai.service.impl; +import cn.hutool.core.exceptions.ExceptionUtil; import cn.iocoder.yudao.framework.ai.chat.ChatResponse; +import cn.iocoder.yudao.framework.ai.chat.messages.MessageType; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.ai.config.AiClient; +import cn.iocoder.yudao.framework.common.exception.ServerException; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.module.ai.ErrorCodeConstants; +import cn.iocoder.yudao.module.ai.dataobject.AiChatConversationDO; +import cn.iocoder.yudao.module.ai.dataobject.AiChatMessageDO; +import cn.iocoder.yudao.module.ai.dataobject.AiChatRoleDO; import cn.iocoder.yudao.module.ai.enums.AiClientNameEnum; +import cn.iocoder.yudao.module.ai.enums.ChatConversationTypeEnum; +import cn.iocoder.yudao.module.ai.enums.ChatTypeEnum; +import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; +import cn.iocoder.yudao.module.ai.mapper.AiChatMessageMapper; +import cn.iocoder.yudao.module.ai.mapper.AiChatRoleMapper; import cn.iocoder.yudao.module.ai.service.ChatService; import cn.iocoder.yudao.module.ai.vo.ChatReq; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import reactor.core.publisher.Flux; /** @@ -24,6 +38,10 @@ import reactor.core.publisher.Flux; public class ChatServiceImpl implements ChatService { private final AiClient aiClient; + private final AiChatRoleMapper aiChatRoleMapper; + private final AiChatMessageMapper aiChatMessageMapper; + private final AiChatConversationMapper aiChatConversationMapper; + /** * chat @@ -31,16 +49,84 @@ public class ChatServiceImpl implements ChatService { * @param req * @return */ + @Transactional(rollbackFor = Exception.class) public String chat(ChatReq req) { + // 获取 client 类型 AiClientNameEnum clientNameEnum = AiClientNameEnum.valueOfName(req.getModal()); - // 创建 chat 需要的 Prompt - Prompt prompt = new Prompt(req.getPrompt()); - req.setTopK(req.getTopK()); - req.setTopP(req.getTopP()); - req.setTemperature(req.getTemperature()); - // 发送 call 调用 - ChatResponse call = aiClient.call(prompt, clientNameEnum.getName()); - return call.getResult().getOutput().getContent(); + // 获取 对话类型(新建还是继续) + ChatConversationTypeEnum chatConversationTypeEnum = ChatConversationTypeEnum.valueOfType(req.getConversationType()); + + AiChatConversationDO aiChatConversationDO; + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + if (ChatConversationTypeEnum.NEW == chatConversationTypeEnum) { + // 创建一个新的对话 + aiChatConversationDO = createNewChatConversation(req, loginUserId); + } else { + // 继续对话 + if (req.getConversationId() == null) { + throw new ServerException(ErrorCodeConstants.AI_CHAT_CONTINUE_CONVERSATION_ID_NOT_NULL); + } + aiChatConversationDO = aiChatConversationMapper.selectById(req.getConversationId()); + } + + String content; + try { + // 创建 chat 需要的 Prompt + Prompt prompt = new Prompt(req.getPrompt()); + req.setTopK(req.getTopK()); + req.setTopP(req.getTopP()); + req.setTemperature(req.getTemperature()); + // 发送 call 调用 + ChatResponse call = aiClient.call(prompt, clientNameEnum.getName()); + content = call.getResult().getOutput().getContent(); + } catch (Exception e) { + content = ExceptionUtil.getMessage(e); + } + + // 增加 chat message 记录 + aiChatMessageMapper.insert( + new AiChatMessageDO() + .setId(null) + .setChatConversationId(aiChatConversationDO.getId()) + .setUserId(loginUserId) + .setMessage(req.getPrompt()) + .setMessageType(MessageType.USER.getValue()) + .setTopK(req.getTopK()) + .setTopP(req.getTopP()) + .setTemperature(req.getTemperature()) + ); + + // chat count 先+1 + aiChatConversationMapper.updateIncrChatCount(req.getConversationId()); + return content; + } + + private AiChatConversationDO createNewChatConversation(ChatReq req, Long loginUserId) { + // 获取 chat 角色 + String chatRoleName = null; + ChatTypeEnum chatTypeEnum = null; + Long chatRoleId = req.getChatRoleId(); + if (req.getChatRoleId() != null) { + AiChatRoleDO aiChatRoleDO = aiChatRoleMapper.selectById(chatRoleId); + if (aiChatRoleDO == null) { + throw new ServerException(ErrorCodeConstants.AI_CHAT_ROLE_NOT_EXISTENT); + } + chatTypeEnum = ChatTypeEnum.ROLE_CHAT; + chatRoleName = aiChatRoleDO.getRoleName(); + } else { + chatTypeEnum = ChatTypeEnum.USER_CHAT; + } + // + AiChatConversationDO insertChatConversation = new AiChatConversationDO() + .setId(null) + .setUserId(loginUserId) + .setChatRoleId(req.getChatRoleId()) + .setChatRoleName(chatRoleName) + .setChatType(chatTypeEnum.getType()) + .setChatCount(1) + .setChatTitle(req.getPrompt().substring(0, 20) + "..."); + aiChatConversationMapper.insert(insertChatConversation); + return insertChatConversation; } /** diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java index 754cb0572..321d429c5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java @@ -24,19 +24,29 @@ public class ChatReq { @Schema(description = "填入固定值,1 issues, 2 pr") private String prompt; + @Schema(description = "chat角色模板") + private Long chatRoleId; + @Schema(description = "用于控制随机性和多样性的温度参数") - private Float temperature; + private Double temperature; @Schema(description = "生成时,核采样方法的概率阈值。例如,取值为0.8时,仅保留累计概率之和大于等于0.8的概率分布中的token,\n" + " * 作为随机采样的候选集。取值范围为(0,1.0),取值越大,生成的随机性越高;取值越低,生成的随机性越低。\n" + " * 默认值为0.8。注意,取值不要大于等于1\n") - private Float topP; + private Double topP; @Schema(description = "在生成消息时采用的Top-K采样大小,表示模型生成回复时考虑的候选项集合的大小") - private Integer topK; + private Double topK; @Schema(description = "ai模型(查看 AiClientNameEnum)") @NotNull(message = "模型不能为空!") @Size(max = 30, message = "模型字符最大30个字符!") private String modal; + + @Schema(description = "对话类型(new、continue)") + @NotNull(message = "对话类型,不能为空!") + private String conversationType; + + @Schema(description = "对话Id") + private Long conversationId; } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/AbstractMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/AbstractMessage.java index d622cf9f8..8c8e60d5a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/AbstractMessage.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/AbstractMessage.java @@ -59,7 +59,7 @@ public abstract class AbstractMessage implements Message { } protected AbstractMessage(MessageType messageType, String textContent, List mediaData, - Map messageProperties) { + Map messageProperties) { Assert.notNull(messageType, "Message type must not be null"); Assert.notNull(textContent, "Content must not be null"); From b925c2c7ccaa00336cf4e8b024db63d61d995173 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 14 Apr 2024 18:41:03 +0800 Subject: [PATCH 104/684] =?UTF-8?q?spring-web=20=E6=94=B9=E4=B8=BA=20start?= =?UTF-8?q?=20security?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-module-ai/yudao-module-ai-biz/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/pom.xml b/yudao-module-ai/yudao-module-ai-biz/pom.xml index cb13949c0..d87818569 100644 --- a/yudao-module-ai/yudao-module-ai-biz/pom.xml +++ b/yudao-module-ai/yudao-module-ai-biz/pom.xml @@ -36,7 +36,7 @@ cn.iocoder.boot - yudao-spring-boot-starter-web + yudao-spring-boot-starter-security cn.iocoder.boot From efab5517d79c1b4eb025db8e90810516ee8b7e0e Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 14 Apr 2024 18:41:21 +0800 Subject: [PATCH 105/684] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20chat=20=E8=AF=B7?= =?UTF-8?q?=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao-module-ai-biz/src/main/resources/http/chat.http | 4 ++-- .../src/main/resources/http/http-client.env.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http index 95a928480..1b645017e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http @@ -16,14 +16,14 @@ tenant-id: 1 } ### chat call -GET {{baseUrl}}/ai/chat?prompt=中国怎么样 +GET {{baseUrl}}/ai/chat?prompt=中国怎么样&modal=qianWen tenant-id: 1 Authorization: {{token}} ### chat call -GET {{baseUrl}}/ai/chatStream?prompt=苹果是什么颜色? +GET {{baseUrl}}/ai/chatStream?prompt=苹果是什么颜色?&modal=yiYan3_5_8k tenant-id: 1 Authorization: {{token}} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json index 5beca6fd1..c5adaf3e1 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json @@ -1,6 +1,6 @@ { "dev": { "baseUrl": "http://127.0.0.1:48080", - "token": "Bearer cff0ce99ddb14ea89c62ff4de1c31180" + "token": "Bearer 7d25823e225f4e0d8f9a96b0fa608649" } } \ No newline at end of file From 905ce773e92b811c343853931bebfc0f8b896360 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 16 Apr 2024 20:39:52 +0800 Subject: [PATCH 106/684] =?UTF-8?q?=E4=BC=98=E5=8C=96swagger=20=E6=B3=A8?= =?UTF-8?q?=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iocoder/yudao/module/ai/vo/ChatReq.java | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java index 321d429c5..67828e6ba 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.ai.vo; -import cn.iocoder.yudao.module.ai.enums.AiClientNameEnum; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; @@ -18,14 +17,25 @@ import lombok.experimental.Accessors; @Accessors(chain = true) public class ChatReq { + @Schema(description = "chat角色模板") + private Long chatRoleId; + + @Schema(description = "对话Id") + private Long conversationId; + + @Schema(description = "对话类型(new、continue),如果是new会创建一个新的对话,continue就会继续对话!") + @NotNull(message = "对话类型,不能为空!") + private String conversationType; @NotNull(message = "提示词不能为空!") - @Size(max = 3000, message = "提示词最大3000个字符!") + @Size(max = 5000, message = "提示词最大5000个字符!") @Schema(description = "填入固定值,1 issues, 2 pr") private String prompt; - @Schema(description = "chat角色模板") - private Long chatRoleId; + @Schema(description = "ai模型(查看 AiClientNameEnum)") + @NotNull(message = "模型不能为空!") + @Size(max = 30, message = "模型字符最大30个字符!") + private String modal; @Schema(description = "用于控制随机性和多样性的温度参数") private Double temperature; @@ -38,15 +48,4 @@ public class ChatReq { @Schema(description = "在生成消息时采用的Top-K采样大小,表示模型生成回复时考虑的候选项集合的大小") private Double topK; - @Schema(description = "ai模型(查看 AiClientNameEnum)") - @NotNull(message = "模型不能为空!") - @Size(max = 30, message = "模型字符最大30个字符!") - private String modal; - - @Schema(description = "对话类型(new、continue)") - @NotNull(message = "对话类型,不能为空!") - private String conversationType; - - @Schema(description = "对话Id") - private Long conversationId; } From f84d25d3b710f0788c0427f5f0d59739a291033d Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 18 Apr 2024 16:09:45 +0800 Subject: [PATCH 107/684] =?UTF-8?q?stream=20=E4=BF=9D=E5=AD=98=E8=81=8A?= =?UTF-8?q?=E5=A4=A9=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/controller/ChatController.java | 27 +---- .../yudao/module/ai/service/ChatService.java | 7 +- .../ai/service/impl/ChatServiceImpl.java | 105 +++++++++++++++--- 3 files changed, 92 insertions(+), 47 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java index 3a71c5434..d9f2d2b97 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.ai.controller; import cn.hutool.core.exceptions.ExceptionUtil; import cn.iocoder.yudao.framework.ai.chat.ChatResponse; -import cn.iocoder.yudao.framework.ai.config.AiClient; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.ai.service.ChatService; import cn.iocoder.yudao.module.ai.vo.ChatReq; @@ -38,7 +37,6 @@ import java.util.function.Consumer; public class ChatController { @Autowired - private AiClient aiClient; private final ChatService chatService; @Operation(summary = "聊天-chat", description = "这个一般等待时间比较久,需要全部完成才会返回!") @@ -52,30 +50,7 @@ public class ChatController { @GetMapping(value = "/chatStream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public SseEmitter chatStream(@Validated @ModelAttribute ChatReq req) { Utf8SseEmitter sseEmitter = new Utf8SseEmitter(); - Flux streamResponse = chatService.chatStream(req); - streamResponse.subscribe( - new Consumer() { - @Override - public void accept(ChatResponse chatResponse) { - String content = chatResponse.getResults().get(0).getOutput().getContent(); - try { - sseEmitter.send(content, MediaType.APPLICATION_JSON); - } catch (IOException e) { - log.error("发送异常{}", ExceptionUtil.getMessage(e)); - // 如果不是因为关闭而抛出异常,则重新连接 - sseEmitter.completeWithError(e); - } - } - }, - error -> { - // - log.error("subscribe错误 {}", ExceptionUtil.getMessage(error)); - }, - () -> { - log.info("发送完成!"); - sseEmitter.complete(); - } - ); + chatService.chatStream(req, sseEmitter); return sseEmitter; } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatService.java index f72c52493..fd19d822a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatService.java @@ -1,9 +1,7 @@ package cn.iocoder.yudao.module.ai.service; -import cn.iocoder.yudao.framework.ai.chat.ChatResponse; -import cn.iocoder.yudao.module.ai.enums.AiClientNameEnum; +import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; import cn.iocoder.yudao.module.ai.vo.ChatReq; -import reactor.core.publisher.Flux; /** * 聊天 chat @@ -26,7 +24,8 @@ public interface ChatService { * chat stream * * @param req + * @param sseEmitter * @return */ - Flux chatStream(ChatReq req); + void chatStream(ChatReq req, Utf8SseEmitter sseEmitter); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java index 6fe226181..a2d8e54e2 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java @@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.ai.config.AiClient; import cn.iocoder.yudao.framework.common.exception.ServerException; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; +import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; import cn.iocoder.yudao.module.ai.dataobject.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dataobject.AiChatMessageDO; import cn.iocoder.yudao.module.ai.dataobject.AiChatRoleDO; @@ -21,10 +22,14 @@ import cn.iocoder.yudao.module.ai.service.ChatService; import cn.iocoder.yudao.module.ai.vo.ChatReq; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import reactor.core.publisher.Flux; +import java.io.IOException; +import java.util.function.Consumer; + /** * 聊天 service * @@ -51,25 +56,17 @@ public class ChatServiceImpl implements ChatService { */ @Transactional(rollbackFor = Exception.class) public String chat(ChatReq req) { + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 获取 client 类型 AiClientNameEnum clientNameEnum = AiClientNameEnum.valueOfName(req.getModal()); // 获取 对话类型(新建还是继续) ChatConversationTypeEnum chatConversationTypeEnum = ChatConversationTypeEnum.valueOfType(req.getConversationType()); + AiChatConversationDO aiChatConversationDO = getChatConversationNoExistToCreate(req, chatConversationTypeEnum, loginUserId); - AiChatConversationDO aiChatConversationDO; - Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); - if (ChatConversationTypeEnum.NEW == chatConversationTypeEnum) { - // 创建一个新的对话 - aiChatConversationDO = createNewChatConversation(req, loginUserId); - } else { - // 继续对话 - if (req.getConversationId() == null) { - throw new ServerException(ErrorCodeConstants.AI_CHAT_CONTINUE_CONVERSATION_ID_NOT_NULL); - } - aiChatConversationDO = aiChatConversationMapper.selectById(req.getConversationId()); - } + // 保存 chat message + saveChatMessage(req, aiChatConversationDO.getId(), loginUserId); - String content; + String content = null; try { // 创建 chat 需要的 Prompt Prompt prompt = new Prompt(req.getPrompt()); @@ -81,13 +78,19 @@ public class ChatServiceImpl implements ChatService { content = call.getResult().getOutput().getContent(); } catch (Exception e) { content = ExceptionUtil.getMessage(e); + } finally { + // 保存 chat message + saveSystemChatMessage(req, aiChatConversationDO.getId(), loginUserId, content); } + return content; + } + private void saveChatMessage(ChatReq req, Long chatConversationId, Long loginUserId) { // 增加 chat message 记录 aiChatMessageMapper.insert( new AiChatMessageDO() .setId(null) - .setChatConversationId(aiChatConversationDO.getId()) + .setChatConversationId(chatConversationId) .setUserId(loginUserId) .setMessage(req.getPrompt()) .setMessageType(MessageType.USER.getValue()) @@ -98,7 +101,39 @@ public class ChatServiceImpl implements ChatService { // chat count 先+1 aiChatConversationMapper.updateIncrChatCount(req.getConversationId()); - return content; + } + + public void saveSystemChatMessage(ChatReq req, Long chatConversationId, Long loginUserId, String systemPrompts) { + // 增加 chat message 记录 + aiChatMessageMapper.insert( + new AiChatMessageDO() + .setId(null) + .setChatConversationId(chatConversationId) + .setUserId(loginUserId) + .setMessage(systemPrompts) + .setMessageType(MessageType.SYSTEM.getValue()) + .setTopK(req.getTopK()) + .setTopP(req.getTopP()) + .setTemperature(req.getTemperature()) + ); + + // chat count 先+1 + aiChatConversationMapper.updateIncrChatCount(req.getConversationId()); + } + + private AiChatConversationDO getChatConversationNoExistToCreate(ChatReq req, ChatConversationTypeEnum chatConversationTypeEnum, Long loginUserId) { + AiChatConversationDO aiChatConversationDO; + if (ChatConversationTypeEnum.NEW == chatConversationTypeEnum) { + // 创建一个新的对话 + aiChatConversationDO = createNewChatConversation(req, loginUserId); + } else { + // 继续对话 + if (req.getConversationId() == null) { + throw new ServerException(ErrorCodeConstants.AI_CHAT_CONTINUE_CONVERSATION_ID_NOT_NULL); + } + aiChatConversationDO = aiChatConversationMapper.selectById(req.getConversationId()); + } + return aiChatConversationDO; } private AiChatConversationDO createNewChatConversation(ChatReq req, Long loginUserId) { @@ -133,16 +168,52 @@ public class ChatServiceImpl implements ChatService { * chat stream * * @param req + * @param sseEmitter * @return */ @Override - public Flux chatStream(ChatReq req) { + public void chatStream(ChatReq req, Utf8SseEmitter sseEmitter) { + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + // 获取 client 类型 AiClientNameEnum clientNameEnum = AiClientNameEnum.valueOfName(req.getModal()); + // 获取 对话类型(新建还是继续) + ChatConversationTypeEnum chatConversationTypeEnum = ChatConversationTypeEnum.valueOfType(req.getConversationType()); + AiChatConversationDO aiChatConversationDO = getChatConversationNoExistToCreate(req, chatConversationTypeEnum, loginUserId); // 创建 chat 需要的 Prompt Prompt prompt = new Prompt(req.getPrompt()); req.setTopK(req.getTopK()); req.setTopP(req.getTopP()); req.setTemperature(req.getTemperature()); - return aiClient.stream(prompt, clientNameEnum.getName()); + // 保存 chat message + saveChatMessage(req, aiChatConversationDO.getId(), loginUserId); + Flux streamResponse = aiClient.stream(prompt, clientNameEnum.getName()); + + StringBuffer contentBuffer = new StringBuffer(); + streamResponse.subscribe( + new Consumer() { + @Override + public void accept(ChatResponse chatResponse) { + String content = chatResponse.getResults().get(0).getOutput().getContent(); + try { + contentBuffer.append(content); + sseEmitter.send(content, MediaType.APPLICATION_JSON); + } catch (IOException e) { + log.error("发送异常{}", ExceptionUtil.getMessage(e)); + // 如果不是因为关闭而抛出异常,则重新连接 + sseEmitter.completeWithError(e); + } + } + }, + error -> { + // + log.error("subscribe错误 {}", ExceptionUtil.getMessage(error)); + }, + () -> { + log.info("发送完成!"); + sseEmitter.complete(); + // 保存 chat message + saveSystemChatMessage(req, aiChatConversationDO.getId(), loginUserId, contentBuffer.toString()); + } + ); } } From 00c2ca8b48267b464327a1a14cc6fa1fab34625d Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 18 Apr 2024 16:59:15 +0800 Subject: [PATCH 108/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0chat=20=E5=AF=B9?= =?UTF-8?q?=E8=AF=9D=EF=BC=8C=E5=88=97=E8=A1=A8=E3=80=81=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E3=80=81=E5=8D=95=E4=B8=AA=E3=80=81=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ChatConversationController.java | 58 +++++++++++++++ .../ai/convert/ChatConversationConvert.java | 37 ++++++++++ .../ai/service/ChatConversationService.java | 48 ++++++++++++ .../impl/ChatConversationServiceImpl.java | 74 +++++++++++++++++++ .../ai/vo/ChatConversationCreateReq.java | 23 ++++++ .../ai/vo/ChatConversationCreateRes.java | 11 +++ .../module/ai/vo/ChatConversationListReq.java | 20 +++++ .../module/ai/vo/ChatConversationRes.java | 11 +++ 8 files changed, 282 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatConversationConvert.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatConversationService.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateReq.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateRes.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationListReq.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationRes.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java new file mode 100644 index 000000000..4fc1b7fd8 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.ai.controller; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.ai.service.ChatConversationService; +import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateReq; +import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateRes; +import cn.iocoder.yudao.module.ai.vo.ChatConversationListReq; +import cn.iocoder.yudao.module.ai.vo.ChatConversationRes; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * ia 模块 + * + * @author fansili + * @time 2024/4/13 17:44 + * @since 1.0 + */ +@Tag(name = "A2聊天-对话") +@RestController +@RequestMapping("/ai/chat/conversation") +@Slf4j +@AllArgsConstructor +public class ChatConversationController { + + private final ChatConversationService chatConversationService; + + @Operation(summary = "创建 - 对话") + @PostMapping("/create") + public CommonResult create(@RequestBody @Validated ChatConversationCreateReq req) { + return CommonResult.success(chatConversationService.create(req)); + } + + @Operation(summary = "获取 - 获取对话") + @GetMapping("/getConversation") + public CommonResult getConversation(@RequestParam("id") Long id) { + return CommonResult.success(chatConversationService.getConversation(id)); + } + + @Operation(summary = "获取 - 获取对话list") + @GetMapping("/listConversation") + public CommonResult> listConversation(@ModelAttribute @Validated ChatConversationListReq req) { + return CommonResult.success(chatConversationService.listConversation(req)); + } + + @Operation(summary = "删除") + @DeleteMapping("/listConversation") + public CommonResult delete(@RequestParam("id") Long id) { + chatConversationService.delete(id); + return CommonResult.success(null); + } +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatConversationConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatConversationConvert.java new file mode 100644 index 000000000..3ecabcc7c --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatConversationConvert.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.ai.convert; + +import cn.iocoder.yudao.module.ai.dataobject.AiChatConversationDO; +import cn.iocoder.yudao.module.ai.vo.ChatConversationRes; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 聊天 对话 convert + * + * @author fansili + * @time 2024/4/18 16:39 + * @since 1.0 + */ +@Mapper +public interface ChatConversationConvert { + + ChatConversationConvert INSTANCE = Mappers.getMapper(ChatConversationConvert.class); + + /** + * 转换 - 多个 ChatConversationRes + * + * @param top100Conversation + * @return + */ + List covnertChatConversationResList(List top100Conversation); + + /** + * 转换 - 单个 ChatConversationRes + * + * @param aiChatConversationDO + * @return + */ + ChatConversationRes covnertChatConversationRes(AiChatConversationDO aiChatConversationDO); +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatConversationService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatConversationService.java new file mode 100644 index 000000000..cb52f725c --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatConversationService.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.ai.service; + +import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateReq; +import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateRes; +import cn.iocoder.yudao.module.ai.vo.ChatConversationListReq; +import cn.iocoder.yudao.module.ai.vo.ChatConversationRes; + +import java.util.List; + +/** + * chat 对话 + * + * @fansili + * @since v1.0 + */ +public interface ChatConversationService { + + /** + * 对话 - 创建 + * + * @param req + * @return + */ + ChatConversationRes create(ChatConversationCreateReq req); + + /** + * 获取 - 对话 + * + * @param id + * @return + */ + ChatConversationRes getConversation(Long id); + + /** + * 获取 - 对话列表 + * + * @param req + * @return + */ + List listConversation(ChatConversationListReq req); + + /** + * 删除 - 根据id + * + * @param id + */ + void delete(Long id); +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java new file mode 100644 index 000000000..2278df935 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.ai.service.impl; + +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.module.ai.convert.ChatConversationConvert; +import cn.iocoder.yudao.module.ai.dataobject.AiChatConversationDO; +import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; +import cn.iocoder.yudao.module.ai.service.ChatConversationService; +import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateReq; +import cn.iocoder.yudao.module.ai.vo.ChatConversationListReq; +import cn.iocoder.yudao.module.ai.vo.ChatConversationRes; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * chat 对话 + * + * @fansili + * @since v1.0 + */ +@Service +@Slf4j +@AllArgsConstructor +public class ChatConversationServiceImpl implements ChatConversationService { + + private final AiChatConversationMapper aiChatConversationMapper; + + @Override + public ChatConversationRes create(ChatConversationCreateReq req) { + // 获取用户id + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + // 查询最新的对话 + AiChatConversationDO latestConversation = aiChatConversationMapper.selectLatestConversation(loginUserId); + // 如果有对话没有被使用过,那就返回这个 + if (latestConversation != null && latestConversation.getChatCount() <= 0) { + return ChatConversationConvert.INSTANCE.covnertChatConversationRes(latestConversation); + } + // 创建新的 Conversation + AiChatConversationDO insertConversation = new AiChatConversationDO(); + insertConversation.setId(null); + insertConversation.setUserId(loginUserId); + insertConversation.setChatRoleId(null); + insertConversation.setChatRoleName(null); + insertConversation.setChatTitle(null); + insertConversation.setChatCount(0); + insertConversation.setChatType(req.getChatType()); + aiChatConversationMapper.insert(insertConversation); + // 转换 res + return ChatConversationConvert.INSTANCE.covnertChatConversationRes(latestConversation); + } + + @Override + public ChatConversationRes getConversation(Long id) { + AiChatConversationDO aiChatConversationDO = aiChatConversationMapper.selectById(id); + return ChatConversationConvert.INSTANCE.covnertChatConversationRes(aiChatConversationDO); + } + + @Override + public List listConversation(ChatConversationListReq req) { + // 获取用户id + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + // 查询前100对话 + List top100Conversation + = aiChatConversationMapper.selectTop100Conversation(loginUserId, req.getSearch()); + return ChatConversationConvert.INSTANCE.covnertChatConversationResList(top100Conversation); + } + + @Override + public void delete(Long id) { + aiChatConversationMapper.deleteById(id); + } +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateReq.java new file mode 100644 index 000000000..a39c9e2ed --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateReq.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.ai.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 聊天对话 + * + * @author fansili + * @time 2024/4/18 16:24 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class ChatConversationCreateReq { + + @Schema(description = "对话类型(roleChat、userChat)") + @NotNull(message = "聊天类型不能为空!") + private String chatType; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateRes.java new file mode 100644 index 000000000..3117aad9d --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateRes.java @@ -0,0 +1,11 @@ +package cn.iocoder.yudao.module.ai.vo; + +/** + * 聊天对话 res + * + * @author fansili + * @time 2024/4/18 16:24 + * @since 1.0 + */ +public class ChatConversationCreateRes { +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationListReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationListReq.java new file mode 100644 index 000000000..846c8b2bc --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationListReq.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.ai.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 聊天对话 list req + * + * @author fansili + * @time 2024/4/18 16:24 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class ChatConversationListReq { + + @Schema(description = "查询根据title") + private String search; +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationRes.java new file mode 100644 index 000000000..95eca40e3 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationRes.java @@ -0,0 +1,11 @@ +package cn.iocoder.yudao.module.ai.vo; + +/** + * 聊天对话 res + * + * @author fansili + * @time 2024/4/18 16:24 + * @since 1.0 + */ +public class ChatConversationRes { +} From 66d020892019ead137c71a9263c2b99ca0103a3c Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 18 Apr 2024 16:59:46 +0800 Subject: [PATCH 109/684] =?UTF-8?q?1=E3=80=81=E5=A2=9E=E5=8A=A0=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E6=9C=80=E6=96=B0=E7=9A=84=E5=AF=B9=E8=AF=9D=202?= =?UTF-8?q?=E3=80=81=E5=A2=9E=E5=8A=A0=E8=8E=B7=E5=8F=96top100=E7=9A=84?= =?UTF-8?q?=E5=AF=B9=E8=AF=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/dataobject/AiChatConversationDO.java | 4 +- .../ai/mapper/AiChatConversationMapper.java | 37 +++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatConversationDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatConversationDO.java index 8f1956392..c48baa1c6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatConversationDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatConversationDO.java @@ -30,10 +30,10 @@ public class AiChatConversationDO extends BaseDO { @Schema(description = "chat角色名称") private String chatRoleName; - @Schema(description = "对话标题(有程序自动生成)") + @Schema(description = "聊天标题(有程序自动生成)") private String chatTitle; - @Schema(description = "对话标题(有程序自动生成)") + @Schema(description = "聊天次数(有程序自动生成)") private Integer chatCount; @Schema(description = "对话类型(roleChat、userChat)") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java index 6e018a892..f6f58e7a0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java @@ -1,12 +1,19 @@ package cn.iocoder.yudao.module.ai.mapper; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.module.ai.dataobject.AiChatConversationDO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Update; import org.springframework.stereotype.Repository; +import java.util.List; + /** * message mapper * @@ -21,4 +28,34 @@ public interface AiChatConversationMapper extends BaseMapperX pageResult = selectPage(new PageParam().setPageNo(1).setPageSize(1), + new LambdaQueryWrapper() + .eq(AiChatConversationDO::getUserId, loginUserId) + .orderByDesc(AiChatConversationDO::getId)); + if (CollUtil.isEmpty(pageResult.getList())) { + return null; + } + return pageResult.getList().get(0); + } + + /** + * 查询 - 前100 + * + * @param search + */ + default List selectTop100Conversation(Long loginUserId, String search) { + LambdaQueryWrapper queryWrapper + = new LambdaQueryWrapper().eq(AiChatConversationDO::getUserId, loginUserId); + if (!StrUtil.isBlank(search)) { + queryWrapper.like(AiChatConversationDO::getChatTitle, search); + } + queryWrapper.orderByDesc(AiChatConversationDO::getId); + return selectPage(new PageParam().setPageNo(1).setPageSize(100), queryWrapper).getList(); + } } From e8f4dd790599dc172362235b295e4b570b297eef Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 18 Apr 2024 17:00:45 +0800 Subject: [PATCH 110/684] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AF=B9=E8=AF=9D=20?= =?UTF-8?q?res=20=E8=BF=94=E5=9B=9E=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/vo/ChatConversationRes.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationRes.java index 95eca40e3..3a2bb16d5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationRes.java @@ -1,5 +1,9 @@ package cn.iocoder.yudao.module.ai.vo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + /** * 聊天对话 res * @@ -7,5 +11,28 @@ package cn.iocoder.yudao.module.ai.vo; * @time 2024/4/18 16:24 * @since 1.0 */ +@Data +@Accessors(chain = true) public class ChatConversationRes { + + @Schema(description = "id") + private Long id; + + @Schema(description = "用户id") + private Long userId; + + @Schema(description = "chat角色Id") + private Long chatRoleId; + + @Schema(description = "chat角色名称") + private String chatRoleName; + + @Schema(description = "聊天标题(有程序自动生成)") + private String chatTitle; + + @Schema(description = "聊天次数(有程序自动生成)") + private Integer chatCount; + + @Schema(description = "对话类型(roleChat、userChat)") + private String chatType; } From a33ea4aa820ce49d4bc42d0a6b89e4f206374eaf Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 18 Apr 2024 17:08:45 +0800 Subject: [PATCH 111/684] =?UTF-8?q?=E5=88=A0=E9=99=A4=20=E5=AF=B9=E8=AF=9D?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/iocoder/yudao/module/ai/vo/ChatReq.java | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java index 67828e6ba..87ac95544 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java @@ -17,26 +17,23 @@ import lombok.experimental.Accessors; @Accessors(chain = true) public class ChatReq { - @Schema(description = "chat角色模板") - private Long chatRoleId; + @Schema(description = "ai模型(查看 AiClientNameEnum)") + @NotNull(message = "模型不能为空!") + @Size(max = 30, message = "模型字符最大30个字符!") + private String modal; @Schema(description = "对话Id") + @NotNull(message = "对话id不能为空") private Long conversationId; - @Schema(description = "对话类型(new、continue),如果是new会创建一个新的对话,continue就会继续对话!") - @NotNull(message = "对话类型,不能为空!") - private String conversationType; + @Schema(description = "chat角色模板") + private Long chatRoleId; @NotNull(message = "提示词不能为空!") @Size(max = 5000, message = "提示词最大5000个字符!") @Schema(description = "填入固定值,1 issues, 2 pr") private String prompt; - @Schema(description = "ai模型(查看 AiClientNameEnum)") - @NotNull(message = "模型不能为空!") - @Size(max = 30, message = "模型字符最大30个字符!") - private String modal; - @Schema(description = "用于控制随机性和多样性的温度参数") private Double temperature; From 2ce5c805de98fc8594d808f4725edfe9f3ed15b0 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 18 Apr 2024 17:09:00 +0800 Subject: [PATCH 112/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20chat=E5=AF=B9?= =?UTF-8?q?=E8=AF=9D=E4=B8=8D=E5=AD=98=E5=9C=A8errorCode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/iocoder/yudao/module/ai/ErrorCodeConstants.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index d4ecf4df8..e3e1c869d 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -15,5 +15,14 @@ public interface ErrorCodeConstants { ErrorCode AI_MODULE_NOT_SUPPORTED = new ErrorCode(1_022_000_000, "AI模型暂不支持!"); ErrorCode AI_CHAT_ROLE_NOT_EXISTENT = new ErrorCode(1_022_000_001, "AI Role 不存在!");; + + ErrorCode AI_CHAT_CONTINUE_CONVERSATION_ID_NOT_NULL = new ErrorCode(1_022_000_002, "chat 继续对话,对话id不能为空!");; + + + + ErrorCode AI_CHAT_CONTINUE_NOT_EXIST = new ErrorCode(1_022_000_020, "chat对话不存在!");; + + + } From 97d4e56c8136a6f6306f7a67432c51fc8ec3e05b Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 18 Apr 2024 17:09:27 +0800 Subject: [PATCH 113/684] =?UTF-8?q?=E5=AF=B9=E8=AF=9D=E4=B8=8D=E5=AD=98?= =?UTF-8?q?=E5=9C=A8=E6=97=B6=EF=BC=8Cthow=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/service/impl/ChatConversationServiceImpl.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java index 2278df935..0dd533959 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.ai.service.impl; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.convert.ChatConversationConvert; import cn.iocoder.yudao.module.ai.dataobject.AiChatConversationDO; import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; @@ -54,6 +56,9 @@ public class ChatConversationServiceImpl implements ChatConversationService { @Override public ChatConversationRes getConversation(Long id) { AiChatConversationDO aiChatConversationDO = aiChatConversationMapper.selectById(id); + if (aiChatConversationDO == null) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CHAT_CONTINUE_NOT_EXIST); + } return ChatConversationConvert.INSTANCE.covnertChatConversationRes(aiChatConversationDO); } From 25523fd53ee0d9cd9657c14f85f7f298a6094728 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 18 Apr 2024 17:10:08 +0800 Subject: [PATCH 114/684] =?UTF-8?q?=E8=B0=83=E6=95=B4=20chat=20=E5=92=8C?= =?UTF-8?q?=20steamChat=20=E8=8E=B7=E5=8F=96=E5=AF=B9=E8=AF=9D=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/service/impl/ChatServiceImpl.java | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java index a2d8e54e2..913944dc0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java @@ -18,7 +18,9 @@ import cn.iocoder.yudao.module.ai.enums.ChatTypeEnum; import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.mapper.AiChatMessageMapper; import cn.iocoder.yudao.module.ai.mapper.AiChatRoleMapper; +import cn.iocoder.yudao.module.ai.service.ChatConversationService; import cn.iocoder.yudao.module.ai.service.ChatService; +import cn.iocoder.yudao.module.ai.vo.ChatConversationRes; import cn.iocoder.yudao.module.ai.vo.ChatReq; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -46,6 +48,7 @@ public class ChatServiceImpl implements ChatService { private final AiChatRoleMapper aiChatRoleMapper; private final AiChatMessageMapper aiChatMessageMapper; private final AiChatConversationMapper aiChatConversationMapper; + private final ChatConversationService chatConversationService; /** @@ -59,13 +62,10 @@ public class ChatServiceImpl implements ChatService { Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 获取 client 类型 AiClientNameEnum clientNameEnum = AiClientNameEnum.valueOfName(req.getModal()); - // 获取 对话类型(新建还是继续) - ChatConversationTypeEnum chatConversationTypeEnum = ChatConversationTypeEnum.valueOfType(req.getConversationType()); - AiChatConversationDO aiChatConversationDO = getChatConversationNoExistToCreate(req, chatConversationTypeEnum, loginUserId); - + // 获取对话信息 + ChatConversationRes conversationRes = chatConversationService.getConversation(req.getConversationId()); // 保存 chat message - saveChatMessage(req, aiChatConversationDO.getId(), loginUserId); - + saveChatMessage(req, conversationRes.getId(), loginUserId); String content = null; try { // 创建 chat 需要的 Prompt @@ -80,7 +80,7 @@ public class ChatServiceImpl implements ChatService { content = ExceptionUtil.getMessage(e); } finally { // 保存 chat message - saveSystemChatMessage(req, aiChatConversationDO.getId(), loginUserId, content); + saveSystemChatMessage(req, conversationRes.getId(), loginUserId, content); } return content; } @@ -176,16 +176,15 @@ public class ChatServiceImpl implements ChatService { Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 获取 client 类型 AiClientNameEnum clientNameEnum = AiClientNameEnum.valueOfName(req.getModal()); - // 获取 对话类型(新建还是继续) - ChatConversationTypeEnum chatConversationTypeEnum = ChatConversationTypeEnum.valueOfType(req.getConversationType()); - AiChatConversationDO aiChatConversationDO = getChatConversationNoExistToCreate(req, chatConversationTypeEnum, loginUserId); + // 获取对话信息 + ChatConversationRes conversationRes = chatConversationService.getConversation(req.getConversationId()); // 创建 chat 需要的 Prompt Prompt prompt = new Prompt(req.getPrompt()); req.setTopK(req.getTopK()); req.setTopP(req.getTopP()); req.setTemperature(req.getTemperature()); // 保存 chat message - saveChatMessage(req, aiChatConversationDO.getId(), loginUserId); + saveChatMessage(req, conversationRes.getId(), loginUserId); Flux streamResponse = aiClient.stream(prompt, clientNameEnum.getName()); StringBuffer contentBuffer = new StringBuffer(); @@ -212,7 +211,7 @@ public class ChatServiceImpl implements ChatService { log.info("发送完成!"); sseEmitter.complete(); // 保存 chat message - saveSystemChatMessage(req, aiChatConversationDO.getId(), loginUserId, contentBuffer.toString()); + saveSystemChatMessage(req, conversationRes.getId(), loginUserId, contentBuffer.toString()); } ); } From 2e4dca2d6f7c6e8fe88c667e443dfb18f3b882f4 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 18 Apr 2024 17:10:44 +0800 Subject: [PATCH 115/684] =?UTF-8?q?=E5=88=A0=E9=99=A4=20chat=20old?= =?UTF-8?q?=E5=AF=B9=E8=AF=9D=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/service/impl/ChatServiceImpl.java | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java index 913944dc0..069de7092 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java @@ -13,7 +13,6 @@ import cn.iocoder.yudao.module.ai.dataobject.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dataobject.AiChatMessageDO; import cn.iocoder.yudao.module.ai.dataobject.AiChatRoleDO; import cn.iocoder.yudao.module.ai.enums.AiClientNameEnum; -import cn.iocoder.yudao.module.ai.enums.ChatConversationTypeEnum; import cn.iocoder.yudao.module.ai.enums.ChatTypeEnum; import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.mapper.AiChatMessageMapper; @@ -121,21 +120,6 @@ public class ChatServiceImpl implements ChatService { aiChatConversationMapper.updateIncrChatCount(req.getConversationId()); } - private AiChatConversationDO getChatConversationNoExistToCreate(ChatReq req, ChatConversationTypeEnum chatConversationTypeEnum, Long loginUserId) { - AiChatConversationDO aiChatConversationDO; - if (ChatConversationTypeEnum.NEW == chatConversationTypeEnum) { - // 创建一个新的对话 - aiChatConversationDO = createNewChatConversation(req, loginUserId); - } else { - // 继续对话 - if (req.getConversationId() == null) { - throw new ServerException(ErrorCodeConstants.AI_CHAT_CONTINUE_CONVERSATION_ID_NOT_NULL); - } - aiChatConversationDO = aiChatConversationMapper.selectById(req.getConversationId()); - } - return aiChatConversationDO; - } - private AiChatConversationDO createNewChatConversation(ChatReq req, Long loginUserId) { // 获取 chat 角色 String chatRoleName = null; From b68117c846947f9835fcc135861688798ce38bc6 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 18 Apr 2024 17:31:05 +0800 Subject: [PATCH 116/684] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=AF=B9=E8=AF=9D=20?= =?UTF-8?q?create=20res?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/vo/ChatConversationCreateRes.java | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateRes.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateRes.java deleted file mode 100644 index 3117aad9d..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateRes.java +++ /dev/null @@ -1,11 +0,0 @@ -package cn.iocoder.yudao.module.ai.vo; - -/** - * 聊天对话 res - * - * @author fansili - * @time 2024/4/18 16:24 - * @since 1.0 - */ -public class ChatConversationCreateRes { -} From 97c12d193203c380f36f4839004d1b9e435f4cdb Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 18 Apr 2024 17:31:58 +0800 Subject: [PATCH 117/684] =?UTF-8?q?conversation=20=E5=85=85=E6=BB=A1=20tit?= =?UTF-8?q?le=20=E5=92=8C=20count?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/dataobject/AiChatConversationDO.java | 11 ++++---- .../module/ai/dataobject/AiChatMessageDO.java | 26 +++---------------- .../ai/mapper/AiChatConversationMapper.java | 2 +- .../impl/ChatConversationServiceImpl.java | 4 +-- .../ai/service/impl/ChatServiceImpl.java | 4 +-- .../module/ai/vo/ChatConversationRes.java | 10 +++---- 6 files changed, 19 insertions(+), 38 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatConversationDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatConversationDO.java index c48baa1c6..79bb281e7 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatConversationDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatConversationDO.java @@ -30,13 +30,12 @@ public class AiChatConversationDO extends BaseDO { @Schema(description = "chat角色名称") private String chatRoleName; - @Schema(description = "聊天标题(有程序自动生成)") - private String chatTitle; + @Schema(description = "标题(有程序自动生成)") + private String title; + + @Schema(description = "对话类型(roleChat、userChat)") + private String type; @Schema(description = "聊天次数(有程序自动生成)") private Integer chatCount; - - @Schema(description = "对话类型(roleChat、userChat)") - private String chatType; - } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatMessageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatMessageDO.java index 9047180ec..53d274ae1 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatMessageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatMessageDO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.ai.dataobject; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.experimental.Accessors; -import java.util.Date; - /** * ai 聊天 message * @@ -13,7 +13,8 @@ import java.util.Date; */ @Data @Accessors(chain = true) -public class AiChatMessageDO { +@TableName("ai_chat_message") +public class AiChatMessageDO extends BaseDO { /** * 编号,作为每条聊天记录的唯一标识符 @@ -58,23 +59,4 @@ public class AiChatMessageDO { */ private Double temperature; - /** - * 创建该记录的操作员ID - */ - private Long createdBy; - - /** - * 记录创建的时间戳 - */ - private Date createdTime; - - /** - * 最后更新该记录的操作员ID - */ - private Long updatedBy; - - /** - * 记录最后更新的时间戳 - */ - private Date updatedTime; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java index f6f58e7a0..bfc7bc0aa 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java @@ -53,7 +53,7 @@ public interface AiChatConversationMapper extends BaseMapperX queryWrapper = new LambdaQueryWrapper().eq(AiChatConversationDO::getUserId, loginUserId); if (!StrUtil.isBlank(search)) { - queryWrapper.like(AiChatConversationDO::getChatTitle, search); + queryWrapper.like(AiChatConversationDO::getTitle, search); } queryWrapper.orderByDesc(AiChatConversationDO::getId); return selectPage(new PageParam().setPageNo(1).setPageSize(100), queryWrapper).getList(); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java index 0dd533959..52af7f7b5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java @@ -45,9 +45,9 @@ public class ChatConversationServiceImpl implements ChatConversationService { insertConversation.setUserId(loginUserId); insertConversation.setChatRoleId(null); insertConversation.setChatRoleName(null); - insertConversation.setChatTitle(null); + insertConversation.setTitle(null); insertConversation.setChatCount(0); - insertConversation.setChatType(req.getChatType()); + insertConversation.setType(req.getChatType()); aiChatConversationMapper.insert(insertConversation); // 转换 res return ChatConversationConvert.INSTANCE.covnertChatConversationRes(latestConversation); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java index 069de7092..bf3c9ff62 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java @@ -141,9 +141,9 @@ public class ChatServiceImpl implements ChatService { .setUserId(loginUserId) .setChatRoleId(req.getChatRoleId()) .setChatRoleName(chatRoleName) - .setChatType(chatTypeEnum.getType()) + .setType(chatTypeEnum.getType()) .setChatCount(1) - .setChatTitle(req.getPrompt().substring(0, 20) + "..."); + .setTitle(req.getPrompt().substring(0, 20) + "..."); aiChatConversationMapper.insert(insertChatConversation); return insertChatConversation; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationRes.java index 3a2bb16d5..aa11c0464 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationRes.java @@ -27,12 +27,12 @@ public class ChatConversationRes { @Schema(description = "chat角色名称") private String chatRoleName; - @Schema(description = "聊天标题(有程序自动生成)") - private String chatTitle; + @Schema(description = "标题(有程序自动生成)") + private String title; + + @Schema(description = "对话类型(roleChat、userChat)") + private String type; @Schema(description = "聊天次数(有程序自动生成)") private Integer chatCount; - - @Schema(description = "对话类型(roleChat、userChat)") - private String chatType; } From 1a08be9a27689c983d95a33ff0a8b3ae22e1e8a1 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 18 Apr 2024 17:32:30 +0800 Subject: [PATCH 118/684] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=B2=A1=E7=94=A8?= =?UTF-8?q?=E7=9A=84=20import?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/controller/ChatConversationController.java | 1 - .../iocoder/yudao/module/ai/service/ChatConversationService.java | 1 - 2 files changed, 2 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java index 4fc1b7fd8..110937c61 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.ai.controller; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.ai.service.ChatConversationService; import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateReq; -import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateRes; import cn.iocoder.yudao.module.ai.vo.ChatConversationListReq; import cn.iocoder.yudao.module.ai.vo.ChatConversationRes; import io.swagger.v3.oas.annotations.Operation; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatConversationService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatConversationService.java index cb52f725c..e5073bd6b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatConversationService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatConversationService.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateReq; -import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateRes; import cn.iocoder.yudao.module.ai.vo.ChatConversationListReq; import cn.iocoder.yudao.module.ai.vo.ChatConversationRes; From 27bfb0d25dabdfb9b4310af0ca3026190f7914cb Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 18 Apr 2024 17:37:28 +0800 Subject: [PATCH 119/684] =?UTF-8?q?=E5=85=B3=E9=97=AD=E7=A7=9F=E6=88=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-server/src/main/resources/application-local.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 87b40adb2..8fede4785 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -271,6 +271,8 @@ yudao: enable: false demo: false # 关闭演示模式 tencent-lbs-key: TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E # QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc + tenant: + enable: false justauth: enabled: true From de8b80699eca2f0c50063e271592fce61a23a48a Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 19 Apr 2024 06:18:24 +0800 Subject: [PATCH 120/684] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20http=20=E8=AF=B7?= =?UTF-8?q?=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/http/chat-conversation.http | 36 +++++++++++++++++++ .../src/main/resources/http/chat.http | 2 +- .../main/resources/http/http-client.env.json | 5 ++- 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-conversation.http diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-conversation.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-conversation.http new file mode 100644 index 000000000..2c0429883 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-conversation.http @@ -0,0 +1,36 @@ + +### 登录 详细使用 https://www.jetbrains.com/help/idea/testing-restful-web-services.html、https://www.cnblogs.com/crazymakercircle/p/14317222.html + +POST {{baseUrl}}/admin-api/system/auth/login +Content-Type: application/json +tenant-id: 1 + +{ + "username": "admin", + "password": "123456", + "captchaVerification": "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==", + "socialCode": "1024", + "socialState": "9b2ffbc1-7425-4155-9894-9d5c08541d62", + "socialCodeValid": true +} + + +> {% + client.log(`Today is ${$isoTimestamp}`) +%} + +### chat call +GET {{baseUrl}}/ai/chat?modal=qianWen&conversationId=111&prompt=中国好看吗? +tenant-id: 1 +Authorization: {{xtoken}} + + + +### chat call +GET {{baseUrl}}/ai/chatStream?prompt=苹果是什么颜色?&modal=yiYan3_5_8k +tenant-id: 1 +Authorization: {{token}} + + + + diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http index 1b645017e..e850d79a8 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http @@ -16,7 +16,7 @@ tenant-id: 1 } ### chat call -GET {{baseUrl}}/ai/chat?prompt=中国怎么样&modal=qianWen +GET {{baseUrl}}/ai/chat?modal=qianWen&conversationId=111&prompt=中国好看吗? tenant-id: 1 Authorization: {{token}} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json index c5adaf3e1..a76673c48 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json @@ -1,6 +1,9 @@ { + "global": { + "token": "--" + }, "dev": { "baseUrl": "http://127.0.0.1:48080", - "token": "Bearer 7d25823e225f4e0d8f9a96b0fa608649" + "token": "Bearer 2f807aacab534a4095cec0bac9c2af40" } } \ No newline at end of file From 8b84e24f96c9dee8cb1160f658407f2246243bd4 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 20 Apr 2024 17:49:58 +0800 Subject: [PATCH 121/684] =?UTF-8?q?dataobject=20=E7=A7=BB=E5=8A=A8?= =?UTF-8?q?=E5=88=B0=20dal=20=E9=87=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/cn/iocoder/yudao/module/ai/dal/1 | 0 .../module/ai/{ => dal}/dataobject/AiChatConversationDO.java | 2 +- .../module/ai/{ => dal}/dataobject/AiChatMessageDO.java | 2 +- .../yudao/module/ai/{ => dal}/dataobject/AiChatRoleDO.java | 5 ++++- 4 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/1 rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{ => dal}/dataobject/AiChatConversationDO.java (95%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{ => dal}/dataobject/AiChatMessageDO.java (96%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{ => dal}/dataobject/AiChatRoleDO.java (88%) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/1 b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/1 new file mode 100644 index 000000000..e69de29bb diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatConversationDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatConversationDO.java similarity index 95% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatConversationDO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatConversationDO.java index 79bb281e7..7f5a142b3 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatConversationDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatConversationDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.dataobject; +package cn.iocoder.yudao.module.ai.dal.dataobject; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.TableName; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatMessageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatMessageDO.java similarity index 96% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatMessageDO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatMessageDO.java index 53d274ae1..5ed372ab4 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatMessageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatMessageDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.dataobject; +package cn.iocoder.yudao.module.ai.dal.dataobject; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.TableName; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatRoleDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatRoleDO.java similarity index 88% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatRoleDO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatRoleDO.java index a049e3cfc..49ff42f87 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dataobject/AiChatRoleDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatRoleDO.java @@ -1,6 +1,8 @@ -package cn.iocoder.yudao.module.ai.dataobject; +package cn.iocoder.yudao.module.ai.dal.dataobject; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; import lombok.Data; import lombok.experimental.Accessors; @@ -16,6 +18,7 @@ public class AiChatRoleDO extends BaseDO { /** * 编号,表示聊天角色在数据库中的唯一标识符 */ + @TableId(type = IdType.AUTO) private Long id; /** From 01031bcdf65f87018e17763a0c143776d8583f37 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 20 Apr 2024 17:50:23 +0800 Subject: [PATCH 122/684] =?UTF-8?q?=E7=A7=BB=E5=8A=A8dataobject=20?= =?UTF-8?q?=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/convert/ChatConversationConvert.java | 2 +- .../yudao/module/ai/mapper/AiChatConversationMapper.java | 2 +- .../cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java | 2 +- .../cn/iocoder/yudao/module/ai/mapper/AiChatRoleMapper.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatConversationConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatConversationConvert.java index 3ecabcc7c..b2f6951e4 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatConversationConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatConversationConvert.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.ai.convert; -import cn.iocoder.yudao.module.ai.dataobject.AiChatConversationDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatConversationDO; import cn.iocoder.yudao.module.ai.vo.ChatConversationRes; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java index bfc7bc0aa..30aa1dff5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java @@ -5,7 +5,7 @@ import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.module.ai.dataobject.AiChatConversationDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatConversationDO; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java index 0545a7e2f..b121a0601 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.ai.mapper; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.module.ai.dataobject.AiChatMessageDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatMessageDO; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatRoleMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatRoleMapper.java index 32393c409..9f415cadf 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatRoleMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatRoleMapper.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.ai.mapper; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.module.ai.dataobject.AiChatRoleDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatRoleDO; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; From 5d6a3ff0b4eefee0c32d30fa0bc0be3d898e99d7 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 20 Apr 2024 17:50:56 +0800 Subject: [PATCH 123/684] =?UTF-8?q?service=20=E7=A7=BB=E5=8A=A8dataobject?= =?UTF-8?q?=20=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/service/impl/ChatConversationServiceImpl.java | 4 ++-- .../yudao/module/ai/service/impl/ChatServiceImpl.java | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java index 52af7f7b5..1318351cd 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.convert.ChatConversationConvert; -import cn.iocoder.yudao.module.ai.dataobject.AiChatConversationDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatConversationDO; import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.service.ChatConversationService; import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateReq; @@ -50,7 +50,7 @@ public class ChatConversationServiceImpl implements ChatConversationService { insertConversation.setType(req.getChatType()); aiChatConversationMapper.insert(insertConversation); // 转换 res - return ChatConversationConvert.INSTANCE.covnertChatConversationRes(latestConversation); + return ChatConversationConvert.INSTANCE.covnertChatConversationRes(insertConversation); } @Override diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java index bf3c9ff62..0bb7211cb 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java @@ -9,9 +9,9 @@ import cn.iocoder.yudao.framework.common.exception.ServerException; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; -import cn.iocoder.yudao.module.ai.dataobject.AiChatConversationDO; -import cn.iocoder.yudao.module.ai.dataobject.AiChatMessageDO; -import cn.iocoder.yudao.module.ai.dataobject.AiChatRoleDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatConversationDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatMessageDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatRoleDO; import cn.iocoder.yudao.module.ai.enums.AiClientNameEnum; import cn.iocoder.yudao.module.ai.enums.ChatTypeEnum; import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; From 83d17051bea6ea09377f2063764c5d841a644b73 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 20 Apr 2024 17:51:03 +0800 Subject: [PATCH 124/684] =?UTF-8?q?=E8=B0=83=E6=95=B4=20controller=20url?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/ChatConversationController.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java index 110937c61..d17a385a1 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java @@ -37,20 +37,20 @@ public class ChatConversationController { } @Operation(summary = "获取 - 获取对话") - @GetMapping("/getConversation") - public CommonResult getConversation(@RequestParam("id") Long id) { + @GetMapping("/{id}") + public CommonResult getConversation(@PathVariable("id") Long id) { return CommonResult.success(chatConversationService.getConversation(id)); } @Operation(summary = "获取 - 获取对话list") - @GetMapping("/listConversation") + @GetMapping("/list") public CommonResult> listConversation(@ModelAttribute @Validated ChatConversationListReq req) { return CommonResult.success(chatConversationService.listConversation(req)); } @Operation(summary = "删除") - @DeleteMapping("/listConversation") - public CommonResult delete(@RequestParam("id") Long id) { + @DeleteMapping("/{id}") + public CommonResult delete(@PathVariable("id") Long id) { chatConversationService.delete(id); return CommonResult.success(null); } From dc44fe1cf9843496a57aabfe210707c118a9dd9b Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 20 Apr 2024 17:53:41 +0800 Subject: [PATCH 125/684] =?UTF-8?q?=E4=B8=B4=E6=97=B6=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 0 -> 8196 bytes .../resources/http/chat-conversation.http | 32 +++++------------- .../main/resources/http/http-client.env.json | 2 +- 3 files changed, 10 insertions(+), 24 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..8406d508bca176e90b7f717667ad1c8f1a08dc3d GIT binary patch literal 8196 zcmeHM&2G~`5S~p!0GT#hp-9~~HE2>@BaY1uGG9Uw7wF59^rXHr68Gpim%4i$NcAu>4DZB~bD z=W?9M3{E10lgM`#d4(e6?!ehnokTm6W;6^K1|}Kc+PzATX`NPRtysUuE>`$vT1IdD zlnpbYISMJJ9=RCzs6kth5p7dIJ6Yv_g8Zx@tJIgs2E7A5RJFxTO}j=L@MxJ<=?P>5 z2v0-2*AO$5!kYx1^l6~!{?K&G(0!}>P}?2y9Mc6BVOx2xA z-!vO@iVYvJJBXzZ7JU_2UeS=36y!D{W28?bc$3hchW;`Y-2=u$EZ7y1I25Sp$}J6D zSN2xXF1+t)_z!=9=WC?lWtM#^WZAU+ec=1*{=~Uf#H&|M^*@mL3N}?6G6Rb?E>Gd0 z2M$9$e*|Y_(ZbcK7JOVy7uO@v{NP+IT2b>rjRl#cqGb*j(bJghBZ>nJ&-q)#Pm3Xe z_k2$$`u!$z`A@B+U@4^mY-w3h=A15Cxv21&GIz8;$)L>UBF<89!-?$Y?47Fbj?%sx z$|u`bw;u-SpxOK`O6AIhnW|N_X06xV-FVa;ID=u@agvvO^em1;_jvBO&jWw7S--Xt zM*}B_{6qo*&xgvZ7eVC3qfR`Gyi{Vl*@9KGYMb>Nhlj1!!}|+%>)zd?1^ckIwA94G zQuD#lQO&x3`_7|{&AqS}#T*8j$iI>Bs8-uY98OTN-%X-0j`-1cj8jqO=!`N@&f=Qq z`hV^8-~Z2O^d>CBfMI|c5S7*LYKJGM@WHjVjs6Cm8|#fTDIpkSISwhyambTD3^BK% h%9wU8$C<<#w156Xz#_ha^{-#^{x|P`nT_XX_ys@j>-_)# literal 0 HcmV?d00001 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-conversation.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-conversation.http index 2c0429883..02c147e03 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-conversation.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-conversation.http @@ -1,36 +1,22 @@ ### 登录 详细使用 https://www.jetbrains.com/help/idea/testing-restful-web-services.html、https://www.cnblogs.com/crazymakercircle/p/14317222.html -POST {{baseUrl}}/admin-api/system/auth/login +### 对话 - 创建对话 +POST {{baseUrl}}/ai/chat/conversation/create Content-Type: application/json -tenant-id: 1 +Authorization: {{token}} { - "username": "admin", - "password": "123456", - "captchaVerification": "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==", - "socialCode": "1024", - "socialState": "9b2ffbc1-7425-4155-9894-9d5c08541d62", - "socialCodeValid": true + "chatType": "userChat" } -> {% - client.log(`Today is ${$isoTimestamp}`) -%} - -### chat call -GET {{baseUrl}}/ai/chat?modal=qianWen&conversationId=111&prompt=中国好看吗? -tenant-id: 1 -Authorization: {{xtoken}} - - - -### chat call -GET {{baseUrl}}/ai/chatStream?prompt=苹果是什么颜色?&modal=yiYan3_5_8k -tenant-id: 1 +### 对话 - id获取 +GET {{baseUrl}}/ai/chat/conversation/1781604279872581644 Authorization: {{token}} - +### 对话 - id获取 +DELETE {{baseUrl}}/ai/chat/conversation/1781604279872581644 +Authorization: {{token}} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json index a76673c48..b66e855a5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json @@ -4,6 +4,6 @@ }, "dev": { "baseUrl": "http://127.0.0.1:48080", - "token": "Bearer 2f807aacab534a4095cec0bac9c2af40" + "token": "Bearer a9bf9c8c10cb47fc92bc9aac95b63f5b" } } \ No newline at end of file From 1ab1538afebe6bfa3de9206c56fa6660e387e94f Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 23 Apr 2024 16:29:26 +0800 Subject: [PATCH 126/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=88=9B=E5=BB=BArol?= =?UTF-8?q?e=E5=AF=B9=E8=AF=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/enums/ChatConversationTypeEnum.java | 5 +- .../ChatConversationController.java | 17 ++++-- .../ai/mapper/AiChatConversationMapper.java | 6 +- .../ai/service/ChatConversationService.java | 17 +++++- .../impl/ChatConversationServiceImpl.java | 56 +++++++++++++++---- .../ai/service/impl/ChatServiceImpl.java | 51 ++++------------- .../ai/vo/ChatConversationCreateRoleReq.java | 26 +++++++++ ...ava => ChatConversationCreateUserReq.java} | 9 ++- .../resources/http/chat-conversation.http | 7 ++- 9 files changed, 125 insertions(+), 69 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateRoleReq.java rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/{ChatConversationCreateReq.java => ChatConversationCreateUserReq.java} (62%) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatConversationTypeEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatConversationTypeEnum.java index 4a699618d..18891bbe7 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatConversationTypeEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatConversationTypeEnum.java @@ -15,8 +15,9 @@ import lombok.Getter; @Getter public enum ChatConversationTypeEnum { - NEW("new", "新建对话"), - CONTINUE("continue", "继续对话"), + // roleChat、userChat + ROLE_CHAT("roleChat", "角色对话"), + USER_CHAT("userChat", "用户对话"), ; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java index d17a385a1..2133ccb60 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java @@ -2,7 +2,8 @@ package cn.iocoder.yudao.module.ai.controller; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.ai.service.ChatConversationService; -import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateReq; +import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateRoleReq; +import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateUserReq; import cn.iocoder.yudao.module.ai.vo.ChatConversationListReq; import cn.iocoder.yudao.module.ai.vo.ChatConversationRes; import io.swagger.v3.oas.annotations.Operation; @@ -30,10 +31,16 @@ public class ChatConversationController { private final ChatConversationService chatConversationService; - @Operation(summary = "创建 - 对话") - @PostMapping("/create") - public CommonResult create(@RequestBody @Validated ChatConversationCreateReq req) { - return CommonResult.success(chatConversationService.create(req)); + @Operation(summary = "创建 - 对话普通对话") + @PostMapping("/createConversation") + public CommonResult createConversation(@RequestBody @Validated ChatConversationCreateUserReq req) { + return CommonResult.success(chatConversationService.createConversation(req)); + } + + @Operation(summary = "创建 - 对话角色对话") + @PostMapping("/createRoleConversation") + public CommonResult createRoleConversation(@RequestBody @Validated ChatConversationCreateRoleReq req) { + return CommonResult.success(chatConversationService.createRoleConversation(req)); } @Operation(summary = "获取 - 获取对话") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java index 30aa1dff5..6da3fdc5b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java @@ -24,7 +24,11 @@ import java.util.List; @Mapper public interface AiChatConversationMapper extends BaseMapperX { - + /** + * 更新 - chat count + * + * @param id + */ @Update("update ai_chat_conversation set chat_count = chat_count + 1 where id = #{id}") void updateIncrChatCount(@Param("id") Long id); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatConversationService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatConversationService.java index e5073bd6b..428a26e10 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatConversationService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatConversationService.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.ai.service; -import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateReq; +import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateRoleReq; +import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateUserReq; import cn.iocoder.yudao.module.ai.vo.ChatConversationListReq; import cn.iocoder.yudao.module.ai.vo.ChatConversationRes; @@ -15,12 +16,21 @@ import java.util.List; public interface ChatConversationService { /** - * 对话 - 创建 + * 对话 - 创建普通对话 * * @param req * @return */ - ChatConversationRes create(ChatConversationCreateReq req); + ChatConversationRes createConversation(ChatConversationCreateUserReq req); + + /** + * 对话 - 创建role对话 + * + * @param req + * @return + */ + ChatConversationRes createRoleConversation(ChatConversationCreateRoleReq req); + /** * 获取 - 对话 @@ -44,4 +54,5 @@ public interface ChatConversationService { * @param id */ void delete(Long id); + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java index 1318351cd..7b6f5fa8d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java @@ -5,13 +5,18 @@ import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.convert.ChatConversationConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatConversationDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatRoleDO; +import cn.iocoder.yudao.module.ai.enums.ChatConversationTypeEnum; import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; +import cn.iocoder.yudao.module.ai.mapper.AiChatRoleMapper; import cn.iocoder.yudao.module.ai.service.ChatConversationService; -import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateReq; +import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateRoleReq; +import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateUserReq; import cn.iocoder.yudao.module.ai.vo.ChatConversationListReq; import cn.iocoder.yudao.module.ai.vo.ChatConversationRes; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; import org.springframework.stereotype.Service; import java.util.List; @@ -27,10 +32,11 @@ import java.util.List; @AllArgsConstructor public class ChatConversationServiceImpl implements ChatConversationService { + private final AiChatRoleMapper aiChatRoleMapper; private final AiChatConversationMapper aiChatConversationMapper; @Override - public ChatConversationRes create(ChatConversationCreateReq req) { + public ChatConversationRes createConversation(ChatConversationCreateUserReq req) { // 获取用户id Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 查询最新的对话 @@ -40,19 +46,47 @@ public class ChatConversationServiceImpl implements ChatConversationService { return ChatConversationConvert.INSTANCE.covnertChatConversationRes(latestConversation); } // 创建新的 Conversation - AiChatConversationDO insertConversation = new AiChatConversationDO(); - insertConversation.setId(null); - insertConversation.setUserId(loginUserId); - insertConversation.setChatRoleId(null); - insertConversation.setChatRoleName(null); - insertConversation.setTitle(null); - insertConversation.setChatCount(0); - insertConversation.setType(req.getChatType()); - aiChatConversationMapper.insert(insertConversation); + AiChatConversationDO insertConversation = saveConversation(req.getTitle(), loginUserId, + null, null, ChatConversationTypeEnum.USER_CHAT); // 转换 res return ChatConversationConvert.INSTANCE.covnertChatConversationRes(insertConversation); } + @Override + public ChatConversationRes createRoleConversation(ChatConversationCreateRoleReq req) { + // 获取用户id + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + // 查询最新的对话 + AiChatConversationDO latestConversation = aiChatConversationMapper.selectLatestConversation(loginUserId); + // 如果有对话没有被使用过,那就返回这个 + if (latestConversation != null && latestConversation.getChatCount() <= 0) { + return ChatConversationConvert.INSTANCE.covnertChatConversationRes(latestConversation); + } + AiChatRoleDO aiChatRoleDO = aiChatRoleMapper.selectById(req.getChatRoleId()); + // 创建新的 Conversation + AiChatConversationDO insertConversation = saveConversation(req.getTitle(), loginUserId, + req.getChatRoleId(), aiChatRoleDO.getRoleName(), ChatConversationTypeEnum.ROLE_CHAT); + // 转换 res + return ChatConversationConvert.INSTANCE.covnertChatConversationRes(insertConversation); + } + + private @NotNull AiChatConversationDO saveConversation(String title, + Long userId, + Long chatRoleId, + String chatRoleName, + ChatConversationTypeEnum typeEnum) { + AiChatConversationDO insertConversation = new AiChatConversationDO(); + insertConversation.setId(null); + insertConversation.setUserId(userId); + insertConversation.setChatRoleId(chatRoleId); + insertConversation.setChatRoleName(chatRoleName); + insertConversation.setTitle(title); + insertConversation.setChatCount(0); + insertConversation.setType(typeEnum.getType()); + aiChatConversationMapper.insert(insertConversation); + return insertConversation; + } + @Override public ChatConversationRes getConversation(Long id) { AiChatConversationDO aiChatConversationDO = aiChatConversationMapper.selectById(id); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java index 0bb7211cb..57e6b7358 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java @@ -5,15 +5,10 @@ import cn.iocoder.yudao.framework.ai.chat.ChatResponse; import cn.iocoder.yudao.framework.ai.chat.messages.MessageType; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.ai.config.AiClient; -import cn.iocoder.yudao.framework.common.exception.ServerException; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; -import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatMessageDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatRoleDO; import cn.iocoder.yudao.module.ai.enums.AiClientNameEnum; -import cn.iocoder.yudao.module.ai.enums.ChatTypeEnum; import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.mapper.AiChatMessageMapper; import cn.iocoder.yudao.module.ai.mapper.AiChatRoleMapper; @@ -49,7 +44,6 @@ public class ChatServiceImpl implements ChatService { private final AiChatConversationMapper aiChatConversationMapper; private final ChatConversationService chatConversationService; - /** * chat * @@ -64,7 +58,7 @@ public class ChatServiceImpl implements ChatService { // 获取对话信息 ChatConversationRes conversationRes = chatConversationService.getConversation(req.getConversationId()); // 保存 chat message - saveChatMessage(req, conversationRes.getId(), loginUserId); + saveChatMessage(req, conversationRes, loginUserId); String content = null; try { // 创建 chat 需要的 Prompt @@ -75,16 +69,19 @@ public class ChatServiceImpl implements ChatService { // 发送 call 调用 ChatResponse call = aiClient.call(prompt, clientNameEnum.getName()); content = call.getResult().getOutput().getContent(); + // 更新 conversation + } catch (Exception e) { content = ExceptionUtil.getMessage(e); } finally { // 保存 chat message - saveSystemChatMessage(req, conversationRes.getId(), loginUserId, content); + saveSystemChatMessage(req, conversationRes, loginUserId, content); } return content; } - private void saveChatMessage(ChatReq req, Long chatConversationId, Long loginUserId) { + private void saveChatMessage(ChatReq req, ChatConversationRes conversationRes, Long loginUserId) { + Long chatConversationId = conversationRes.getId(); // 增加 chat message 记录 aiChatMessageMapper.insert( new AiChatMessageDO() @@ -97,12 +94,12 @@ public class ChatServiceImpl implements ChatService { .setTopP(req.getTopP()) .setTemperature(req.getTemperature()) ); - // chat count 先+1 aiChatConversationMapper.updateIncrChatCount(req.getConversationId()); } - public void saveSystemChatMessage(ChatReq req, Long chatConversationId, Long loginUserId, String systemPrompts) { + public void saveSystemChatMessage(ChatReq req, ChatConversationRes conversationRes, Long loginUserId, String systemPrompts) { + Long chatConversationId = conversationRes.getId(); // 增加 chat message 记录 aiChatMessageMapper.insert( new AiChatMessageDO() @@ -120,34 +117,6 @@ public class ChatServiceImpl implements ChatService { aiChatConversationMapper.updateIncrChatCount(req.getConversationId()); } - private AiChatConversationDO createNewChatConversation(ChatReq req, Long loginUserId) { - // 获取 chat 角色 - String chatRoleName = null; - ChatTypeEnum chatTypeEnum = null; - Long chatRoleId = req.getChatRoleId(); - if (req.getChatRoleId() != null) { - AiChatRoleDO aiChatRoleDO = aiChatRoleMapper.selectById(chatRoleId); - if (aiChatRoleDO == null) { - throw new ServerException(ErrorCodeConstants.AI_CHAT_ROLE_NOT_EXISTENT); - } - chatTypeEnum = ChatTypeEnum.ROLE_CHAT; - chatRoleName = aiChatRoleDO.getRoleName(); - } else { - chatTypeEnum = ChatTypeEnum.USER_CHAT; - } - // - AiChatConversationDO insertChatConversation = new AiChatConversationDO() - .setId(null) - .setUserId(loginUserId) - .setChatRoleId(req.getChatRoleId()) - .setChatRoleName(chatRoleName) - .setType(chatTypeEnum.getType()) - .setChatCount(1) - .setTitle(req.getPrompt().substring(0, 20) + "..."); - aiChatConversationMapper.insert(insertChatConversation); - return insertChatConversation; - } - /** * chat stream * @@ -168,7 +137,7 @@ public class ChatServiceImpl implements ChatService { req.setTopP(req.getTopP()); req.setTemperature(req.getTemperature()); // 保存 chat message - saveChatMessage(req, conversationRes.getId(), loginUserId); + saveChatMessage(req, conversationRes, loginUserId); Flux streamResponse = aiClient.stream(prompt, clientNameEnum.getName()); StringBuffer contentBuffer = new StringBuffer(); @@ -195,7 +164,7 @@ public class ChatServiceImpl implements ChatService { log.info("发送完成!"); sseEmitter.complete(); // 保存 chat message - saveSystemChatMessage(req, conversationRes.getId(), loginUserId, contentBuffer.toString()); + saveSystemChatMessage(req, conversationRes, loginUserId, contentBuffer.toString()); } ); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateRoleReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateRoleReq.java new file mode 100644 index 000000000..9af6a44ef --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateRoleReq.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.ai.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 聊天对话 + * + * @author fansili + * @time 2024/4/18 16:24 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class ChatConversationCreateRoleReq { + + @Schema(description = "chat角色Id") + @NotNull(message = "聊天角色id不能为空!") + private Long chatRoleId; + + @Schema(description = "标题(有程序自动生成)") + @NotNull(message = "标题不能为空!") + private String title; +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateUserReq.java similarity index 62% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateUserReq.java index a39c9e2ed..9f967175e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateUserReq.java @@ -14,10 +14,9 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class ChatConversationCreateReq { - - @Schema(description = "对话类型(roleChat、userChat)") - @NotNull(message = "聊天类型不能为空!") - private String chatType; +public class ChatConversationCreateUserReq { + @Schema(description = "对话标题") + @NotNull(message = "标题不能为空!") + private String title; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-conversation.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-conversation.http index 02c147e03..65230d9e9 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-conversation.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-conversation.http @@ -16,7 +16,12 @@ GET {{baseUrl}}/ai/chat/conversation/1781604279872581644 Authorization: {{token}} -### 对话 - id获取 +### 对话 - list +GET {{baseUrl}}/ai/chat/conversation/list +Authorization: {{token}} + + +### 对话 - 删除 DELETE {{baseUrl}}/ai/chat/conversation/1781604279872581644 Authorization: {{token}} From d8c2d0d66ae442df4f1ff3a03d8e13cf2f5232bf Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 24 Apr 2024 16:40:26 +0800 Subject: [PATCH 127/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20chat=E8=A7=92?= =?UTF-8?q?=E8=89=B2=20source=20enum?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/enums/ChatRoleSourceEnum.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleSourceEnum.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleSourceEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleSourceEnum.java new file mode 100644 index 000000000..388640f42 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleSourceEnum.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.ai.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * chat角色 source + * + * @author fansili + * @time 2024/4/24 16:37 + * @since 1.0 + */ +@AllArgsConstructor +@Getter +public enum ChatRoleSourceEnum { + + SYSTEM("system", "系统"), + CUSTOMER("customer", "用户自定义"), + + + ; + + private String type; + + private String name; +} From c5dd1d50e7521914a92e5d61dd0ca52990300adf Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 24 Apr 2024 16:44:08 +0800 Subject: [PATCH 128/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0chat=20role=20?= =?UTF-8?q?=E5=88=86=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/enums/ChatRoleClassifyEnum.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleClassifyEnum.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleClassifyEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleClassifyEnum.java new file mode 100644 index 000000000..583bf7483 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleClassifyEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.ai.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 聊天role 分类 + * + * @author fansili + * @time 2024/4/24 16:41 + * @since 1.0 + */ +@AllArgsConstructor +@Getter +public enum ChatRoleClassifyEnum { + + WRITING("writing", "写作"), + + ENTERTAINMENT("entertainment", "娱乐"), + + ; + + + private String classify; + + private String name; + + + public static ChatRoleClassifyEnum valueOfClassify(String classify) { + for (ChatRoleClassifyEnum itemEnum : ChatRoleClassifyEnum.values()) { + if (itemEnum.getClassify().equals(classify)) { + return itemEnum; + } + } + throw new IllegalArgumentException("Invalid MessageType value: " + classify); + } +} From e4dc715458d353d5b5d1eecdd2d22c322986effa Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 24 Apr 2024 16:45:58 +0800 Subject: [PATCH 129/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8F=AF=E8=A7=81?= =?UTF-8?q?=E8=8C=83=E5=9B=B4=20enum?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/enums/ChatRoleVisibilityEnum.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleVisibilityEnum.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleVisibilityEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleVisibilityEnum.java new file mode 100644 index 000000000..eef31935a --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleVisibilityEnum.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.ai.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * chat角色 可见范围 + * + * @author fansili + * @time 2024/4/24 16:44 + * @since 1.0 + */ +@AllArgsConstructor +@Getter +public enum ChatRoleVisibilityEnum { + + PUBLIC("public", "公开"), + PRIVATE("private", "私有的"), + + ; + + private String type; + + private String name; +} From c75e415b61108679e9b1259d1598f5c29c913cd9 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 24 Apr 2024 16:47:32 +0800 Subject: [PATCH 130/684] =?UTF-8?q?enum=20=E5=A2=9E=E5=8A=A0=20valueOfType?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/enums/ChatRoleSourceEnum.java | 10 ++++++++++ .../yudao/module/ai/enums/ChatRoleVisibilityEnum.java | 11 +++++++++++ 2 files changed, 21 insertions(+) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleSourceEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleSourceEnum.java index 388640f42..877da17ba 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleSourceEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleSourceEnum.java @@ -23,4 +23,14 @@ public enum ChatRoleSourceEnum { private String type; private String name; + + + public static ChatRoleSourceEnum valueOfType(String type) { + for (ChatRoleSourceEnum itemEnum : ChatRoleSourceEnum.values()) { + if (itemEnum.getType().equals(type)) { + return itemEnum; + } + } + throw new IllegalArgumentException("Invalid MessageType value: " + type); + } } diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleVisibilityEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleVisibilityEnum.java index eef31935a..c8b09aedb 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleVisibilityEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleVisibilityEnum.java @@ -22,4 +22,15 @@ public enum ChatRoleVisibilityEnum { private String type; private String name; + + + public static ChatRoleVisibilityEnum valueOfType(String type) { + for (ChatRoleVisibilityEnum itemEnum : ChatRoleVisibilityEnum.values()) { + if (itemEnum.getType().equals(type)) { + return itemEnum; + } + } + throw new IllegalArgumentException("Invalid MessageType value: " + type); + } + } From 410893bc2978ddb50976cc8ba3500a1ebf4ecdf0 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 24 Apr 2024 16:48:14 +0800 Subject: [PATCH 131/684] =?UTF-8?q?chat=E8=A7=92=E8=89=B2=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=EF=BC=8C=E8=A7=92=E8=89=B2=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/convert/ChatRoleConvert.java | 29 ++++++++++++++ .../module/ai/service/ChatRoleService.java | 5 ++- .../ai/service/impl/ChatRoleServiceImpl.java | 28 ++++++++++++-- .../yudao/module/ai/vo/ChatRoleAddReq.java | 38 ++++++++++++++++++- .../yudao/module/ai/vo/ChatRoleListRes.java | 37 ++++++++++++++++++ 5 files changed, 131 insertions(+), 6 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatRoleConvert.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatRoleConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatRoleConvert.java new file mode 100644 index 000000000..de5bece68 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatRoleConvert.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.ai.convert; + +import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatRoleDO; +import cn.iocoder.yudao.module.ai.vo.ChatRoleListRes; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 聊天 对话 convert + * + * @author fansili + * @time 2024/4/18 16:39 + * @since 1.0 + */ +@Mapper +public interface ChatRoleConvert { + + ChatRoleConvert INSTANCE = Mappers.getMapper(ChatRoleConvert.class); + + /** + * 转换 - ChatRoleListRes + * + * @param roleList + * @return + */ + List convertChatRoleListRes(List roleList); +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java index c4c46a5ef..839e29ad7 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java @@ -1,8 +1,11 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.vo.*; +import java.util.List; + /** * chat 角色 * @@ -17,7 +20,7 @@ public interface ChatRoleService { * @param req * @return */ - CommonResult list(ChatRoleListReq req); + PageResult list(ChatRoleListReq req); /** * chat角色 - 添加 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java index 310e8f766..1d46367fb 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java @@ -1,12 +1,19 @@ package cn.iocoder.yudao.module.ai.service.impl; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.ai.convert.ChatRoleConvert; +import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatRoleDO; +import cn.iocoder.yudao.module.ai.mapper.AiChatRoleMapper; import cn.iocoder.yudao.module.ai.service.ChatRoleService; import cn.iocoder.yudao.module.ai.vo.*; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.util.List; + /** * chat 角色 * @@ -18,10 +25,25 @@ import org.springframework.stereotype.Service; @Slf4j public class ChatRoleServiceImpl implements ChatRoleService { + private final AiChatRoleMapper aiChatRoleMapper; @Override - public CommonResult list(ChatRoleListReq req) { - return null; + public PageResult list(ChatRoleListReq req) { + // 查询条件 + LambdaQueryWrapperX queryWrapperX = new LambdaQueryWrapperX<>(); + // search 查询 + if (!StrUtil.isBlank(req.getSearch())) { + queryWrapperX.eq(AiChatRoleDO::getRoleName, req.getSearch()); + } + // 默认排序id desc + queryWrapperX.orderByDesc(AiChatRoleDO::getId); + // + PageResult aiChatRoleDOPageResult = aiChatRoleMapper.selectPage(req, queryWrapperX); + Long total = aiChatRoleDOPageResult.getTotal(); + List roleList = aiChatRoleDOPageResult.getList(); + // 换货res + List chatRoleListResList = ChatRoleConvert.INSTANCE.convertChatRoleListRes(roleList); + return new PageResult<>(chatRoleListResList, total); } @Override diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleAddReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleAddReq.java index 2c2dfcbff..da08f11cb 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleAddReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleAddReq.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; import lombok.Data; import lombok.experimental.Accessors; @@ -15,6 +16,39 @@ import lombok.experimental.Accessors; @Accessors(chain = true) public class ChatRoleAddReq extends PageParam { - @Schema(description = "查询") - private String search; + @NotNull + @Schema(description = "模型编号,关联到角色使用的特定模型") + private String modelId; + + @NotNull + @Schema(description = "角色名,角色的显示名称") + private String roleName; + + @NotNull + @Schema(description = "角色介绍,详细描述角色的功能或用途") + private String roleIntroduce; + + @NotNull + @Schema(description = "角色来源,如 system(系统预置)、customer(用户自定义)") + private String roleSource; + + @NotNull + @Schema(description = "分类,角色所属的类别,如娱乐、创作等") + private String classify; + + @NotNull + @Schema(description = "发布状态,0表示仅自己可见,1表示公开,2表示禁用") + private String visibility; + + @NotNull + @Schema(description = "生成时的Top-K采样候选集大小") + private Double topK; + + @NotNull + @Schema(description = "生成时使用的核采样方法的概率阈值") + private Double topP; + + @NotNull + @Schema(description = "用于控制随机性和多样性的温度参数") + private Double temperature; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleListRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleListRes.java index 8423c66b9..5babda544 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleListRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleListRes.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.ai.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; @@ -12,4 +13,40 @@ import lombok.experimental.Accessors; @Data @Accessors(chain = true) public class ChatRoleListRes { + + @Schema(description = "id") + private Long id; + + @Schema(description = "用户id") + private Long userId; + + @Schema(description = "模型id") + private String modelId; + + @Schema(description = "角色名字") + private String roleName; + + @Schema(description = "角色介绍,详细描述角色的功能或用途") + private String roleIntroduce; + + @Schema(description = "角色来源,如 system(系统预置)、customer(用户自定义)") + private String roleSource; + + @Schema(description = "分类,角色所属的类别,如娱乐、创作等") + private String classify; + + @Schema(description = "发布状态,0表示仅自己可见,1表示公开,2表示禁用") + private String visibility; + + @Schema(description = "生成时的Top-K采样候选集大小") + private Double topK; + + @Schema(description = "生成时使用的核采样方法的概率阈值") + private Double topP; + + @Schema(description = "用于控制随机性和多样性的温度参数") + private Double temperature; + + @Schema(description = "角色的使用次数统计") + private Integer useCount; } From 4cc87539d8af08377876520129b82d03dd71c267 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 24 Apr 2024 17:09:24 +0800 Subject: [PATCH 132/684] =?UTF-8?q?chat=E8=A7=92=E8=89=B2=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20add=20=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/convert/ChatRoleConvert.java | 9 +++++++++ .../module/ai/service/ChatRoleService.java | 2 +- .../ai/service/impl/ChatRoleServiceImpl.java | 17 +++++++++++++++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatRoleConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatRoleConvert.java index de5bece68..c3c7cb7f0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatRoleConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatRoleConvert.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.ai.convert; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatRoleDO; +import cn.iocoder.yudao.module.ai.vo.ChatRoleAddReq; import cn.iocoder.yudao.module.ai.vo.ChatRoleListRes; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -26,4 +27,12 @@ public interface ChatRoleConvert { * @return */ List convertChatRoleListRes(List roleList); + + /** + * 转换 - AiChatRoleDO + * + * @param req + * @return + */ + AiChatRoleDO convertAiChatRoleDO(ChatRoleAddReq req); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java index 839e29ad7..2b7734107 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java @@ -28,7 +28,7 @@ public interface ChatRoleService { * @param req * @return */ - ChatRoleListRes add(ChatRoleAddReq req); + void add(ChatRoleAddReq req); /** * chat角色 - 修改 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java index 1d46367fb..3285785ea 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java @@ -3,8 +3,12 @@ package cn.iocoder.yudao.module.ai.service.impl; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.convert.ChatRoleConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatRoleDO; +import cn.iocoder.yudao.module.ai.enums.ChatRoleClassifyEnum; +import cn.iocoder.yudao.module.ai.enums.ChatRoleSourceEnum; +import cn.iocoder.yudao.module.ai.enums.ChatRoleVisibilityEnum; import cn.iocoder.yudao.module.ai.mapper.AiChatRoleMapper; import cn.iocoder.yudao.module.ai.service.ChatRoleService; import cn.iocoder.yudao.module.ai.vo.*; @@ -47,8 +51,17 @@ public class ChatRoleServiceImpl implements ChatRoleService { } @Override - public ChatRoleListRes add(ChatRoleAddReq req) { - return null; + public void add(ChatRoleAddReq req) { + // 转换enum,并校验enum + ChatRoleClassifyEnum.valueOfClassify(req.getClassify()); + ChatRoleVisibilityEnum.valueOfType(req.getVisibility()); + ChatRoleSourceEnum.valueOfType(req.getRoleSource()); + // 转换do + AiChatRoleDO insertAiChatRoleDO = ChatRoleConvert.INSTANCE.convertAiChatRoleDO(req); + insertAiChatRoleDO.setUserId(SecurityFrameworkUtils.getLoginUserId()); + insertAiChatRoleDO.setUseCount(0); + // 保存 + aiChatRoleMapper.insert(insertAiChatRoleDO); } @Override From c44f558e3d3b72911eff02476eb5bdfa66a3ed02 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 24 Apr 2024 17:16:19 +0800 Subject: [PATCH 133/684] =?UTF-8?q?=E8=A7=92=E8=89=B2=E5=A2=9E=E5=8A=A0=20?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/ErrorCodeConstants.java | 1 + .../module/ai/convert/ChatRoleConvert.java | 9 ++++ .../ai/service/impl/ChatRoleServiceImpl.java | 15 ++++++- .../yudao/module/ai/vo/ChatRoleUpdateReq.java | 43 ++++++++++++++++++- 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index e3e1c869d..939de5cb9 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -22,6 +22,7 @@ public interface ErrorCodeConstants { ErrorCode AI_CHAT_CONTINUE_NOT_EXIST = new ErrorCode(1_022_000_020, "chat对话不存在!");; + ErrorCode AI_CHAT_ROLE_NOT_EXIST = new ErrorCode(1_022_000_020, "chatRole不存在!");; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatRoleConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatRoleConvert.java index c3c7cb7f0..d30ea8010 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatRoleConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatRoleConvert.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.ai.convert; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatRoleDO; import cn.iocoder.yudao.module.ai.vo.ChatRoleAddReq; import cn.iocoder.yudao.module.ai.vo.ChatRoleListRes; +import cn.iocoder.yudao.module.ai.vo.ChatRoleUpdateReq; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -35,4 +36,12 @@ public interface ChatRoleConvert { * @return */ AiChatRoleDO convertAiChatRoleDO(ChatRoleAddReq req); + + /** + * 转换 - AiChatRoleDO + * + * @param req + * @return + */ + AiChatRoleDO convertAiChatRoleDO(ChatRoleUpdateReq req); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java index 3285785ea..da3f83548 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java @@ -1,9 +1,11 @@ package cn.iocoder.yudao.module.ai.service.impl; import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.convert.ChatRoleConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatRoleDO; import cn.iocoder.yudao.module.ai.enums.ChatRoleClassifyEnum; @@ -66,7 +68,18 @@ public class ChatRoleServiceImpl implements ChatRoleService { @Override public void update(ChatRoleUpdateReq req) { - + // 转换enum,并校验enum + ChatRoleClassifyEnum.valueOfClassify(req.getClassify()); + ChatRoleVisibilityEnum.valueOfType(req.getVisibility()); + ChatRoleSourceEnum.valueOfType(req.getRoleSource()); + // 检查角色是否存在 + AiChatRoleDO aiChatRoleDO = aiChatRoleMapper.selectById(req.getId()); + if (aiChatRoleDO == null) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CHAT_ROLE_NOT_EXIST); + } + // 转换do + AiChatRoleDO updateChatRole = ChatRoleConvert.INSTANCE.convertAiChatRoleDO(req); + aiChatRoleMapper.updateById(updateChatRole); } @Override diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateReq.java index 2f98e4f79..3187fca43 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateReq.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; import lombok.Data; import lombok.experimental.Accessors; @@ -15,6 +16,44 @@ import lombok.experimental.Accessors; @Accessors(chain = true) public class ChatRoleUpdateReq extends PageParam { - @Schema(description = "查询") - private String search; + + @NotNull + @Schema(description = "编号") + private Long id; + + @NotNull + @Schema(description = "模型编号,关联到角色使用的特定模型") + private String modelId; + + @NotNull + @Schema(description = "角色名,角色的显示名称") + private String roleName; + + @NotNull + @Schema(description = "角色介绍,详细描述角色的功能或用途") + private String roleIntroduce; + + @NotNull + @Schema(description = "角色来源,如 system(系统预置)、customer(用户自定义)") + private String roleSource; + + @NotNull + @Schema(description = "分类,角色所属的类别,如娱乐、创作等") + private String classify; + + @NotNull + @Schema(description = "发布状态,0表示仅自己可见,1表示公开,2表示禁用") + private String visibility; + + @NotNull + @Schema(description = "生成时的Top-K采样候选集大小") + private Double topK; + + @NotNull + @Schema(description = "生成时使用的核采样方法的概率阈值") + private Double topP; + + @NotNull + @Schema(description = "用于控制随机性和多样性的温度参数") + private Double temperature; } From 591002f0593e3d9515634bc870a8c27d690f36ba Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 24 Apr 2024 17:19:34 +0800 Subject: [PATCH 134/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0chat=20role=20?= =?UTF-8?q?=E5=8F=AF=E8=A7=81=E6=80=A7=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/service/impl/ChatRoleServiceImpl.java | 25 +++++++++++++++---- .../ai/vo/ChatRoleUpdateVisibilityReq.java | 10 ++++++-- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java index da3f83548..2fdb16681 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java @@ -73,22 +73,37 @@ public class ChatRoleServiceImpl implements ChatRoleService { ChatRoleVisibilityEnum.valueOfType(req.getVisibility()); ChatRoleSourceEnum.valueOfType(req.getRoleSource()); // 检查角色是否存在 - AiChatRoleDO aiChatRoleDO = aiChatRoleMapper.selectById(req.getId()); - if (aiChatRoleDO == null) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CHAT_ROLE_NOT_EXIST); - } + validateChatRoleExists(req.getId()); // 转换do AiChatRoleDO updateChatRole = ChatRoleConvert.INSTANCE.convertAiChatRoleDO(req); aiChatRoleMapper.updateById(updateChatRole); } + @Override public void updateVisibility(ChatRoleUpdateVisibilityReq req) { - + // 转换enum,并校验enum + ChatRoleVisibilityEnum.valueOfType(req.getVisibility()); + // 检查角色是否存在 + validateChatRoleExists(req.getId()); + // 更新 + aiChatRoleMapper.updateById(new AiChatRoleDO() + .setId(req.getId()) + .setVisibility(req.getVisibility()) + ); } @Override public void delete(Long chatRoleId) { } + + private AiChatRoleDO validateChatRoleExists(Long id) { + AiChatRoleDO aiChatRoleDO = aiChatRoleMapper.selectById(id); + if (aiChatRoleDO == null) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CHAT_ROLE_NOT_EXIST); + } + return aiChatRoleDO; + } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateVisibilityReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateVisibilityReq.java index 3ae25f4ab..22241dc0d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateVisibilityReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateVisibilityReq.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; import lombok.Data; import lombok.experimental.Accessors; @@ -15,6 +16,11 @@ import lombok.experimental.Accessors; @Accessors(chain = true) public class ChatRoleUpdateVisibilityReq extends PageParam { - @Schema(description = "查询") - private String search; + @NotNull + @Schema(description = "编号") + private Long id; + + @NotNull + @Schema(description = "发布状态,0表示仅自己可见,1表示公开,2表示禁用") + private String visibility; } From 7aef30cbe84180286ae92f1eb31ff99169c8a79c Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 24 Apr 2024 17:20:13 +0800 Subject: [PATCH 135/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20chat=20role=20?= =?UTF-8?q?=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/service/impl/ChatRoleServiceImpl.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java index 2fdb16681..4f96840b5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java @@ -95,7 +95,10 @@ public class ChatRoleServiceImpl implements ChatRoleService { @Override public void delete(Long chatRoleId) { - + // 检查角色是否存在 + validateChatRoleExists(chatRoleId); + // 删除 + aiChatRoleMapper.deleteById(chatRoleId); } private AiChatRoleDO validateChatRoleExists(Long id) { @@ -105,5 +108,4 @@ public class ChatRoleServiceImpl implements ChatRoleService { } return aiChatRoleDO; } - } From 1f5878ed5be8e00e181777cbb04b1b4328cad612 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 24 Apr 2024 17:24:55 +0800 Subject: [PATCH 136/684] =?UTF-8?q?=E8=B0=83=E6=95=B4controller=20swagger?= =?UTF-8?q?=20=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/controller/ChatController.java | 2 +- .../ChatConversationController.java | 2 +- .../ai/controller/ChatMessageController.java | 22 +++++++++++++++++++ .../ai/controller/ChatRoleController.java | 9 ++++++-- 4 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatMessageController.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java index d9f2d2b97..9b7f9f3a9 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java @@ -29,7 +29,7 @@ import java.util.function.Consumer; * @time 2024/4/13 17:44 * @since 1.0 */ -@Tag(name = "AI模块") +@Tag(name = "A1-AI聊天") @RestController @RequestMapping("/ai") @Slf4j diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java index 2133ccb60..ffd75cd44 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java @@ -22,7 +22,7 @@ import java.util.List; * @time 2024/4/13 17:44 * @since 1.0 */ -@Tag(name = "A2聊天-对话") +@Tag(name = "A2-聊天-对话") @RestController @RequestMapping("/ai/chat/conversation") @Slf4j diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatMessageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatMessageController.java new file mode 100644 index 000000000..227932e78 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatMessageController.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.ai.controller; + +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * chat message + * + * @author fansili + * @time 2024/4/24 17:22 + * @since 1.0 + */ +@Tag(name = "A3-聊天-对话") +@RestController +@RequestMapping("/ai/chat/conversation") +@Slf4j +@AllArgsConstructor +public class ChatMessageController { +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatRoleController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatRoleController.java index 4b3e61c09..fbd3ae779 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatRoleController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatRoleController.java @@ -1,10 +1,13 @@ package cn.iocoder.yudao.module.ai.controller; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.service.ChatRoleService; import cn.iocoder.yudao.module.ai.vo.*; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -14,8 +17,10 @@ import org.springframework.web.bind.annotation.*; * @fansili * @since v1.0 */ +@Tag(name = "A4-chat角色") @RestController -@RequestMapping("/chat-role") +@RequestMapping("/ai/chat/role") +@Slf4j @AllArgsConstructor public class ChatRoleController { @@ -23,7 +28,7 @@ public class ChatRoleController { @Operation(summary = "chat角色 - 角色列表") @GetMapping("/list") - public CommonResult list(@Validated @ModelAttribute ChatRoleListReq req) { + public PageResult list(@Validated @ModelAttribute ChatRoleListReq req) { return chatRoleService.list(req); } From 64fdd045a5006c8fae0bbae02395da10e51fb36d Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 24 Apr 2024 17:50:11 +0800 Subject: [PATCH 137/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20chat=20message=20?= =?UTF-8?q?=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/ChatMessageController.java | 28 ++++++++- .../module/ai/mapper/AiChatMessageMapper.java | 14 +++++ .../module/ai/service/ChatMessageService.java | 31 ++++++++++ .../service/impl/ChatMessageServiceImpl.java | 57 +++++++++++++++++++ .../module/ai/vo/ChatMessageListRes.java | 42 ++++++++++++++ .../yudao/module/ai/vo/ChatMessageReq.java | 23 ++++++++ 6 files changed, 192 insertions(+), 3 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatMessageService.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatMessageServiceImpl.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageListRes.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageReq.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatMessageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatMessageController.java index 227932e78..3c6749e21 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatMessageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatMessageController.java @@ -1,10 +1,16 @@ package cn.iocoder.yudao.module.ai.controller; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.ai.service.ChatMessageService; +import cn.iocoder.yudao.module.ai.vo.ChatMessageListRes; +import cn.iocoder.yudao.module.ai.vo.ChatMessageReq; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; /** * chat message @@ -15,8 +21,24 @@ import org.springframework.web.bind.annotation.RestController; */ @Tag(name = "A3-聊天-对话") @RestController -@RequestMapping("/ai/chat/conversation") +@RequestMapping("/ai/chat/message") @Slf4j @AllArgsConstructor public class ChatMessageController { + + private final ChatMessageService chatMessageService; + + @Operation(summary = "聊天记录", description = "查询个人的聊天记录") + @GetMapping("/list") + public PageResult list(@Validated @ModelAttribute ChatMessageReq req) { + return chatMessageService.list(req); + } + + @Operation(summary = "聊天记录", description = "查询个人的聊天记录") + @DeleteMapping("/{chatConversationId}/{id}") + public CommonResult delete(@PathVariable("chatConversationId") Long chatConversationId, + @PathVariable("id") Long id) { + chatMessageService.delete(chatConversationId, id); + return CommonResult.success(null); + } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java index b121a0601..0947cac7b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.ai.mapper; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatMessageDO; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; @@ -14,4 +15,17 @@ import org.springframework.stereotype.Repository; @Repository @Mapper public interface AiChatMessageMapper extends BaseMapperX { + + /** + * 删除 - 根据 Conversation 和 id + * + * @param chatConversationId + * @param id + */ + default int deleteByConversationAndId(Long chatConversationId, Long id) { + return this.delete(new LambdaQueryWrapperX() + .eq(AiChatMessageDO::getChatConversationId, chatConversationId) + .eq(AiChatMessageDO::getId, id) + ); + } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatMessageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatMessageService.java new file mode 100644 index 000000000..625bc1b2e --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatMessageService.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.ai.service; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.ai.vo.ChatMessageListRes; +import cn.iocoder.yudao.module.ai.vo.ChatMessageReq; + +/** + * chat message + * + * @author fansili + * @time 2024/4/24 17:25 + * @since 1.0 + */ +public interface ChatMessageService { + + /** + * message - 列表 + * + * @param req + * @return + */ + PageResult list(ChatMessageReq req); + + /** + * message - 删除 + * + * @param chatConversationId + * @param id + */ + void delete(Long chatConversationId, Long id); +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatMessageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatMessageServiceImpl.java new file mode 100644 index 000000000..7d3513810 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatMessageServiceImpl.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.ai.service.impl; + +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.module.ai.ErrorCodeConstants; +import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatConversationDO; +import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; +import cn.iocoder.yudao.module.ai.mapper.AiChatMessageMapper; +import cn.iocoder.yudao.module.ai.service.ChatMessageService; +import cn.iocoder.yudao.module.ai.vo.ChatMessageListRes; +import cn.iocoder.yudao.module.ai.vo.ChatMessageReq; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * chat message + * + * @author fansili + * @time 2024/4/24 17:25 + * @since 1.0 + */ +@AllArgsConstructor +@Service +@Slf4j +public class ChatMessageServiceImpl implements ChatMessageService { + + private final AiChatMessageMapper aiChatMessageMapper; + private final AiChatConversationMapper aiChatConversationMapper; + + @Override + public PageResult list(ChatMessageReq req) { + return null; + } + + @Override + public void delete(Long chatConversationId, Long id) { + // 获取登录用户 + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + // 校验 ChatConversation + validateChatConversation(chatConversationId, loginUserId); + // 删除 + aiChatMessageMapper.deleteByConversationAndId(chatConversationId, id); + } + + private AiChatConversationDO validateChatConversation(Long chatConversationId, Long loginUserId) { + AiChatConversationDO aiChatConversationDO = aiChatConversationMapper.selectById(chatConversationId); + if (aiChatConversationDO == null) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CHAT_CONTINUE_NOT_EXIST); + } + if (!aiChatConversationDO.getUserId().equals(loginUserId)) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CHAT_CONVERSATION_NOT_YOURS); + } + return aiChatConversationDO; + } +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageListRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageListRes.java new file mode 100644 index 000000000..52017c062 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageListRes.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.ai.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 看板 message list req + * + * @author fansili + * @time 2024/4/24 17:28 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class ChatMessageListRes { + + @Schema(description = "编号") + private Long id; + + @Schema(description = "聊天ID,关联到特定的会话或对话") + private Long chatConversationId; + + @Schema(description = "角色ID,用于标识发送消息的用户或系统的身份") + private Long userId; + + @Schema(description = "消息具体内容,存储用户的发言或者系统响应的文字信息") + private String message; + + @Schema(description = "消息类型,枚举值可能包括'system'(系统消息)、'user'(用户消息)和'assistant'(助手消息)") + private String messageType; + + @Schema(description = "在生成消息时采用的Top-K采样大小") + private Double topK; + + @Schema(description = "Top-P核采样方法的概率阈值") + private Double topP; + + @Schema(description = "温度参数,用于调整生成回复的随机性和多样性程度,") + private Double temperature; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageReq.java new file mode 100644 index 000000000..72aa633f0 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageReq.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.ai.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * chat message list req + * + * @author fansili + * @time 2024/4/14 16:12 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class ChatMessageReq { + + @Schema(description = "聊天ID,关联到特定的会话或对话") + @NotNull + private Long chatConversationId; + +} From 6b8174a5a6474dd0ab2be7c1e3fb3b378456ec4d Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 24 Apr 2024 18:57:15 +0800 Subject: [PATCH 138/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0message=20list=20?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/ErrorCodeConstants.java | 6 ++-- .../module/ai/convert/ChatMessageConvert.java | 29 +++++++++++++++++++ .../module/ai/mapper/AiChatMessageMapper.java | 2 ++ .../service/impl/ChatMessageServiceImpl.java | 15 +++++++++- .../yudao/module/ai/vo/ChatMessageReq.java | 3 +- 5 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatMessageConvert.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index 939de5cb9..39ad9b55b 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -21,8 +21,10 @@ public interface ErrorCodeConstants { - ErrorCode AI_CHAT_CONTINUE_NOT_EXIST = new ErrorCode(1_022_000_020, "chat对话不存在!");; - ErrorCode AI_CHAT_ROLE_NOT_EXIST = new ErrorCode(1_022_000_020, "chatRole不存在!");; + ErrorCode AI_CHAT_CONTINUE_NOT_EXIST = new ErrorCode(1_022_000_020, "chat对话不存在!"); + ErrorCode AI_CHAT_CONVERSATION_NOT_YOURS = new ErrorCode(1_022_000_021, "这条chat对话不是你的!"); + + ErrorCode AI_CHAT_ROLE_NOT_EXIST = new ErrorCode(1_022_000_040, "chatRole不存在!"); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatMessageConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatMessageConvert.java new file mode 100644 index 000000000..9176d01a0 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatMessageConvert.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.ai.convert; + +import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatMessageDO; +import cn.iocoder.yudao.module.ai.vo.ChatMessageListRes; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 聊天 对话 convert + * + * @author fansili + * @time 2024/4/18 16:39 + * @since 1.0 + */ +@Mapper +public interface ChatMessageConvert { + + ChatMessageConvert INSTANCE = Mappers.getMapper(ChatMessageConvert.class); + + /** + * 转换 ChatMessageListRes + * + * @param list + * @return + */ + List convert(List list); +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java index 0947cac7b..ed1127a0b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.ai.mapper; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatMessageDO; +import cn.iocoder.yudao.module.ai.vo.ChatMessageReq; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; @@ -28,4 +29,5 @@ public interface AiChatMessageMapper extends BaseMapperX { .eq(AiChatMessageDO::getId, id) ); } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatMessageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatMessageServiceImpl.java index 7d3513810..ab0c05ff4 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatMessageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatMessageServiceImpl.java @@ -2,9 +2,12 @@ package cn.iocoder.yudao.module.ai.service.impl; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; +import cn.iocoder.yudao.module.ai.convert.ChatMessageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatConversationDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatMessageDO; import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.mapper.AiChatMessageMapper; import cn.iocoder.yudao.module.ai.service.ChatMessageService; @@ -14,6 +17,8 @@ import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.util.List; + /** * chat message * @@ -31,7 +36,15 @@ public class ChatMessageServiceImpl implements ChatMessageService { @Override public PageResult list(ChatMessageReq req) { - return null; + // 查询 + LambdaQueryWrapperX queryWrapperX = new LambdaQueryWrapperX<>(); + queryWrapperX.eq(AiChatMessageDO::getChatConversationId, req.getChatConversationId()); + // 默认排序 + queryWrapperX.orderByDesc(AiChatMessageDO::getId); + PageResult pageResult = aiChatMessageMapper.selectPage(req, queryWrapperX); + // 转换 res + List messageListResList = ChatMessageConvert.INSTANCE.convert(pageResult.getList()); + return new PageResult(messageListResList, pageResult.getTotal()); } @Override diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageReq.java index 72aa633f0..b0f38a321 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageReq.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.ai.vo; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -14,7 +15,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class ChatMessageReq { +public class ChatMessageReq extends PageParam { @Schema(description = "聊天ID,关联到特定的会话或对话") @NotNull From 3556e460e76da2a2b5360cd06e135db56ec5e125 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 24 Apr 2024 19:04:16 +0800 Subject: [PATCH 139/684] =?UTF-8?q?=E6=B5=8B=E8=AF=95=20chat=20message?= =?UTF-8?q?=EF=BC=88list=20=E5=92=8C=20delete=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/controller/ChatMessageController.java | 2 +- .../src/main/resources/http/chat-message.http | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-message.http diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatMessageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatMessageController.java index 3c6749e21..f86450848 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatMessageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatMessageController.java @@ -34,7 +34,7 @@ public class ChatMessageController { return chatMessageService.list(req); } - @Operation(summary = "聊天记录", description = "查询个人的聊天记录") + @Operation(summary = "聊天记录 - 删除", description = "删除记录") @DeleteMapping("/{chatConversationId}/{id}") public CommonResult delete(@PathVariable("chatConversationId") Long chatConversationId, @PathVariable("id") Long id) { diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-message.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-message.http new file mode 100644 index 000000000..b39eda5ff --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-message.http @@ -0,0 +1,10 @@ + + +### message list +GET {{baseUrl}}/ai/chat/message/list?chatConversationId=1781604279872581644 +Authorization: {{token}} + + +### message delete +DELETE {{baseUrl}}/ai/chat/message/1781604279872581644/8 +Authorization: {{token}} From a0b3bd32b0d283003d099a00ccd6ffcc7a3818b3 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 24 Apr 2024 19:34:57 +0800 Subject: [PATCH 140/684] =?UTF-8?q?=E6=B5=8B=E8=AF=95=20role=EF=BC=8C?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E5=92=8C=E6=B7=BB=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/ChatRoleController.java | 17 +++++++++-------- .../module/ai/dal/dataobject/AiChatRoleDO.java | 4 +++- .../module/ai/service/ChatRoleService.java | 3 ++- .../ai/service/impl/ChatRoleServiceImpl.java | 5 +++-- .../yudao/module/ai/vo/ChatRoleAddReq.java | 2 +- .../yudao/module/ai/vo/ChatRoleUpdateReq.java | 5 ----- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatRoleController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatRoleController.java index fbd3ae779..79da1bc8c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatRoleController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatRoleController.java @@ -19,7 +19,7 @@ import org.springframework.web.bind.annotation.*; */ @Tag(name = "A4-chat角色") @RestController -@RequestMapping("/ai/chat/role") +@RequestMapping("/ai/chat") @Slf4j @AllArgsConstructor public class ChatRoleController { @@ -27,34 +27,35 @@ public class ChatRoleController { private final ChatRoleService chatRoleService; @Operation(summary = "chat角色 - 角色列表") - @GetMapping("/list") + @GetMapping("/role/list") public PageResult list(@Validated @ModelAttribute ChatRoleListReq req) { return chatRoleService.list(req); } @Operation(summary = "chat角色 - 添加") - @PutMapping("/add") + @PutMapping("/role") public CommonResult add(@Validated @RequestBody ChatRoleAddReq req) { chatRoleService.add(req); return CommonResult.success(null); } @Operation(summary = "chat角色 - 修改") - @PostMapping("/update") - public CommonResult update(@Validated @RequestBody ChatRoleUpdateReq req) { - chatRoleService.update(req); + @PostMapping("/role/{id}") + public CommonResult update(@PathVariable("id") Long id, + @Validated @RequestBody ChatRoleUpdateReq req) { + chatRoleService.update(id, req); return CommonResult.success(null); } @Operation(summary = "chat角色 - 修改可见性") - @PostMapping("/update-visibility") + @PostMapping("/role/update-visibility") public CommonResult updateVisibility(@Validated @RequestBody ChatRoleUpdateVisibilityReq req) { chatRoleService.updateVisibility(req); return CommonResult.success(null); } @Operation(summary = "chat角色 - 修改可见性") - @DeleteMapping("/delete") + @DeleteMapping("/role") public CommonResult delete(@RequestParam("chatRoleId") Long chatRoleId) { chatRoleService.delete(chatRoleId); return CommonResult.success(null); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatRoleDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatRoleDO.java index 49ff42f87..4683a81fa 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatRoleDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatRoleDO.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.ai.dal.dataobject; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.experimental.Accessors; @@ -14,6 +15,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) +@TableName("ai_chat_role") public class AiChatRoleDO extends BaseDO { /** * 编号,表示聊天角色在数据库中的唯一标识符 @@ -52,7 +54,7 @@ public class AiChatRoleDO extends BaseDO { private String classify; /** - * 发布状态,0表示仅自己可见,1表示公开,2表示禁用 + * 发布状态,private 表示仅自己可见,public表示公开,disable表示禁用 */ private String visibility; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java index 2b7734107..7302b4243 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java @@ -33,9 +33,10 @@ public interface ChatRoleService { /** * chat角色 - 修改 * + * @param id * @param req */ - void update(ChatRoleUpdateReq req); + void update(Long id, ChatRoleUpdateReq req); /** diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java index 4f96840b5..a88d2a8e9 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java @@ -67,15 +67,16 @@ public class ChatRoleServiceImpl implements ChatRoleService { } @Override - public void update(ChatRoleUpdateReq req) { + public void update(Long id, ChatRoleUpdateReq req) { // 转换enum,并校验enum ChatRoleClassifyEnum.valueOfClassify(req.getClassify()); ChatRoleVisibilityEnum.valueOfType(req.getVisibility()); ChatRoleSourceEnum.valueOfType(req.getRoleSource()); // 检查角色是否存在 - validateChatRoleExists(req.getId()); + validateChatRoleExists(id); // 转换do AiChatRoleDO updateChatRole = ChatRoleConvert.INSTANCE.convertAiChatRoleDO(req); + updateChatRole.setId(id); aiChatRoleMapper.updateById(updateChatRole); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleAddReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleAddReq.java index da08f11cb..2c83bc59a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleAddReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleAddReq.java @@ -37,7 +37,7 @@ public class ChatRoleAddReq extends PageParam { private String classify; @NotNull - @Schema(description = "发布状态,0表示仅自己可见,1表示公开,2表示禁用") + @Schema(description = "发布状态,private 表示仅自己可见,public表示公开,disable表示禁用\n") private String visibility; @NotNull diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateReq.java index 3187fca43..6ec165ed8 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateReq.java @@ -16,11 +16,6 @@ import lombok.experimental.Accessors; @Accessors(chain = true) public class ChatRoleUpdateReq extends PageParam { - - @NotNull - @Schema(description = "编号") - private Long id; - @NotNull @Schema(description = "模型编号,关联到角色使用的特定模型") private String modelId; From cec8cc7a2b2dfc925ca660fb2c929a06f1cd6f56 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 24 Apr 2024 19:38:19 +0800 Subject: [PATCH 141/684] =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=9Achat?= =?UTF-8?q?=E8=A7=92=E8=89=B2=20-=20=E4=BF=AE=E6=94=B9=E5=8F=AF=E8=A7=81?= =?UTF-8?q?=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/ChatRoleController.java | 15 +++--- .../module/ai/service/ChatRoleService.java | 3 +- .../ai/service/impl/ChatRoleServiceImpl.java | 6 +-- .../ai/vo/ChatRoleUpdateVisibilityReq.java | 4 -- .../src/main/resources/http/chat-role.http | 51 +++++++++++++++++++ 5 files changed, 64 insertions(+), 15 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatRoleController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatRoleController.java index 79da1bc8c..947329674 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatRoleController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatRoleController.java @@ -48,16 +48,17 @@ public class ChatRoleController { } @Operation(summary = "chat角色 - 修改可见性") - @PostMapping("/role/update-visibility") - public CommonResult updateVisibility(@Validated @RequestBody ChatRoleUpdateVisibilityReq req) { - chatRoleService.updateVisibility(req); + @PostMapping("/role/{id}/update-visibility") + public CommonResult updateVisibility(@PathVariable("id") Long id, + @Validated @RequestBody ChatRoleUpdateVisibilityReq req) { + chatRoleService.updateVisibility(id, req); return CommonResult.success(null); } - @Operation(summary = "chat角色 - 修改可见性") - @DeleteMapping("/role") - public CommonResult delete(@RequestParam("chatRoleId") Long chatRoleId) { - chatRoleService.delete(chatRoleId); + @Operation(summary = "chat角色 - 删除") + @DeleteMapping("/role/{id}") + public CommonResult delete(@PathVariable("id") Long id) { + chatRoleService.delete(id); return CommonResult.success(null); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java index 7302b4243..d189455e1 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java @@ -42,9 +42,10 @@ public interface ChatRoleService { /** * chat角色 - 修改可见性 * + * @param id * @param req */ - void updateVisibility(ChatRoleUpdateVisibilityReq req); + void updateVisibility(Long id, ChatRoleUpdateVisibilityReq req); /** * chat角色 - 删除 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java index a88d2a8e9..af2e8336b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java @@ -82,14 +82,14 @@ public class ChatRoleServiceImpl implements ChatRoleService { @Override - public void updateVisibility(ChatRoleUpdateVisibilityReq req) { + public void updateVisibility(Long id, ChatRoleUpdateVisibilityReq req) { // 转换enum,并校验enum ChatRoleVisibilityEnum.valueOfType(req.getVisibility()); // 检查角色是否存在 - validateChatRoleExists(req.getId()); + validateChatRoleExists(id); // 更新 aiChatRoleMapper.updateById(new AiChatRoleDO() - .setId(req.getId()) + .setId(id) .setVisibility(req.getVisibility()) ); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateVisibilityReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateVisibilityReq.java index 22241dc0d..764972f49 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateVisibilityReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateVisibilityReq.java @@ -16,10 +16,6 @@ import lombok.experimental.Accessors; @Accessors(chain = true) public class ChatRoleUpdateVisibilityReq extends PageParam { - @NotNull - @Schema(description = "编号") - private Long id; - @NotNull @Schema(description = "发布状态,0表示仅自己可见,1表示公开,2表示禁用") private String visibility; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http new file mode 100644 index 000000000..add6d382b --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http @@ -0,0 +1,51 @@ + +### chat角色 - list +GET {{baseUrl}}/ai/chat/role/list?pageNo=1&pageSize=20&search= +Authorization: {{token}} + + +### chat add +PUT {{baseUrl}}/ai/chat/role +Content-Type: application/json +Authorization: {{token}} + +{ + "modelId": 1, + "roleName": "小红书写作v1", + "roleIntroduce": "采用gpt3.5模型,拥有小红书优质作者写作经验。", + "roleSource": "system", + "classify": "writing", + "visibility": "public", + "topK": 0.2, + "topP": 0.4, + "temperature": 0.7 +} + + +### chat update +POST {{baseUrl}}/ai/chat/role/1 +Content-Type: application/json +Authorization: {{token}} + +{ + "modelId": 1, + "roleName": "小红书写作v1---hh😄", + "roleIntroduce": "采用gpt3.5模型,拥有小红书优质作者写作经验。", + "roleSource": "system", + "classify": "writing", + "visibility": "public", + "topK": 0.2, + "topP": 0.4, + "temperature": 0.7 +} + +### chat update +POST {{baseUrl}}/ai/chat/role/1/update-visibility +Content-Type: application/json +Authorization: {{token}} + +{ + "visibility": "private" +} + + From 9e412ffec8cf32a60b01223c978567a744dee714 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 24 Apr 2024 19:38:58 +0800 Subject: [PATCH 142/684] =?UTF-8?q?=E6=B5=8B=E8=AF=95=EF=BC=8Crole?= =?UTF-8?q?=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/http/chat-role.http | 7 +++++++ .../yudao-module-ai-biz/src/main/resources/http/chat.http | 6 ++---- .../src/main/resources/http/http-client.env.json | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http index add6d382b..ae7e42c8f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http @@ -49,3 +49,10 @@ Authorization: {{token}} } + +### chat update +DELETE {{baseUrl}}/ai/chat/role/1 +Content-Type: application/json +Authorization: {{token}} + + diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http index e850d79a8..133a0eedb 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http @@ -16,15 +16,13 @@ tenant-id: 1 } ### chat call -GET {{baseUrl}}/ai/chat?modal=qianWen&conversationId=111&prompt=中国好看吗? -tenant-id: 1 +GET {{baseUrl}}/ai/chat?modal=qianWen&conversationId=1781604279872581644&prompt=中国好看吗? Authorization: {{token}} ### chat call -GET {{baseUrl}}/ai/chatStream?prompt=苹果是什么颜色?&modal=yiYan3_5_8k -tenant-id: 1 +GET {{baseUrl}}/ai/chatStream?conversationId=1781604279872581644&prompt=苹果是什么颜色?&modal=yiYan3_5_8k Authorization: {{token}} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json index b66e855a5..23d6d4656 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/http-client.env.json @@ -4,6 +4,6 @@ }, "dev": { "baseUrl": "http://127.0.0.1:48080", - "token": "Bearer a9bf9c8c10cb47fc92bc9aac95b63f5b" + "token": "Bearer 66346cc899e243b081321bd1336a257a" } } \ No newline at end of file From 2fde9b124d6675c02635933d25b4b1d6ae2c73ec Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 24 Apr 2024 20:07:58 +0800 Subject: [PATCH 143/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0ai=20modal=EF=BC=88?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E5=88=97=E8=A1=A8=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/AiChatModalController.java | 55 +++++++++++++++++++ .../module/ai/convert/ChatModalConvert.java | 24 ++++++++ .../ai/dal/dataobject/AiChatModalDO.java | 47 ++++++++++++++++ .../module/ai/mapper/AiChatModalMapper.java | 18 ++++++ .../module/ai/service/AiChatModalService.java | 20 +++++++ .../service/impl/AiChatModalServiceImpl.java | 53 ++++++++++++++++++ .../yudao/module/ai/vo/AiChatModalAddReq.java | 16 ++++++ .../module/ai/vo/AiChatModalListReq.java | 21 +++++++ .../module/ai/vo/AiChatModalListRes.java | 16 ++++++ .../module/ai/vo/ChatMessageDeleteReq.java | 28 ++++++++++ 10 files changed, 298 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatModalConvert.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatModalMapper.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalAddReq.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListReq.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageDeleteReq.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java new file mode 100644 index 000000000..2258e2ee0 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.ai.controller; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.ai.service.AiChatModalService; +import cn.iocoder.yudao.module.ai.vo.AiChatModalAddReq; +import cn.iocoder.yudao.module.ai.vo.AiChatModalListReq; +import cn.iocoder.yudao.module.ai.vo.AiChatModalListRes; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +/** + * ai 模型 + * + * @author fansili + * @time 2024/4/24 19:42 + * @since 1.0 + */ +@Tag(name = "A6-AI模型") +@RestController +@RequestMapping("/ai/chat") +@Slf4j +@AllArgsConstructor +public class AiChatModalController { + + private final AiChatModalService aiChatModalService; + + @Operation(summary = "ai模型 - 模型照片上传") + @GetMapping("/modal/list") + public PageResult list(@ModelAttribute AiChatModalListReq req) { + return aiChatModalService.list(req); + } + + @Operation(summary = "ai模型 - 添加") + @PutMapping("/modal") + public CommonResult add(@RequestBody @Validated AiChatModalAddReq req) { + aiChatModalService.add(req); + return CommonResult.success(null); + } + + @Operation(summary = "ai模型 - 模型照片上传") + @PutMapping("/modal/{id}/updateImage") + public CommonResult updateImage(@PathVariable("id") Long id, + MultipartFile file) { + // todo yunai 文件上传这里放哪里 + return CommonResult.success(null); + } + + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatModalConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatModalConvert.java new file mode 100644 index 000000000..9611953ac --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatModalConvert.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.ai.convert; + +import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO; +import cn.iocoder.yudao.module.ai.vo.AiChatModalListRes; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 聊天 对话 convert + * + * @author fansili + * @time 2024/4/18 16:39 + * @since 1.0 + */ +@Mapper +public interface ChatModalConvert { + + ChatModalConvert INSTANCE = Mappers.getMapper(ChatModalConvert.class); + + + List convertAiChatModalListRes(List list); +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java new file mode 100644 index 000000000..b4b8f4414 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.ai.dal.dataobject; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * ai 模型 + * + * @author fansili + * @time 2024/4/24 19:39 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class AiChatModalDO extends BaseDO { + + /** + * 编号 + */ + private Long id; + /** + * 模型名字 + */ + private Long modelName; + /** + * 模型类型(qianwen、yiyan、xinghuo、openai) + */ + private String modelType; + /** + * 模型照片 + */ + private String modalImage; + /** + * 模型配置JSON + */ + private String modelConfig; + /** + * 模型图片 + */ + private String modelImage; + /** + * 禁用 0、正常 1、禁用 + */ + private Integer disable; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatModalMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatModalMapper.java new file mode 100644 index 000000000..118cda294 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatModalMapper.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.ai.mapper; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Repository; + +/** + * chat modal + * + * @author fansili + * @time 2024/4/24 19:41 + * @since 1.0 + */ +@Repository +@Mapper +public interface AiChatModalMapper extends BaseMapperX { +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java new file mode 100644 index 000000000..230b0f1b8 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.ai.service; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.ai.vo.AiChatModalAddReq; +import cn.iocoder.yudao.module.ai.vo.AiChatModalListReq; +import cn.iocoder.yudao.module.ai.vo.AiChatModalListRes; + +/** + * ai modal + * + * @author fansili + * @time 2024/4/24 19:42 + * @since 1.0 + */ +public interface AiChatModalService { + + PageResult list(AiChatModalListReq req); + + void add(AiChatModalAddReq req); +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java new file mode 100644 index 000000000..60e510902 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.ai.service.impl; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.ai.convert.ChatModalConvert; +import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO; +import cn.iocoder.yudao.module.ai.mapper.AiChatModalMapper; +import cn.iocoder.yudao.module.ai.service.AiChatModalService; +import cn.iocoder.yudao.module.ai.vo.AiChatModalAddReq; +import cn.iocoder.yudao.module.ai.vo.AiChatModalListReq; +import cn.iocoder.yudao.module.ai.vo.AiChatModalListRes; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * ai 模型 + * + * @author fansili + * @time 2024/4/24 19:42 + * @since 1.0 + */ +@AllArgsConstructor +@Service +@Slf4j +public class AiChatModalServiceImpl implements AiChatModalService { + + private final AiChatModalMapper aiChatModalMapper; + + @Override + public PageResult list(AiChatModalListReq req) { + LambdaQueryWrapperX queryWrapperX = new LambdaQueryWrapperX<>(); + // search + if (!StrUtil.isBlank(req.getSearch())) { + queryWrapperX.like(AiChatModalDO::getModelName, req.getSearch().trim()); + } + // 默认排序 + queryWrapperX.orderByDesc(AiChatModalDO::getId); + // 查询 + PageResult aiChatModalDOPageResult = aiChatModalMapper.selectPage(req, queryWrapperX); + // 转换 res + List resList = ChatModalConvert.INSTANCE.convertAiChatModalListRes(aiChatModalDOPageResult.getList()); + return new PageResult<>(resList, aiChatModalDOPageResult.getTotal()); + } + + @Override + public void add(AiChatModalAddReq req) { + + } +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalAddReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalAddReq.java new file mode 100644 index 000000000..1af1d8768 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalAddReq.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.ai.vo; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * ai chat modal + * + * @author fansili + * @time 2024/4/24 19:47 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class AiChatModalAddReq { +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListReq.java new file mode 100644 index 000000000..6801aadb2 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListReq.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.ai.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * modal list + * + * @author fansili + * @time 2024/4/24 19:56 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class AiChatModalListReq extends PageParam { + + @Schema(description = "名字搜搜") + private String search; +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java new file mode 100644 index 000000000..aa869ed23 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.ai.vo; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * modal list + * + * @author fansili + * @time 2024/4/24 19:56 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class AiChatModalListRes { +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageDeleteReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageDeleteReq.java new file mode 100644 index 000000000..9b2986e81 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageDeleteReq.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.ai.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * chat message list req + * + * @author fansili + * @time 2024/4/14 16:12 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class ChatMessageDeleteReq extends PageParam { + + @Schema(description = "id") + @NotNull + private Long id; + + @Schema(description = "聊天ID,关联到特定的会话或对话") + @NotNull + private Long chatConversationId; + +} From 77f3226d278ac2d180d4480d63f1a4726000cafb Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 24 Apr 2024 20:20:51 +0800 Subject: [PATCH 144/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20ai=20modal=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/enums/AiChatModalDisableEnum.java | 26 +++++++++++++++++++ .../ai/controller/AiChatModalController.java | 2 +- .../module/ai/convert/ChatModalConvert.java | 16 +++++++++++- .../ai/dal/dataobject/AiChatModalDO.java | 4 --- .../service/impl/AiChatModalServiceImpl.java | 8 +++++- .../yudao/module/ai/vo/AiChatModalAddReq.java | 20 ++++++++++++++ 6 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatModalDisableEnum.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatModalDisableEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatModalDisableEnum.java new file mode 100644 index 000000000..5b780ec6e --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatModalDisableEnum.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.ai.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * ai modal disable + * + * @author fansili + * @time 2024/4/24 20:15 + * @since 1.0 + */ +@AllArgsConstructor +@Getter +public enum AiChatModalDisableEnum { + + NO(0, "未禁用"), + YES(1, "禁用"), + + + ; + + private Integer value; + + private String name; +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java index 2258e2ee0..fa3c679dc 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java @@ -44,7 +44,7 @@ public class AiChatModalController { } @Operation(summary = "ai模型 - 模型照片上传") - @PutMapping("/modal/{id}/updateImage") + @PostMapping("/modal/{id}/updateImage") public CommonResult updateImage(@PathVariable("id") Long id, MultipartFile file) { // todo yunai 文件上传这里放哪里 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatModalConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatModalConvert.java index 9611953ac..a83d4f0ef 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatModalConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatModalConvert.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.ai.convert; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO; +import cn.iocoder.yudao.module.ai.vo.AiChatModalAddReq; import cn.iocoder.yudao.module.ai.vo.AiChatModalListRes; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -19,6 +20,19 @@ public interface ChatModalConvert { ChatModalConvert INSTANCE = Mappers.getMapper(ChatModalConvert.class); - + /** + * 转换 - AiChatModalListRes + * + * @param list + * @return + */ List convertAiChatModalListRes(List list); + + /** + * 转换 - AiChatModalDO + * + * @param req + * @return + */ + AiChatModalDO convertAiChatModalDO(AiChatModalAddReq req); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java index b4b8f4414..9eab9e37b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java @@ -35,10 +35,6 @@ public class AiChatModalDO extends BaseDO { * 模型配置JSON */ private String modelConfig; - /** - * 模型图片 - */ - private String modelImage; /** * 禁用 0、正常 1、禁用 */ diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java index 60e510902..533895a23 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.convert.ChatModalConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO; +import cn.iocoder.yudao.module.ai.enums.AiChatModalDisableEnum; import cn.iocoder.yudao.module.ai.mapper.AiChatModalMapper; import cn.iocoder.yudao.module.ai.service.AiChatModalService; import cn.iocoder.yudao.module.ai.vo.AiChatModalAddReq; @@ -48,6 +49,11 @@ public class AiChatModalServiceImpl implements AiChatModalService { @Override public void add(AiChatModalAddReq req) { - + // 转换 do + AiChatModalDO insertChatModalDO = ChatModalConvert.INSTANCE.convertAiChatModalDO(req); + // + insertChatModalDO.setDisable(AiChatModalDisableEnum.NO.getValue()); + // 保存数据库 + aiChatModalMapper.insert(insertChatModalDO); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalAddReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalAddReq.java index 1af1d8768..b20c92d5b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalAddReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalAddReq.java @@ -1,5 +1,8 @@ package cn.iocoder.yudao.module.ai.vo; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; import lombok.Data; import lombok.experimental.Accessors; @@ -13,4 +16,21 @@ import lombok.experimental.Accessors; @Data @Accessors(chain = true) public class AiChatModalAddReq { + + @NotNull + @Schema(description = "模型名字") + @Size(max = 60, message = "模型名字最大60") + private String modelName; + + @NotNull + @Schema(description = "模型类型(qianwen、yiyan、xinghuo、openai)") + @Size(max = 32, message = "模型类型最大32") + private String modelType; + + @Schema(description = "模型照片") + private String modalImage; + + @Schema(description = "模型配置JSON") + private String modelConfig; + } From e4eadd8c9906843981bc7b5987ebb6a3260b1eb0 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 24 Apr 2024 20:25:46 +0800 Subject: [PATCH 145/684] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20modal=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/ErrorCodeConstants.java | 3 +++ .../ai/controller/AiChatModalController.java | 7 +++++++ .../module/ai/service/AiChatModalService.java | 2 ++ .../service/impl/AiChatModalServiceImpl.java | 20 +++++++++++++++++++ .../module/ai/vo/AiChatModalListReq.java | 1 + 5 files changed, 33 insertions(+) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index 39ad9b55b..8609df6a9 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -28,4 +28,7 @@ public interface ErrorCodeConstants { + ErrorCode AI_MODAL_NOT_EXIST = new ErrorCode(1_022_000_060, "ai模型不存在!"); + + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java index fa3c679dc..854194041 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java @@ -51,5 +51,12 @@ public class AiChatModalController { return CommonResult.success(null); } + @Operation(summary = "ai模型 - 修改") + @PostMapping("/modal/{id}") + public CommonResult update(@PathVariable Long id, + @RequestBody @Validated AiChatModalAddReq req) { + aiChatModalService.update(id, req); + return CommonResult.success(null); + } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java index 230b0f1b8..d8366ad63 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java @@ -17,4 +17,6 @@ public interface AiChatModalService { PageResult list(AiChatModalListReq req); void add(AiChatModalAddReq req); + + void update(Long id, AiChatModalAddReq req); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java index 533895a23..0e043eafb 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java @@ -1,8 +1,10 @@ package cn.iocoder.yudao.module.ai.service.impl; import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.convert.ChatModalConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO; import cn.iocoder.yudao.module.ai.enums.AiChatModalDisableEnum; @@ -56,4 +58,22 @@ public class AiChatModalServiceImpl implements AiChatModalService { // 保存数据库 aiChatModalMapper.insert(insertChatModalDO); } + + @Override + public void update(Long id, AiChatModalAddReq req) { + // 校验模型是否存在 + validateChatModalExists(id); + // 转换 updateChatModalDO + AiChatModalDO updateChatModalDO = ChatModalConvert.INSTANCE.convertAiChatModalDO(req); + updateChatModalDO.setId(id); + // 更新数据库 + aiChatModalMapper.updateById(updateChatModalDO); + } + + private void validateChatModalExists(Long id) { + AiChatModalDO aiChatModalDO = aiChatModalMapper.selectById(id); + if (aiChatModalDO == null) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_NOT_EXIST); + } + } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListReq.java index 6801aadb2..2aa6b931f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListReq.java @@ -18,4 +18,5 @@ public class AiChatModalListReq extends PageParam { @Schema(description = "名字搜搜") private String search; + } From d6a8ec6bd20afc7cc856b72f0b83f9103b7f5c5a Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 24 Apr 2024 20:26:12 +0800 Subject: [PATCH 146/684] =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=9Amodal=20?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E6=9F=A5=E8=AF=A2=E7=9A=84=E9=83=BD=E6=98=AF?= =?UTF-8?q?=E6=9C=AA=E7=A6=81=E7=94=A8=E7=9A=84modal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/service/impl/AiChatModalServiceImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java index 0e043eafb..8f3e3a881 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java @@ -36,6 +36,8 @@ public class AiChatModalServiceImpl implements AiChatModalService { @Override public PageResult list(AiChatModalListReq req) { LambdaQueryWrapperX queryWrapperX = new LambdaQueryWrapperX<>(); + // 查询的都是未禁用的模型 + queryWrapperX.eq(AiChatModalDO::getDisable, AiChatModalDisableEnum.NO.getValue()); // search if (!StrUtil.isBlank(req.getSearch())) { queryWrapperX.like(AiChatModalDO::getModelName, req.getSearch().trim()); From faade05528268847c89d6f1bab5f2efab0502920 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 25 Apr 2024 15:00:42 +0800 Subject: [PATCH 147/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91ai?= =?UTF-8?q?=20modal=20=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/service/AiChatModalService.java | 17 +++++++++++++ .../module/ai/vo/AiChatModalListRes.java | 25 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java index d8366ad63..f35f62380 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java @@ -14,9 +14,26 @@ import cn.iocoder.yudao.module.ai.vo.AiChatModalListRes; */ public interface AiChatModalService { + /** + * ai modal - 列表 + * + * @param req + * @return + */ PageResult list(AiChatModalListReq req); + /** + * ai modal - 添加 + * + * @param req + */ void add(AiChatModalAddReq req); + /** + * ai modal - 更新 + * + * @param id + * @param req + */ void update(Long id, AiChatModalAddReq req); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java index aa869ed23..4c5cdbb51 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java @@ -13,4 +13,29 @@ import lombok.experimental.Accessors; @Data @Accessors(chain = true) public class AiChatModalListRes { + /** + * 编号 + */ + private Long id; + /** + * 模型名字 + */ + private Long modelName; + /** + * 模型类型(qianwen、yiyan、xinghuo、openai) + */ + private String modelType; + /** + * 模型照片 + */ + private String modalImage; + /** + * 模型配置JSON + */ + private String modelConfig; + /** + * 禁用 0、正常 1、禁用 + */ + private Integer disable; + } From f85c89a405d6970e05f8e61fb98c699ada7a73dd Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 25 Apr 2024 15:15:33 +0800 Subject: [PATCH 148/684] =?UTF-8?q?modal=20=E5=A2=9E=E5=8A=A0=E5=88=A0?= =?UTF-8?q?=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/controller/AiChatModalController.java | 6 ++++++ .../yudao/module/ai/service/AiChatModalService.java | 8 ++++++++ .../module/ai/service/impl/AiChatModalServiceImpl.java | 8 ++++++++ 3 files changed, 22 insertions(+) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java index 854194041..7bf12d15c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java @@ -59,4 +59,10 @@ public class AiChatModalController { return CommonResult.success(null); } + @Operation(summary = "ai模型 - 删除") + @DeleteMapping("/modal/{id}") + public CommonResult delete(@PathVariable Long id) { + aiChatModalService.delete(id); + return CommonResult.success(null); + } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java index f35f62380..5681c1ba0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java @@ -36,4 +36,12 @@ public interface AiChatModalService { * @param req */ void update(Long id, AiChatModalAddReq req); + + /** + * ai modal - 删除 + * + * @param id + */ + void delete(Long id); + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java index 8f3e3a881..af1a223c8 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java @@ -72,6 +72,14 @@ public class AiChatModalServiceImpl implements AiChatModalService { aiChatModalMapper.updateById(updateChatModalDO); } + @Override + public void delete(Long id) { + // 检查 modal 是否存在 + validateChatModalExists(id); + // 删除 delete + aiChatModalMapper.deleteById(id); + } + private void validateChatModalExists(Long id) { AiChatModalDO aiChatModalDO = aiChatModalMapper.selectById(id); if (aiChatModalDO == null) { From 1673081b7dc2de65c33f3fdecedcce6279be0843 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 25 Apr 2024 15:38:08 +0800 Subject: [PATCH 149/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91mod?= =?UTF-8?q?al=20=E4=B8=AD=E7=9A=84=20config=20=E6=B2=A1=E6=9C=89=E4=BB=80?= =?UTF-8?q?=E4=B9=88=E4=BD=9C=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/cn/iocoder/yudao/module/ai/dal/1 | 0 .../yudao/module/ai/dal/dataobject/AiChatModalDO.java | 6 ++---- .../main/java/cn/iocoder/yudao/module/ai/dal/pageinfo.java | 7 +++++++ .../main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/1 create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/pageinfo.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/1 b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/1 deleted file mode 100644 index e69de29bb..000000000 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java index 9eab9e37b..646a5e534 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.ai.dal.dataobject; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.experimental.Accessors; @@ -13,6 +14,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) +@TableName("ai_chat_modal") public class AiChatModalDO extends BaseDO { /** @@ -31,10 +33,6 @@ public class AiChatModalDO extends BaseDO { * 模型照片 */ private String modalImage; - /** - * 模型配置JSON - */ - private String modelConfig; /** * 禁用 0、正常 1、禁用 */ diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/pageinfo.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/pageinfo.java new file mode 100644 index 000000000..ce4001112 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/pageinfo.java @@ -0,0 +1,7 @@ +package cn.iocoder.yudao.module.ai.dal; + +/** + * @author fansili + * @time 2024/4/25 15:36 + * @since 1.0 + */ diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java index 87ac95544..cf41e4cf8 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java @@ -19,7 +19,7 @@ public class ChatReq { @Schema(description = "ai模型(查看 AiClientNameEnum)") @NotNull(message = "模型不能为空!") - @Size(max = 30, message = "模型字符最大30个字符!") + @Size(max = 30, message = "模型字符最大 30个字符!") private String modal; @Schema(description = "对话Id") From 5cec6d52e0509dd8b4a13e0291b6afc2b03f381e Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 25 Apr 2024 15:42:30 +0800 Subject: [PATCH 150/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91mod?= =?UTF-8?q?al=20=E5=A2=9E=E5=8A=A0config=20=E5=8F=AF=E8=83=BD=E8=80=83?= =?UTF-8?q?=E8=99=91=E6=95=B0=E6=8D=AE=E5=BA=93=E6=9D=A5=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96=20ai=20modal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/dal/dataobject/AiChatModalDO.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java index 646a5e534..1c30531fa 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java @@ -37,5 +37,8 @@ public class AiChatModalDO extends BaseDO { * 禁用 0、正常 1、禁用 */ private Integer disable; - + /** + * modal 配置(json) + */ + private String config; } From 71e3240af6d8f2f29f1b847d0853881c81e108d0 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 25 Apr 2024 15:48:48 +0800 Subject: [PATCH 151/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96=EF=BC=8C=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0ai=E5=89=8D=E7=BC=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...m.java => AiChatConversationTypeEnum.java} | 6 +- ...yEnum.java => AiChatRoleClassifyEnum.java} | 6 +- ...rceEnum.java => AiChatRoleSourceEnum.java} | 6 +- ...num.java => AiChatRoleVisibilityEnum.java} | 6 +- ...{ChatTypeEnum.java => AiChatTypeEnum.java} | 6 +- ...iModelEnum.java => AiOpenAiModelEnum.java} | 2 +- ...tController.java => AiChatController.java} | 18 ++---- ...java => AiChatConversationController.java} | 22 +++---- ...ller.java => AiChatMessageController.java} | 12 ++-- ...troller.java => AiChatRoleController.java} | 14 ++--- ...rt.java => AiChatConversationConvert.java} | 10 ++-- ...Convert.java => AiChatMessageConvert.java} | 8 +-- ...alConvert.java => AiChatModalConvert.java} | 4 +- ...oleConvert.java => AiChatRoleConvert.java} | 16 ++--- .../module/ai/mapper/AiChatMessageMapper.java | 1 - .../ai/service/AiChatConversationService.java | 58 +++++++++++++++++++ ...Service.java => AiChatMessageService.java} | 8 +-- ...oleService.java => AiChatRoleService.java} | 13 ++--- .../{ChatService.java => AiChatService.java} | 8 +-- .../ai/service/ChatConversationService.java | 58 ------------------- ...ava => AiChatConversationServiceImpl.java} | 42 +++++++------- ...mpl.java => AiChatMessageServiceImpl.java} | 14 ++--- .../service/impl/AiChatModalServiceImpl.java | 8 +-- ...ceImpl.java => AiChatRoleServiceImpl.java} | 40 ++++++------- ...erviceImpl.java => AiChatServiceImpl.java} | 24 ++++---- ...a => AiChatConversationCreateRoleReq.java} | 2 +- ...a => AiChatConversationCreateUserReq.java} | 2 +- ...eq.java => AiChatConversationListReq.java} | 2 +- ...ionRes.java => AiChatConversationRes.java} | 2 +- ...teReq.java => AiChatMessageDeleteReq.java} | 2 +- ...ListRes.java => AiChatMessageListRes.java} | 2 +- ...tMessageReq.java => AiChatMessageReq.java} | 2 +- .../ai/vo/{ChatReq.java => AiChatReq.java} | 2 +- .../yudao/module/ai/vo/AiChatReqVO.java | 4 +- ...tRoleAddReq.java => AiChatRoleAddReq.java} | 2 +- ...oleListReq.java => AiChatRoleListReq.java} | 2 +- ...oleListRes.java => AiChatRoleListRes.java} | 2 +- ...pdateReq.java => AiChatRoleUpdateReq.java} | 2 +- ...ava => AiChatRoleUpdateVisibilityReq.java} | 2 +- 39 files changed, 215 insertions(+), 225 deletions(-) rename yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/{ChatConversationTypeEnum.java => AiChatConversationTypeEnum.java} (75%) rename yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/{ChatRoleClassifyEnum.java => AiChatRoleClassifyEnum.java} (74%) rename yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/{ChatRoleSourceEnum.java => AiChatRoleSourceEnum.java} (75%) rename yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/{ChatRoleVisibilityEnum.java => AiChatRoleVisibilityEnum.java} (73%) rename yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/{ChatTypeEnum.java => AiChatTypeEnum.java} (78%) rename yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/{OpenAiModelEnum.java => AiOpenAiModelEnum.java} (96%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/{ChatController.java => AiChatController.java} (78%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/{ChatConversationController.java => AiChatConversationController.java} (62%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/{ChatMessageController.java => AiChatMessageController.java} (76%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/{ChatRoleController.java => AiChatRoleController.java} (79%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/{ChatConversationConvert.java => AiChatConversationConvert.java} (57%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/{ChatMessageConvert.java => AiChatMessageConvert.java} (61%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/{ChatModalConvert.java => AiChatModalConvert.java} (86%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/{ChatRoleConvert.java => AiChatRoleConvert.java} (53%) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/{ChatMessageService.java => AiChatMessageService.java} (65%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/{ChatRoleService.java => AiChatRoleService.java} (66%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/{ChatService.java => AiChatService.java} (67%) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatConversationService.java rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/{ChatConversationServiceImpl.java => AiChatConversationServiceImpl.java} (68%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/{ChatMessageServiceImpl.java => AiChatMessageServiceImpl.java} (83%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/{ChatRoleServiceImpl.java => AiChatRoleServiceImpl.java} (67%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/{ChatServiceImpl.java => AiChatServiceImpl.java} (86%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/{ChatConversationCreateRoleReq.java => AiChatConversationCreateRoleReq.java} (92%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/{ChatConversationCreateUserReq.java => AiChatConversationCreateUserReq.java} (90%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/{ChatConversationListReq.java => AiChatConversationListReq.java} (89%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/{ChatConversationRes.java => AiChatConversationRes.java} (95%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/{ChatMessageDeleteReq.java => AiChatMessageDeleteReq.java} (91%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/{ChatMessageListRes.java => AiChatMessageListRes.java} (97%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/{ChatMessageReq.java => AiChatMessageReq.java} (91%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/{ChatReq.java => AiChatReq.java} (98%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/{ChatRoleAddReq.java => AiChatRoleAddReq.java} (96%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/{ChatRoleListReq.java => AiChatRoleListReq.java} (87%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/{ChatRoleListRes.java => AiChatRoleListRes.java} (97%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/{ChatRoleUpdateReq.java => AiChatRoleUpdateReq.java} (96%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/{ChatRoleUpdateVisibilityReq.java => AiChatRoleUpdateVisibilityReq.java} (88%) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatConversationTypeEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatConversationTypeEnum.java similarity index 75% rename from yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatConversationTypeEnum.java rename to yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatConversationTypeEnum.java index 18891bbe7..a91bed98d 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatConversationTypeEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatConversationTypeEnum.java @@ -13,7 +13,7 @@ import lombok.Getter; */ @AllArgsConstructor @Getter -public enum ChatConversationTypeEnum { +public enum AiChatConversationTypeEnum { // roleChat、userChat ROLE_CHAT("roleChat", "角色对话"), @@ -25,8 +25,8 @@ public enum ChatConversationTypeEnum { private String name; - public static ChatConversationTypeEnum valueOfType(String type) { - for (ChatConversationTypeEnum itemEnum : ChatConversationTypeEnum.values()) { + public static AiChatConversationTypeEnum valueOfType(String type) { + for (AiChatConversationTypeEnum itemEnum : AiChatConversationTypeEnum.values()) { if (itemEnum.getType().equals(type)) { return itemEnum; } diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleClassifyEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleClassifyEnum.java similarity index 74% rename from yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleClassifyEnum.java rename to yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleClassifyEnum.java index 583bf7483..2221ef737 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleClassifyEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleClassifyEnum.java @@ -12,7 +12,7 @@ import lombok.Getter; */ @AllArgsConstructor @Getter -public enum ChatRoleClassifyEnum { +public enum AiChatRoleClassifyEnum { WRITING("writing", "写作"), @@ -26,8 +26,8 @@ public enum ChatRoleClassifyEnum { private String name; - public static ChatRoleClassifyEnum valueOfClassify(String classify) { - for (ChatRoleClassifyEnum itemEnum : ChatRoleClassifyEnum.values()) { + public static AiChatRoleClassifyEnum valueOfClassify(String classify) { + for (AiChatRoleClassifyEnum itemEnum : AiChatRoleClassifyEnum.values()) { if (itemEnum.getClassify().equals(classify)) { return itemEnum; } diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleSourceEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleSourceEnum.java similarity index 75% rename from yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleSourceEnum.java rename to yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleSourceEnum.java index 877da17ba..94b004456 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleSourceEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleSourceEnum.java @@ -12,7 +12,7 @@ import lombok.Getter; */ @AllArgsConstructor @Getter -public enum ChatRoleSourceEnum { +public enum AiChatRoleSourceEnum { SYSTEM("system", "系统"), CUSTOMER("customer", "用户自定义"), @@ -25,8 +25,8 @@ public enum ChatRoleSourceEnum { private String name; - public static ChatRoleSourceEnum valueOfType(String type) { - for (ChatRoleSourceEnum itemEnum : ChatRoleSourceEnum.values()) { + public static AiChatRoleSourceEnum valueOfType(String type) { + for (AiChatRoleSourceEnum itemEnum : AiChatRoleSourceEnum.values()) { if (itemEnum.getType().equals(type)) { return itemEnum; } diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleVisibilityEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleVisibilityEnum.java similarity index 73% rename from yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleVisibilityEnum.java rename to yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleVisibilityEnum.java index c8b09aedb..ec7a19a2c 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatRoleVisibilityEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleVisibilityEnum.java @@ -12,7 +12,7 @@ import lombok.Getter; */ @AllArgsConstructor @Getter -public enum ChatRoleVisibilityEnum { +public enum AiChatRoleVisibilityEnum { PUBLIC("public", "公开"), PRIVATE("private", "私有的"), @@ -24,8 +24,8 @@ public enum ChatRoleVisibilityEnum { private String name; - public static ChatRoleVisibilityEnum valueOfType(String type) { - for (ChatRoleVisibilityEnum itemEnum : ChatRoleVisibilityEnum.values()) { + public static AiChatRoleVisibilityEnum valueOfType(String type) { + for (AiChatRoleVisibilityEnum itemEnum : AiChatRoleVisibilityEnum.values()) { if (itemEnum.getType().equals(type)) { return itemEnum; } diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatTypeEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatTypeEnum.java similarity index 78% rename from yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatTypeEnum.java rename to yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatTypeEnum.java index cdf7c3ba0..6ee7fabf6 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ChatTypeEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatTypeEnum.java @@ -12,7 +12,7 @@ import lombok.Getter; */ @AllArgsConstructor @Getter -public enum ChatTypeEnum { +public enum AiChatTypeEnum { ROLE_CHAT("roleChat", "角色模板聊天"), USER_CHAT("userChat", "用户普通聊天"), @@ -23,8 +23,8 @@ public enum ChatTypeEnum { private String name; - public static ChatTypeEnum valueOfType(String type) { - for (ChatTypeEnum itemEnum : ChatTypeEnum.values()) { + public static AiChatTypeEnum valueOfType(String type) { + for (AiChatTypeEnum itemEnum : AiChatTypeEnum.values()) { if (itemEnum.getType().equals(type)) { return itemEnum; } diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/OpenAiModelEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiOpenAiModelEnum.java similarity index 96% rename from yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/OpenAiModelEnum.java rename to yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiOpenAiModelEnum.java index 3daa3f57b..d87c980ba 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/OpenAiModelEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiOpenAiModelEnum.java @@ -10,7 +10,7 @@ import lombok.Getter; */ @Getter @AllArgsConstructor -public enum OpenAiModelEnum { +public enum AiOpenAiModelEnum { /** * open ai 3.5模型 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatController.java similarity index 78% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatController.java index 9b7f9f3a9..09b83fcad 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatController.java @@ -1,10 +1,8 @@ package cn.iocoder.yudao.module.ai.controller; -import cn.hutool.core.exceptions.ExceptionUtil; -import cn.iocoder.yudao.framework.ai.chat.ChatResponse; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.ai.service.ChatService; -import cn.iocoder.yudao.module.ai.vo.ChatReq; +import cn.iocoder.yudao.module.ai.service.AiChatService; +import cn.iocoder.yudao.module.ai.vo.AiChatReq; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; @@ -17,10 +15,6 @@ import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; -import reactor.core.publisher.Flux; - -import java.io.IOException; -import java.util.function.Consumer; /** * ia 模块 @@ -34,21 +28,21 @@ import java.util.function.Consumer; @RequestMapping("/ai") @Slf4j @AllArgsConstructor -public class ChatController { +public class AiChatController { @Autowired - private final ChatService chatService; + private final AiChatService chatService; @Operation(summary = "聊天-chat", description = "这个一般等待时间比较久,需要全部完成才会返回!") @GetMapping("/chat") - public CommonResult chat(@Validated @ModelAttribute ChatReq req) { + public CommonResult chat(@Validated @ModelAttribute AiChatReq req) { return CommonResult.success(chatService.chat(req)); } // TODO @芋艿:调用这个方法异常,Unable to handle the Spring Security Exception because the response is already committed. @Operation(summary = "聊天-stream", description = "这里跟通义千问一样采用的是 Server-Sent Events (SSE) 通讯模式") @GetMapping(value = "/chatStream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) - public SseEmitter chatStream(@Validated @ModelAttribute ChatReq req) { + public SseEmitter chatStream(@Validated @ModelAttribute AiChatReq req) { Utf8SseEmitter sseEmitter = new Utf8SseEmitter(); chatService.chatStream(req, sseEmitter); return sseEmitter; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatConversationController.java similarity index 62% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatConversationController.java index ffd75cd44..e0f942042 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatConversationController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatConversationController.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.ai.controller; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.ai.service.ChatConversationService; -import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateRoleReq; -import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateUserReq; -import cn.iocoder.yudao.module.ai.vo.ChatConversationListReq; -import cn.iocoder.yudao.module.ai.vo.ChatConversationRes; +import cn.iocoder.yudao.module.ai.service.AiChatConversationService; +import cn.iocoder.yudao.module.ai.vo.AiChatConversationCreateRoleReq; +import cn.iocoder.yudao.module.ai.vo.AiChatConversationCreateUserReq; +import cn.iocoder.yudao.module.ai.vo.AiChatConversationListReq; +import cn.iocoder.yudao.module.ai.vo.AiChatConversationRes; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; @@ -27,31 +27,31 @@ import java.util.List; @RequestMapping("/ai/chat/conversation") @Slf4j @AllArgsConstructor -public class ChatConversationController { +public class AiChatConversationController { - private final ChatConversationService chatConversationService; + private final AiChatConversationService chatConversationService; @Operation(summary = "创建 - 对话普通对话") @PostMapping("/createConversation") - public CommonResult createConversation(@RequestBody @Validated ChatConversationCreateUserReq req) { + public CommonResult createConversation(@RequestBody @Validated AiChatConversationCreateUserReq req) { return CommonResult.success(chatConversationService.createConversation(req)); } @Operation(summary = "创建 - 对话角色对话") @PostMapping("/createRoleConversation") - public CommonResult createRoleConversation(@RequestBody @Validated ChatConversationCreateRoleReq req) { + public CommonResult createRoleConversation(@RequestBody @Validated AiChatConversationCreateRoleReq req) { return CommonResult.success(chatConversationService.createRoleConversation(req)); } @Operation(summary = "获取 - 获取对话") @GetMapping("/{id}") - public CommonResult getConversation(@PathVariable("id") Long id) { + public CommonResult getConversation(@PathVariable("id") Long id) { return CommonResult.success(chatConversationService.getConversation(id)); } @Operation(summary = "获取 - 获取对话list") @GetMapping("/list") - public CommonResult> listConversation(@ModelAttribute @Validated ChatConversationListReq req) { + public CommonResult> listConversation(@ModelAttribute @Validated AiChatConversationListReq req) { return CommonResult.success(chatConversationService.listConversation(req)); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatMessageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatMessageController.java similarity index 76% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatMessageController.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatMessageController.java index f86450848..ecfb6c865 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatMessageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatMessageController.java @@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.ai.controller; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.ai.service.ChatMessageService; -import cn.iocoder.yudao.module.ai.vo.ChatMessageListRes; -import cn.iocoder.yudao.module.ai.vo.ChatMessageReq; +import cn.iocoder.yudao.module.ai.service.AiChatMessageService; +import cn.iocoder.yudao.module.ai.vo.AiChatMessageListRes; +import cn.iocoder.yudao.module.ai.vo.AiChatMessageReq; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; @@ -24,13 +24,13 @@ import org.springframework.web.bind.annotation.*; @RequestMapping("/ai/chat/message") @Slf4j @AllArgsConstructor -public class ChatMessageController { +public class AiChatMessageController { - private final ChatMessageService chatMessageService; + private final AiChatMessageService chatMessageService; @Operation(summary = "聊天记录", description = "查询个人的聊天记录") @GetMapping("/list") - public PageResult list(@Validated @ModelAttribute ChatMessageReq req) { + public PageResult list(@Validated @ModelAttribute AiChatMessageReq req) { return chatMessageService.list(req); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatRoleController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatRoleController.java similarity index 79% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatRoleController.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatRoleController.java index 947329674..137b8bfa4 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/ChatRoleController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatRoleController.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.ai.controller; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.ai.service.ChatRoleService; +import cn.iocoder.yudao.module.ai.service.AiChatRoleService; import cn.iocoder.yudao.module.ai.vo.*; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -22,19 +22,19 @@ import org.springframework.web.bind.annotation.*; @RequestMapping("/ai/chat") @Slf4j @AllArgsConstructor -public class ChatRoleController { +public class AiChatRoleController { - private final ChatRoleService chatRoleService; + private final AiChatRoleService chatRoleService; @Operation(summary = "chat角色 - 角色列表") @GetMapping("/role/list") - public PageResult list(@Validated @ModelAttribute ChatRoleListReq req) { + public PageResult list(@Validated @ModelAttribute AiChatRoleListReq req) { return chatRoleService.list(req); } @Operation(summary = "chat角色 - 添加") @PutMapping("/role") - public CommonResult add(@Validated @RequestBody ChatRoleAddReq req) { + public CommonResult add(@Validated @RequestBody AiChatRoleAddReq req) { chatRoleService.add(req); return CommonResult.success(null); } @@ -42,7 +42,7 @@ public class ChatRoleController { @Operation(summary = "chat角色 - 修改") @PostMapping("/role/{id}") public CommonResult update(@PathVariable("id") Long id, - @Validated @RequestBody ChatRoleUpdateReq req) { + @Validated @RequestBody AiChatRoleUpdateReq req) { chatRoleService.update(id, req); return CommonResult.success(null); } @@ -50,7 +50,7 @@ public class ChatRoleController { @Operation(summary = "chat角色 - 修改可见性") @PostMapping("/role/{id}/update-visibility") public CommonResult updateVisibility(@PathVariable("id") Long id, - @Validated @RequestBody ChatRoleUpdateVisibilityReq req) { + @Validated @RequestBody AiChatRoleUpdateVisibilityReq req) { chatRoleService.updateVisibility(id, req); return CommonResult.success(null); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatConversationConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java similarity index 57% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatConversationConvert.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java index b2f6951e4..d6c93a1a5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatConversationConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.ai.convert; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatConversationDO; -import cn.iocoder.yudao.module.ai.vo.ChatConversationRes; +import cn.iocoder.yudao.module.ai.vo.AiChatConversationRes; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -15,9 +15,9 @@ import java.util.List; * @since 1.0 */ @Mapper -public interface ChatConversationConvert { +public interface AiChatConversationConvert { - ChatConversationConvert INSTANCE = Mappers.getMapper(ChatConversationConvert.class); + AiChatConversationConvert INSTANCE = Mappers.getMapper(AiChatConversationConvert.class); /** * 转换 - 多个 ChatConversationRes @@ -25,7 +25,7 @@ public interface ChatConversationConvert { * @param top100Conversation * @return */ - List covnertChatConversationResList(List top100Conversation); + List covnertChatConversationResList(List top100Conversation); /** * 转换 - 单个 ChatConversationRes @@ -33,5 +33,5 @@ public interface ChatConversationConvert { * @param aiChatConversationDO * @return */ - ChatConversationRes covnertChatConversationRes(AiChatConversationDO aiChatConversationDO); + AiChatConversationRes covnertChatConversationRes(AiChatConversationDO aiChatConversationDO); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatMessageConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java similarity index 61% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatMessageConvert.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java index 9176d01a0..3a920a466 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatMessageConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.ai.convert; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatMessageDO; -import cn.iocoder.yudao.module.ai.vo.ChatMessageListRes; +import cn.iocoder.yudao.module.ai.vo.AiChatMessageListRes; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -15,9 +15,9 @@ import java.util.List; * @since 1.0 */ @Mapper -public interface ChatMessageConvert { +public interface AiChatMessageConvert { - ChatMessageConvert INSTANCE = Mappers.getMapper(ChatMessageConvert.class); + AiChatMessageConvert INSTANCE = Mappers.getMapper(AiChatMessageConvert.class); /** * 转换 ChatMessageListRes @@ -25,5 +25,5 @@ public interface ChatMessageConvert { * @param list * @return */ - List convert(List list); + List convert(List list); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatModalConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java similarity index 86% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatModalConvert.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java index a83d4f0ef..cb3f644c0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatModalConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java @@ -16,9 +16,9 @@ import java.util.List; * @since 1.0 */ @Mapper -public interface ChatModalConvert { +public interface AiChatModalConvert { - ChatModalConvert INSTANCE = Mappers.getMapper(ChatModalConvert.class); + AiChatModalConvert INSTANCE = Mappers.getMapper(AiChatModalConvert.class); /** * 转换 - AiChatModalListRes diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatRoleConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java similarity index 53% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatRoleConvert.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java index d30ea8010..80977c442 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/ChatRoleConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.ai.convert; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.vo.ChatRoleAddReq; -import cn.iocoder.yudao.module.ai.vo.ChatRoleListRes; -import cn.iocoder.yudao.module.ai.vo.ChatRoleUpdateReq; +import cn.iocoder.yudao.module.ai.vo.AiChatRoleAddReq; +import cn.iocoder.yudao.module.ai.vo.AiChatRoleUpdateReq; +import cn.iocoder.yudao.module.ai.vo.AiChatRoleListRes; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -17,9 +17,9 @@ import java.util.List; * @since 1.0 */ @Mapper -public interface ChatRoleConvert { +public interface AiChatRoleConvert { - ChatRoleConvert INSTANCE = Mappers.getMapper(ChatRoleConvert.class); + AiChatRoleConvert INSTANCE = Mappers.getMapper(AiChatRoleConvert.class); /** * 转换 - ChatRoleListRes @@ -27,7 +27,7 @@ public interface ChatRoleConvert { * @param roleList * @return */ - List convertChatRoleListRes(List roleList); + List convertChatRoleListRes(List roleList); /** * 转换 - AiChatRoleDO @@ -35,7 +35,7 @@ public interface ChatRoleConvert { * @param req * @return */ - AiChatRoleDO convertAiChatRoleDO(ChatRoleAddReq req); + AiChatRoleDO convertAiChatRoleDO(AiChatRoleAddReq req); /** * 转换 - AiChatRoleDO @@ -43,5 +43,5 @@ public interface ChatRoleConvert { * @param req * @return */ - AiChatRoleDO convertAiChatRoleDO(ChatRoleUpdateReq req); + AiChatRoleDO convertAiChatRoleDO(AiChatRoleUpdateReq req); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java index ed1127a0b..cdac20ad6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.ai.mapper; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatMessageDO; -import cn.iocoder.yudao.module.ai.vo.ChatMessageReq; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java new file mode 100644 index 000000000..fbae7c8c4 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.ai.service; + +import cn.iocoder.yudao.module.ai.vo.AiChatConversationCreateRoleReq; +import cn.iocoder.yudao.module.ai.vo.AiChatConversationCreateUserReq; +import cn.iocoder.yudao.module.ai.vo.AiChatConversationListReq; +import cn.iocoder.yudao.module.ai.vo.AiChatConversationRes; + +import java.util.List; + +/** + * chat 对话 + * + * @fansili + * @since v1.0 + */ +public interface AiChatConversationService { + + /** + * 对话 - 创建普通对话 + * + * @param req + * @return + */ + AiChatConversationRes createConversation(AiChatConversationCreateUserReq req); + + /** + * 对话 - 创建role对话 + * + * @param req + * @return + */ + AiChatConversationRes createRoleConversation(AiChatConversationCreateRoleReq req); + + + /** + * 获取 - 对话 + * + * @param id + * @return + */ + AiChatConversationRes getConversation(Long id); + + /** + * 获取 - 对话列表 + * + * @param req + * @return + */ + List listConversation(AiChatConversationListReq req); + + /** + * 删除 - 根据id + * + * @param id + */ + void delete(Long id); + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatMessageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatMessageService.java similarity index 65% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatMessageService.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatMessageService.java index 625bc1b2e..ef1cfa468 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatMessageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatMessageService.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.ai.vo.ChatMessageListRes; -import cn.iocoder.yudao.module.ai.vo.ChatMessageReq; +import cn.iocoder.yudao.module.ai.vo.AiChatMessageListRes; +import cn.iocoder.yudao.module.ai.vo.AiChatMessageReq; /** * chat message @@ -11,7 +11,7 @@ import cn.iocoder.yudao.module.ai.vo.ChatMessageReq; * @time 2024/4/24 17:25 * @since 1.0 */ -public interface ChatMessageService { +public interface AiChatMessageService { /** * message - 列表 @@ -19,7 +19,7 @@ public interface ChatMessageService { * @param req * @return */ - PageResult list(ChatMessageReq req); + PageResult list(AiChatMessageReq req); /** * message - 删除 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java similarity index 66% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java index d189455e1..d3bd201e9 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java @@ -1,18 +1,15 @@ package cn.iocoder.yudao.module.ai.service; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.vo.*; -import java.util.List; - /** * chat 角色 * * @fansili * @since v1.0 */ -public interface ChatRoleService { +public interface AiChatRoleService { /** * 获取聊天角色列表 @@ -20,7 +17,7 @@ public interface ChatRoleService { * @param req * @return */ - PageResult list(ChatRoleListReq req); + PageResult list(AiChatRoleListReq req); /** * chat角色 - 添加 @@ -28,7 +25,7 @@ public interface ChatRoleService { * @param req * @return */ - void add(ChatRoleAddReq req); + void add(AiChatRoleAddReq req); /** * chat角色 - 修改 @@ -36,7 +33,7 @@ public interface ChatRoleService { * @param id * @param req */ - void update(Long id, ChatRoleUpdateReq req); + void update(Long id, AiChatRoleUpdateReq req); /** @@ -45,7 +42,7 @@ public interface ChatRoleService { * @param id * @param req */ - void updateVisibility(Long id, ChatRoleUpdateVisibilityReq req); + void updateVisibility(Long id, AiChatRoleUpdateVisibilityReq req); /** * chat角色 - 删除 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java similarity index 67% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatService.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java index fd19d822a..b3596e9cf 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; -import cn.iocoder.yudao.module.ai.vo.ChatReq; +import cn.iocoder.yudao.module.ai.vo.AiChatReq; /** * 聊天 chat @@ -10,7 +10,7 @@ import cn.iocoder.yudao.module.ai.vo.ChatReq; * @time 2024/4/14 15:55 * @since 1.0 */ -public interface ChatService { +public interface AiChatService { /** * chat @@ -18,7 +18,7 @@ public interface ChatService { * @param req * @return */ - String chat(ChatReq req); + String chat(AiChatReq req); /** * chat stream @@ -27,5 +27,5 @@ public interface ChatService { * @param sseEmitter * @return */ - void chatStream(ChatReq req, Utf8SseEmitter sseEmitter); + void chatStream(AiChatReq req, Utf8SseEmitter sseEmitter); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatConversationService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatConversationService.java deleted file mode 100644 index 428a26e10..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/ChatConversationService.java +++ /dev/null @@ -1,58 +0,0 @@ -package cn.iocoder.yudao.module.ai.service; - -import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateRoleReq; -import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateUserReq; -import cn.iocoder.yudao.module.ai.vo.ChatConversationListReq; -import cn.iocoder.yudao.module.ai.vo.ChatConversationRes; - -import java.util.List; - -/** - * chat 对话 - * - * @fansili - * @since v1.0 - */ -public interface ChatConversationService { - - /** - * 对话 - 创建普通对话 - * - * @param req - * @return - */ - ChatConversationRes createConversation(ChatConversationCreateUserReq req); - - /** - * 对话 - 创建role对话 - * - * @param req - * @return - */ - ChatConversationRes createRoleConversation(ChatConversationCreateRoleReq req); - - - /** - * 获取 - 对话 - * - * @param id - * @return - */ - ChatConversationRes getConversation(Long id); - - /** - * 获取 - 对话列表 - * - * @param req - * @return - */ - List listConversation(ChatConversationListReq req); - - /** - * 删除 - 根据id - * - * @param id - */ - void delete(Long id); - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java similarity index 68% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java index 7b6f5fa8d..8e6a520c7 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java @@ -3,17 +3,17 @@ package cn.iocoder.yudao.module.ai.service.impl; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; -import cn.iocoder.yudao.module.ai.convert.ChatConversationConvert; +import cn.iocoder.yudao.module.ai.convert.AiChatConversationConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.enums.ChatConversationTypeEnum; +import cn.iocoder.yudao.module.ai.enums.AiChatConversationTypeEnum; import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.mapper.AiChatRoleMapper; -import cn.iocoder.yudao.module.ai.service.ChatConversationService; -import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateRoleReq; -import cn.iocoder.yudao.module.ai.vo.ChatConversationCreateUserReq; -import cn.iocoder.yudao.module.ai.vo.ChatConversationListReq; -import cn.iocoder.yudao.module.ai.vo.ChatConversationRes; +import cn.iocoder.yudao.module.ai.service.AiChatConversationService; +import cn.iocoder.yudao.module.ai.vo.AiChatConversationCreateRoleReq; +import cn.iocoder.yudao.module.ai.vo.AiChatConversationCreateUserReq; +import cn.iocoder.yudao.module.ai.vo.AiChatConversationListReq; +import cn.iocoder.yudao.module.ai.vo.AiChatConversationRes; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; @@ -30,51 +30,51 @@ import java.util.List; @Service @Slf4j @AllArgsConstructor -public class ChatConversationServiceImpl implements ChatConversationService { +public class AiChatConversationServiceImpl implements AiChatConversationService { private final AiChatRoleMapper aiChatRoleMapper; private final AiChatConversationMapper aiChatConversationMapper; @Override - public ChatConversationRes createConversation(ChatConversationCreateUserReq req) { + public AiChatConversationRes createConversation(AiChatConversationCreateUserReq req) { // 获取用户id Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 查询最新的对话 AiChatConversationDO latestConversation = aiChatConversationMapper.selectLatestConversation(loginUserId); // 如果有对话没有被使用过,那就返回这个 if (latestConversation != null && latestConversation.getChatCount() <= 0) { - return ChatConversationConvert.INSTANCE.covnertChatConversationRes(latestConversation); + return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(latestConversation); } // 创建新的 Conversation AiChatConversationDO insertConversation = saveConversation(req.getTitle(), loginUserId, - null, null, ChatConversationTypeEnum.USER_CHAT); + null, null, AiChatConversationTypeEnum.USER_CHAT); // 转换 res - return ChatConversationConvert.INSTANCE.covnertChatConversationRes(insertConversation); + return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(insertConversation); } @Override - public ChatConversationRes createRoleConversation(ChatConversationCreateRoleReq req) { + public AiChatConversationRes createRoleConversation(AiChatConversationCreateRoleReq req) { // 获取用户id Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 查询最新的对话 AiChatConversationDO latestConversation = aiChatConversationMapper.selectLatestConversation(loginUserId); // 如果有对话没有被使用过,那就返回这个 if (latestConversation != null && latestConversation.getChatCount() <= 0) { - return ChatConversationConvert.INSTANCE.covnertChatConversationRes(latestConversation); + return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(latestConversation); } AiChatRoleDO aiChatRoleDO = aiChatRoleMapper.selectById(req.getChatRoleId()); // 创建新的 Conversation AiChatConversationDO insertConversation = saveConversation(req.getTitle(), loginUserId, - req.getChatRoleId(), aiChatRoleDO.getRoleName(), ChatConversationTypeEnum.ROLE_CHAT); + req.getChatRoleId(), aiChatRoleDO.getRoleName(), AiChatConversationTypeEnum.ROLE_CHAT); // 转换 res - return ChatConversationConvert.INSTANCE.covnertChatConversationRes(insertConversation); + return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(insertConversation); } private @NotNull AiChatConversationDO saveConversation(String title, Long userId, Long chatRoleId, String chatRoleName, - ChatConversationTypeEnum typeEnum) { + AiChatConversationTypeEnum typeEnum) { AiChatConversationDO insertConversation = new AiChatConversationDO(); insertConversation.setId(null); insertConversation.setUserId(userId); @@ -88,22 +88,22 @@ public class ChatConversationServiceImpl implements ChatConversationService { } @Override - public ChatConversationRes getConversation(Long id) { + public AiChatConversationRes getConversation(Long id) { AiChatConversationDO aiChatConversationDO = aiChatConversationMapper.selectById(id); if (aiChatConversationDO == null) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CHAT_CONTINUE_NOT_EXIST); } - return ChatConversationConvert.INSTANCE.covnertChatConversationRes(aiChatConversationDO); + return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(aiChatConversationDO); } @Override - public List listConversation(ChatConversationListReq req) { + public List listConversation(AiChatConversationListReq req) { // 获取用户id Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 查询前100对话 List top100Conversation = aiChatConversationMapper.selectTop100Conversation(loginUserId, req.getSearch()); - return ChatConversationConvert.INSTANCE.covnertChatConversationResList(top100Conversation); + return AiChatConversationConvert.INSTANCE.covnertChatConversationResList(top100Conversation); } @Override diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatMessageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatMessageServiceImpl.java similarity index 83% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatMessageServiceImpl.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatMessageServiceImpl.java index ab0c05ff4..576fff3f5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatMessageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatMessageServiceImpl.java @@ -5,14 +5,14 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; -import cn.iocoder.yudao.module.ai.convert.ChatMessageConvert; +import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatMessageDO; import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.mapper.AiChatMessageMapper; -import cn.iocoder.yudao.module.ai.service.ChatMessageService; -import cn.iocoder.yudao.module.ai.vo.ChatMessageListRes; -import cn.iocoder.yudao.module.ai.vo.ChatMessageReq; +import cn.iocoder.yudao.module.ai.service.AiChatMessageService; +import cn.iocoder.yudao.module.ai.vo.AiChatMessageListRes; +import cn.iocoder.yudao.module.ai.vo.AiChatMessageReq; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -29,13 +29,13 @@ import java.util.List; @AllArgsConstructor @Service @Slf4j -public class ChatMessageServiceImpl implements ChatMessageService { +public class AiChatMessageServiceImpl implements AiChatMessageService { private final AiChatMessageMapper aiChatMessageMapper; private final AiChatConversationMapper aiChatConversationMapper; @Override - public PageResult list(ChatMessageReq req) { + public PageResult list(AiChatMessageReq req) { // 查询 LambdaQueryWrapperX queryWrapperX = new LambdaQueryWrapperX<>(); queryWrapperX.eq(AiChatMessageDO::getChatConversationId, req.getChatConversationId()); @@ -43,7 +43,7 @@ public class ChatMessageServiceImpl implements ChatMessageService { queryWrapperX.orderByDesc(AiChatMessageDO::getId); PageResult pageResult = aiChatMessageMapper.selectPage(req, queryWrapperX); // 转换 res - List messageListResList = ChatMessageConvert.INSTANCE.convert(pageResult.getList()); + List messageListResList = AiChatMessageConvert.INSTANCE.convert(pageResult.getList()); return new PageResult(messageListResList, pageResult.getTotal()); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java index af1a223c8..9e4b6e41d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; -import cn.iocoder.yudao.module.ai.convert.ChatModalConvert; +import cn.iocoder.yudao.module.ai.convert.AiChatModalConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO; import cn.iocoder.yudao.module.ai.enums.AiChatModalDisableEnum; import cn.iocoder.yudao.module.ai.mapper.AiChatModalMapper; @@ -47,14 +47,14 @@ public class AiChatModalServiceImpl implements AiChatModalService { // 查询 PageResult aiChatModalDOPageResult = aiChatModalMapper.selectPage(req, queryWrapperX); // 转换 res - List resList = ChatModalConvert.INSTANCE.convertAiChatModalListRes(aiChatModalDOPageResult.getList()); + List resList = AiChatModalConvert.INSTANCE.convertAiChatModalListRes(aiChatModalDOPageResult.getList()); return new PageResult<>(resList, aiChatModalDOPageResult.getTotal()); } @Override public void add(AiChatModalAddReq req) { // 转换 do - AiChatModalDO insertChatModalDO = ChatModalConvert.INSTANCE.convertAiChatModalDO(req); + AiChatModalDO insertChatModalDO = AiChatModalConvert.INSTANCE.convertAiChatModalDO(req); // insertChatModalDO.setDisable(AiChatModalDisableEnum.NO.getValue()); // 保存数据库 @@ -66,7 +66,7 @@ public class AiChatModalServiceImpl implements AiChatModalService { // 校验模型是否存在 validateChatModalExists(id); // 转换 updateChatModalDO - AiChatModalDO updateChatModalDO = ChatModalConvert.INSTANCE.convertAiChatModalDO(req); + AiChatModalDO updateChatModalDO = AiChatModalConvert.INSTANCE.convertAiChatModalDO(req); updateChatModalDO.setId(id); // 更新数据库 aiChatModalMapper.updateById(updateChatModalDO); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java similarity index 67% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java index af2e8336b..870168e2a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java @@ -6,13 +6,13 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; -import cn.iocoder.yudao.module.ai.convert.ChatRoleConvert; +import cn.iocoder.yudao.module.ai.convert.AiChatRoleConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.enums.ChatRoleClassifyEnum; -import cn.iocoder.yudao.module.ai.enums.ChatRoleSourceEnum; -import cn.iocoder.yudao.module.ai.enums.ChatRoleVisibilityEnum; +import cn.iocoder.yudao.module.ai.enums.AiChatRoleClassifyEnum; +import cn.iocoder.yudao.module.ai.enums.AiChatRoleSourceEnum; +import cn.iocoder.yudao.module.ai.enums.AiChatRoleVisibilityEnum; import cn.iocoder.yudao.module.ai.mapper.AiChatRoleMapper; -import cn.iocoder.yudao.module.ai.service.ChatRoleService; +import cn.iocoder.yudao.module.ai.service.AiChatRoleService; import cn.iocoder.yudao.module.ai.vo.*; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -29,12 +29,12 @@ import java.util.List; @Service @AllArgsConstructor @Slf4j -public class ChatRoleServiceImpl implements ChatRoleService { +public class AiChatRoleServiceImpl implements AiChatRoleService { private final AiChatRoleMapper aiChatRoleMapper; @Override - public PageResult list(ChatRoleListReq req) { + public PageResult list(AiChatRoleListReq req) { // 查询条件 LambdaQueryWrapperX queryWrapperX = new LambdaQueryWrapperX<>(); // search 查询 @@ -48,18 +48,18 @@ public class ChatRoleServiceImpl implements ChatRoleService { Long total = aiChatRoleDOPageResult.getTotal(); List roleList = aiChatRoleDOPageResult.getList(); // 换货res - List chatRoleListResList = ChatRoleConvert.INSTANCE.convertChatRoleListRes(roleList); + List chatRoleListResList = AiChatRoleConvert.INSTANCE.convertChatRoleListRes(roleList); return new PageResult<>(chatRoleListResList, total); } @Override - public void add(ChatRoleAddReq req) { + public void add(AiChatRoleAddReq req) { // 转换enum,并校验enum - ChatRoleClassifyEnum.valueOfClassify(req.getClassify()); - ChatRoleVisibilityEnum.valueOfType(req.getVisibility()); - ChatRoleSourceEnum.valueOfType(req.getRoleSource()); + AiChatRoleClassifyEnum.valueOfClassify(req.getClassify()); + AiChatRoleVisibilityEnum.valueOfType(req.getVisibility()); + AiChatRoleSourceEnum.valueOfType(req.getRoleSource()); // 转换do - AiChatRoleDO insertAiChatRoleDO = ChatRoleConvert.INSTANCE.convertAiChatRoleDO(req); + AiChatRoleDO insertAiChatRoleDO = AiChatRoleConvert.INSTANCE.convertAiChatRoleDO(req); insertAiChatRoleDO.setUserId(SecurityFrameworkUtils.getLoginUserId()); insertAiChatRoleDO.setUseCount(0); // 保存 @@ -67,24 +67,24 @@ public class ChatRoleServiceImpl implements ChatRoleService { } @Override - public void update(Long id, ChatRoleUpdateReq req) { + public void update(Long id, AiChatRoleUpdateReq req) { // 转换enum,并校验enum - ChatRoleClassifyEnum.valueOfClassify(req.getClassify()); - ChatRoleVisibilityEnum.valueOfType(req.getVisibility()); - ChatRoleSourceEnum.valueOfType(req.getRoleSource()); + AiChatRoleClassifyEnum.valueOfClassify(req.getClassify()); + AiChatRoleVisibilityEnum.valueOfType(req.getVisibility()); + AiChatRoleSourceEnum.valueOfType(req.getRoleSource()); // 检查角色是否存在 validateChatRoleExists(id); // 转换do - AiChatRoleDO updateChatRole = ChatRoleConvert.INSTANCE.convertAiChatRoleDO(req); + AiChatRoleDO updateChatRole = AiChatRoleConvert.INSTANCE.convertAiChatRoleDO(req); updateChatRole.setId(id); aiChatRoleMapper.updateById(updateChatRole); } @Override - public void updateVisibility(Long id, ChatRoleUpdateVisibilityReq req) { + public void updateVisibility(Long id, AiChatRoleUpdateVisibilityReq req) { // 转换enum,并校验enum - ChatRoleVisibilityEnum.valueOfType(req.getVisibility()); + AiChatRoleVisibilityEnum.valueOfType(req.getVisibility()); // 检查角色是否存在 validateChatRoleExists(id); // 更新 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java similarity index 86% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index 57e6b7358..1caad8ada 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/ChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -12,10 +12,10 @@ import cn.iocoder.yudao.module.ai.enums.AiClientNameEnum; import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.mapper.AiChatMessageMapper; import cn.iocoder.yudao.module.ai.mapper.AiChatRoleMapper; -import cn.iocoder.yudao.module.ai.service.ChatConversationService; -import cn.iocoder.yudao.module.ai.service.ChatService; -import cn.iocoder.yudao.module.ai.vo.ChatConversationRes; -import cn.iocoder.yudao.module.ai.vo.ChatReq; +import cn.iocoder.yudao.module.ai.service.AiChatConversationService; +import cn.iocoder.yudao.module.ai.service.AiChatService; +import cn.iocoder.yudao.module.ai.vo.AiChatConversationRes; +import cn.iocoder.yudao.module.ai.vo.AiChatReq; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.MediaType; @@ -36,13 +36,13 @@ import java.util.function.Consumer; @Slf4j @Service @AllArgsConstructor -public class ChatServiceImpl implements ChatService { +public class AiChatServiceImpl implements AiChatService { private final AiClient aiClient; private final AiChatRoleMapper aiChatRoleMapper; private final AiChatMessageMapper aiChatMessageMapper; private final AiChatConversationMapper aiChatConversationMapper; - private final ChatConversationService chatConversationService; + private final AiChatConversationService chatConversationService; /** * chat @@ -51,12 +51,12 @@ public class ChatServiceImpl implements ChatService { * @return */ @Transactional(rollbackFor = Exception.class) - public String chat(ChatReq req) { + public String chat(AiChatReq req) { Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 获取 client 类型 AiClientNameEnum clientNameEnum = AiClientNameEnum.valueOfName(req.getModal()); // 获取对话信息 - ChatConversationRes conversationRes = chatConversationService.getConversation(req.getConversationId()); + AiChatConversationRes conversationRes = chatConversationService.getConversation(req.getConversationId()); // 保存 chat message saveChatMessage(req, conversationRes, loginUserId); String content = null; @@ -80,7 +80,7 @@ public class ChatServiceImpl implements ChatService { return content; } - private void saveChatMessage(ChatReq req, ChatConversationRes conversationRes, Long loginUserId) { + private void saveChatMessage(AiChatReq req, AiChatConversationRes conversationRes, Long loginUserId) { Long chatConversationId = conversationRes.getId(); // 增加 chat message 记录 aiChatMessageMapper.insert( @@ -98,7 +98,7 @@ public class ChatServiceImpl implements ChatService { aiChatConversationMapper.updateIncrChatCount(req.getConversationId()); } - public void saveSystemChatMessage(ChatReq req, ChatConversationRes conversationRes, Long loginUserId, String systemPrompts) { + public void saveSystemChatMessage(AiChatReq req, AiChatConversationRes conversationRes, Long loginUserId, String systemPrompts) { Long chatConversationId = conversationRes.getId(); // 增加 chat message 记录 aiChatMessageMapper.insert( @@ -125,12 +125,12 @@ public class ChatServiceImpl implements ChatService { * @return */ @Override - public void chatStream(ChatReq req, Utf8SseEmitter sseEmitter) { + public void chatStream(AiChatReq req, Utf8SseEmitter sseEmitter) { Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 获取 client 类型 AiClientNameEnum clientNameEnum = AiClientNameEnum.valueOfName(req.getModal()); // 获取对话信息 - ChatConversationRes conversationRes = chatConversationService.getConversation(req.getConversationId()); + AiChatConversationRes conversationRes = chatConversationService.getConversation(req.getConversationId()); // 创建 chat 需要的 Prompt Prompt prompt = new Prompt(req.getPrompt()); req.setTopK(req.getTopK()); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateRoleReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateRoleReq.java similarity index 92% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateRoleReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateRoleReq.java index 9af6a44ef..95223ce9f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateRoleReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateRoleReq.java @@ -14,7 +14,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class ChatConversationCreateRoleReq { +public class AiChatConversationCreateRoleReq { @Schema(description = "chat角色Id") @NotNull(message = "聊天角色id不能为空!") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateUserReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateUserReq.java similarity index 90% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateUserReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateUserReq.java index 9f967175e..c8276ef80 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationCreateUserReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateUserReq.java @@ -14,7 +14,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class ChatConversationCreateUserReq { +public class AiChatConversationCreateUserReq { @Schema(description = "对话标题") @NotNull(message = "标题不能为空!") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationListReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationListReq.java similarity index 89% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationListReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationListReq.java index 846c8b2bc..208bf67a2 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationListReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationListReq.java @@ -13,7 +13,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class ChatConversationListReq { +public class AiChatConversationListReq { @Schema(description = "查询根据title") private String search; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationRes.java similarity index 95% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationRes.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationRes.java index aa11c0464..ca8254d5f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatConversationRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationRes.java @@ -13,7 +13,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class ChatConversationRes { +public class AiChatConversationRes { @Schema(description = "id") private Long id; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageDeleteReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatMessageDeleteReq.java similarity index 91% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageDeleteReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatMessageDeleteReq.java index 9b2986e81..dafd7d84f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageDeleteReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatMessageDeleteReq.java @@ -15,7 +15,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class ChatMessageDeleteReq extends PageParam { +public class AiChatMessageDeleteReq extends PageParam { @Schema(description = "id") @NotNull diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageListRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatMessageListRes.java similarity index 97% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageListRes.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatMessageListRes.java index 52017c062..ecfbc009c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageListRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatMessageListRes.java @@ -13,7 +13,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class ChatMessageListRes { +public class AiChatMessageListRes { @Schema(description = "编号") private Long id; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatMessageReq.java similarity index 91% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatMessageReq.java index b0f38a321..60b7e91ee 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatMessageReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatMessageReq.java @@ -15,7 +15,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class ChatMessageReq extends PageParam { +public class AiChatMessageReq extends PageParam { @Schema(description = "聊天ID,关联到特定的会话或对话") @NotNull diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatReq.java similarity index 98% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatReq.java index cf41e4cf8..0597f8990 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatReq.java @@ -15,7 +15,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class ChatReq { +public class AiChatReq { @Schema(description = "ai模型(查看 AiClientNameEnum)") @NotNull(message = "模型不能为空!") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatReqVO.java index eafbecda5..f4bca2fd6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatReqVO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.ai.vo; -import cn.iocoder.yudao.module.ai.enums.OpenAiModelEnum; +import cn.iocoder.yudao.module.ai.enums.AiOpenAiModelEnum; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -16,6 +16,6 @@ public class AiChatReqVO { @Schema(description = "AI模型", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "AI模型不能为空") - private OpenAiModelEnum aiModel; + private AiOpenAiModelEnum aiModel; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleAddReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleAddReq.java similarity index 96% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleAddReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleAddReq.java index 2c83bc59a..63342c61b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleAddReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleAddReq.java @@ -14,7 +14,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class ChatRoleAddReq extends PageParam { +public class AiChatRoleAddReq extends PageParam { @NotNull @Schema(description = "模型编号,关联到角色使用的特定模型") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleListReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleListReq.java similarity index 87% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleListReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleListReq.java index 32a028b94..1dd5e54ce 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleListReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleListReq.java @@ -13,7 +13,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class ChatRoleListReq extends PageParam { +public class AiChatRoleListReq extends PageParam { @Schema(description = "查询") private String search; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleListRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleListRes.java similarity index 97% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleListRes.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleListRes.java index 5babda544..8f582cc58 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleListRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleListRes.java @@ -12,7 +12,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class ChatRoleListRes { +public class AiChatRoleListRes { @Schema(description = "id") private Long id; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleUpdateReq.java similarity index 96% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleUpdateReq.java index 6ec165ed8..c6197f8d4 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleUpdateReq.java @@ -14,7 +14,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class ChatRoleUpdateReq extends PageParam { +public class AiChatRoleUpdateReq extends PageParam { @NotNull @Schema(description = "模型编号,关联到角色使用的特定模型") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateVisibilityReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleUpdateVisibilityReq.java similarity index 88% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateVisibilityReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleUpdateVisibilityReq.java index 764972f49..d0d216b24 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/ChatRoleUpdateVisibilityReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleUpdateVisibilityReq.java @@ -14,7 +14,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class ChatRoleUpdateVisibilityReq extends PageParam { +public class AiChatRoleUpdateVisibilityReq extends PageParam { @NotNull @Schema(description = "发布状态,0表示仅自己可见,1表示公开,2表示禁用") From 4db96fa36117734507e3b073ec94524c3b330aeb Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 25 Apr 2024 16:17:33 +0800 Subject: [PATCH 152/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=20ai=20=E7=BB=98=E7=94=BB=EF=BC=8C?= =?UTF-8?q?=E9=9C=80=E8=A6=81=E7=9A=84=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/AiImageController.java | 24 +++++++++++++ .../ai/dal/dataobject/AiDrawingImage.java | 36 +++++++++++++++++++ .../module/ai/service/AiImageService.java | 11 ++++++ .../ai/service/impl/AiImageServiceImpl.java | 22 ++++++++++++ 4 files changed, 93 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiDrawingImage.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java new file mode 100644 index 000000000..1f10398e9 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.ai.controller; + +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * ai作图 + * + * @author fansili + * @time 2024/4/25 15:49 + * @since 1.0 + */ +@Tag(name = "A10-ai作图") +@RestController +@RequestMapping("/ai/chat/message") +@Slf4j +@AllArgsConstructor +public class AiImageController { + + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiDrawingImage.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiDrawingImage.java new file mode 100644 index 000000000..3b29be61b --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiDrawingImage.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.ai.dal.dataobject; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * ai 绘画 + * + * @author fansili + * @time 2024/4/25 15:53 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +@TableName("ai_drawing_image") +public class AiDrawingImage extends BaseDO { + + @TableId(type = IdType.AUTO) + private Long id; + + @Schema(description = "提示词") + private String prompt; + + @Schema(description = "绘画状态:提交、排队、绘画中、绘画完成、绘画失败") + private String drawingStatus; + + @Schema(description = "绘画图片地址") + private String drawingImageUrl; + +} + diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java new file mode 100644 index 000000000..703359f3c --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java @@ -0,0 +1,11 @@ +package cn.iocoder.yudao.module.ai.service; + +/** + * ai 作图 + * + * @author fansili + * @time 2024/4/25 15:50 + * @since 1.0 + */ +public interface AiImageService { +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java new file mode 100644 index 000000000..872099935 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.ai.service.impl; + +import cn.iocoder.yudao.module.ai.service.AiImageService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * ai 作图 + * + * @author fansili + * @time 2024/4/25 15:51 + * @since 1.0 + */ +@AllArgsConstructor +@Service +@Slf4j +public class AiImageServiceImpl implements AiImageService { + + + +} From 4a6b4e5f65d36d6af15ace9b022a0efbd1652fe2 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 25 Apr 2024 16:31:02 +0800 Subject: [PATCH 153/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E4=BC=98=E5=8C=96=20chat=20=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/config/YudaoAiAutoConfiguration.java | 28 ------------------- 1 file changed, 28 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index 7e734cd2a..cefe096e8 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -12,15 +12,10 @@ import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatClient; import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanOptions; import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanApi; import cn.iocoder.yudao.framework.ai.exception.AiException; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.InitializingBean; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Bean; -import org.springframework.context.support.GenericApplicationContext; import java.util.HashMap; import java.util.Map; @@ -65,29 +60,6 @@ public class YudaoAiAutoConfiguration { return chatMap; } - public static class InitChatClient implements InitializingBean, ApplicationContextAware { - - private GenericApplicationContext applicationContext; - private YudaoAiProperties yudaoAiProperties; - - public InitChatClient(YudaoAiProperties yudaoAiProperties) { - this.yudaoAiProperties = yudaoAiProperties; - } - - @Override - public void afterPropertiesSet() { - - - System.err.println(applicationContext.getBean("qianWen")); - System.err.println(applicationContext.getBean("yiYan")); - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = (GenericApplicationContext) applicationContext; - } - } - private static Object createChatClient(YudaoAiProperties.ChatProperties chatProperties) { if (AiPlatformEnum.XING_HUO == chatProperties.getAiPlatform()) { YudaoAiProperties.XingHuoProperties xingHuoProperties = (YudaoAiProperties.XingHuoProperties) chatProperties; From edb2a844cc1fbe3477e6d10c2aed0f10991c67f9 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 25 Apr 2024 16:32:19 +0800 Subject: [PATCH 154/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E4=BC=98=E5=8C=96=20yudao=20client=20=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/iocoder/yudao/framework/ai/config/YudaoAiClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiClient.java index 2f584c40a..eaed5557a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiClient.java @@ -16,7 +16,7 @@ import java.util.Map; * @time 2024/4/14 10:27 * @since 1.0 */ -public class YudaoAiClient implements AiClient{ +public class YudaoAiClient implements AiClient { protected Map chatClientMap; From 44f7c841de1878f61e51df966d1114456380d77b Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 25 Apr 2024 16:56:54 +0800 Subject: [PATCH 155/684] =?UTF-8?q?=E3=80=90=E4=BF=AE=E6=94=B9=E3=80=91?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20dall2\dall3=20=E7=BB=98=E7=94=BB=E6=96=B9?= =?UTF-8?q?=E6=B3=95=EF=BC=8C=E8=BF=98=E6=9C=AA=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/AiImageController.java | 17 +++++++++++++- ...rawingImage.java => AiDrawingImageDO.java} | 2 +- .../module/ai/service/AiImageService.java | 11 ++++++++++ .../ai/service/impl/AiImageServiceImpl.java | 5 +++++ .../module/ai/vo/AiImageDallDrawingReq.java | 22 +++++++++++++++++++ 5 files changed, 55 insertions(+), 2 deletions(-) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/{AiDrawingImage.java => AiDrawingImageDO.java} (94%) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageDallDrawingReq.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java index 1f10398e9..dad0d00f4 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java @@ -1,10 +1,17 @@ package cn.iocoder.yudao.module.ai.controller; +import cn.iocoder.yudao.module.ai.service.AiImageService; +import cn.iocoder.yudao.module.ai.vo.AiImageDallDrawingReq; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; /** * ai作图 @@ -15,10 +22,18 @@ import org.springframework.web.bind.annotation.RestController; */ @Tag(name = "A10-ai作图") @RestController -@RequestMapping("/ai/chat/message") +@RequestMapping("/ai/image") @Slf4j @AllArgsConstructor public class AiImageController { + private final AiImageService aiImageService; + @Operation(summary = "dall2/dall3绘画", description = "openAi dall3是付费的!") + @GetMapping("/dallDrawing") + public SseEmitter dallDrawing(@Validated @ModelAttribute AiImageDallDrawingReq req) { + Utf8SseEmitter sseEmitter = new Utf8SseEmitter(); + aiImageService.dallDrawing(req, sseEmitter); + return null; + } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiDrawingImage.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiDrawingImageDO.java similarity index 94% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiDrawingImage.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiDrawingImageDO.java index 3b29be61b..87d885deb 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiDrawingImage.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiDrawingImageDO.java @@ -18,7 +18,7 @@ import lombok.experimental.Accessors; @Data @Accessors(chain = true) @TableName("ai_drawing_image") -public class AiDrawingImage extends BaseDO { +public class AiDrawingImageDO extends BaseDO { @TableId(type = IdType.AUTO) private Long id; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java index 703359f3c..05e512d24 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java @@ -1,5 +1,8 @@ package cn.iocoder.yudao.module.ai.service; +import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; +import cn.iocoder.yudao.module.ai.vo.AiImageDallDrawingReq; + /** * ai 作图 * @@ -8,4 +11,12 @@ package cn.iocoder.yudao.module.ai.service; * @since 1.0 */ public interface AiImageService { + + /** + * ai绘画 - dall2/dall3 绘画 + * + * @param req + * @param sseEmitter + */ + void dallDrawing(AiImageDallDrawingReq req, Utf8SseEmitter sseEmitter); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java index 872099935..2221ae3be 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.ai.service.impl; +import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; import cn.iocoder.yudao.module.ai.service.AiImageService; +import cn.iocoder.yudao.module.ai.vo.AiImageDallDrawingReq; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -18,5 +20,8 @@ import org.springframework.stereotype.Service; public class AiImageServiceImpl implements AiImageService { + @Override + public void dallDrawing(AiImageDallDrawingReq req, Utf8SseEmitter sseEmitter) { + } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageDallDrawingReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageDallDrawingReq.java new file mode 100644 index 000000000..e640e818a --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageDallDrawingReq.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.ai.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * dall2/dall2 绘画 + * + * @author fansili + * @time 2024/4/25 16:24 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class AiImageDallDrawingReq { + + @Schema(description = "提示词") + @NotNull(message = "提示词不能为空!") + private String prompt; +} From 2adb5accc4e132059d3c06c0d6bbd183a19e5bcc Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 25 Apr 2024 18:05:08 +0800 Subject: [PATCH 156/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91ai?= =?UTF-8?q?=20chat=20client=E8=87=AA=E5=8A=A8=E9=85=8D=E7=BD=AE=E5=92=8C?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/enums/AiClientNameEnum.java | 37 ------ .../module/ai/config/AiChatClientFactory.java | 48 +++++++ .../ai/service/impl/AiChatServiceImpl.java | 18 ++- .../src/main/resources/http/chat.http | 2 +- .../yudao/framework/ai/AiPlatformEnum.java | 23 ++-- .../yudao/framework/ai/config/AiClient.java | 19 --- .../ai/config/YudaoAiAutoConfiguration.java | 122 ++++++------------ .../framework/ai/config/YudaoAiClient.java | 44 ------- .../ai/config/YudaoAiImageProperties.java | 99 ++++++++++++++ .../ai/config/YudaoAiProperties.java | 15 ++- .../src/main/resources/application-local.yaml | 11 +- 11 files changed, 226 insertions(+), 212 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiClientNameEnum.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/AiClient.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiClient.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiImageProperties.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiClientNameEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiClientNameEnum.java deleted file mode 100644 index 9dc5149e7..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiClientNameEnum.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * ai client 名字 - * - * 这个需要根据配置文件起的来决定 - * - * @author fansili - * @time 2024/4/14 16:02 - * @since 1.0 - */ -@AllArgsConstructor -@Getter -public enum AiClientNameEnum { - - QIAN_WEN("qianWen", "千问模型!"), - YI_YAN_3_5_8K("yiYan3_5_8k", "文心一言(3.5-8k)"), - XING_HUO("xingHuo", "星火模型!"), - - ; - - private String name; - - private String message; - - public static AiClientNameEnum valueOfName(String name) { - for (AiClientNameEnum nameEnum : AiClientNameEnum.values()) { - if (nameEnum.getName().equals(name)) { - return nameEnum; - } - } - throw new IllegalArgumentException("Invalid MessageType value: " + name); - } -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java new file mode 100644 index 000000000..6ee948994 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.ai.config; + +import cn.iocoder.yudao.framework.ai.AiPlatformEnum; +import cn.iocoder.yudao.framework.ai.chat.ChatClient; +import cn.iocoder.yudao.framework.ai.chat.StreamingChatClient; +import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient; +import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatClient; +import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; + +/** + * factory + * + * @author fansili + * @time 2024/4/25 17:36 + * @since 1.0 + */ +@Component +public class AiChatClientFactory { + + @Autowired + private ApplicationContext applicationContext; + + public ChatClient getChatClient(AiPlatformEnum platformEnum) { + if (AiPlatformEnum.QIAN_WEN == platformEnum) { + return applicationContext.getBean(QianWenChatClient.class); + } else if (AiPlatformEnum.YI_YAN == platformEnum) { + return applicationContext.getBean(YiYanChatClient.class); + } else if (AiPlatformEnum.XING_HUO == platformEnum) { + return applicationContext.getBean(XingHuoChatClient.class); + } + throw new IllegalArgumentException("不支持的 chat client!"); + } + + // TODO yunai 要不再加一个接口,让他们拥有 ChatClient、StreamingChatClient 功能 + public StreamingChatClient getStreamingChatClient(AiPlatformEnum platformEnum) { + if (AiPlatformEnum.QIAN_WEN == platformEnum) { + return applicationContext.getBean(QianWenChatClient.class); + } else if (AiPlatformEnum.YI_YAN == platformEnum) { + return applicationContext.getBean(YiYanChatClient.class); + } else if (AiPlatformEnum.XING_HUO == platformEnum) { + return applicationContext.getBean(XingHuoChatClient.class); + } + throw new IllegalArgumentException("不支持的 chat client!"); + } +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index 1caad8ada..ed2f02697 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -1,14 +1,16 @@ package cn.iocoder.yudao.module.ai.service.impl; import cn.hutool.core.exceptions.ExceptionUtil; +import cn.iocoder.yudao.framework.ai.AiPlatformEnum; +import cn.iocoder.yudao.framework.ai.chat.ChatClient; import cn.iocoder.yudao.framework.ai.chat.ChatResponse; +import cn.iocoder.yudao.framework.ai.chat.StreamingChatClient; import cn.iocoder.yudao.framework.ai.chat.messages.MessageType; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; -import cn.iocoder.yudao.framework.ai.config.AiClient; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.module.ai.config.AiChatClientFactory; import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatMessageDO; -import cn.iocoder.yudao.module.ai.enums.AiClientNameEnum; import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.mapper.AiChatMessageMapper; import cn.iocoder.yudao.module.ai.mapper.AiChatRoleMapper; @@ -38,7 +40,7 @@ import java.util.function.Consumer; @AllArgsConstructor public class AiChatServiceImpl implements AiChatService { - private final AiClient aiClient; + private final AiChatClientFactory aiChatClientFactory; private final AiChatRoleMapper aiChatRoleMapper; private final AiChatMessageMapper aiChatMessageMapper; private final AiChatConversationMapper aiChatConversationMapper; @@ -54,7 +56,7 @@ public class AiChatServiceImpl implements AiChatService { public String chat(AiChatReq req) { Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 获取 client 类型 - AiClientNameEnum clientNameEnum = AiClientNameEnum.valueOfName(req.getModal()); + AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(req.getModal()); // 获取对话信息 AiChatConversationRes conversationRes = chatConversationService.getConversation(req.getConversationId()); // 保存 chat message @@ -67,7 +69,8 @@ public class AiChatServiceImpl implements AiChatService { req.setTopP(req.getTopP()); req.setTemperature(req.getTemperature()); // 发送 call 调用 - ChatResponse call = aiClient.call(prompt, clientNameEnum.getName()); + ChatClient chatClient = aiChatClientFactory.getChatClient(platformEnum); + ChatResponse call = chatClient.call(prompt); content = call.getResult().getOutput().getContent(); // 更新 conversation @@ -128,7 +131,7 @@ public class AiChatServiceImpl implements AiChatService { public void chatStream(AiChatReq req, Utf8SseEmitter sseEmitter) { Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 获取 client 类型 - AiClientNameEnum clientNameEnum = AiClientNameEnum.valueOfName(req.getModal()); + AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(req.getModal()); // 获取对话信息 AiChatConversationRes conversationRes = chatConversationService.getConversation(req.getConversationId()); // 创建 chat 需要的 Prompt @@ -138,7 +141,8 @@ public class AiChatServiceImpl implements AiChatService { req.setTemperature(req.getTemperature()); // 保存 chat message saveChatMessage(req, conversationRes, loginUserId); - Flux streamResponse = aiClient.stream(prompt, clientNameEnum.getName()); + StreamingChatClient streamingChatClient = aiChatClientFactory.getStreamingChatClient(platformEnum); + Flux streamResponse = streamingChatClient.stream(prompt); StringBuffer contentBuffer = new StringBuffer(); streamResponse.subscribe( diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http index 133a0eedb..829b74f45 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http @@ -16,7 +16,7 @@ tenant-id: 1 } ### chat call -GET {{baseUrl}}/ai/chat?modal=qianWen&conversationId=1781604279872581644&prompt=中国好看吗? +GET {{baseUrl}}/ai/chat?modal=qianwen&conversationId=1781604279872581644&prompt=中国好看吗? Authorization: {{token}} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java index 8a11dac7f..e939efb5d 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java @@ -3,10 +3,6 @@ package cn.iocoder.yudao.framework.ai; import lombok.AllArgsConstructor; import lombok.Getter; -import java.util.Arrays; -import java.util.Map; -import java.util.stream.Collectors; - /** * 讯飞星火 模型 * @@ -24,15 +20,22 @@ import java.util.stream.Collectors; public enum AiPlatformEnum { - YI_YAN("yiyan"), - QIAN_WEN("qianwen"), - XING_HUO("xinghuo"), + YI_YAN("yiyan", "一言"), + QIAN_WEN("qianwen", "千问"), + XING_HUO("xinghuo", "星火"), ; - public static final Map mapValues - = Arrays.stream(values()).collect(Collectors.toMap(AiPlatformEnum::name, o -> o)); + private String platform; + private String name; - private String value; + public static AiPlatformEnum valueOfPlatform(String platform) { + for (AiPlatformEnum itemEnum : AiPlatformEnum.values()) { + if (itemEnum.getPlatform().equals(platform)) { + return itemEnum; + } + } + throw new IllegalArgumentException("Invalid MessageType value: " + platform); + } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/AiClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/AiClient.java deleted file mode 100644 index f976dcfbf..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/AiClient.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.framework.ai.config; - -import cn.iocoder.yudao.framework.ai.chat.ChatResponse; -import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; -import reactor.core.publisher.Flux; - -/** - * ai client传入 - * - * @author fansili - * @time 2024/4/14 10:27 - * @since 1.0 - */ -public interface AiClient { - - ChatResponse call(Prompt prompt, String clientName); - - Flux stream(Prompt prompt, String clientName); -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index cefe096e8..abf4eee77 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -1,7 +1,5 @@ package cn.iocoder.yudao.framework.ai.config; -import cn.hutool.core.bean.BeanUtil; -import cn.iocoder.yudao.framework.ai.AiPlatformEnum; import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient; import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenOptions; import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenApi; @@ -11,15 +9,11 @@ import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoApi; import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatClient; import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanOptions; import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanApi; -import cn.iocoder.yudao.framework.ai.exception.AiException; import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; -import java.util.HashMap; -import java.util.Map; - /** * ai 自动配置 * @@ -32,86 +26,46 @@ import java.util.Map; public class YudaoAiAutoConfiguration { @Bean - @ConditionalOnMissingBean(value = AiClient.class) - public AiClient aiClient(YudaoAiProperties yudaoAiProperties) { - Map chatClientMap = buildChatClientMap(yudaoAiProperties); - return new YudaoAiClient(chatClientMap); + @ConditionalOnProperty(value = "yudao.ai.xinghuo.enable", havingValue = "true") + public XingHuoChatClient xingHuoChatClient(YudaoAiProperties yudaoAiProperties) { + YudaoAiProperties.XingHuoProperties xingHuoProperties = yudaoAiProperties.getXinghuo(); + return new XingHuoChatClient( + new XingHuoApi( + xingHuoProperties.getAppId(), + xingHuoProperties.getAppKey(), + xingHuoProperties.getSecretKey() + ), + new XingHuoOptions().setChatModel(xingHuoProperties.getChatModel()) + ); } - public Map buildChatClientMap(YudaoAiProperties yudaoAiProperties) { - Map chatMap = new HashMap<>(); - for (Map.Entry> properties : yudaoAiProperties.entrySet()) { - String beanName = properties.getKey(); - Map aiPlatformMap = properties.getValue(); - - // 检查平台类型是否正确 - String aiPlatform = String.valueOf(aiPlatformMap.get("aiPlatform")); - if (!AiPlatformEnum.mapValues.containsKey(aiPlatform)) { - throw new AiException("AI平台名称错误! 可以参考 AiPlatformEnum 类!"); - } - // 获取平台类型 - AiPlatformEnum aiPlatformEnum = AiPlatformEnum.mapValues.get(aiPlatform); - // 获取 chat properties - YudaoAiProperties.ChatProperties chatProperties = getChatProperties(aiPlatformEnum, aiPlatformMap); - // 创建客户端 - Object chatClient = createChatClient(chatProperties); - chatMap.put(beanName, chatClient); - } - return chatMap; + @Bean + @ConditionalOnProperty(value = "yudao.ai.qianwen.enable", havingValue = "true") + public QianWenChatClient qianWenChatClient(YudaoAiProperties yudaoAiProperties) { + YudaoAiProperties.QianWenProperties qianWenProperties = yudaoAiProperties.getQianwen(); + return new QianWenChatClient( + new QianWenApi( + qianWenProperties.getAccessKeyId(), + qianWenProperties.getAccessKeySecret(), + qianWenProperties.getAgentKey(), + qianWenProperties.getEndpoint() + ), + new QianWenOptions() + .setAppId(qianWenProperties.getAppId()) + ); } - private static Object createChatClient(YudaoAiProperties.ChatProperties chatProperties) { - if (AiPlatformEnum.XING_HUO == chatProperties.getAiPlatform()) { - YudaoAiProperties.XingHuoProperties xingHuoProperties = (YudaoAiProperties.XingHuoProperties) chatProperties; - return new XingHuoChatClient( - new XingHuoApi( - xingHuoProperties.getAppId(), - xingHuoProperties.getAppKey(), - xingHuoProperties.getSecretKey() - ), - new XingHuoOptions().setChatModel(xingHuoProperties.getChatModel()) - ); - } else if (AiPlatformEnum.QIAN_WEN == chatProperties.getAiPlatform()) { - YudaoAiProperties.QianWenProperties qianWenProperties = (YudaoAiProperties.QianWenProperties) chatProperties; - return new QianWenChatClient( - new QianWenApi( - qianWenProperties.getAccessKeyId(), - qianWenProperties.getAccessKeySecret(), - qianWenProperties.getAgentKey(), - qianWenProperties.getEndpoint() - ), - new QianWenOptions() - .setAppId(qianWenProperties.getAppId()) - ); - } else if (AiPlatformEnum.YI_YAN == chatProperties.getAiPlatform()) { - YudaoAiProperties.YiYanProperties yiYanProperties = (YudaoAiProperties.YiYanProperties) chatProperties; - return new YiYanChatClient( - new YiYanApi( - yiYanProperties.getAppKey(), - yiYanProperties.getSecretKey(), - yiYanProperties.getChatModel(), - yiYanProperties.getRefreshTokenSecondTime() - ), - new YiYanOptions().setMax_output_tokens(2048)); - } - throw new AiException("不支持的Ai类型!"); - } - - - private static YudaoAiProperties.ChatProperties getChatProperties(AiPlatformEnum aiPlatformEnum, Map aiPlatformMap) { - if (AiPlatformEnum.XING_HUO == aiPlatformEnum) { - YudaoAiProperties.XingHuoProperties xingHuoProperties = new YudaoAiProperties.XingHuoProperties(); - BeanUtil.fillBeanWithMap(aiPlatformMap, xingHuoProperties, true); - return xingHuoProperties; - } else if (AiPlatformEnum.YI_YAN == aiPlatformEnum) { - YudaoAiProperties.YiYanProperties yiYanProperties = new YudaoAiProperties.YiYanProperties(); - BeanUtil.fillBeanWithMap(aiPlatformMap, yiYanProperties, true); - return yiYanProperties; - } else if (AiPlatformEnum.QIAN_WEN == aiPlatformEnum) { - YudaoAiProperties.QianWenProperties qianWenProperties = new YudaoAiProperties.QianWenProperties(); - BeanUtil.fillBeanWithMap(aiPlatformMap, qianWenProperties, true); - return qianWenProperties; - } - throw new AiException("不支持的Ai类型!"); + @Bean + @ConditionalOnProperty(value = "yudao.ai.yiyan.enable", havingValue = "true") + public YiYanChatClient yiYanChatClient(YudaoAiProperties yudaoAiProperties) { + YudaoAiProperties.YiYanProperties yiYanProperties = yudaoAiProperties.getYiyan(); + return new YiYanChatClient( + new YiYanApi( + yiYanProperties.getAppKey(), + yiYanProperties.getSecretKey(), + yiYanProperties.getChatModel(), + yiYanProperties.getRefreshTokenSecondTime() + ), + new YiYanOptions().setMax_output_tokens(2048)); } } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiClient.java deleted file mode 100644 index eaed5557a..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiClient.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.iocoder.yudao.framework.ai.config; - -import cn.iocoder.yudao.framework.ai.chat.ChatClient; -import cn.iocoder.yudao.framework.ai.chat.ChatResponse; -import cn.iocoder.yudao.framework.ai.chat.StreamingChatClient; -import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; -import cn.iocoder.yudao.framework.ai.exception.AiException; -import reactor.core.publisher.Flux; - -import java.util.Map; - -/** - * yudao ai client - * - * @author fansili - * @time 2024/4/14 10:27 - * @since 1.0 - */ -public class YudaoAiClient implements AiClient { - - protected Map chatClientMap; - - public YudaoAiClient(Map chatClientMap) { - this.chatClientMap = chatClientMap; - } - - @Override - public ChatResponse call(Prompt prompt, String clientName) { - if (!chatClientMap.containsKey(clientName)) { - throw new AiException("clientName不存在!"); - } - ChatClient chatClient = (ChatClient) chatClientMap.get(clientName); - return chatClient.call(prompt); - } - - @Override - public Flux stream(Prompt prompt, String clientName) { - if (!chatClientMap.containsKey(clientName)) { - throw new AiException("clientName不存在!"); - } - StreamingChatClient streamingChatClient = (StreamingChatClient) chatClientMap.get(clientName); - return streamingChatClient.stream(prompt); - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiImageProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiImageProperties.java new file mode 100644 index 000000000..11246df68 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiImageProperties.java @@ -0,0 +1,99 @@ +package cn.iocoder.yudao.framework.ai.config; + +import cn.iocoder.yudao.framework.ai.AiPlatformEnum; +import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel; +import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoOptions; +import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel; +import lombok.Data; +import lombok.experimental.Accessors; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * ai 自动配置 + * + * @author fansili + * @time 2024/4/12 16:29 + * @since 1.0 + */ + +@Data +@Accessors(chain = true) +public class YudaoAiImageProperties extends LinkedHashMap> { + + private String initType; + private QianWenProperties qianwen; + private XingHuoOptions xinghuo; + private YiYanProperties yiyan; + + @Data + @Accessors(chain = true) + public static class QianWenProperties extends ChatProperties { + /** + * 阿里云:服务器接入点 + */ + private String endpoint = "bailian.cn-beijing.aliyuncs.com"; + /** + * 阿里云:权限 accessKeyId + */ + private String accessKeyId; + /** + * 阿里云:权限 accessKeySecret + */ + private String accessKeySecret; + /** + * 阿里云:agentKey + */ + private String agentKey; + /** + * 阿里云:agentKey(相当于应用id) + */ + private String appId; + + } + + @Data + @Accessors(chain = true) + public static class XingHuoProperties extends ChatProperties { + private String appId; + private String appKey; + private String secretKey; + private XingHuoChatModel chatModel; + } + + @Data + @Accessors(chain = true) + public static class YiYanProperties extends ChatProperties { + /** + * appKey + */ + private String appKey; + /** + * secretKey + */ + private String secretKey; + /** + * 模型 + */ + private YiYanChatModel chatModel = YiYanChatModel.ERNIE4_3_5_8K; + /** + * token 刷新时间(默认 86400 = 24小时) + */ + private int refreshTokenSecondTime = 86400; + } + + @Data + @Accessors(chain = true) + public static class ChatProperties { + + private AiPlatformEnum aiPlatform; + + private Float temperature; + + private Float topP; + + private Integer topK; + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java index 58d08af3e..40f310f4e 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java @@ -7,9 +7,6 @@ import lombok.Data; import lombok.experimental.Accessors; import org.springframework.boot.context.properties.ConfigurationProperties; -import java.util.LinkedHashMap; -import java.util.Map; - /** * ai 自动配置 * @@ -18,17 +15,21 @@ import java.util.Map; * @since 1.0 */ @Data +@Accessors(chain = true) @ConfigurationProperties(prefix = "yudao.ai") -public class YudaoAiProperties extends LinkedHashMap> { +public class YudaoAiProperties { -// private QianWenProperties qianWen; -// private XingHuoProperties xingHuo; -// private YiYanProperties yiYan; + private String initSource; + private QianWenProperties qianwen; + private XingHuoProperties xinghuo; + private YiYanProperties yiyan; @Data @Accessors(chain = true) public static class ChatProperties { + private boolean enable = false; + private AiPlatformEnum aiPlatform; private Float temperature; diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 8fede4785..e0ca7072c 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -224,7 +224,9 @@ wx: # 芋道配置项,设置当前项目所有自定义的配置 yudao: ai: - qianWen: + initSource: yaml + qianwen: + enable: true aiPlatform: QIAN_WEN temperature: 1 topP: 1 @@ -234,7 +236,8 @@ yudao: accessKeySecret: ZJ0JQeyjzxxm5CfeTV6k1wNE9UsvZP agentKey: f0c1088824594f589c8f10567ccd929f_p_efm appId: 5f14955f201a44eb8dbe0c57250a32ce - xingHuo: + xinghuo: + enable: true aiPlatform: XING_HUO temperature: 1 topP: 1 @@ -243,7 +246,8 @@ yudao: appKey: cb6415c19d6162cda07b47316fcb0416 secretKey: Y2JiYTIxZjA3MDMxMjNjZjQzYzVmNzdh chatModel: XING_HUO_3_5 - yiYan3_5_8k: + yiyan: + enable: true aiPlatform: YI_YAN temperature: 1 topP: 1 @@ -252,6 +256,7 @@ yudao: secretKey: R9mYF9dl9KASgi5RUq0FQt3wRisSnOcK refreshTokenSecondTime: 86400 chatModel: ERNIE4_3_5_8K + captcha: enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试; security: From 64b6b45bc68f545bf386e15ec603368240a21d18 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 26 Apr 2024 13:42:50 +0800 Subject: [PATCH 157/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E5=8D=83=E9=97=AE=E5=A4=A7=E6=A8=A1=E5=9E=8B=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=EF=BC=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/chatqianwen/QianWenChatModal.java | 33 +++++++++++++++++++ .../ai/chatqianwen/package-info.java | 2 ++ .../ai/chatyiyan/YiYanChatModel.java | 7 ++-- 3 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatModal.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatModal.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatModal.java new file mode 100644 index 000000000..5c9298d45 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatModal.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.framework.ai.chatqianwen; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 千问 chat 模型 + * + * 模型地址:https://help.aliyun.com/document_detail/2712576.html + * + * @author fansili + * @time 2024/4/26 10:15 + * @since 1.0 + */ +@AllArgsConstructor +@Getter +public enum QianWenChatModal { + + qwen_turbo("通义千问超大规模语言模型", "qwen-turbo"), + qwen_plus("通义千问超大规模语言模型增强版", "qwen-plus"), + qwen_max("通义千问千亿级别超大规模语言模型", "qwen-max"), + qwen_max_0403("通义千问千亿级别超大规模语言模型-0403", "qwen-max-0403"), + qwen_max_0107("通义千问千亿级别超大规模语言模型-0107", "qwen-max-0107"), + qwen_max_1201("通义千问千亿级别超大规模语言模型-1201", "qwen-max-1201"), + qwen_max_longcontext("通义千问千亿级别超大规模语言模型-28k tokens", "qwen-max-longcontext"), + + ; + + private String name; + + private String value; + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/package-info.java index eb46035e0..c22dbe067 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/package-info.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/package-info.java @@ -3,6 +3,8 @@ * * 链接:https://www.aliyun.com/search?k=%E9%80%9A%E4%B9%89%E5%A4%A7%E6%A8%A1%E5%9E%8B&scene=all * + * 千问所有模型:https://bailian.console.aliyun.com/?spm=5176.28515448.J_TC9GqcHi2edq9zUs9ZsDQ.1.417338b17zJTjy#/efm/my_model + * * author: fansili * time: 2024/3/13 21:05 */ diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatModel.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatModel.java index 77675430e..b901a4dc7 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatModel.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatModel.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.ai.chatyiyan; +import lombok.AllArgsConstructor; import lombok.Getter; /** @@ -11,6 +12,7 @@ import lombok.Getter; * time: 2024/3/9 12:01 */ @Getter +@AllArgsConstructor public enum YiYanChatModel { ERNIE4_0("ERNIE 4.0", "/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions_pro"), @@ -23,11 +25,6 @@ public enum YiYanChatModel { ; - YiYanChatModel(String value, String uri) { - this.value = value; - this.uri = uri; - } - private String value; private String uri; From be8d9c1a5f195fea30c5df5a0e7d9e49ef720e06 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 26 Apr 2024 18:05:14 +0800 Subject: [PATCH 158/684] =?UTF-8?q?=E3=80=90=E9=80=9A=E4=B9=89=E5=8D=83?= =?UTF-8?q?=E9=97=AE=E3=80=91=E9=87=8D=E6=96=B0=E5=AF=B9=E6=8E=A5=E9=98=BF?= =?UTF-8?q?=E9=87=8C=E4=BA=91=E9=80=9A=E4=B9=89=E5=89=8D=E6=96=87=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/dal/dataobject/AiChatModalDO.java | 16 ++- .../module/ai/vo/AiChatModalListRes.java | 2 +- .../src/main/resources/http/chat-modal.http | 19 +++ .../yudao-spring-boot-starter-ai/pom.xml | 11 +- .../yudao/framework/ai/AiPlatformEnum.java | 8 +- .../ai/chatqianwen/QianWenChatClient.java | 108 ++++++++---------- .../ai/chatqianwen/QianWenChatModal.java | 21 ++-- .../ai/chatqianwen/QianWenOptions.java | 13 +-- .../ai/chatqianwen/api/QianWenApi.java | 81 +++++++------ .../api/QianWenChatCompletion.java | 3 +- .../api/QianWenChatCompletionRequest.java | 10 +- .../ai/config/YudaoAiAutoConfiguration.java | 5 +- .../api/MidjourneyInteractionsApi.java | 6 +- .../listener/MidjourneyMessageListener.java | 6 +- 14 files changed, 160 insertions(+), 149 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-modal.http diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java index 1c30531fa..c417e5a44 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java @@ -22,13 +22,23 @@ public class AiChatModalDO extends BaseDO { */ private Long id; /** - * 模型名字 + * 模型key */ - private Long modelName; + private String modelKey; /** - * 模型类型(qianwen、yiyan、xinghuo、openai) + * 模型类型 参考:{@link cn.iocoder.yudao.framework.ai.AiPlatformEnum} + */ + private String modelPlatform; + /** + * 模型类型 + * {@link cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel} + * {@link cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel} */ private String modelType; + /** + * 模型名字 + */ + private String modelName; /** * 模型照片 */ diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java index 4c5cdbb51..3d1701560 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java @@ -20,7 +20,7 @@ public class AiChatModalListRes { /** * 模型名字 */ - private Long modelName; + private String modelName; /** * 模型类型(qianwen、yiyan、xinghuo、openai) */ diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-modal.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-modal.http new file mode 100644 index 000000000..aa2949920 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-modal.http @@ -0,0 +1,19 @@ + + +### chat call +GET {{baseUrl}}/ai/chat/modal/list +Authorization: {{token}} + + + +### chat call +PUT {{baseUrl}}/ai/chat/modal +Content-Type: application/json +Authorization: {{token}} + +{ + "modelName": "小红书Ai写作大模型", + "modelType": "yiyan", + "modalImage": "", + "modelConfig": "" +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml index 81d303ab6..3a52489a5 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml @@ -110,9 +110,9 @@ - com.aliyun - broadscope-bailian-sdk-java - 1.3.0 + com.alibaba + dashscope-sdk-java + 2.11.0 org.apache.httpcomponents @@ -129,6 +129,11 @@ com.fasterxml.jackson.core jackson-databind + + com.alibaba.fastjson2 + fastjson2 + 2.0.45 + com.squareup.okhttp3 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java index e939efb5d..717ced538 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java @@ -4,13 +4,7 @@ import lombok.AllArgsConstructor; import lombok.Getter; /** - * 讯飞星火 模型 - * - * 文档地址:https://www.xfyun.cn/doc/spark/Web.html#_1-%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E - * - * 1tokens 约等于1.5个中文汉字 或者 0.8个英文单词 - * 星火V1.5支持[搜索]内置插件;星火V2.0、V3.0和V3.5支持[搜索]、[天气]、[日期]、[诗词]、[字词]、[股票]六个内置插件 - * 星火V3.5 现已支持system、Function Call 功能。 + * ai 模型平台 * * author: fansili * time: 2024/3/11 10:12 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java index 7bab37586..6aaf47d35 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java @@ -1,14 +1,15 @@ package cn.iocoder.yudao.framework.ai.chatqianwen; -import cn.hutool.core.util.IdUtil; -import cn.hutool.json.JSONUtil; import cn.iocoder.yudao.framework.ai.chat.*; -import cn.iocoder.yudao.framework.ai.chat.messages.MessageType; import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenApi; +import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenChatCompletionRequest; import cn.iocoder.yudao.framework.ai.chatyiyan.exception.YiYanApiException; -import com.aliyun.broadscope.bailian.sdk.models.*; +import com.alibaba.dashscope.aigc.generation.GenerationResult; +import com.alibaba.dashscope.aigc.generation.models.QwenParam; +import com.alibaba.dashscope.common.Message; +import io.reactivex.Flowable; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.retry.RetryCallback; @@ -23,9 +24,9 @@ import java.util.stream.Collectors; /** * 阿里 通义千问 client - * + *

* 文档地址:https://help.aliyun.com/document_detail/2587494.html?spm=a2c4g.2587492.0.0.53f33c566sXskp - * + *

* author: fansili * time: 2024/3/13 21:06 */ @@ -37,7 +38,9 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient { private QianWenOptions qianWenOptions; - public QianWenChatClient() {} + public QianWenChatClient() { + } + public QianWenChatClient(QianWenApi qianWenApi) { this.qianWenApi = qianWenApi; } @@ -59,7 +62,7 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient { public void onError(RetryContext context, RetryCallback callback, Throwable throwable) { log.warn("重试异常:" + context.getRetryCount(), throwable); - }; + } }) .build(); @@ -68,21 +71,21 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient { return this.retryTemplate.execute(ctx -> { // ctx 会有重试的信息 // 创建 request 请求,stream模式需要供应商支持 - CompletionsRequest request = this.createRequest(prompt, false); + QianWenChatCompletionRequest request = this.createRequest(prompt, false); // 调用 callWithFunctionSupport 发送请求 - ResponseEntity responseEntity = qianWenApi.chatCompletionEntity(request); + ResponseEntity responseEntity = qianWenApi.chatCompletionEntity(request); // 获取结果封装 chatCompletion - CompletionsResponse response = responseEntity.getBody(); - if (!response.isSuccess()) { - return new ChatResponse(List.of(new Generation(String.format("failed to create completion, requestId: %s, code: %s, message: %s\n", - response.getRequestId(), response.getCode(), response.getMessage())))); - } + GenerationResult response = responseEntity.getBody(); +// if (!response.isSuccess()) { +// return new ChatResponse(List.of(new Generation(String.format("failed to create completion, requestId: %s, code: %s, message: %s\n", +// response.getRequestId(), response.getCode(), response.getMessage())))); +// } // 转换为 Generation 返回 - return new ChatResponse(List.of(new Generation(response.getData().getText()))); + return new ChatResponse(List.of(new Generation(response.getOutput().getText()))); }); } - private CompletionsRequest createRequest(Prompt prompt, boolean stream) { + private QianWenChatCompletionRequest createRequest(Prompt prompt, boolean stream) { // 两个都为null 则没有配置文件 if (qianWenOptions == null && prompt.getOptions() == null) { throw new ChatException("ChatOptions 未配置参数!"); @@ -93,61 +96,40 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient { options = (ChatOptions) prompt.getOptions(); } // Prompt 里面是一个 ChatOptions,用户可以随意传入,这里做一下判断 - if (!(options instanceof QianWenOptions)) { + if (!(options instanceof QianWenOptions qianWenOptions)) { throw new ChatException("Prompt 传入的不是 QianWenOptions!"); } - QianWenOptions qianWenOptions = (QianWenOptions) options; - // 需要额外处理 - if (!stream) { - // 如果不需要 stream 输出,那么需要将这个设置为false,不然只会输出最后几个文字 - if (qianWenOptions.getParameters() == null) { - qianWenOptions.setParameters(new CompletionsRequest.Parameter().setIncrementalOutput(false)); - } else { - qianWenOptions.getParameters().setIncrementalOutput(false); - } - } else { - // 如果不需要 stream 输出,设置为true这样不会输出累加内容 - if (qianWenOptions.getParameters() == null) { - qianWenOptions.setParameters(new CompletionsRequest.Parameter().setIncrementalOutput(true)); - } else { - qianWenOptions.getParameters().setIncrementalOutput(true); - } - } - - // 创建request - return new CompletionsRequest() - // 请求唯一标识,请确保RequestId不重复。 - .setRequestId(IdUtil.getSnowflakeNextIdStr()) - // 设置 appid - .setAppId(qianWenOptions.getAppId()) - .setMessages(prompt.getInstructions().stream().map(m -> { - // 转换成 千问 对于的请求message - if (MessageType.USER == m.getMessageType()) { - return new ChatUserMessage(m.getContent()); - } else if (MessageType.SYSTEM == m.getMessageType()) { - return new ChatSystemMessage(m.getContent()); - } else if (MessageType.ASSISTANT == m.getMessageType()) { - return new ChatAssistantMessage(m.getContent()); - } - throw new ChatException(String.format("存在不能适配的消息! %s", JSONUtil.toJsonPrettyStr(m))); + return (QianWenChatCompletionRequest) QianWenChatCompletionRequest.builder() + .model(qianWenApi.getQianWenChatModal().getValue()) + .apiKey(qianWenApi.getApiKey()) + .messages(prompt.getInstructions().stream().map(m -> { + Message message = new Message(); + message.setRole(m.getMessageType().getValue()); + message.setContent(m.getContent()); + return message; }).collect(Collectors.toList())) - // 返回choice message结果 - .setParameters(qianWenOptions.getParameters()) - // 设置 ChatOptions 里面公共的参数 - .setTopP(options.getTopP() == null ? null : options.getTopP().doubleValue()) - // 设置输出方式 - .setStream(stream); + .resultFormat(QwenParam.ResultFormat.MESSAGE) + // 动态改变的三个参数 + .topP(Double.valueOf(qianWenOptions.getTopP())) + .topK(qianWenOptions.getTopK()) + .temperature(qianWenOptions.getTemperature()) + .incrementalOutput(true) + .build(); } @Override public Flux stream(Prompt prompt) { // ctx 会有重试的信息 // 创建 request 请求,stream模式需要供应商支持 - CompletionsRequest request = this.createRequest(prompt, true); + QianWenChatCompletionRequest request = this.createRequest(prompt, true); // 调用 callWithFunctionSupport 发送请求 - Flux response = this.qianWenApi.chatCompletionStream(request); - return response.map(res -> { - return new ChatResponse(List.of(new Generation(res.getData().getText()))); - }); + Flowable responseResult = this.qianWenApi.chatCompletionStream(request); + return Flux.create(fluxSink -> + responseResult.subscribe( + value -> fluxSink.next(new ChatResponse(List.of(new Generation(value.getOutput().getText())))), + error -> fluxSink.error(error), + () -> fluxSink.complete() + ) + ); } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatModal.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatModal.java index 5c9298d45..96646233a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatModal.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatModal.java @@ -7,6 +7,7 @@ import lombok.Getter; * 千问 chat 模型 * * 模型地址:https://help.aliyun.com/document_detail/2712576.html + * 模型介绍:https://help.aliyun.com/document_detail/2666503.html?spm=a2c4g.2701795.0.0.26eb34dfKzcWN4 * * @author fansili * @time 2024/4/26 10:15 @@ -16,18 +17,22 @@ import lombok.Getter; @Getter public enum QianWenChatModal { - qwen_turbo("通义千问超大规模语言模型", "qwen-turbo"), - qwen_plus("通义千问超大规模语言模型增强版", "qwen-plus"), - qwen_max("通义千问千亿级别超大规模语言模型", "qwen-max"), - qwen_max_0403("通义千问千亿级别超大规模语言模型-0403", "qwen-max-0403"), - qwen_max_0107("通义千问千亿级别超大规模语言模型-0107", "qwen-max-0107"), - qwen_max_1201("通义千问千亿级别超大规模语言模型-1201", "qwen-max-1201"), - qwen_max_longcontext("通义千问千亿级别超大规模语言模型-28k tokens", "qwen-max-longcontext"), + // 千问付费模型 + QWEN_TURBO("通义千问超大规模语言模型", "qwen-turbo"), + QWEN_PLUS("通义千问超大规模语言模型增强版", "qwen-plus"), + QWEN_MAX("通义千问千亿级别超大规模语言模型", "qwen-max"), + QWEN_MAX_0403("通义千问千亿级别超大规模语言模型-0403", "qwen-max-0403"), + QWEN_MAX_0107("通义千问千亿级别超大规模语言模型-0107", "qwen-max-0107"), + QWEN_MAX_1201("通义千问千亿级别超大规模语言模型-1201", "qwen-max-1201"), + QWEN_MAX_LONGCONTEXT("通义千问千亿级别超大规模语言模型-28k tokens", "qwen-max-longcontext"), + + // 开源模型 + // https://help.aliyun.com/document_detail/2666503.html?spm=a2c4g.2701795.0.0.26eb34dfKzcWN4 + QWEN_72B_CHAT("通义千问1.5对外开源的72B规模参数量的经过人类指令对齐的chat模型", "qwen-72b-chat"), ; private String name; private String value; - } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenOptions.java index 26c6ef66f..eb598d366 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenOptions.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.framework.ai.chatqianwen; import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; -import com.aliyun.broadscope.bailian.sdk.models.CompletionsRequest; import lombok.Data; import lombok.experimental.Accessors; @@ -34,22 +33,18 @@ public class QianWenOptions implements ChatOptions { * 默认值为0.8。注意,取值不要大于等于1 */ private Float topP; - /** - * 模型参数设置。 - */ - private CompletionsRequest.Parameter parameters = new CompletionsRequest.Parameter(); // // 适配 ChatOptions @Override public Float getTemperature() { - return Float.parseFloat(this.parameters.getTemperature().toString()); + return null; } @Override public void setTemperature(Float temperature) { - this.parameters.setTemperature(Double.valueOf(temperature.toString())); + } @Override @@ -59,12 +54,12 @@ public class QianWenOptions implements ChatOptions { @Override public Integer getTopK() { - return this.parameters.getTopK(); + return null; } @Override public void setTopK(Integer topK) { - this.parameters.setTopK(topK); + } @Data diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenApi.java index c8170af0f..2095e32ce 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenApi.java @@ -1,64 +1,63 @@ package cn.iocoder.yudao.framework.ai.chatqianwen.api; -import com.aliyun.broadscope.bailian.sdk.AccessTokenClient; -import com.aliyun.broadscope.bailian.sdk.ApplicationClient; -import com.aliyun.broadscope.bailian.sdk.models.CompletionsRequest; -import com.aliyun.broadscope.bailian.sdk.models.CompletionsResponse; +import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatModal; +import cn.iocoder.yudao.framework.ai.exception.AiException; +import com.alibaba.dashscope.aigc.generation.Generation; +import com.alibaba.dashscope.aigc.generation.GenerationResult; +import com.alibaba.dashscope.common.Message; +import com.alibaba.dashscope.common.Role; +import com.alibaba.dashscope.exception.InputRequiredException; +import com.alibaba.dashscope.exception.NoApiKeyException; +import io.reactivex.Flowable; import lombok.Getter; import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; -import reactor.core.publisher.Flux; // TODO done @fansili:是不是挪到 api 包里?按照 spring ai 的结构;根目录只放 client 和 options + /** * 阿里 通义千问 - * - * https://www.aliyun.com/search?k=%E9%80%9A%E4%B9%89%E5%A4%A7%E6%A8%A1%E5%9E%8B&scene=all - * + *

* author: fansili * time: 2024/3/13 21:09 */ @Getter public class QianWenApi { - /** - * accessKeyId、accessKeySecret、agentKey、appId 获取方式如下链接 - * https://help.aliyun.com/document_detail/2587494.html?spm=a2c4g.2587492.0.0.53f33c566sXskp - */ - private String accessKeyId; - private String accessKeySecret; - private String agentKey; - private String appId; - private String endpoint = "bailian.cn-beijing.aliyuncs.com"; - private String token; - private ApplicationClient client; + // api key 获取地址:https://bailian.console.aliyun.com/?spm=5176.28197581.0.0.38db29a4G3GcVb&apiKey=1#/api-key + private String apiKey = "sk-Zsd81gZYg7"; + private Generation gen = new Generation(); + private QianWenChatModal qianWenChatModal; - public QianWenApi(String accessKeyId, String accessKeySecret, String agentKey, String endpoint) { - this.accessKeyId = accessKeyId; - this.accessKeySecret = accessKeySecret; - this.agentKey = agentKey; + public QianWenApi(String apiKey, QianWenChatModal qianWenChatModal) { + this.apiKey = apiKey; + this.qianWenChatModal = qianWenChatModal; + } - if (endpoint != null) { - this.endpoint = endpoint; + public ResponseEntity chatCompletionEntity(QianWenChatCompletionRequest request) { + Message userMsg = Message.builder().role(Role.USER.getValue()).content("用萝卜、土豆、茄子做饭,给我个菜谱").build(); + + GenerationResult call; + try { + call = gen.call(request); + } catch (NoApiKeyException e) { + throw new AiException("没有找到apiKey!" + e.getMessage()); + } catch (InputRequiredException e) { + throw new AiException("chat缺少必填字段!" + e.getMessage()); } - - // 获取token - AccessTokenClient accessTokenClient = new AccessTokenClient(accessKeyId, accessKeySecret, agentKey); - token = accessTokenClient.getToken(); - // 构建client - client = ApplicationClient.builder() - .token(token) - .build(); - } - - public ResponseEntity chatCompletionEntity(CompletionsRequest request) { - // 发送请求 - CompletionsResponse response = client.completions(request); // 阿里云的这个 http code 随便设置,外面判断是否成功用的 CompletionsResponse.isSuccess - return new ResponseEntity<>(response, HttpStatusCode.valueOf(200)); + return new ResponseEntity<>(call, HttpStatusCode.valueOf(200)); } - public Flux chatCompletionStream(CompletionsRequest request) { - return client.streamCompletions(request); + public Flowable chatCompletionStream(QianWenChatCompletionRequest request) { + Flowable resultFlowable; + try { + resultFlowable = gen.streamCall(request); + } catch (NoApiKeyException e) { + throw new AiException("没有找到apiKey!" + e.getMessage()); + } catch (InputRequiredException e) { + throw new AiException("chat缺少必填字段!" + e.getMessage()); + } + return resultFlowable; } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletion.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletion.java index 4e646748e..474a7d826 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletion.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletion.java @@ -1,10 +1,9 @@ package cn.iocoder.yudao.framework.ai.chatqianwen.api; -import com.aliyun.broadscope.bailian.sdk.models.CompletionsResponse; /** * author: fansili * time: 2024/3/13 21:07 */ -public class QianWenChatCompletion extends CompletionsResponse { +public class QianWenChatCompletion { } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletionRequest.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletionRequest.java index c3e27da62..5017ea4ea 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletionRequest.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletionRequest.java @@ -1,12 +1,16 @@ package cn.iocoder.yudao.framework.ai.chatqianwen.api; -import com.aliyun.broadscope.bailian.sdk.models.ChatRequestMessage; -import com.aliyun.broadscope.bailian.sdk.models.ChatUserMessage; +import com.alibaba.dashscope.aigc.generation.models.QwenParam; /** + * 千问 + * * author: fansili * time: 2024/3/13 21:07 */ -public class QianWenChatCompletionRequest extends ChatRequestMessage { +public class QianWenChatCompletionRequest extends QwenParam { + protected QianWenChatCompletionRequest(QwenParamBuilder b) { + super(b); + } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index abf4eee77..483e88477 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.framework.ai.config; import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient; +import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatModal; import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenOptions; import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenApi; import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatClient; @@ -45,10 +46,8 @@ public class YudaoAiAutoConfiguration { YudaoAiProperties.QianWenProperties qianWenProperties = yudaoAiProperties.getQianwen(); return new QianWenChatClient( new QianWenApi( - qianWenProperties.getAccessKeyId(), - qianWenProperties.getAccessKeySecret(), qianWenProperties.getAgentKey(), - qianWenProperties.getEndpoint() + QianWenChatModal.QWEN_72B_CHAT ), new QianWenOptions() .setAppId(qianWenProperties.getAppId()) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractionsApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractionsApi.java index f71a81667..e0b2334eb 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractionsApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractionsApi.java @@ -2,13 +2,13 @@ package cn.iocoder.yudao.framework.ai.midjourney.api; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; -import cn.iocoder.yudao.framework.ai.midjourney.util.MidjourneyUtil; import cn.iocoder.yudao.framework.ai.midjourney.api.req.AttachmentsReq; import cn.iocoder.yudao.framework.ai.midjourney.api.req.DescribeReq; import cn.iocoder.yudao.framework.ai.midjourney.api.req.ReRollReq; import cn.iocoder.yudao.framework.ai.midjourney.api.res.UploadAttachmentsRes; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; +import cn.iocoder.yudao.framework.ai.midjourney.util.MidjourneyUtil; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; import org.springframework.core.io.FileSystemResource; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java index 5e63b079c..a044f3613 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java @@ -11,7 +11,7 @@ import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyConstants; import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyGennerateStatusEnum; import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyMessageTypeEnum; import cn.iocoder.yudao.framework.ai.midjourney.util.MidjourneyUtil; -import com.alibaba.fastjson.JSON; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.utils.data.DataObject; @@ -45,13 +45,13 @@ public class MidjourneyMessageListener { // 转换 components if (!data.getArray(MidjourneyConstants.MSG_COMPONENTS).isEmpty()) { String componentsJson = StrUtil.str(data.getArray(MidjourneyConstants.MSG_COMPONENTS).toJson(), "UTF-8"); - List components = JSON.parseArray(componentsJson, MidjourneyMessage.ComponentType.class); + List components = JsonUtils.parseArray(componentsJson, MidjourneyMessage.ComponentType.class); mjMessage.setComponents(components); } // 转换附件 if (!data.getArray(MidjourneyConstants.MSG_ATTACHMENTS).isEmpty()) { String attachmentsJson = StrUtil.str(data.getArray(MidjourneyConstants.MSG_ATTACHMENTS).toJson(), "UTF-8"); - List attachments = JSON.parseArray(attachmentsJson, MidjourneyMessage.Attachment.class); + List attachments = JsonUtils.parseArray(attachmentsJson, MidjourneyMessage.Attachment.class); mjMessage.setAttachments(attachments); } // 转换状态 From 2ef64a0a506c02c490f2a625859a09909196d211 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 26 Apr 2024 18:24:57 +0800 Subject: [PATCH 159/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E9=85=8D=E7=BD=AE=EF=BC=8C=E9=80=82=E9=85=8D?= =?UTF-8?q?=E6=96=B0=E7=9A=84=E5=8D=83=E9=97=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/chatqianwen/QianWenOptions.java | 5 ---- .../ai/config/YudaoAiAutoConfiguration.java | 9 +++++--- .../ai/config/YudaoAiProperties.java | 23 ++++++------------- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenOptions.java index eb598d366..bc7564df5 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenOptions.java @@ -18,11 +18,6 @@ import java.util.List; @Accessors public class QianWenOptions implements ChatOptions { - private String appId; - /** - * 是否流式输出, 默认为否。 - */ - private Boolean stream; /** * 用户与模型的对话历史 */ diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index 483e88477..2eadf156b 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -44,13 +44,16 @@ public class YudaoAiAutoConfiguration { @ConditionalOnProperty(value = "yudao.ai.qianwen.enable", havingValue = "true") public QianWenChatClient qianWenChatClient(YudaoAiProperties yudaoAiProperties) { YudaoAiProperties.QianWenProperties qianWenProperties = yudaoAiProperties.getQianwen(); + QianWenOptions qianWenOptions = new QianWenOptions(); + qianWenOptions.setTopK(qianWenProperties.getTopK()); + qianWenOptions.setTopP(qianWenProperties.getTopP()); + qianWenOptions.setTemperature(qianWenProperties.getTemperature()); return new QianWenChatClient( new QianWenApi( - qianWenProperties.getAgentKey(), + qianWenProperties.getApiKey(), QianWenChatModal.QWEN_72B_CHAT ), - new QianWenOptions() - .setAppId(qianWenProperties.getAppId()) + qianWenOptions ); } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java index 40f310f4e..4ccfb2a4c 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java @@ -42,26 +42,15 @@ public class YudaoAiProperties { @Data @Accessors(chain = true) public static class QianWenProperties extends ChatProperties { + /** - * 阿里云:服务器接入点 + * api key */ - private String endpoint = "bailian.cn-beijing.aliyuncs.com"; + private String apiKey; /** - * 阿里云:权限 accessKeyId + * model */ - private String accessKeyId; - /** - * 阿里云:权限 accessKeySecret - */ - private String accessKeySecret; - /** - * 阿里云:agentKey - */ - private String agentKey; - /** - * 阿里云:agentKey(相当于应用id) - */ - private String appId; + private YiYanChatModel model; } @@ -93,5 +82,7 @@ public class YudaoAiProperties { * token 刷新时间(默认 86400 = 24小时) */ private int refreshTokenSecondTime = 86400; + + private YiYanChatModel model; } } From 63c5f90596bcdd66e735a6559721c1f5a670388c Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 27 Apr 2024 16:51:41 +0800 Subject: [PATCH 160/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E5=85=BC=E5=AE=B9=E9=98=BF=E9=87=8C=E4=BA=91=E5=8D=83=E9=97=AE?= =?UTF-8?q?=E5=BC=80=E6=BA=90=E6=A8=A1=E5=9E=8B=EF=BC=8C=E5=92=8C=E4=BB=98?= =?UTF-8?q?=E8=B4=B9=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/chatqianwen/QianWenChatClient.java | 67 +++++++++++------- .../ai/chatqianwen/QianWenOptions.java | 6 +- .../ai/chatqianwen/api/QianWenApi.java | 7 +- .../ai/config/YudaoAiAutoConfiguration.java | 1 + .../ai/config/YudaoAiProperties.java | 4 ++ .../ai/chat/QianWenChatClientTests.java | 68 ++++++++++++++++--- .../MidjourneyInteractionsTests.java | 4 +- .../src/main/resources/application-local.yaml | 13 ++-- 8 files changed, 121 insertions(+), 49 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java index 6aaf47d35..be8648350 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java @@ -4,13 +4,14 @@ import cn.iocoder.yudao.framework.ai.chat.*; import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenApi; -import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenChatCompletionRequest; import cn.iocoder.yudao.framework.ai.chatyiyan.exception.YiYanApiException; import com.alibaba.dashscope.aigc.generation.GenerationResult; import com.alibaba.dashscope.aigc.generation.models.QwenParam; import com.alibaba.dashscope.common.Message; +import com.google.common.collect.Lists; import io.reactivex.Flowable; import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; import org.springframework.http.ResponseEntity; import org.springframework.retry.RetryCallback; import org.springframework.retry.RetryContext; @@ -71,7 +72,7 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient { return this.retryTemplate.execute(ctx -> { // ctx 会有重试的信息 // 创建 request 请求,stream模式需要供应商支持 - QianWenChatCompletionRequest request = this.createRequest(prompt, false); + QwenParam request = this.createRequest(prompt, false); // 调用 callWithFunctionSupport 发送请求 ResponseEntity responseEntity = qianWenApi.chatCompletionEntity(request); // 获取结果封装 chatCompletion @@ -81,11 +82,41 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient { // response.getRequestId(), response.getCode(), response.getMessage())))); // } // 转换为 Generation 返回 - return new ChatResponse(List.of(new Generation(response.getOutput().getText()))); + return new ChatResponse(response.getOutput().getChoices().stream() + .map(choices -> new Generation(choices.getMessage().getContent())) + .collect(Collectors.toList())); }); } - private QianWenChatCompletionRequest createRequest(Prompt prompt, boolean stream) { + private QwenParam createRequest(Prompt prompt, boolean stream) { + // 获取 ChatOptions + QianWenOptions chatOptions = getChatOptions(prompt); + // + List messageList = Lists.newArrayList(); + prompt.getInstructions().stream().forEach(instruction -> { + Message message = new Message(); + message.setRole(instruction.getMessageType().getValue()); + message.setContent(instruction.getContent()); + messageList.add(message); + }); + return QwenParam.builder() + .model(qianWenApi.getQianWenChatModal().getValue()) + .prompt(prompt.getContents()) + .messages(messageList) + .maxTokens(chatOptions.getMaxTokens()) + .resultFormat(QwenParam.ResultFormat.MESSAGE) + .topP(Double.valueOf(chatOptions.getTopP())) + .topK(chatOptions.getTopK()) + .temperature(chatOptions.getTemperature()) + // 控制流式输出模式,即后面的内容会包含已经输出的内容;设置为True,将开启增量输出模式,后面的输出不会包含已经输出的内容,您需要自行拼接整体输出 + .incrementalOutput(true) + /* set the random seed, optional, default to 1234 if not set */ + .seed(100) + .apiKey(qianWenApi.getApiKey()) + .build(); + } + + private @NotNull QianWenOptions getChatOptions(Prompt prompt) { // 两个都为null 则没有配置文件 if (qianWenOptions == null && prompt.getOptions() == null) { throw new ChatException("ChatOptions 未配置参数!"); @@ -96,37 +127,27 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient { options = (ChatOptions) prompt.getOptions(); } // Prompt 里面是一个 ChatOptions,用户可以随意传入,这里做一下判断 - if (!(options instanceof QianWenOptions qianWenOptions)) { + if (!(options instanceof QianWenOptions)) { throw new ChatException("Prompt 传入的不是 QianWenOptions!"); } - return (QianWenChatCompletionRequest) QianWenChatCompletionRequest.builder() - .model(qianWenApi.getQianWenChatModal().getValue()) - .apiKey(qianWenApi.getApiKey()) - .messages(prompt.getInstructions().stream().map(m -> { - Message message = new Message(); - message.setRole(m.getMessageType().getValue()); - message.setContent(m.getContent()); - return message; - }).collect(Collectors.toList())) - .resultFormat(QwenParam.ResultFormat.MESSAGE) - // 动态改变的三个参数 - .topP(Double.valueOf(qianWenOptions.getTopP())) - .topK(qianWenOptions.getTopK()) - .temperature(qianWenOptions.getTemperature()) - .incrementalOutput(true) - .build(); + return (QianWenOptions) options; } @Override public Flux stream(Prompt prompt) { // ctx 会有重试的信息 // 创建 request 请求,stream模式需要供应商支持 - QianWenChatCompletionRequest request = this.createRequest(prompt, true); + QwenParam request = this.createRequest(prompt, true); // 调用 callWithFunctionSupport 发送请求 Flowable responseResult = this.qianWenApi.chatCompletionStream(request); + return Flux.create(fluxSink -> responseResult.subscribe( - value -> fluxSink.next(new ChatResponse(List.of(new Generation(value.getOutput().getText())))), + value -> fluxSink.next( + new ChatResponse(value.getOutput().getChoices().stream() + .map(choices -> new Generation(choices.getMessage().getContent())) + .collect(Collectors.toList())) + ), error -> fluxSink.error(error), () -> fluxSink.complete() ) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenOptions.java index bc7564df5..4cec86466 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenOptions.java @@ -15,7 +15,7 @@ import java.util.List; * time: 2024/3/15 19:57 */ @Data -@Accessors +@Accessors(chain = true) public class QianWenOptions implements ChatOptions { /** @@ -28,6 +28,10 @@ public class QianWenOptions implements ChatOptions { * 默认值为0.8。注意,取值不要大于等于1 */ private Float topP; + /** + * 用于限制模型生成token的数量,max_tokens设置的是生成上限,并不表示一定会生成这么多的token数量。其中qwen1.5-14b-chat、qwen1.5-7b-chat、qwen-14b-chat和qwen-7b-chat最大值和默认值均为1500,qwen-1.8b-chat、qwen-1.8b-longcontext-chat和qwen-72b-chat最大值和默认值均为2000 + */ + private Integer maxTokens = 1500; // // 适配 ChatOptions diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenApi.java index 2095e32ce..c5d2bb680 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenApi.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatModal; import cn.iocoder.yudao.framework.ai.exception.AiException; import com.alibaba.dashscope.aigc.generation.Generation; import com.alibaba.dashscope.aigc.generation.GenerationResult; +import com.alibaba.dashscope.aigc.generation.models.QwenParam; import com.alibaba.dashscope.common.Message; import com.alibaba.dashscope.common.Role; import com.alibaba.dashscope.exception.InputRequiredException; @@ -34,9 +35,7 @@ public class QianWenApi { this.qianWenChatModal = qianWenChatModal; } - public ResponseEntity chatCompletionEntity(QianWenChatCompletionRequest request) { - Message userMsg = Message.builder().role(Role.USER.getValue()).content("用萝卜、土豆、茄子做饭,给我个菜谱").build(); - + public ResponseEntity chatCompletionEntity(QwenParam request) { GenerationResult call; try { call = gen.call(request); @@ -49,7 +48,7 @@ public class QianWenApi { return new ResponseEntity<>(call, HttpStatusCode.valueOf(200)); } - public Flowable chatCompletionStream(QianWenChatCompletionRequest request) { + public Flowable chatCompletionStream(QwenParam request) { Flowable resultFlowable; try { resultFlowable = gen.streamCall(request); diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index 2eadf156b..fa61eeb3f 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -47,6 +47,7 @@ public class YudaoAiAutoConfiguration { QianWenOptions qianWenOptions = new QianWenOptions(); qianWenOptions.setTopK(qianWenProperties.getTopK()); qianWenOptions.setTopP(qianWenProperties.getTopP()); + qianWenOptions.setMaxTokens(qianWenProperties.getMaxTokens()); qianWenOptions.setTemperature(qianWenProperties.getTemperature()); return new QianWenChatClient( new QianWenApi( diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java index 4ccfb2a4c..71358aee0 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java @@ -47,6 +47,10 @@ public class YudaoAiProperties { * api key */ private String apiKey; + /** + * 用于限制模型生成token的数量,max_tokens设置的是生成上限,并不表示一定会生成这么多的token数量 + */ + private Integer maxTokens; /** * model */ diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java index 0a748667b..16ddfa45d 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java @@ -1,13 +1,25 @@ package cn.iocoder.yudao.framework.ai.chat; +import cn.iocoder.yudao.framework.ai.chat.messages.SystemMessage; +import cn.iocoder.yudao.framework.ai.chat.messages.UserMessage; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; -import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenApi; import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient; +import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatModal; import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenOptions; +import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenApi; +import com.alibaba.dashscope.aigc.generation.GenerationResult; +import com.alibaba.dashscope.aigc.generation.models.QwenParam; +import com.alibaba.dashscope.common.Message; +import com.alibaba.dashscope.common.MessageManager; +import com.alibaba.dashscope.common.Role; +import com.alibaba.dashscope.exception.InputRequiredException; +import com.alibaba.dashscope.exception.NoApiKeyException; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; +import java.util.ArrayList; +import java.util.List; import java.util.Scanner; import java.util.function.Consumer; @@ -21,28 +33,34 @@ public class QianWenChatClientTests { @Before public void setup() { - QianWenApi qianWenApi = new QianWenApi( - "LTAI5tNTVhXW4fLKUjMrr98z", - "ZJ0JQeyjzxxm5CfeTV6k1wNE9UsvZP", - "f0c1088824594f589c8f10567ccd929f_p_efm", - null - ); + QianWenApi qianWenApi = new QianWenApi("sk-Zsd81gZYg7", QianWenChatModal.QWEN_72B_CHAT); + QianWenOptions qianWenOptions = new QianWenOptions(); + qianWenOptions.setTopP(0.8F); + qianWenOptions.setTopK(3); + qianWenOptions.setTemperature(0.6F); qianWenChatClient = new QianWenChatClient( qianWenApi, - new QianWenOptions() - .setAppId("5f14955f201a44eb8dbe0c57250a32ce") + qianWenOptions ); } @Test public void callTest() { - ChatResponse call = qianWenChatClient.call(new Prompt("Java语言怎么样?")); + List messages = new ArrayList<>(); + messages.add(new SystemMessage("你是一个优质的小红书文艺作者,抒写着各城市的美好文化和风景。")); + messages.add(new UserMessage("长沙怎么样?")); + + ChatResponse call = qianWenChatClient.call(new Prompt(messages)); System.err.println(call.getResult()); } @Test public void streamTest() { - Flux flux = qianWenChatClient.stream(new Prompt("Java语言怎么样?")); + List messages = new ArrayList<>(); + messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。")); + messages.add(new UserMessage("长沙怎么样?")); + + Flux flux = qianWenChatClient.stream(new Prompt(messages)); flux.subscribe(new Consumer() { @Override public void accept(ChatResponse chatResponse) { @@ -54,4 +72,32 @@ public class QianWenChatClientTests { Scanner scanner = new Scanner(System.in); scanner.nextLine(); } + + @Test + public void qianwenDemoTest() throws NoApiKeyException, InputRequiredException { + com.alibaba.dashscope.aigc.generation.Generation gen = new com.alibaba.dashscope.aigc.generation.Generation(); + MessageManager msgManager = new MessageManager(10); + Message systemMsg = + Message.builder().role(Role.SYSTEM.getValue()).content("You are a helpful assistant.").build(); + Message userMsg = Message.builder().role(Role.USER.getValue()).content("就当前的海洋污染的情况,写一份限塑的倡议书提纲,需要有理有据地号召大家克制地使用塑料制品").build(); + msgManager.add(systemMsg); + msgManager.add(userMsg); + QwenParam param = + QwenParam.builder().model("qwen-72b-chat").messages(msgManager.get()) + .resultFormat(QwenParam.ResultFormat.MESSAGE) + .topP(0.8) + /* set the random seed, optional, default to 1234 if not set */ + .seed(100) + .apiKey("sk-Zsd81gZYg7") + .build(); + GenerationResult result = gen.call(param); + System.out.println(result); + System.out.println("-----------------"); + System.out.println("-----------------"); + msgManager.add(result); + param.setPrompt("能否缩短一些,只讲三点"); + param.setMessages(msgManager.get()); + result = gen.call(param); + System.out.println(result); + } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java index 1ed3afc1d..0ecf54f8b 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java @@ -6,7 +6,7 @@ import cn.iocoder.yudao.framework.ai.midjourney.api.req.AttachmentsReq; import cn.iocoder.yudao.framework.ai.midjourney.api.req.DescribeReq; import cn.iocoder.yudao.framework.ai.midjourney.api.req.ReRollReq; import cn.iocoder.yudao.framework.ai.midjourney.api.res.UploadAttachmentsRes; -import com.alibaba.fastjson.JSON; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import org.junit.Before; import org.junit.Test; import org.springframework.core.io.FileSystemResource; @@ -58,7 +58,7 @@ public class MidjourneyInteractionsTests { new AttachmentsReq().setFileSystemResource( new FileSystemResource(new File("/Users/fansili/Downloads/DSC01402.JPG"))) ); - System.err.println(JSON.toJSONString(res)); + System.err.println(JsonUtils.toJsonString(res)); } @Test diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index e0ca7072c..c13db0164 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -228,14 +228,11 @@ yudao: qianwen: enable: true aiPlatform: QIAN_WEN - temperature: 1 - topP: 1 - topK: 1 - endpoint: bailian.cn-beijing.aliyuncs.com - accessKeyId: LTAI5tNTVhXW4fLKUjMrr98z - accessKeySecret: ZJ0JQeyjzxxm5CfeTV6k1wNE9UsvZP - agentKey: f0c1088824594f589c8f10567ccd929f_p_efm - appId: 5f14955f201a44eb8dbe0c57250a32ce + temperature: 0.85 + topP: 0.8 + topK: 0 + api-key: sk-Zsd81gZYg7 + max-tokens: 1500 xinghuo: enable: true aiPlatform: XING_HUO From 8b2dcaf910d94c936f1f1db899e8b8e14f141131 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 27 Apr 2024 16:59:15 +0800 Subject: [PATCH 161/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E8=AE=AF=E9=A3=9E=E6=98=9F=E7=81=AB=E5=85=BC=E5=AE=B9=20system?= =?UTF-8?q?=E3=80=81assistant=E3=80=81user?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/chatxinghuo/XingHuoChatClient.java | 11 +++++++---- .../ai/chat/XingHuoChatClientTests.java | 17 +++++++++++++++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java index 849a70d75..c257203b1 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java @@ -117,12 +117,15 @@ public class XingHuoChatClient implements ChatClient, StreamingChatClient { chatParameter.setDomain(xingHuoOptions.getChatModel().getValue()); XingHuoChatCompletionRequest.Parameter parameter = new XingHuoChatCompletionRequest.Parameter().setChat(chatParameter); // 创建 payload text 信息 - XingHuoChatCompletionRequest.Payload.Message.Text text = new XingHuoChatCompletionRequest.Payload.Message.Text(); - text.setRole(XingHuoChatCompletionRequest.Payload.Message.Text.Role.USER.getName()); - text.setContent(prompt.getContents()); + List texts = prompt.getInstructions().stream().map(message -> { + XingHuoChatCompletionRequest.Payload.Message.Text text = new XingHuoChatCompletionRequest.Payload.Message.Text(); + text.setContent(message.getContent()); + text.setRole(message.getMessageType().getValue()); + return text; + }).collect(Collectors.toList()); // 创建 payload XingHuoChatCompletionRequest.Payload payload = new XingHuoChatCompletionRequest.Payload() - .setMessage(new XingHuoChatCompletionRequest.Payload.Message().setText(List.of(text))); + .setMessage(new XingHuoChatCompletionRequest.Payload.Message().setText(texts)); // 创建 request return new XingHuoChatCompletionRequest() .setHeader(header) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java index 2340ad9a3..ee32b6717 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java @@ -1,5 +1,8 @@ package cn.iocoder.yudao.framework.ai.chat; +import cn.iocoder.yudao.framework.ai.chat.messages.Message; +import cn.iocoder.yudao.framework.ai.chat.messages.SystemMessage; +import cn.iocoder.yudao.framework.ai.chat.messages.UserMessage; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatClient; import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel; @@ -9,6 +12,8 @@ import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; +import java.util.ArrayList; +import java.util.List; import java.util.Scanner; import java.util.function.Consumer; @@ -37,13 +42,21 @@ public class XingHuoChatClientTests { @Test public void callTest() { - ChatResponse call = xingHuoChatClient.call(new Prompt("java和go那个性能更好!")); + List messages = new ArrayList<>(); + messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。")); + messages.add(new UserMessage("长沙怎么样?")); + + ChatResponse call = xingHuoChatClient.call(new Prompt(messages)); System.err.println(call.getResult()); } @Test public void streamTest() { - Flux stream = xingHuoChatClient.stream(new Prompt("java和go那个性能更好!")); + List messages = new ArrayList<>(); + messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。")); + messages.add(new UserMessage("长沙怎么样?")); + + Flux stream = xingHuoChatClient.stream(new Prompt(messages)); stream.subscribe(new Consumer() { @Override public void accept(ChatResponse chatResponse) { From eef9ed1b3e3b39c7eebf9e596af3fc396bb88d6e Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 27 Apr 2024 17:22:40 +0800 Subject: [PATCH 162/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E9=85=8D=E7=BD=AE=E4=BC=98=E5=8C=96=EF=BC=8C?= =?UTF-8?q?=E6=98=9F=E7=81=AB=E3=80=81=E4=B8=80=E8=A8=80=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20topK=20topP=20maxToken=20Temperature=20=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/config/YudaoAiAutoConfiguration.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index fa61eeb3f..b9be65407 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -30,13 +30,19 @@ public class YudaoAiAutoConfiguration { @ConditionalOnProperty(value = "yudao.ai.xinghuo.enable", havingValue = "true") public XingHuoChatClient xingHuoChatClient(YudaoAiProperties yudaoAiProperties) { YudaoAiProperties.XingHuoProperties xingHuoProperties = yudaoAiProperties.getXinghuo(); + // 转换配置 + XingHuoOptions xingHuoOptions = new XingHuoOptions(); + xingHuoOptions.setChatModel(xingHuoProperties.getChatModel()); + xingHuoOptions.setTopK(xingHuoProperties.getTopK()); + xingHuoOptions.setTemperature(xingHuoProperties.getTemperature()); + xingHuoOptions.setMaxTokens(xingHuoProperties.getMaxTokens()); return new XingHuoChatClient( new XingHuoApi( xingHuoProperties.getAppId(), xingHuoProperties.getAppKey(), xingHuoProperties.getSecretKey() ), - new XingHuoOptions().setChatModel(xingHuoProperties.getChatModel()) + xingHuoOptions ); } @@ -44,6 +50,7 @@ public class YudaoAiAutoConfiguration { @ConditionalOnProperty(value = "yudao.ai.qianwen.enable", havingValue = "true") public QianWenChatClient qianWenChatClient(YudaoAiProperties yudaoAiProperties) { YudaoAiProperties.QianWenProperties qianWenProperties = yudaoAiProperties.getQianwen(); + // 转换配置 QianWenOptions qianWenOptions = new QianWenOptions(); qianWenOptions.setTopK(qianWenProperties.getTopK()); qianWenOptions.setTopP(qianWenProperties.getTopP()); @@ -62,6 +69,12 @@ public class YudaoAiAutoConfiguration { @ConditionalOnProperty(value = "yudao.ai.yiyan.enable", havingValue = "true") public YiYanChatClient yiYanChatClient(YudaoAiProperties yudaoAiProperties) { YudaoAiProperties.YiYanProperties yiYanProperties = yudaoAiProperties.getYiyan(); + // 转换配置 + YiYanOptions yiYanOptions = new YiYanOptions(); + yiYanOptions.setTopK(yiYanProperties.getTopK()); + yiYanOptions.setTopP(yiYanProperties.getTopP()); + yiYanOptions.setTemperature(yiYanProperties.getTemperature()); + yiYanOptions.setMaxOutputTokens(yiYanProperties.getMaxTokens()); return new YiYanChatClient( new YiYanApi( yiYanProperties.getAppKey(), @@ -69,6 +82,7 @@ public class YudaoAiAutoConfiguration { yiYanProperties.getChatModel(), yiYanProperties.getRefreshTokenSecondTime() ), - new YiYanOptions().setMax_output_tokens(2048)); + yiYanOptions + ); } } \ No newline at end of file From e4bb7262c3acaf493c5489adc210694eb83910dc Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 27 Apr 2024 17:23:15 +0800 Subject: [PATCH 163/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E6=98=9F=E7=81=AB=E5=85=BC=E5=AE=B9=20ChatOptions=20=E9=85=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/chatxinghuo/XingHuoOptions.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoOptions.java index dd839403e..7d5603282 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoOptions.java @@ -6,7 +6,7 @@ import lombok.experimental.Accessors; /** * 讯飞星火 - * + *

* author: fansili * time: 2024/3/16 20:29 */ @@ -16,7 +16,7 @@ public class XingHuoOptions implements ChatOptions { /** * https://www.xfyun.cn/doc/spark/Web.html#_1-%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E - * + *

* 指定访问的领域: * general指向V1.5版本; * generalv2指向V2版本; @@ -33,25 +33,25 @@ public class XingHuoOptions implements ChatOptions { * V1.5取值为[1,4096] * V2.0、V3.0和V3.5取值为[1,8192],默认为2048。 */ - private Integer max_tokens; + private Integer maxTokens; /** * 取值为[1,6],默认为4 */ - private Integer top_k; + private Integer topK; /** - * 需要保障用户下的唯一性,用于关联用户会话 + * 需要保障用户下的唯一性,用于关联用户会话 */ - private String chat_id; + private String chatId; @Override public Float getTemperature() { - return null; + return this.temperature; } @Override public void setTemperature(Float temperature) { - + this.temperature = temperature; } @Override @@ -66,11 +66,11 @@ public class XingHuoOptions implements ChatOptions { @Override public Integer getTopK() { - return null; + return this.topK; } @Override public void setTopK(Integer topK) { - + this.topK = topK; } } From c811f3a4c21c40be211ed8b7c9dedc34f18dacc7 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 27 Apr 2024 17:23:52 +0800 Subject: [PATCH 164/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E6=8A=BD=E7=A6=BB=20maxTokens=20=E4=BD=9C=E4=B8=BA=E5=85=AC?= =?UTF-8?q?=E5=85=B1=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/framework/ai/config/YudaoAiProperties.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java index 71358aee0..d638a2b06 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java @@ -37,6 +37,10 @@ public class YudaoAiProperties { private Float topP; private Integer topK; + /** + * 用于限制模型生成token的数量,max_tokens设置的是生成上限,并不表示一定会生成这么多的token数量 + */ + private Integer maxTokens; } @Data @@ -47,10 +51,6 @@ public class YudaoAiProperties { * api key */ private String apiKey; - /** - * 用于限制模型生成token的数量,max_tokens设置的是生成上限,并不表示一定会生成这么多的token数量 - */ - private Integer maxTokens; /** * model */ From 10a94c3ef20aeb6767f3f5327a2552bdfa28c6da Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 27 Apr 2024 18:29:58 +0800 Subject: [PATCH 165/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E5=A4=84=E7=90=86=E7=99=BE=E5=BA=A6=20system=20=E8=A7=92?= =?UTF-8?q?=E8=89=B2=E5=AE=9A=E5=88=B6=E5=A4=B1=E6=95=88=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/chatyiyan/YiYanChatClient.java | 62 ++++++++++++++----- .../framework/ai/chatyiyan/YiYanOptions.java | 10 ++- .../framework/ai/chat/YiYanChatTests.java | 31 ++++++++-- 3 files changed, 77 insertions(+), 26 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java index fae550da8..d95e9fb99 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java @@ -2,6 +2,8 @@ package cn.iocoder.yudao.framework.ai.chatyiyan; import cn.hutool.core.bean.BeanUtil; import cn.iocoder.yudao.framework.ai.chat.*; +import cn.iocoder.yudao.framework.ai.chat.messages.Message; +import cn.iocoder.yudao.framework.ai.chat.messages.MessageType; import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanApi; @@ -9,6 +11,7 @@ import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletion; import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletionRequest; import cn.iocoder.yudao.framework.ai.chatyiyan.exception.YiYanApiException; import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; import org.springframework.http.ResponseEntity; import org.springframework.retry.RetryCallback; import org.springframework.retry.RetryContext; @@ -18,10 +21,11 @@ import reactor.core.publisher.Flux; import java.time.Duration; import java.util.List; +import java.util.stream.Collectors; /** * 文心一言 - * + *

* author: fansili * time: 2024/3/8 19:11 */ @@ -52,7 +56,9 @@ public class YiYanChatClient implements ChatClient, StreamingChatClient { public void onError(RetryContext context, RetryCallback callback, Throwable throwable) { log.warn("重试异常:" + context.getRetryCount(), throwable); - }; + } + + ; }) .build(); @@ -92,6 +98,42 @@ public class YiYanChatClient implements ChatClient, StreamingChatClient { } private YiYanChatCompletionRequest createRequest(Prompt prompt, boolean stream) { + // 获取配置 + YiYanOptions useOptions = getYiYanOptions(prompt); + // 创建 request + + // tip: 百度的 system 不在 message 里面 + // tip:百度的 message 只有 user 和 assistant + // https://cloud.baidu.com/doc/WENXINWORKSHOP/s/clntwmv7t + + // 获取 user 和 assistant + List messageList = prompt.getInstructions().stream() + // 过滤 system + .filter(msg -> MessageType.SYSTEM != msg.getMessageType()) + .map(msg -> new YiYanChatCompletionRequest.Message() + .setRole(msg.getMessageType().getValue()) + .setContent(msg.getContent()) + ).toList(); + // 获取 system + String systemPrompt = prompt.getInstructions().stream() + .filter(msg -> MessageType.SYSTEM == msg.getMessageType()) + .map(Message::getContent) + .collect(Collectors.joining()); + + YiYanChatCompletionRequest request = new YiYanChatCompletionRequest(messageList); + // 复制 qianWenOptions 属性取 request(这里 options 属性和 request 基本保持一致) + // top: 由于遵循 spring-ai规范,支持在构建client的时候传入默认的 chatOptions + BeanUtil.copyProperties(useOptions, request); + request.setTop_p(useOptions.getTopP()); + request.setMax_output_tokens(useOptions.getMaxOutputTokens()); + request.setTemperature(useOptions.getTemperature()); + request.setSystem(systemPrompt); + // 设置 stream + request.setStream(stream); + return request; + } + + private @NotNull YiYanOptions getYiYanOptions(Prompt prompt) { // 两个都为null 则没有配置文件 if (yiYanOptions == null && prompt.getOptions() == null) { throw new ChatException("ChatOptions 未配置参数!"); @@ -106,19 +148,7 @@ public class YiYanChatClient implements ChatClient, StreamingChatClient { throw new ChatException("Prompt 传入的不是 YiYanOptions!"); } // 转换 YiYanOptions - YiYanOptions qianWenOptions = (YiYanOptions) options; - // 创建 request - List messageList = prompt.getInstructions().stream().map( - msg -> new YiYanChatCompletionRequest.Message() - .setRole(msg.getMessageType().getValue()) - .setContent(msg.getContent()) - ).toList(); - YiYanChatCompletionRequest request = new YiYanChatCompletionRequest(messageList); - // 复制 qianWenOptions 属性取 request(这里 options 属性和 request 基本保持一致) - // top: 由于遵循 spring-ai规范,支持在构建client的时候传入默认的 chatOptions - BeanUtil.copyProperties(qianWenOptions, request); - // 设置 stream - request.setStream(stream); - return request; + YiYanOptions useOptions = (YiYanOptions) options; + return useOptions; } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanOptions.java index 4b1bc3fe6..84f0ced4c 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanOptions.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.framework.ai.chatyiyan; import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletionRequest; -import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import lombok.experimental.Accessors; @@ -40,7 +39,7 @@ public class YiYanOptions implements ChatOptions { * (2)默认0.8,取值范围 [0, 1.0] * 必填:否 */ - private Float top_p; + private Float topP; /** * 通过对已生成的token增加惩罚,减少重复生成的现象。说明: * (1)值越大表示惩罚越大 @@ -84,7 +83,7 @@ public class YiYanOptions implements ChatOptions { * 指定模型最大输出token数,范围[2, 2048] * 必填:否 */ - private Integer max_output_tokens; + private Integer maxOutputTokens; /** * 指定响应内容的格式,说明: * (1)可选值: @@ -122,12 +121,12 @@ public class YiYanOptions implements ChatOptions { @Override public Float getTopP() { - return top_p; + return topP; } @Override public void setTopP(Float topP) { - this.top_p = topP; + this.topP = topP; } // 百度么有 topK @@ -139,6 +138,5 @@ public class YiYanOptions implements ChatOptions { @Override public void setTopK(Integer topK) { - } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java index 326f52552..df98541fc 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java @@ -1,5 +1,8 @@ package cn.iocoder.yudao.framework.ai.chat; +import cn.iocoder.yudao.framework.ai.chat.messages.Message; +import cn.iocoder.yudao.framework.ai.chat.messages.SystemMessage; +import cn.iocoder.yudao.framework.ai.chat.messages.UserMessage; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatClient; import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel; @@ -9,11 +12,13 @@ import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; +import java.util.ArrayList; +import java.util.List; import java.util.Scanner; /** * chat 文心一言 - * + *

* author: fansili * time: 2024/3/12 20:59 */ @@ -29,18 +34,36 @@ public class YiYanChatTests { YiYanChatModel.ERNIE4_3_5_8K, 86400 ); - yiYanChatClient = new YiYanChatClient(yiYanApi, new YiYanOptions().setMax_output_tokens(2048)); + YiYanOptions yiYanOptions = new YiYanOptions(); + yiYanOptions.setMaxOutputTokens(2048); + yiYanOptions.setTopP(0.6f); + yiYanOptions.setTemperature(0.85f); + yiYanChatClient = new YiYanChatClient( + yiYanApi, + yiYanOptions + ); } @Test public void callTest() { - ChatResponse call = yiYanChatClient.call(new Prompt("什么编程语言最好?")); + + // tip: 百度的message 有特殊规则(最后一个message为当前请求的信息,前面的message为历史对话信息) + // tip: 地址 https://cloud.baidu.com/doc/WENXINWORKSHOP/s/jlil56u11 + List messages = new ArrayList<>(); + messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景,所有问题都采用文言文回答。")); + messages.add(new UserMessage("长沙怎么样?")); + + ChatResponse call = yiYanChatClient.call(new Prompt(messages)); System.err.println(call.getResult()); } @Test public void streamTest() { - Flux fluxResponse = yiYanChatClient.stream(new Prompt("用java帮我写一个快排算法?")); + List messages = new ArrayList<>(); + messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景,所有问题都采用文言文回答。")); + messages.add(new UserMessage("长沙怎么样?")); + + Flux fluxResponse = yiYanChatClient.stream(new Prompt(messages)); fluxResponse.subscribe(chatResponse -> System.err.print(chatResponse.getResult().getOutput().getContent())); // 阻止退出 Scanner scanner = new Scanner(System.in); From d37c1c4ecc2d57306eb1ddc6ecce1634931780e5 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 27 Apr 2024 18:31:31 +0800 Subject: [PATCH 166/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E7=BB=9F=E4=B8=80=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20max-tokens=E9=85=8D=E7=BD=AE=20=E5=92=8C=20topP=20t?= =?UTF-8?q?opK=20=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application-local.yaml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index c13db0164..4ca742981 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -228,17 +228,18 @@ yudao: qianwen: enable: true aiPlatform: QIAN_WEN + max-tokens: 1500 temperature: 0.85 topP: 0.8 topK: 0 api-key: sk-Zsd81gZYg7 - max-tokens: 1500 xinghuo: enable: true aiPlatform: XING_HUO - temperature: 1 - topP: 1 - topK: 1 + max-tokens: 1500 + temperature: 0.85 + topP: 0.8 + topK: 0 appId: 13c8cca6 appKey: cb6415c19d6162cda07b47316fcb0416 secretKey: Y2JiYTIxZjA3MDMxMjNjZjQzYzVmNzdh @@ -246,9 +247,10 @@ yudao: yiyan: enable: true aiPlatform: YI_YAN - temperature: 1 - topP: 1 - topK: 1 + max-tokens: 1500 + temperature: 0.85 + topP: 0.8 + topK: 0 appKey: x0cuLZ7XsaTCU08vuJWO87Lg secretKey: R9mYF9dl9KASgi5RUq0FQt3wRisSnOcK refreshTokenSecondTime: 86400 From a34d925973a8e44ca90869254a561b28ed8d699f Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 28 Apr 2024 11:51:22 +0800 Subject: [PATCH 167/684] =?UTF-8?q?=E3=80=90=E6=9B=B4=E6=96=B0=E3=80=91sql?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/chat.sql | 235 ++++++++++++------ 1 file changed, 161 insertions(+), 74 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/chat.sql b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/chat.sql index e06f3e9bc..6fd87f4f4 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/chat.sql +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/chat.sql @@ -1,79 +1,166 @@ -DROP TABLE IF EXISTS chat_role; -CREATE TABLE chat_role( - `id` bigint COMMENT '编号' , - `user_id` bigint COMMENT '用户id' , - `model_id` VARCHAR(255) COMMENT '模型编号' , - `role_name` VARCHAR(32) COMMENT '角色名' , - `role_introduce` VARCHAR(255) COMMENT '介绍' , - `role_source` VARCHAR(32) COMMENT '角色来源(system、customer)' , - `classify` VARCHAR(32) COMMENT '分类(娱乐、创作)' , - `publish` tinyint COMMENT '发布(0、自己可见 1、公开 2、禁用)' , - `top_k` DECIMAL(4,2) COMMENT '生成时,采样候选集的大小' , - `top_p` DECIMAL(24,6) COMMENT '生成时,核采样方法的概率阈值。' , - `temperature` DECIMAL(24,6) COMMENT '用于控制随机性和多样性的程度' , - `use_count` INT COMMENT '使用次数' , - `CREATED_BY` bigint COMMENT '创建人' , - `CREATED_TIME` DATETIME COMMENT '创建时间' , - `UPDATED_BY` bigint COMMENT '更新人' , - `UPDATED_TIME` DATETIME COMMENT '更新时间' -) COMMENT = 'chat角色;'; +/* + Navicat Premium Data Transfer -DROP TABLE IF EXISTS chat_history; -CREATE TABLE chat_history( - `id` bigint COMMENT '编号' , - `chat_id` bigint COMMENT '聊天id' , - `user_id` VARCHAR(32) COMMENT '角色名' , - `message` TEXT COMMENT '消息' , - `message_type` DECIMAL(4,2) COMMENT 'system、user、assistant' , - `top_k` DECIMAL(4,2) COMMENT '生成时,采样候选集的大小' , - `top_p` DECIMAL(24,6) COMMENT '生成时,核采样方法的概率阈值。' , - `temperature` DECIMAL(24,6) COMMENT '用于控制随机性和多样性的程度' , - `CREATED_BY` bigint COMMENT '创建人' , - `CREATED_TIME` DATETIME COMMENT '创建时间' , - `UPDATED_BY` bigint COMMENT '更新人' , - `UPDATED_TIME` DATETIME COMMENT '更新时间' -) COMMENT = '聊天记录;'; + Source Server : localhost + Source Server Type : MySQL + Source Server Version : 80034 (8.0.34) + Source Host : localhost:3306 + Source Schema : ruoyi-vue-pro -DROP TABLE IF EXISTS user; -CREATE TABLE user( - `id` bigint COMMENT '编号' , - `username` VARCHAR(32) COMMENT '用户名' , - `nickname` VARCHAR(32) COMMENT '昵称' , - `mobile` VARCHAR(32) COMMENT '手机号' , - `avatar_url` VARCHAR(128) COMMENT '头像' , - `password` VARCHAR(32) COMMENT '密码' , - `publish` tinyint COMMENT '发布(0、未发布 1、已发布)' , - `disable` VARCHAR(255) COMMENT '禁用(0、正常 1、禁用)' , - `CREATED_BY` bigint COMMENT '创建人' , - `CREATED_TIME` DATETIME COMMENT '创建时间' , - `UPDATED_BY` bigint COMMENT '更新人' , - `UPDATED_TIME` DATETIME COMMENT '更新时间' -) COMMENT = '用户;'; + Target Server Type : MySQL + Target Server Version : 80034 (8.0.34) + File Encoding : 65001 -DROP TABLE IF EXISTS chat; -CREATE TABLE chat( - `id` bigint COMMENT '编号' , - `user_id` bigint COMMENT '用户id' , - `chat_role_id` VARCHAR(255) COMMENT '模型id' , - `chat_title` VARCHAR(128) COMMENT '聊天标题' , - `chat_count` INT COMMENT '聊天次数' , - `CREATED_BY` bigint COMMENT '创建人' , - `CREATED_TIME` DATETIME COMMENT '创建时间' , - `UPDATED_BY` bigint COMMENT '更人' , - `UPDATED_TIME` DATETIME COMMENT '更新时间' -) COMMENT = '聊天;'; + Date: 28/04/2024 11:50:47 +*/ -DROP TABLE IF EXISTS chat_model; -CREATE TABLE chat_model( - `id` bigint COMMENT '编号' , - `model_name` bigint COMMENT '模型名字' , - `model_type` VARCHAR(32) COMMENT '模型类型(qianwen、yiyan、xinghuo、openai)' , - `model_config` TEXT(128) COMMENT '模型配置JSON' , - `model_image` VARCHAR(255) COMMENT '模型图片' , - `disable` tinyint COMMENT '禁用 0、正常 1、禁用' , - `CREATED_BY` bigint COMMENT '创建人' , - `CREATED_TIME` DATETIME COMMENT '创建时间' , - `UPDATED_BY` bigint COMMENT '更新人' , - `UPDATED_TIME` DATETIME COMMENT '更新时间' -) COMMENT = '聊天模型;'; +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; +-- ---------------------------- +-- Table structure for ai_chat_conversation +-- ---------------------------- +DROP TABLE IF EXISTS `ai_chat_conversation`; +CREATE TABLE `ai_chat_conversation` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `user_id` bigint DEFAULT NULL COMMENT '用户id', + `chat_role_id` bigint DEFAULT NULL COMMENT '聊天角色', + `chat_role_name` varchar(128) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '聊天角色名称', + `title` varchar(256) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '标题', + `type` varchar(16) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '对话类型', + `chat_count` int DEFAULT NULL COMMENT '聊天次数', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `creator` bigint DEFAULT NULL COMMENT '创建用户', + `updater` bigint DEFAULT NULL COMMENT '更新用户', + `deleted` bit(1) DEFAULT b'0' COMMENT '删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1781604279872581645 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; + +-- ---------------------------- +-- Records of ai_chat_conversation +-- ---------------------------- +BEGIN; +INSERT INTO `ai_chat_conversation` (`id`, `user_id`, `chat_role_id`, `chat_role_name`, `title`, `type`, `chat_count`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (1781604279872581644, 1, NULL, NULL, '中国好看吗?', 'userChat', 32, '2024-04-20 16:59:32', '2024-04-20 16:59:32', 1, 1, b'0'); +COMMIT; + +-- ---------------------------- +-- Table structure for ai_chat_message +-- ---------------------------- +DROP TABLE IF EXISTS `ai_chat_message`; +CREATE TABLE `ai_chat_message` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `chat_conversation_id` bigint DEFAULT NULL COMMENT '对话id', + `user_id` bigint DEFAULT NULL COMMENT '用户id', + `message` text COLLATE utf8mb4_0900_bin COMMENT '对话message', + `message_type` varchar(16) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '对话类型system、user、assistant\n', + `top_k` float DEFAULT NULL COMMENT '在生成消息时采用的Top-K采样大小', + `top_p` float DEFAULT NULL COMMENT 'Top-P核采样方法的概率阈值', + `temperature` float DEFAULT NULL COMMENT '用于调整生成回复的随机性和多样性程度', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `creator` bigint DEFAULT NULL COMMENT '创建用户', + `updater` bigint DEFAULT NULL COMMENT '更新用户', + `deleted` bit(1) DEFAULT b'0' COMMENT '删除', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; + +-- ---------------------------- +-- Records of ai_chat_message +-- ---------------------------- +BEGIN; +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (1, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-20 18:22:41', '2024-04-20 18:22:41', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (2, 1781604279872581644, 1, '作为一个AI助手,我没有个人感受和偏好。但是,中国是一个拥有丰富历史、文化和自然景观的国家,有许多令人惊叹的地方,如长城、故宫、西湖、张家界、九寨沟等著名景点,吸引了无数国内外游客的喜爱。每个人对于\"好看\"的定义可能不同,但中国无疑有着独特的魅力和多样性。', 'system', NULL, NULL, NULL, '2024-04-20 18:22:44', '2024-04-20 18:22:44', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (3, 1781604279872581644, 1, '苹果是什么颜色?', 'user', NULL, NULL, NULL, '2024-04-20 18:23:05', '2024-04-20 18:23:05', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (4, 1781604279872581644, 1, '苹果的颜色可以根据品种的不同而有所差异。常见的苹果颜色有红色、黄色和青绿色。除了这些基本颜色,苹果还可能呈现出淡红色、深红色等不同的红色调。\n\n这些颜色只是影响苹果的外观,对苹果的口感和营养价值没有影响。苹果口感酸甜,营养丰富,深受人们喜爱。', 'system', NULL, NULL, NULL, '2024-04-20 18:23:11', '2024-04-20 18:23:11', NULL, NULL, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (5, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-23 10:46:48', '2024-04-23 10:46:48', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (6, 1781604279872581644, 1, '作为一个AI助手,我没有个人感受和偏好。但是,中国是一个拥有丰富历史、文化和自然景观的国家,有许多令人惊叹的地方,如长城、故宫、西湖、张家界、九寨沟等著名景点,吸引了无数国内外游客的喜爱。每个人对于\"好看\"的定义可能不同,但中国无疑有着独特的魅力和多样性。', 'system', NULL, NULL, NULL, '2024-04-23 10:46:52', '2024-04-23 10:46:52', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (7, 1781604279872581644, 1, '苹果是什么颜色?', 'user', NULL, NULL, NULL, '2024-04-23 10:46:55', '2024-04-23 10:46:55', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (8, 1781604279872581644, 1, '苹果的颜色因品种和成熟度的不同而异。常见的苹果颜色有红色、黄色和青绿色。除此之外,还有一些苹果品种可能呈现出淡红色、深红色等不同的红色调,或者带有条纹或斑点。总的来说,苹果的颜色非常多样化,但最常见的是红色、黄色和青绿色。', 'system', NULL, NULL, NULL, '2024-04-23 10:47:03', '2024-04-23 10:47:03', NULL, NULL, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (9, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-23 13:49:16', '2024-04-23 13:49:16', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (10, 1781604279872581644, 1, '作为一个AI助手,我没有个人感受和偏好。但是,中国是一个拥有丰富历史、文化和自然景观的国家,有许多令人惊叹的地方,如长城、故宫、西湖、张家界、九寨沟等著名景点,吸引了无数国内外游客的喜爱。每个人对于\"好看\"的定义可能不同,但中国无疑有着独特的魅力和多样性。', 'system', NULL, NULL, NULL, '2024-04-23 13:49:19', '2024-04-23 13:49:19', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (11, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-25 17:55:39', '2024-04-25 17:55:39', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (12, 1781604279872581644, 1, 'NoSuchBeanDefinitionException: No qualifying bean of type \'cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient\' available', 'system', NULL, NULL, NULL, '2024-04-25 17:55:39', '2024-04-25 17:55:39', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (13, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-25 17:56:12', '2024-04-25 17:56:12', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (14, 1781604279872581644, 1, 'NoSuchBeanDefinitionException: No qualifying bean of type \'cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient\' available', 'system', NULL, NULL, NULL, '2024-04-25 17:56:12', '2024-04-25 17:56:12', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (15, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-25 17:56:24', '2024-04-25 17:56:24', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (16, 1781604279872581644, 1, 'NoSuchBeanDefinitionException: No qualifying bean of type \'cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient\' available', 'system', NULL, NULL, NULL, '2024-04-25 17:56:24', '2024-04-25 17:56:24', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (17, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-25 17:56:41', '2024-04-25 17:56:41', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (18, 1781604279872581644, 1, 'NoSuchBeanDefinitionException: No qualifying bean of type \'cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient\' available', 'system', NULL, NULL, NULL, '2024-04-25 17:56:59', '2024-04-25 17:56:59', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (19, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-25 17:58:15', '2024-04-25 17:58:15', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (20, 1781604279872581644, 1, '作为一个AI助手,我没有个人感受和偏好。但是,中国是一个拥有丰富历史、文化和自然景观的国家,有许多令人惊叹的地方,如长城、故宫、西湖、张家界、九寨沟等著名景点,吸引了无数国内外游客的喜爱。每个人对于\"好看\"的定义可能不同,但中国无疑有着独特的魅力和多样性。', 'system', NULL, NULL, NULL, '2024-04-25 17:58:19', '2024-04-25 17:58:19', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (21, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-26 18:27:13', '2024-04-26 18:27:13', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (22, 1781604279872581644, 1, 'ClassCastException: class com.alibaba.dashscope.aigc.generation.models.QwenParam cannot be cast to class cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenChatCompletionRequest (com.alibaba.dashscope.aigc.generation.models.QwenParam and cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenChatCompletionRequest are in unnamed module of loader \'app\')', 'system', NULL, NULL, NULL, '2024-04-26 18:27:13', '2024-04-26 18:27:13', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (23, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-26 18:28:12', '2024-04-26 18:28:12', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (24, 1781604279872581644, 1, 'ClassCastException: class com.alibaba.dashscope.aigc.generation.models.QwenParam cannot be cast to class cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenChatCompletionRequest (com.alibaba.dashscope.aigc.generation.models.QwenParam and cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenChatCompletionRequest are in unnamed module of loader \'app\')', 'system', NULL, NULL, NULL, '2024-04-26 18:30:31', '2024-04-26 18:30:31', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (25, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-27 09:39:56', '2024-04-27 09:39:56', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (26, 1781604279872581644, 1, 'ClassCastException: class com.alibaba.dashscope.aigc.generation.models.QwenParam cannot be cast to class cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenChatCompletionRequest (com.alibaba.dashscope.aigc.generation.models.QwenParam and cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenChatCompletionRequest are in unnamed module of loader \'app\')', 'system', NULL, NULL, NULL, '2024-04-27 09:39:56', '2024-04-27 09:39:56', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (27, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-27 09:41:02', '2024-04-27 09:41:02', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (28, 1781604279872581644, 1, 'AiException: 没有找到apiKey!Can not find api-key.', 'system', NULL, NULL, NULL, '2024-04-27 09:41:02', '2024-04-27 09:41:02', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (29, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-27 09:41:58', '2024-04-27 09:41:58', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (30, 1781604279872581644, 1, 'AiException: 没有找到apiKey!Can not find api-key.', 'system', NULL, NULL, NULL, '2024-04-27 09:41:58', '2024-04-27 09:41:58', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (31, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-27 09:42:41', '2024-04-27 09:42:41', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (32, 1781604279872581644, 1, 'ApiException: {\"statusCode\":400,\"message\":\"parameter incremental_output only support stream call\",\"code\":\"InvalidParameter\",\"isJson\":true,\"requestId\":\"9edd3968-6eec-901d-8194-15f497ca0d3a\"}', 'system', NULL, NULL, NULL, '2024-04-27 09:42:42', '2024-04-27 09:42:42', 1, 1, b'0'); +COMMIT; + +-- ---------------------------- +-- Table structure for ai_chat_modal +-- ---------------------------- +DROP TABLE IF EXISTS `ai_chat_modal`; +CREATE TABLE `ai_chat_modal` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `model_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '模型名字\n', + `model_type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '模型类型(自己定义qianwen、yiyan、xinghuo、openai)\n', + `modal_image` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '模型照片\n', + `config` json DEFAULT NULL COMMENT 'Ai配置文件', + `disable` tinyint DEFAULT NULL COMMENT '禁用 0、正常 1、禁用\n', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `creator` bigint DEFAULT NULL COMMENT '创建用户', + `updater` bigint DEFAULT NULL COMMENT '更新用户', + `deleted` bit(1) DEFAULT b'0' COMMENT '删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; + +-- ---------------------------- +-- Records of ai_chat_modal +-- ---------------------------- +BEGIN; +INSERT INTO `ai_chat_modal` (`id`, `model_name`, `model_type`, `modal_image`, `config`, `disable`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (1, '小红书Ai写作大模型', 'yiyan', '', NULL, 0, '2024-04-25 18:10:32', '2024-04-25 18:10:32', 1, 1, b'0'); +COMMIT; + +-- ---------------------------- +-- Table structure for ai_chat_role +-- ---------------------------- +DROP TABLE IF EXISTS `ai_chat_role`; +CREATE TABLE `ai_chat_role` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `user_id` bigint DEFAULT NULL, + `model_id` bigint DEFAULT NULL COMMENT '模型编号,关联到角色使用的特定模型\n', + `role_name` varchar(128) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '角色名,角色的显示名称\n', + `role_introduce` varchar(256) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '角色介绍,详细描述角色的功能或用途\n', + `role_source` varchar(16) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '角色来源,如 system(系统预置)、customer(用户自定义)\n', + `classify` varchar(32) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '分类,角色所属的类别,如娱乐、创作等\n', + `visibility` varchar(16) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '发布状态,private 表示仅自己可见,public表示公开,disable表示禁用\n', + `top_k` float DEFAULT NULL COMMENT '生成时的Top-K采样候选集大小\n', + `top_p` float DEFAULT NULL COMMENT '生成时使用的核采样方法的概率阈值\n', + `temperature` float DEFAULT NULL COMMENT '用于控制随机性和多样性的温度参数\n', + `use_count` int DEFAULT NULL COMMENT '角色的使用次数统计\n', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `creator` bigint DEFAULT NULL COMMENT '创建用户', + `updater` bigint DEFAULT NULL COMMENT '更新用户', + `deleted` bit(1) DEFAULT b'0' COMMENT '删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; + +-- ---------------------------- +-- Records of ai_chat_role +-- ---------------------------- +BEGIN; +INSERT INTO `ai_chat_role` (`id`, `user_id`, `model_id`, `role_name`, `role_introduce`, `role_source`, `classify`, `visibility`, `top_k`, `top_p`, `temperature`, `use_count`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (1, 1, 1, '小红书写作v1---hh😄', '采用gpt3.5模型,拥有小红书优质作者写作经验。', 'system', 'writing', 'private', 0.2, 0.4, 0.7, 0, '2024-04-24 19:21:42', '2024-04-24 19:37:49', 1, 1, b'1'); +INSERT INTO `ai_chat_role` (`id`, `user_id`, `model_id`, `role_name`, `role_introduce`, `role_source`, `classify`, `visibility`, `top_k`, `top_p`, `temperature`, `use_count`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (2, 1, 1, '小红书写作v2', '采用gpt3.5模型,拥有小红书优质作者写作经验。', 'system', 'writing', 'public', 0.2, 0.4, 0.7, 0, '2024-04-24 19:22:05', '2024-04-24 19:22:05', 1, 1, b'0'); +INSERT INTO `ai_chat_role` (`id`, `user_id`, `model_id`, `role_name`, `role_introduce`, `role_source`, `classify`, `visibility`, `top_k`, `top_p`, `temperature`, `use_count`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (3, 1, 1, '小红书写作v1---', '采用gpt3.5模型,拥有小红书优质作者写作经验。', 'system', 'writing', 'public', 0.2, 0.4, 0.7, 0, '2024-04-24 19:29:38', '2024-04-24 19:29:38', 1, 1, b'0'); +COMMIT; + +SET FOREIGN_KEY_CHECKS = 1; From ca0024988caefc33b4e353db16227a6ef3b7e471 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 28 Apr 2024 14:37:31 +0800 Subject: [PATCH 168/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E6=A8=A1=E5=9E=8Benum=E7=BB=9F=E4=B8=80=E4=BA=A4=20model?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/chatqianwen/QianWenChatClient.java | 2 +- .../ai/chatqianwen/QianWenChatModal.java | 11 +++++++++- .../ai/chatxinghuo/XingHuoChatClient.java | 2 +- .../ai/chatxinghuo/XingHuoChatModel.java | 15 ++++++++++--- .../ai/chatyiyan/YiYanChatModel.java | 10 ++++++++- .../ai/config/YudaoAiAutoConfiguration.java | 21 +++++++++++++++++-- .../ai/config/YudaoAiProperties.java | 19 ++++++++++++++--- 7 files changed, 68 insertions(+), 12 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java index be8648350..e18ebe036 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java @@ -100,7 +100,7 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient { messageList.add(message); }); return QwenParam.builder() - .model(qianWenApi.getQianWenChatModal().getValue()) + .model(qianWenApi.getQianWenChatModal().getModel()) .prompt(prompt.getContents()) .messages(messageList) .maxTokens(chatOptions.getMaxTokens()) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatModal.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatModal.java index 96646233a..7fd9411bf 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatModal.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatModal.java @@ -34,5 +34,14 @@ public enum QianWenChatModal { private String name; - private String value; + private String model; + + public static QianWenChatModal valueOfModel(String model) { + for (QianWenChatModal itemEnum : QianWenChatModal.values()) { + if (itemEnum.getModel().equals(model)) { + return itemEnum; + } + } + throw new IllegalArgumentException("Invalid MessageType value: " + model); + } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java index c257203b1..90ae6dfee 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java @@ -114,7 +114,7 @@ public class XingHuoChatClient implements ChatClient, StreamingChatClient { // 创建 params XingHuoChatCompletionRequest.Parameter.Chat chatParameter = new XingHuoChatCompletionRequest.Parameter.Chat(); BeanUtil.copyProperties(xingHuoOptions, chatParameter); - chatParameter.setDomain(xingHuoOptions.getChatModel().getValue()); + chatParameter.setDomain(xingHuoOptions.getChatModel().getModel()); XingHuoChatCompletionRequest.Parameter parameter = new XingHuoChatCompletionRequest.Parameter().setChat(chatParameter); // 创建 payload text 信息 List texts = prompt.getInstructions().stream().map(message -> { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatModel.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatModel.java index e00a622b0..5be9f40a9 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatModel.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatModel.java @@ -30,15 +30,24 @@ public enum XingHuoChatModel { ; - XingHuoChatModel(String name, String value, String uri) { + XingHuoChatModel(String name, String model, String uri) { this.name = name; - this.value = value; + this.model = model; this.uri = uri; } private String name; - private String value; + private String model; private String uri; + + public static XingHuoChatModel valueOfModel(String model) { + for (XingHuoChatModel itemEnum : XingHuoChatModel.values()) { + if (itemEnum.getModel().equals(model)) { + return itemEnum; + } + } + throw new IllegalArgumentException("Invalid MessageType value: " + model); + } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatModel.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatModel.java index b901a4dc7..4c8b3aa85 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatModel.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatModel.java @@ -25,8 +25,16 @@ public enum YiYanChatModel { ; - private String value; + private String model; private String uri; + public static YiYanChatModel valueOfModel(String model) { + for (YiYanChatModel itemEnum : YiYanChatModel.values()) { + if (itemEnum.getModel().equals(model)) { + return itemEnum; + } + } + throw new IllegalArgumentException("Invalid MessageType value: " + model); + } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index b9be65407..385de4cf0 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -10,6 +10,9 @@ import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoApi; import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatClient; import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanOptions; import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanApi; +import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageApi; +import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageClient; +import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageOptions; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -32,7 +35,7 @@ public class YudaoAiAutoConfiguration { YudaoAiProperties.XingHuoProperties xingHuoProperties = yudaoAiProperties.getXinghuo(); // 转换配置 XingHuoOptions xingHuoOptions = new XingHuoOptions(); - xingHuoOptions.setChatModel(xingHuoProperties.getChatModel()); + xingHuoOptions.setChatModel(xingHuoProperties.getModel()); xingHuoOptions.setTopK(xingHuoProperties.getTopK()); xingHuoOptions.setTemperature(xingHuoProperties.getTemperature()); xingHuoOptions.setMaxTokens(xingHuoProperties.getMaxTokens()); @@ -79,10 +82,24 @@ public class YudaoAiAutoConfiguration { new YiYanApi( yiYanProperties.getAppKey(), yiYanProperties.getSecretKey(), - yiYanProperties.getChatModel(), + yiYanProperties.getModel(), yiYanProperties.getRefreshTokenSecondTime() ), yiYanOptions ); } + + + @Bean + @ConditionalOnProperty(value = "yudao.ai.openAiImage.enable", havingValue = "true") + public OpenAiImageClient openAiImageClient(YudaoAiProperties yudaoAiProperties) { + YudaoAiProperties.OpenAiImageProperties openAiImageProperties = yudaoAiProperties.getOpenAiImage(); + // 创建 client + return new OpenAiImageClient( + new OpenAiImageApi(openAiImageProperties.getApiKey()), + new OpenAiImageOptions() + .setModel(openAiImageProperties.getModel()) + .setResponseFormat(OpenAiImageOptions.ResponseFormatEnum.URL.getValue()) + ); + } } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java index d638a2b06..5ec1a9b43 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.ai.config; import cn.iocoder.yudao.framework.ai.AiPlatformEnum; import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel; import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel; +import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageModelEnum; import lombok.Data; import lombok.experimental.Accessors; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -23,6 +24,7 @@ public class YudaoAiProperties { private QianWenProperties qianwen; private XingHuoProperties xinghuo; private YiYanProperties yiyan; + private OpenAiImageProperties openAiImage; @Data @Accessors(chain = true) @@ -64,7 +66,7 @@ public class YudaoAiProperties { private String appId; private String appKey; private String secretKey; - private XingHuoChatModel chatModel; + private XingHuoChatModel model; } @Data @@ -81,12 +83,23 @@ public class YudaoAiProperties { /** * 模型 */ - private YiYanChatModel chatModel = YiYanChatModel.ERNIE4_3_5_8K; + private YiYanChatModel model = YiYanChatModel.ERNIE4_3_5_8K; /** * token 刷新时间(默认 86400 = 24小时) */ private int refreshTokenSecondTime = 86400; + } - private YiYanChatModel model; + @Data + @Accessors(chain = true) + public static class OpenAiImageProperties { + /** + * api key + */ + private String apiKey; + /** + * 模型 + */ + private OpenAiImageModelEnum model = OpenAiImageModelEnum.DALL_E_2; } } From 7d3ed1fef37863419d75d33783d3a34717c0786e Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 28 Apr 2024 14:38:07 +0800 Subject: [PATCH 169/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0open=20ai=20image=20=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/imageopenai/OpenAiImageModelEnum.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageModelEnum.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageModelEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageModelEnum.java new file mode 100644 index 000000000..919dd11d6 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageModelEnum.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.framework.ai.imageopenai; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * open ai + * + * @author fansili + * @time 2024/4/28 14:21 + * @since 1.0 + */ +@AllArgsConstructor +@Getter +public enum OpenAiImageModelEnum { + + DALL_E_2("dall-e-2", "dall-e-2"), + + DALL_E_3("dall-e-3", "dall-e-3") + + ; + + private String model; + + private String name; + + public static OpenAiImageModelEnum valueOfModel(String model) { + for (OpenAiImageModelEnum itemEnum : OpenAiImageModelEnum.values()) { + if (itemEnum.getModel().equals(model)) { + return itemEnum; + } + } + throw new IllegalArgumentException("Invalid MessageType value: " + model); + } +} From 307e08435dc7d0a5d6a8ebd821a9488aa32069ec Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 28 Apr 2024 14:38:25 +0800 Subject: [PATCH 170/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E8=B0=83=E6=95=B4imageSize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/framework/ai/imageopenai/OpenAiImageOptions.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java index c80396521..124f96907 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java @@ -22,7 +22,7 @@ public class OpenAiImageOptions implements ImageOptions { // 可选字段,默认为dall-e-2 // 指定用于生成图像的模型名称。 - private String model = "dall-e-2"; + private OpenAiImageModelEnum model = OpenAiImageModelEnum.DALL_E_2; // 可选字段,默认为1 // 生成图像的数量,必须在1到10之间。对于dall-e-3模型,目前仅支持n=1。 @@ -38,7 +38,7 @@ public class OpenAiImageOptions implements ImageOptions { // 可选字段,默认为1024x1024 // 生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。 - private String imageSize = "1024x1024"; + private String size = "1024x1024"; // 可选字段,默认为vivid // 图像生成的风格。可为vivid(生动)或natural(自然)。vivid会使模型偏向生成超现实和戏剧性的图像,而natural则会让模型产出更自然、不那么超现实的图像。该参数仅对dall-e-3模型有效。 @@ -73,7 +73,7 @@ public class OpenAiImageOptions implements ImageOptions { @Override public String getModel() { - return this.model; + return this.model.getModel(); } @Override From 844ae285e1a07e14c8bf37ffa0494cab1c98ec14 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 28 Apr 2024 16:29:59 +0800 Subject: [PATCH 171/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91ope?= =?UTF-8?q?nai=20image=20=E5=A2=9E=E5=8A=A0=20style=20=E7=94=9F=E6=88=90?= =?UTF-8?q?=E9=A3=8E=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iocoder/yudao/framework/ai/config/YudaoAiProperties.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java index 5ec1a9b43..79c1ff229 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.ai.AiPlatformEnum; import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel; import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageModelEnum; +import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageStyleEnum; import lombok.Data; import lombok.experimental.Accessors; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -101,5 +102,9 @@ public class YudaoAiProperties { * 模型 */ private OpenAiImageModelEnum model = OpenAiImageModelEnum.DALL_E_2; + /** + * 风格 + */ + private OpenAiImageStyleEnum style = OpenAiImageStyleEnum.VIVID; } } From 7467c241f360eaeeaddf340991ab747409c30a80 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 28 Apr 2024 16:33:45 +0800 Subject: [PATCH 172/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91aiI?= =?UTF-8?q?mage=20=E5=A2=9E=E5=8A=A0=20dall-e-2=E3=80=81dall-e-3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/AiImageController.java | 2 +- .../{AiDrawingImageDO.java => AiImageDO.java} | 13 +++++- .../yudao/module/ai/mapper/AiImageMapper.java | 20 +++++++++ .../ai/service/impl/AiImageServiceImpl.java | 45 ++++++++++++++++++- .../module/ai/vo/AiImageDallDrawingReq.java | 9 ++++ 5 files changed, 85 insertions(+), 4 deletions(-) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/{AiDrawingImageDO.java => AiImageDO.java} (66%) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiImageMapper.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java index dad0d00f4..f4a20e5fa 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java @@ -34,6 +34,6 @@ public class AiImageController { public SseEmitter dallDrawing(@Validated @ModelAttribute AiImageDallDrawingReq req) { Utf8SseEmitter sseEmitter = new Utf8SseEmitter(); aiImageService.dallDrawing(req, sseEmitter); - return null; + return sseEmitter; } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiDrawingImageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiImageDO.java similarity index 66% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiDrawingImageDO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiImageDO.java index 87d885deb..c83cdc742 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiDrawingImageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiImageDO.java @@ -17,15 +17,24 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -@TableName("ai_drawing_image") -public class AiDrawingImageDO extends BaseDO { +@TableName("ai_image") +public class AiImageDO extends BaseDO { @TableId(type = IdType.AUTO) private Long id; + @Schema(description = "用户id") + private Long userId; + @Schema(description = "提示词") private String prompt; + @Schema(description = "模型") + private String modal; + + @Schema(description = "生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。") + private String size; + @Schema(description = "绘画状态:提交、排队、绘画中、绘画完成、绘画失败") private String drawingStatus; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiImageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiImageMapper.java new file mode 100644 index 000000000..42cde4c58 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiImageMapper.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.ai.mapper; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.ai.dal.dataobject.AiImageDO; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Repository; + +/** + * ai image + * + * @author fansili + * @time 2024/4/28 14:01 + * @since 1.0 + */ +@Repository +@Mapper +public interface AiImageMapper extends BaseMapperX { + + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java index 2221ae3be..cfa1bf4b8 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java @@ -1,12 +1,25 @@ package cn.iocoder.yudao.module.ai.service.impl; +import cn.iocoder.yudao.framework.ai.image.Image; +import cn.iocoder.yudao.framework.ai.image.ImageGeneration; +import cn.iocoder.yudao.framework.ai.image.ImagePrompt; +import cn.iocoder.yudao.framework.ai.image.ImageResponse; +import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageClient; +import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageModelEnum; +import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageOptions; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; +import cn.iocoder.yudao.module.ai.dal.dataobject.AiImageDO; +import cn.iocoder.yudao.module.ai.mapper.AiImageMapper; import cn.iocoder.yudao.module.ai.service.AiImageService; import cn.iocoder.yudao.module.ai.vo.AiImageDallDrawingReq; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.http.MediaType; import org.springframework.stereotype.Service; +import java.io.IOException; + /** * ai 作图 * @@ -19,9 +32,39 @@ import org.springframework.stereotype.Service; @Slf4j public class AiImageServiceImpl implements AiImageService { + private final AiImageMapper aiImageMapper; + private final OpenAiImageClient openAiImageClient; @Override public void dallDrawing(AiImageDallDrawingReq req, Utf8SseEmitter sseEmitter) { - + // 获取 model + OpenAiImageModelEnum openAiImageModelEnum = OpenAiImageModelEnum.valueOfModel(req.getModal()); + // + OpenAiImageOptions openAiImageOptions = new OpenAiImageOptions(); + openAiImageOptions.setModel(openAiImageModelEnum); + ImageResponse imageResponse = openAiImageClient.call(new ImagePrompt(req.getPrompt(), openAiImageOptions)); + // 发送 + ImageGeneration imageGeneration = imageResponse.getResult(); + try { + sseEmitter.send(imageGeneration, MediaType.APPLICATION_JSON); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + // 发送 complete + sseEmitter.complete(); + } + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + // + // 保存数据库 + Image output = imageGeneration.getOutput(); + String imageUrl = output.getUrl(); + AiImageDO aiImageDO = new AiImageDO(); + aiImageDO.setId(null); + aiImageDO.setPrompt(req.getPrompt()); + aiImageDO.setSize(req.getSize()); + aiImageDO.setModal(req.getModal()); + aiImageDO.setUserId(loginUserId); + aiImageDO.setDrawingImageUrl(imageUrl); + aiImageMapper.insert(aiImageDO); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageDallDrawingReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageDallDrawingReq.java index e640e818a..c52589c8f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageDallDrawingReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageDallDrawingReq.java @@ -19,4 +19,13 @@ public class AiImageDallDrawingReq { @Schema(description = "提示词") @NotNull(message = "提示词不能为空!") private String prompt; + + @Schema(description = "模型") + @NotNull(message = "模型不能为空") + private String modal; + + @Schema(description = "生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。") + @NotNull(message = "size不能为空!") + private String size; + } From 330696fb902725adabdf167b437c58234777efc9 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 28 Apr 2024 16:34:55 +0800 Subject: [PATCH 173/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91aut?= =?UTF-8?q?oconfig=E8=87=AA=E5=8A=A8=E9=85=8D=E7=BD=AE=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20style=20=E9=80=82=E9=85=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/config/YudaoAiAutoConfiguration.java | 1 + .../ai/imageopenai/OpenAiImageStyleEnum.java | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageStyleEnum.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index 385de4cf0..b265f6814 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -100,6 +100,7 @@ public class YudaoAiAutoConfiguration { new OpenAiImageOptions() .setModel(openAiImageProperties.getModel()) .setResponseFormat(OpenAiImageOptions.ResponseFormatEnum.URL.getValue()) + .setStyle(openAiImageProperties.getStyle()) ); } } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageStyleEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageStyleEnum.java new file mode 100644 index 000000000..e586420a5 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageStyleEnum.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.framework.ai.imageopenai; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * open ai image style + * + * @author fansili + * @time 2024/4/28 16:15 + * @since 1.0 + */ +@AllArgsConstructor +@Getter +public enum OpenAiImageStyleEnum { + + // 图像生成的风格。可为vivid(生动)或 natural(自然)。vivid会使模型偏向生成超现实和戏剧性的图像,而natural则会让模型产出更自然、不那么超现实的图像。该参数仅对dall-e-3模型有效。 + + VIVID("vivid", "生动"), + NATURAL("natural", "自然"), + + ; + + private String style; + + private String name; + + public static OpenAiImageStyleEnum valueOfStyle(String style) { + for (OpenAiImageStyleEnum itemEnum : OpenAiImageStyleEnum.values()) { + if (itemEnum.getStyle().equals(style)) { + return itemEnum; + } + } + throw new IllegalArgumentException("Invalid MessageType value: " + style); + } +} From 2cbb6ac8d588805490a52f401d111e2b20bd326b Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 28 Apr 2024 16:36:35 +0800 Subject: [PATCH 174/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E4=BF=AE=E5=A4=8DimageSize=E4=B8=8D=E7=94=9F=E6=95=88=E9=97=AE?= =?UTF-8?q?=E9=A2=98=EF=BC=8C=E5=A2=9E=E5=8A=A0modal=E3=80=81style?= =?UTF-8?q?=E3=80=81size=20=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/imageopenai/OpenAiImageClient.java | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageClient.java index a1083cd18..c5ae757d1 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageClient.java @@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.ai.image.*; import cn.iocoder.yudao.framework.ai.imageopenai.api.OpenAiImageRequest; import cn.iocoder.yudao.framework.ai.imageopenai.api.OpenAiImageResponse; import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; import org.springframework.retry.RetryCallback; import org.springframework.retry.RetryContext; import org.springframework.retry.RetryListener; @@ -58,21 +59,14 @@ public class OpenAiImageClient implements ImageClient { @Override public ImageResponse call(ImagePrompt imagePrompt) { return this.retryTemplate.execute(ctx -> { - // 检查是否配置了 OpenAiImageOptions - if (defaultImageOptions == null && imagePrompt.getOptions() == null) { - throw new ChatException("OpenAiImageOptions 未配置参数!"); - } - // 优先使用 request 中的 ImageOptions - ImageOptions useImageOptions = imagePrompt.getOptions() == null ? defaultImageOptions : imagePrompt.getOptions(); - if (!(useImageOptions instanceof OpenAiImageOptions)) { - throw new ChatException("配置信息不正确,传入的必须是 OpenAiImageOptions!"); - } - // 转换 OpenAiImageOptions - OpenAiImageOptions openAiImageOptions = (OpenAiImageOptions) useImageOptions; + OpenAiImageOptions openAiImageOptions = getOpenAiImageOptions(imagePrompt); // 创建请求 OpenAiImageRequest request = new OpenAiImageRequest(); BeanUtil.copyProperties(openAiImageOptions, request); request.setPrompt(imagePrompt.getInstructions().get(0).getText()); + request.setModel(openAiImageOptions.getModel()); + request.setStyle(openAiImageOptions.getStyle().getStyle()); + request.setSize(openAiImageOptions.getSize()); // 发送请求 OpenAiImageResponse response = openAiImageApi.createImage(request); return new ImageResponse(response.getData().stream().map(res -> { @@ -83,4 +77,19 @@ public class OpenAiImageClient implements ImageClient { }); } + private @NotNull OpenAiImageOptions getOpenAiImageOptions(ImagePrompt imagePrompt) { + // 检查是否配置了 OpenAiImageOptions + if (defaultImageOptions == null && imagePrompt.getOptions() == null) { + throw new ChatException("OpenAiImageOptions 未配置参数!"); + } + // 优先使用 request 中的 ImageOptions + ImageOptions useImageOptions = imagePrompt.getOptions() == null ? defaultImageOptions : imagePrompt.getOptions(); + if (!(useImageOptions instanceof OpenAiImageOptions)) { + throw new ChatException("配置信息不正确,传入的必须是 OpenAiImageOptions!"); + } + // 转换 OpenAiImageOptions + OpenAiImageOptions openAiImageOptions = (OpenAiImageOptions) useImageOptions; + return openAiImageOptions; + } + } From 067fc5814784036dda04d04ff30aa5826249a01a Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 28 Apr 2024 16:37:27 +0800 Subject: [PATCH 175/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E8=A7=A3=E5=86=B3=E8=B0=83=E7=94=A8openai=20image=20=E7=94=9F?= =?UTF-8?q?=E6=88=90=EF=BC=8Cuser=E4=B8=8D=E8=83=BD=E4=B8=BA=E7=A9=BA?= =?UTF-8?q?=E6=83=85=E5=86=B5=EF=BC=8C=E5=9B=BA=E5=AE=9A=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?UID=20=E5=AE=A2=E6=88=B7=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/framework/ai/imageopenai/OpenAiImageOptions.java | 4 ++-- .../framework/ai/imageopenai/api/OpenAiImageRequest.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java index 124f96907..fd06fbe76 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java @@ -42,11 +42,11 @@ public class OpenAiImageOptions implements ImageOptions { // 可选字段,默认为vivid // 图像生成的风格。可为vivid(生动)或natural(自然)。vivid会使模型偏向生成超现实和戏剧性的图像,而natural则会让模型产出更自然、不那么超现实的图像。该参数仅对dall-e-3模型有效。 - private String style = "vivid"; + private OpenAiImageStyleEnum style = OpenAiImageStyleEnum.VIVID; // 可选字段 // 代表您的终端用户的唯一标识符,有助于OpenAI监控并检测滥用行为。了解更多信息请参考官方文档。 - private String endUserId; + private String endUserId = "UID123456"; @Getter public enum ResponseFormatEnum { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageRequest.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageRequest.java index 865dbd136..44ee174a2 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageRequest.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageRequest.java @@ -43,7 +43,7 @@ public class OpenAiImageRequest { // 可选字段,默认为1024x1024 // 生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。 @JsonProperty("size") - private String imageSize = "1024x1024"; + private String size = "1024x1024"; // 可选字段,默认为vivid // 图像生成的风格。可为vivid(生动)或natural(自然)。vivid会使模型偏向生成超现实和戏剧性的图像,而natural则会让模型产出更自然、不那么超现实的图像。该参数仅对dall-e-3模型有效。 @@ -53,6 +53,6 @@ public class OpenAiImageRequest { // 可选字段 // 代表您的终端用户的唯一标识符,有助于OpenAI监控并检测滥用行为。了解更多信息请参考官方文档。 @JsonProperty("user") - private String endUserId; + private String endUserId = "UID123123"; } From 9ff36e51676135f16ec0e3d6bd6f58e5d55fe5fc Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 28 Apr 2024 16:38:23 +0800 Subject: [PATCH 176/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91ope?= =?UTF-8?q?n=20ai=20image=20=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/framework/ai/openAiImage/OpenAiImageClientTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java index c5861f57b..b85ec8841 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java @@ -36,7 +36,7 @@ public class OpenAiImageClientTests { @Test public void callTest() { - ImageResponse call = openAiImageClient.call(new ImagePrompt("我和我的小狗,一起在北极和企鹅玩排球。")); + ImageResponse call = openAiImageClient.call(new ImagePrompt("中国长城!")); System.err.println("url: " + call.getResult().getOutput().getUrl()); System.err.println("base64: " + call.getResult().getOutput().getB64Json()); From 401a83b7a96d577d66b6f622e8ca833513a1ee8a Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 28 Apr 2024 16:38:42 +0800 Subject: [PATCH 177/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20login.http?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/http/login.http | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/login.http diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/login.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/login.http new file mode 100644 index 000000000..aaf282540 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/login.http @@ -0,0 +1,18 @@ + + +### 登录 + +POST {{baseUrl}}/admin-api/system/auth/login +Content-Type: application/json +tenant-id: 1 + +{ + "username": "admin", + "password": "123456", + "captchaVerification": "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==", + "socialCode": "1024", + "socialState": "9b2ffbc1-7425-4155-9894-9d5c08541d62", + "socialCodeValid": true +} + + From c6a029ff8d818271404fea5a412a986308d39568 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 28 Apr 2024 16:38:59 +0800 Subject: [PATCH 178/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=20open=20ai=20image?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao-module-ai-biz/src/main/resources/http/image.http | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http new file mode 100644 index 000000000..069ebf1ba --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http @@ -0,0 +1,5 @@ + +### chat call +GET {{baseUrl}}/ai/image/dallDrawing?modal=dall-e-2&size=256x256&prompt=中国长城 +Authorization: {{token}} + From ad46eb57a5463cfc61ac368fbbc8a3efaf5913ec Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 28 Apr 2024 16:40:42 +0800 Subject: [PATCH 179/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0open=20ai=20dall=5Fe=5F2=20=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-server/src/main/resources/application-local.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 4ca742981..32ab21c73 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -255,6 +255,11 @@ yudao: secretKey: R9mYF9dl9KASgi5RUq0FQt3wRisSnOcK refreshTokenSecondTime: 86400 chatModel: ERNIE4_3_5_8K + openAiImage: + enable: true + api-key: ${OPEN_AI_KEY} + model: dall_e_2 + style: vivid captcha: enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试; From 0311c77e7b9a9b31aec1612013e8fae1c7aca5a0 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 28 Apr 2024 17:25:47 +0800 Subject: [PATCH 180/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E5=A4=84=E7=90=86=20openAi=20image=20=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ai/imageopenai/OpenAiImageClient.java | 6 ++++++ .../ai/imageopenai/api/OpenAiImageResponse.java | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageClient.java index c5ae757d1..4dd536f99 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageClient.java @@ -2,9 +2,11 @@ package cn.iocoder.yudao.framework.ai.imageopenai; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.codec.Base64; +import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; import cn.iocoder.yudao.framework.ai.chat.ChatException; import cn.iocoder.yudao.framework.ai.chatyiyan.exception.YiYanApiException; +import cn.iocoder.yudao.framework.ai.exception.AiException; import cn.iocoder.yudao.framework.ai.image.*; import cn.iocoder.yudao.framework.ai.imageopenai.api.OpenAiImageRequest; import cn.iocoder.yudao.framework.ai.imageopenai.api.OpenAiImageResponse; @@ -69,6 +71,10 @@ public class OpenAiImageClient implements ImageClient { request.setSize(openAiImageOptions.getSize()); // 发送请求 OpenAiImageResponse response = openAiImageApi.createImage(request); + if (response.getError() != null && !StrUtil.isBlank(response.getError().getMessage())) { + // code 错误没有编码,就先根据 message 来进行判断 + throw new AiException("openAi 图片生成失败! " + response.getError().getMessage()); + } return new ImageResponse(response.getData().stream().map(res -> { byte[] bytes = HttpUtil.downloadBytes(res.getUrl()); String base64 = Base64.encode(bytes); diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageResponse.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageResponse.java index 1f4ab6152..02698963e 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageResponse.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageResponse.java @@ -17,6 +17,7 @@ public class OpenAiImageResponse { private long created; private List data; + private Error error; @Data @Accessors(chain = true) @@ -26,4 +27,13 @@ public class OpenAiImageResponse { private String b64_json; } + + @Data + @Accessors(chain = true) + public static class Error { + private String code; + private String message; + private String param; + private String type; + } } From 99d477ac0a4196eaa37cf5a6f6cfe12a862359be Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 28 Apr 2024 17:26:31 +0800 Subject: [PATCH 181/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91?= =?UTF-8?q?=E5=9B=BE=E7=89=87=E7=BB=98=E7=94=BB=E5=A2=9E=E5=8A=A0=20?= =?UTF-8?q?=E7=BB=98=E7=94=BB=E5=A4=B1=E8=B4=A5=E7=8A=B6=E6=80=81=EF=BC=8C?= =?UTF-8?q?=E5=B9=B6=E4=BF=9D=E5=AD=98=E7=BB=98=E7=94=BB=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=EF=BC=8C=E5=90=8C=E6=97=B6=E5=8F=AF=E4=BB=A5?= =?UTF-8?q?=E5=B0=86=E9=94=99=E8=AF=AF=E4=BF=A1=E6=81=AF=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E7=BB=99=E5=89=8D=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/enums/AiChatDrawingStatusEnum.java | 35 ++++++++++++++++ .../module/ai/dal/dataobject/AiImageDO.java | 3 ++ .../ai/service/impl/AiImageServiceImpl.java | 40 ++++++++++++++----- .../module/ai/vo/AiImageDallDrawingReq.java | 4 ++ 4 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatDrawingStatusEnum.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatDrawingStatusEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatDrawingStatusEnum.java new file mode 100644 index 000000000..fef37e13d --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatDrawingStatusEnum.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.ai.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * ai绘画状态 + * + * @author fansili + * @time 2024/4/28 17:05 + * @since 1.0 + */ +@AllArgsConstructor +@Getter +public enum AiChatDrawingStatusEnum { + + COMPLETE("complete", "完成"), + FAIL("fail", "失败"), + + ; + + private String status; + + private String name; + + + public static AiChatDrawingStatusEnum valueOfStatus(String status) { + for (AiChatDrawingStatusEnum itemEnum : AiChatDrawingStatusEnum.values()) { + if (itemEnum.getStatus().equals(status)) { + return itemEnum; + } + } + throw new IllegalArgumentException("Invalid MessageType value: " + status); + } +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiImageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiImageDO.java index c83cdc742..cba6e2800 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiImageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiImageDO.java @@ -41,5 +41,8 @@ public class AiImageDO extends BaseDO { @Schema(description = "绘画图片地址") private String drawingImageUrl; + @Schema(description = "绘画错误信息") + private String drawingError; + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java index cfa1bf4b8..cdb95c78c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java @@ -1,15 +1,17 @@ package cn.iocoder.yudao.module.ai.service.impl; -import cn.iocoder.yudao.framework.ai.image.Image; +import cn.iocoder.yudao.framework.ai.exception.AiException; import cn.iocoder.yudao.framework.ai.image.ImageGeneration; import cn.iocoder.yudao.framework.ai.image.ImagePrompt; import cn.iocoder.yudao.framework.ai.image.ImageResponse; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageClient; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageModelEnum; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageOptions; +import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageStyleEnum; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; import cn.iocoder.yudao.module.ai.dal.dataobject.AiImageDO; +import cn.iocoder.yudao.module.ai.enums.AiChatDrawingStatusEnum; import cn.iocoder.yudao.module.ai.mapper.AiImageMapper; import cn.iocoder.yudao.module.ai.service.AiImageService; import cn.iocoder.yudao.module.ai.vo.AiImageDallDrawingReq; @@ -39,25 +41,43 @@ public class AiImageServiceImpl implements AiImageService { public void dallDrawing(AiImageDallDrawingReq req, Utf8SseEmitter sseEmitter) { // 获取 model OpenAiImageModelEnum openAiImageModelEnum = OpenAiImageModelEnum.valueOfModel(req.getModal()); + OpenAiImageStyleEnum openAiImageStyleEnum = OpenAiImageStyleEnum.valueOfStyle(req.getStyle()); // OpenAiImageOptions openAiImageOptions = new OpenAiImageOptions(); openAiImageOptions.setModel(openAiImageModelEnum); - ImageResponse imageResponse = openAiImageClient.call(new ImagePrompt(req.getPrompt(), openAiImageOptions)); - // 发送 - ImageGeneration imageGeneration = imageResponse.getResult(); + openAiImageOptions.setStyle(openAiImageStyleEnum); + openAiImageOptions.setSize(req.getSize()); + ImageResponse imageResponse; try { - sseEmitter.send(imageGeneration, MediaType.APPLICATION_JSON); + imageResponse = openAiImageClient.call(new ImagePrompt(req.getPrompt(), openAiImageOptions)); + // 发送 + ImageGeneration imageGeneration = imageResponse.getResult(); + // 发送信息 + sendSseEmitter(sseEmitter, imageGeneration); + // 保存数据库 + doSave(req, imageGeneration.getOutput().getUrl(), AiChatDrawingStatusEnum.COMPLETE, null); + } catch (AiException aiException) { + // 保存数据库 + doSave(req, null, AiChatDrawingStatusEnum.FAIL, aiException.getMessage()); + // 发送错误信息 + sendSseEmitter(sseEmitter, aiException.getMessage()); + } + } + + private static void sendSseEmitter(Utf8SseEmitter sseEmitter, Object object) { + try { + sseEmitter.send(object, MediaType.APPLICATION_JSON); } catch (IOException e) { throw new RuntimeException(e); } finally { // 发送 complete sseEmitter.complete(); } - Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); - // + } + + private void doSave(AiImageDallDrawingReq req, String imageUrl, AiChatDrawingStatusEnum drawingStatusEnum, String drawingError) { // 保存数据库 - Image output = imageGeneration.getOutput(); - String imageUrl = output.getUrl(); + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); AiImageDO aiImageDO = new AiImageDO(); aiImageDO.setId(null); aiImageDO.setPrompt(req.getPrompt()); @@ -65,6 +85,8 @@ public class AiImageServiceImpl implements AiImageService { aiImageDO.setModal(req.getModal()); aiImageDO.setUserId(loginUserId); aiImageDO.setDrawingImageUrl(imageUrl); + aiImageDO.setDrawingStatus(drawingStatusEnum.getStatus()); + aiImageDO.setDrawingError(drawingError); aiImageMapper.insert(aiImageDO); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageDallDrawingReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageDallDrawingReq.java index c52589c8f..fb62f2082 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageDallDrawingReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageDallDrawingReq.java @@ -24,6 +24,10 @@ public class AiImageDallDrawingReq { @NotNull(message = "模型不能为空") private String modal; + @Schema(description = "图像生成的风格。可为vivid(生动)或natural(自然)") + @NotNull(message = "图像生成的风格,不能为空!") + private String style; + @Schema(description = "生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。") @NotNull(message = "size不能为空!") private String size; From 198dae62c007f4240321cf373fe8195049e2ff96 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 28 Apr 2024 17:41:49 +0800 Subject: [PATCH 182/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E5=A4=84=E7=90=86=20CommonResult=20Void=20=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/controller/AiChatModalController.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java index 7bf12d15c..9530f23b9 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java @@ -38,14 +38,14 @@ public class AiChatModalController { @Operation(summary = "ai模型 - 添加") @PutMapping("/modal") - public CommonResult add(@RequestBody @Validated AiChatModalAddReq req) { + public CommonResult add(@RequestBody @Validated AiChatModalAddReq req) { aiChatModalService.add(req); return CommonResult.success(null); } @Operation(summary = "ai模型 - 模型照片上传") @PostMapping("/modal/{id}/updateImage") - public CommonResult updateImage(@PathVariable("id") Long id, + public CommonResult updateImage(@PathVariable("id") Long id, MultipartFile file) { // todo yunai 文件上传这里放哪里 return CommonResult.success(null); @@ -53,7 +53,7 @@ public class AiChatModalController { @Operation(summary = "ai模型 - 修改") @PostMapping("/modal/{id}") - public CommonResult update(@PathVariable Long id, + public CommonResult update(@PathVariable Long id, @RequestBody @Validated AiChatModalAddReq req) { aiChatModalService.update(id, req); return CommonResult.success(null); @@ -61,7 +61,7 @@ public class AiChatModalController { @Operation(summary = "ai模型 - 删除") @DeleteMapping("/modal/{id}") - public CommonResult delete(@PathVariable Long id) { + public CommonResult delete(@PathVariable Long id) { aiChatModalService.delete(id); return CommonResult.success(null); } From d14c13b2fc4870fc244b22a2033d152fc0983c45 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 10:59:26 +0800 Subject: [PATCH 183/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91mid?= =?UTF-8?q?journey=20=E8=87=AA=E5=8A=A8=E9=85=8D=E7=BD=AE=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/config/YudaoAiAutoConfiguration.java | 53 +++++++++++++++++++ .../ai/config/YudaoAiProperties.java | 26 +++++++++ .../src/main/resources/application-local.yaml | 6 ++- 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index b265f6814..fa69ee56a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.ai.config; +import cn.hutool.core.io.IoUtil; import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient; import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatModal; import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenOptions; @@ -13,10 +14,21 @@ import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanApi; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageApi; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageClient; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageOptions; +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; +import cn.iocoder.yudao.framework.ai.midjourney.api.MidjourneyInteractionsApi; +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyWebSocketStarter; +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener.MidjourneyMessageListener; +import org.jetbrains.annotations.NotNull; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; +import org.springframework.core.io.Resource; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; /** * ai 自动配置 @@ -103,4 +115,45 @@ public class YudaoAiAutoConfiguration { .setStyle(openAiImageProperties.getStyle()) ); } + + @Bean + @ConditionalOnProperty(value = "yudao.ai.midjourney.enable", havingValue = "true") + public MidjourneyWebSocketStarter midjourneyWebSocketStarter(ApplicationContext applicationContext, YudaoAiProperties yudaoAiProperties) { + // 获取 midjourneyProperties + YudaoAiProperties.MidjourneyProperties midjourneyProperties = yudaoAiProperties.getMidjourney(); + // 获取 midjourneyConfig + MidjourneyConfig midjourneyConfig = getMidjourneyConfig(applicationContext, midjourneyProperties); + // 创建 socket messageListener + MidjourneyMessageListener messageListener = new MidjourneyMessageListener(midjourneyConfig); + // 创建 MidjourneyWebSocketStarter + return new MidjourneyWebSocketStarter(midjourneyProperties.getWssUrl(), null, midjourneyConfig, messageListener); + } + + @Bean + @ConditionalOnProperty(value = "yudao.ai.midjourney.enable", havingValue = "true") + public MidjourneyInteractionsApi midjourneyInteractionsApi(ApplicationContext applicationContext, YudaoAiProperties yudaoAiProperties) { + // 获取 midjourneyConfig + MidjourneyConfig midjourneyConfig = getMidjourneyConfig(applicationContext, yudaoAiProperties.getMidjourney()); + // 创建 MidjourneyInteractionsApi + return new MidjourneyInteractionsApi(midjourneyConfig); + } + + + private static @NotNull MidjourneyConfig getMidjourneyConfig(ApplicationContext applicationContext, + YudaoAiProperties.MidjourneyProperties midjourneyProperties) { + Map requestTemplates = new HashMap<>(); + try { + Resource[] resources = applicationContext.getResources("classpath:http-body/*.json"); + for (var resource : resources) { + String filename = resource.getFilename(); + String params = IoUtil.readUtf8(resource.getInputStream()); + requestTemplates.put(filename.substring(0, filename.length() - 5), params); + } + } catch (IOException e) { + throw new IllegalArgumentException("Midjourney json模板初始化出错! " + e.getMessage()); + } + // 创建 midjourneyConfig + return new MidjourneyConfig(midjourneyProperties.getToken(), + midjourneyProperties.getGuildId(), midjourneyProperties.getChannelId(), requestTemplates); + } } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java index 79c1ff229..f9dcae04a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java @@ -26,6 +26,7 @@ public class YudaoAiProperties { private XingHuoProperties xinghuo; private YiYanProperties yiyan; private OpenAiImageProperties openAiImage; + private MidjourneyProperties midjourney; @Data @Accessors(chain = true) @@ -94,6 +95,8 @@ public class YudaoAiProperties { @Data @Accessors(chain = true) public static class OpenAiImageProperties { + private boolean enable = false; + /** * api key */ @@ -107,4 +110,27 @@ public class YudaoAiProperties { */ private OpenAiImageStyleEnum style = OpenAiImageStyleEnum.VIVID; } + + @Data + @Accessors(chain = true) + public static class MidjourneyProperties { + private boolean enable = false; + + /** + * socket 链接地址 + */ + private String wssUrl = "wss://gateway.discord.gg"; + /** + * token + */ + private String token; + /** + * 服务id + */ + private String guildId; + /** + * 频道id + */ + private String channelId; + } } diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 32ab21c73..ffc9970c9 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -260,7 +260,11 @@ yudao: api-key: ${OPEN_AI_KEY} model: dall_e_2 style: vivid - + midjourney: + enable: true + token: OTcyNzIxMzA0ODkxNDUzNDUw.G_vMOz.BO_Q0sXAD80u5ZKIHPNYDTRX_FgeKL3cKFc53I + guild-id: 1225608134878302329 + channel-id: 1225608134878302332 captcha: enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试; security: From f0fa0e210c83745fbc43a34f59fbbccda9178458 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 12:16:54 +0800 Subject: [PATCH 184/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91mj?= =?UTF-8?q?=20=E5=B0=81=E5=8F=B7=E8=BF=94=E5=9B=9E=E7=9A=84json=EF=BC=8C?= =?UTF-8?q?=E5=90=8E=E6=9C=9F=E6=9C=89=E6=97=B6=E9=97=B4=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mj服务器封号返回信息.json | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/mj服务器封号返回信息.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/mj服务器封号返回信息.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/mj服务器封号返回信息.json new file mode 100644 index 000000000..3b927bf3c --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/mj服务器封号返回信息.json @@ -0,0 +1,82 @@ +{ + "op": 0, + "s": 5, + "t": "MESSAGE_CREATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [], + "interaction_metadata": { + "user_id": "972721304891453450", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1225608134878302329" + }, + "id": "1234353096516173844", + "type": 2, + "user": { + "global_name": "tiger", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + }, + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "clan": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 64, + "type": 20, + "mention_roles": [], + "nonce": "1784794363249700864", + "application_id": "936929561302675456", + "edited_timestamp": null, + "content": "", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [], + "interaction": { + "name": "imagine", + "id": "1234353096516173844", + "type": 2, + "user": { + "global_name": "tiger", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "972721304891453450", + "avatar": "3646118d04fd12dfd301c4fd17afd801", + "username": "jverbalu4990", + "discriminator": "0" + } + }, + "position": 0, + "id": "1234353097535393822", + "embeds": [ + { + "content_scan_version": 0, + "color": 16711680, + "footer": { + "text": "/imagine 中国长城 --ar 1:1 --niji 6" + }, + "description": "You have been blocked from accessing Midjourney. This happens on repeated or serious ToS violations.", + "type": "rich", + "title": "Blocked" + } + ], + "channel_id": "1225608134878302332", + "timestamp": "2024-04-29T03:58:31.624000+00:00" + } +} \ No newline at end of file From a5023cda1d96428c8619f55f13f5ce9a22d8c2bc Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 13:52:49 +0800 Subject: [PATCH 185/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91mj?= =?UTF-8?q?=E6=95=8F=E6=84=9F=E8=AF=8D=E8=BF=94=E5=9B=9E=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=EF=BC=8C=E6=9C=89=E6=97=B6=E9=97=B4=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mj敏感词返回信息.json | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/mj敏感词返回信息.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/mj敏感词返回信息.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/mj敏感词返回信息.json new file mode 100644 index 000000000..9dceb9bf2 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/mj敏感词返回信息.json @@ -0,0 +1,94 @@ +{ + "op": 0, + "s": 5, + "t": "MESSAGE_CREATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [ + { + "components": [ + { + "custom_id": "MJ::Prompts::LLMComplaintSubmit::8d706b5c-36d9-4ef5-af2e-b778c876e39b", + "style": 2, + "label": "Notify developers", + "type": 2 + } + ], + "type": 1 + } + ], + "attachments": [], + "interaction_metadata": { + "user_id": "975372485971312700", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1234355413420347402" + }, + "id": "1234381275448479744", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + }, + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "clan": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 64, + "type": 20, + "mention_roles": [], + "nonce": "1784822542798630912", + "application_id": "936929561302675456", + "edited_timestamp": null, + "content": "", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [], + "interaction": { + "name": "imagine", + "id": "1234381275448479744", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + }, + "position": 0, + "id": "1234381284084809749", + "embeds": [ + { + "content_scan_version": 0, + "color": 16711680, + "footer": { + "text": "/imagine 性感车模,站在车上! --v 6" + }, + "description": "Sorry! Our AI moderator thinks this prompt is probably against our community standards.\n\nPlease review our current community standards:\n\n**ALLOWED**\n- Any image up to PG-13 rating involving fiction, fantasy, mythology.\n- Real images that may be seen as respectful or light-hearted parodies, satire, caricatures\n- Imaginary or exaggerated real-life scenarios, including absurd or humorous situations.\n\n**NOT ALLOWED**\n- Disrespectful, harmful, misleading public figures/events portrayals or potential to mislead.\n- Hate speech, explicit or real-world violence.\n- Nudity or unconsented overtly sexualized public figures.\n- Imagery that might be considered culturally insensitive\n\nThis AI system isn't perfect. If you find it rejecting something innocent please press the **Notify Developers** button and we will review it and try to further improve our performance. Thank you for your help!", + "type": "rich", + "title": "Banned prompt detected" + } + ], + "channel_id": "1234380679576424448", + "timestamp": "2024-04-29T05:50:31.821000+00:00" + } +} \ No newline at end of file From 24479dacfdc0065cace23f26179636023c9c27bf Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 14:11:03 +0800 Subject: [PATCH 186/684] =?UTF-8?q?=E3=80=90=E6=9B=B4=E6=96=B0=E3=80=91?= =?UTF-8?q?=E6=9B=B4=E6=96=B0mj=E7=94=9F=E6=88=90=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../imageGenerationProcess/1.json | 156 +++++++--- .../imageGenerationProcess/10.json | 216 +++++++------ .../imageGenerationProcess/11.json | 216 +++++++------ .../imageGenerationProcess/12.json | 285 +++++++++--------- .../imageGenerationProcess/2.json | 191 ++++++------ .../imageGenerationProcess/3.json | 190 ++++++------ .../imageGenerationProcess/4.json | 190 ++++++------ .../imageGenerationProcess/5.json | 190 ++++++------ .../imageGenerationProcess/6.json | 190 ++++++------ .../imageGenerationProcess/7.json | 190 ++++++------ .../imageGenerationProcess/8.json | 203 +++++++------ .../imageGenerationProcess/9.json | 216 +++++++------ 12 files changed, 1356 insertions(+), 1077 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/1.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/1.json index 156a89e68..3443d35b6 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/1.json +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/1.json @@ -1,41 +1,121 @@ { - "mention_everyone": false, - "pinned": false, - "components": [], - "attachments": [], - "author": { - "global_name": "JVerbalu", - "avatar_decoration_data": null, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - }, - "flags": 0, - "type": 0, - "mention_roles": [], - "nonce": "1225630680067604480", - "edited_timestamp": null, - "content": "南极应该是什么样子?", - "tts": false, - "referenced_message": null, - "mentions": [], - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", - "communication_disabled_until": null, - "roles": [], - "pending": false, + "op": 0, + "s": 17, + "t": "MESSAGE_CREATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [], + "interaction_metadata": { + "user_id": "975372485971312700", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1234355413420347402" + }, + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + }, + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "clan": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, "flags": 0, - "deaf": false, - "mute": false, - "avatar": null - }, - "guild_id": "1225608134878302329", - "id": "1225630681556586556", - "embeds": [], - "channel_id": "1225608134878302332", - "timestamp": "2024-04-05T02:18:45.600000+00:00" + "type": 20, + "mention_roles": [], + "nonce": "1784822781483888640", + "application_id": "936929561302675456", + "edited_timestamp": null, + "content": "**海贼王,在赶海! --v 6.0** - <@975372485971312700> (Waiting to start)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:07:43.807000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:09:06.489349+00:00", + "communication_disabled_until": null, + "roles": [ + "1234355760184561747" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "interaction": { + "name": "imagine", + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:07:43.807000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + }, + "guild_id": "1234355413420347402", + "position": 0, + "id": "1234381516130357379", + "embeds": [], + "channel_id": "1234380679576424448", + "timestamp": "2024-04-29T05:51:27.145000+00:00" + } } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/10.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/10.json index e17f83fea..f107ede24 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/10.json +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/10.json @@ -1,56 +1,107 @@ { - "mention_everyone": false, - "pinned": false, - "components": [], - "attachments": [ - { - "filename": "8f23f288-6028-468b-8056-1e4adef73985_grid_0.webp", - "size": 34624, - "content_type": "image/webp", - "width": 512, - "placeholder_version": 1, - "proxy_url": "https://media.discordapp.net/attachments/1225608134878302332/1225630835240210442/8f23f288-6028-468b-8056-1e4adef73985_grid_0.webp?ex=6621d4aa&is=660f5faa&hm=f58106ba5fa0ddf51abe68493cf460ccd70eb7ef379d2d3865d4b45e230c3037&", - "placeholder": "4CcODwJ/hotGl2iHd2iYd3h3d/kJyLQA", - "id": "1225630835240210442", - "url": "https://cdn.discordapp.com/attachments/1225608134878302332/1225630835240210442/8f23f288-6028-468b-8056-1e4adef73985_grid_0.webp?ex=6621d4aa&is=660f5faa&hm=f58106ba5fa0ddf51abe68493cf460ccd70eb7ef379d2d3865d4b45e230c3037&", - "height": 512 - } - ], - "interaction_metadata": { - "user_id": "972721304891453450", - "name": "imagine", - "authorizing_integration_owners": { - "0": "1225608134878302329" + "op": 0, + "s": 38, + "t": "MESSAGE_UPDATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [ + { + "filename": "5d32f4e8-8d2f-4bef-82d8-bf517e3c3660_grid_0.webp", + "size": 40906, + "content_type": "image/webp", + "width": 512, + "placeholder_version": 1, + "proxy_url": "https://media.discordapp.net/attachments/1234380679576424448/1234381954301038622/5d32f4e8-8d2f-4bef-82d8-bf517e3c3660_grid_0.webp?ex=66308747&is=662f35c7&hm=5cff8b62f6c174b45a80d096eefbea9bf791ccfb50f586734efadbd96b57a114&", + "placeholder": "W/gJHwiCN4VoaZZ4ePd3aIeFCJacgqAG", + "id": "1234381954301038622", + "url": "https://cdn.discordapp.com/attachments/1234380679576424448/1234381954301038622/5d32f4e8-8d2f-4bef-82d8-bf517e3c3660_grid_0.webp?ex=66308747&is=662f35c7&hm=5cff8b62f6c174b45a80d096eefbea9bf791ccfb50f586734efadbd96b57a114&", + "height": 512 + } + ], + "interaction_metadata": { + "user_id": "975372485971312700", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1234355413420347402" + }, + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } }, - "id": "1225630717426274377", - "type": 2 - }, - "author": { - "global_name": null, - "bot": true, - "avatar_decoration_data": null, - "public_flags": 589824, - "id": "936929561302675456", - "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", - "username": "Midjourney Bot", - "discriminator": "9282" - }, - "flags": 0, - "type": 20, - "mention_roles": [], - "application_id": "936929561302675456", - "edited_timestamp": "2024-04-05T02:19:22.200320+00:00", - "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (55%) (fast, stealth)", - "tts": false, - "webhook_id": "936929561302675456", - "mentions": [ - { - "global_name": "JVerbalu", + "author": { + "global_name": null, + "bot": true, "avatar_decoration_data": null, + "clan": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 20, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-29T05:53:11.587132+00:00", + "content": "**海贼王,在赶海! --v 6.0** - <@975372485971312700> (75%) (relaxed)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:07:43.807000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:09:06.489349+00:00", + "communication_disabled_until": null, + "roles": [ + "1234355760184561747" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "interaction": { + "name": "imagine", "member": { "premium_since": null, "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", + "joined_at": "2024-04-29T04:07:43.807000+00:00", "communication_disabled_until": null, "roles": [], "pending": false, @@ -59,57 +110,24 @@ "mute": false, "avatar": null }, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - } - ], - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:35.840941+00:00", - "communication_disabled_until": null, - "roles": [ - "1225608242688819214" - ], - "pending": false, - "flags": 0, - "deaf": false, - "mute": false, - "avatar": null - }, - "interaction": { - "name": "imagine", - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", - "communication_disabled_until": null, - "roles": [], - "pending": false, - "flags": 0, - "deaf": false, - "mute": false, - "avatar": null + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } }, - "id": "1225630717426274377", - "type": 2, - "user": { - "global_name": "JVerbalu", - "avatar_decoration_data": null, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - } - }, - "guild_id": "1225608134878302329", - "position": 0, - "id": "1225630724431024259", - "embeds": [], - "channel_id": "1225608134878302332", - "timestamp": "2024-04-05T02:18:55.822000+00:00" + "guild_id": "1234355413420347402", + "position": 0, + "id": "1234381516130357379", + "embeds": [], + "channel_id": "1234380679576424448", + "timestamp": "2024-04-29T05:51:27.145000+00:00" + } } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/11.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/11.json index 837c89123..f38f1a3e0 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/11.json +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/11.json @@ -1,56 +1,107 @@ { - "mention_everyone": false, - "pinned": false, - "components": [], - "attachments": [ - { - "filename": "8f23f288-6028-468b-8056-1e4adef73985_grid_0.webp", - "size": 46376, - "content_type": "image/webp", - "width": 512, - "placeholder_version": 1, - "proxy_url": "https://media.discordapp.net/attachments/1225608134878302332/1225630846317498469/8f23f288-6028-468b-8056-1e4adef73985_grid_0.webp?ex=6621d4ac&is=660f5fac&hm=efe167b852efc37fe4690253697cee2b8fd350d0b724b3a99004ad36baa09c1f&", - "placeholder": "oSgOFwRvtYxVlnl2d1iIh4h3aPdnmC8F", - "id": "1225630846317498469", - "url": "https://cdn.discordapp.com/attachments/1225608134878302332/1225630846317498469/8f23f288-6028-468b-8056-1e4adef73985_grid_0.webp?ex=6621d4ac&is=660f5fac&hm=efe167b852efc37fe4690253697cee2b8fd350d0b724b3a99004ad36baa09c1f&", - "height": 512 - } - ], - "interaction_metadata": { - "user_id": "972721304891453450", - "name": "imagine", - "authorizing_integration_owners": { - "0": "1225608134878302329" + "op": 0, + "s": 39, + "t": "MESSAGE_UPDATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [ + { + "filename": "5d32f4e8-8d2f-4bef-82d8-bf517e3c3660_grid_0.webp", + "size": 77746, + "content_type": "image/webp", + "width": 512, + "placeholder_version": 1, + "proxy_url": "https://media.discordapp.net/attachments/1234380679576424448/1234381963381444691/5d32f4e8-8d2f-4bef-82d8-bf517e3c3660_grid_0.webp?ex=66308749&is=662f35c9&hm=f87113bb4f667e56747a26812260f18b5c59f1e47991457756e77b576309534a&", + "placeholder": "3OcJDwSASHWaWZZ4eNd2eHiGJyBMgKAG", + "id": "1234381963381444691", + "url": "https://cdn.discordapp.com/attachments/1234380679576424448/1234381963381444691/5d32f4e8-8d2f-4bef-82d8-bf517e3c3660_grid_0.webp?ex=66308749&is=662f35c9&hm=f87113bb4f667e56747a26812260f18b5c59f1e47991457756e77b576309534a&", + "height": 512 + } + ], + "interaction_metadata": { + "user_id": "975372485971312700", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1234355413420347402" + }, + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } }, - "id": "1225630717426274377", - "type": 2 - }, - "author": { - "global_name": null, - "bot": true, - "avatar_decoration_data": null, - "public_flags": 589824, - "id": "936929561302675456", - "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", - "username": "Midjourney Bot", - "discriminator": "9282" - }, - "flags": 0, - "type": 20, - "mention_roles": [], - "application_id": "936929561302675456", - "edited_timestamp": "2024-04-05T02:19:24.805512+00:00", - "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (75%) (fast, stealth)", - "tts": false, - "webhook_id": "936929561302675456", - "mentions": [ - { - "global_name": "JVerbalu", + "author": { + "global_name": null, + "bot": true, "avatar_decoration_data": null, + "clan": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 20, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-29T05:53:13.745586+00:00", + "content": "**海贼王,在赶海! --v 6.0** - <@975372485971312700> (95%) (relaxed)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:07:43.807000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:09:06.489349+00:00", + "communication_disabled_until": null, + "roles": [ + "1234355760184561747" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "interaction": { + "name": "imagine", "member": { "premium_since": null, "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", + "joined_at": "2024-04-29T04:07:43.807000+00:00", "communication_disabled_until": null, "roles": [], "pending": false, @@ -59,57 +110,24 @@ "mute": false, "avatar": null }, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - } - ], - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:35.840941+00:00", - "communication_disabled_until": null, - "roles": [ - "1225608242688819214" - ], - "pending": false, - "flags": 0, - "deaf": false, - "mute": false, - "avatar": null - }, - "interaction": { - "name": "imagine", - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", - "communication_disabled_until": null, - "roles": [], - "pending": false, - "flags": 0, - "deaf": false, - "mute": false, - "avatar": null + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } }, - "id": "1225630717426274377", - "type": 2, - "user": { - "global_name": "JVerbalu", - "avatar_decoration_data": null, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - } - }, - "guild_id": "1225608134878302329", - "position": 0, - "id": "1225630724431024259", - "embeds": [], - "channel_id": "1225608134878302332", - "timestamp": "2024-04-05T02:18:55.822000+00:00" + "guild_id": "1234355413420347402", + "position": 0, + "id": "1234381516130357379", + "embeds": [], + "channel_id": "1234380679576424448", + "timestamp": "2024-04-29T05:51:27.145000+00:00" + } } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/12.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/12.json index 890297b55..53a4c70cc 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/12.json +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/12.json @@ -1,145 +1,152 @@ { - "mention_everyone": false, - "pinned": false, - "components": [ - { - "components": [ - { - "custom_id": "MJ::JOB::upsample::1::8f23f288-6028-468b-8056-1e4adef73985", - "style": 2, - "label": "U1", - "type": 2 - }, - { - "custom_id": "MJ::JOB::upsample::2::8f23f288-6028-468b-8056-1e4adef73985", - "style": 2, - "label": "U2", - "type": 2 - }, - { - "custom_id": "MJ::JOB::upsample::3::8f23f288-6028-468b-8056-1e4adef73985", - "style": 2, - "label": "U3", - "type": 2 - }, - { - "custom_id": "MJ::JOB::upsample::4::8f23f288-6028-468b-8056-1e4adef73985", - "style": 2, - "label": "U4", - "type": 2 - }, - { - "emoji": { - "name": "🔄" + "op": 0, + "s": 40, + "t": "MESSAGE_CREATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [ + { + "components": [ + { + "custom_id": "MJ::JOB::upsample::1::5d32f4e8-8d2f-4bef-82d8-bf517e3c3660", + "style": 2, + "label": "U1", + "type": 2 }, - "custom_id": "MJ::JOB::reroll::0::8f23f288-6028-468b-8056-1e4adef73985::SOLO", - "style": 2, - "type": 2 - } - ], - "type": 1 - }, - { - "components": [ - { - "custom_id": "MJ::JOB::variation::1::8f23f288-6028-468b-8056-1e4adef73985", - "style": 2, - "label": "V1", - "type": 2 - }, - { - "custom_id": "MJ::JOB::variation::2::8f23f288-6028-468b-8056-1e4adef73985", - "style": 2, - "label": "V2", - "type": 2 - }, - { - "custom_id": "MJ::JOB::variation::3::8f23f288-6028-468b-8056-1e4adef73985", - "style": 2, - "label": "V3", - "type": 2 - }, - { - "custom_id": "MJ::JOB::variation::4::8f23f288-6028-468b-8056-1e4adef73985", - "style": 2, - "label": "V4", - "type": 2 - } - ], - "type": 1 - } - ], - "attachments": [ - { - "filename": "jverbalu4990__8f23f288-6028-468b-8056-1e4adef73985.png", - "size": 7092878, - "content_type": "image/png", - "width": 2048, - "placeholder_version": 1, - "proxy_url": "https://media.discordapp.net/attachments/1225608134878302332/1225630861899333652/jverbalu4990__8f23f288-6028-468b-8056-1e4adef73985.png?ex=6621d4b0&is=660f5fb0&hm=658c7766ac3df7e484ccf2e1a30b0afc266ec38e5b2da6c95f12cb7f9c204886&", - "placeholder": "YRgODwJvpY1XlXl2h0iYh4iIePkQqgkB", - "id": "1225630861899333652", - "url": "https://cdn.discordapp.com/attachments/1225608134878302332/1225630861899333652/jverbalu4990__8f23f288-6028-468b-8056-1e4adef73985.png?ex=6621d4b0&is=660f5fb0&hm=658c7766ac3df7e484ccf2e1a30b0afc266ec38e5b2da6c95f12cb7f9c204886&", - "height": 2048 - } - ], - "author": { - "global_name": null, - "bot": true, - "avatar_decoration_data": null, - "public_flags": 589824, - "id": "936929561302675456", - "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", - "username": "Midjourney Bot", - "discriminator": "9282" - }, - "flags": 0, - "type": 0, - "mention_roles": [], - "edited_timestamp": null, - "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (fast, stealth)", - "tts": false, - "referenced_message": null, - "mentions": [ - { - "global_name": "JVerbalu", - "avatar_decoration_data": null, - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", - "communication_disabled_until": null, - "roles": [], - "pending": false, - "flags": 0, - "deaf": false, - "mute": false, - "avatar": null + { + "custom_id": "MJ::JOB::upsample::2::5d32f4e8-8d2f-4bef-82d8-bf517e3c3660", + "style": 2, + "label": "U2", + "type": 2 + }, + { + "custom_id": "MJ::JOB::upsample::3::5d32f4e8-8d2f-4bef-82d8-bf517e3c3660", + "style": 2, + "label": "U3", + "type": 2 + }, + { + "custom_id": "MJ::JOB::upsample::4::5d32f4e8-8d2f-4bef-82d8-bf517e3c3660", + "style": 2, + "label": "U4", + "type": 2 + }, + { + "emoji": { + "name": "\uD83D\uDD04" + }, + "custom_id": "MJ::JOB::reroll::0::5d32f4e8-8d2f-4bef-82d8-bf517e3c3660::SOLO", + "style": 2, + "type": 2 + } + ], + "type": 1 }, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - } - ], - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:35.840941+00:00", - "communication_disabled_until": null, - "roles": [ - "1225608242688819214" + { + "components": [ + { + "custom_id": "MJ::JOB::variation::1::5d32f4e8-8d2f-4bef-82d8-bf517e3c3660", + "style": 2, + "label": "V1", + "type": 2 + }, + { + "custom_id": "MJ::JOB::variation::2::5d32f4e8-8d2f-4bef-82d8-bf517e3c3660", + "style": 2, + "label": "V2", + "type": 2 + }, + { + "custom_id": "MJ::JOB::variation::3::5d32f4e8-8d2f-4bef-82d8-bf517e3c3660", + "style": 2, + "label": "V3", + "type": 2 + }, + { + "custom_id": "MJ::JOB::variation::4::5d32f4e8-8d2f-4bef-82d8-bf517e3c3660", + "style": 2, + "label": "V4", + "type": 2 + } + ], + "type": 1 + } ], - "pending": false, + "attachments": [ + { + "filename": "andrakosq9211__5d32f4e8-8d2f-4bef-82d8-bf517e3c3660.png", + "size": 8327001, + "content_type": "image/png", + "width": 2048, + "placeholder_version": 1, + "proxy_url": "https://media.discordapp.net/attachments/1234380679576424448/1234381975058514001/andrakosq9211__5d32f4e8-8d2f-4bef-82d8-bf517e3c3660.png?ex=6630874c&is=662f35cc&hm=20a8bb9b10c68645c9bd09a52b181de8566802590d070965d0a4738387781bb6&", + "placeholder": "3dcJBwaASHWaWZZ4eNd2aHiGRwE+gLAH", + "id": "1234381975058514001", + "url": "https://cdn.discordapp.com/attachments/1234380679576424448/1234381975058514001/andrakosq9211__5d32f4e8-8d2f-4bef-82d8-bf517e3c3660.png?ex=6630874c&is=662f35cc&hm=20a8bb9b10c68645c9bd09a52b181de8566802590d070965d0a4738387781bb6&", + "height": 2048 + } + ], + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "clan": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, "flags": 0, - "deaf": false, - "mute": false, - "avatar": null - }, - "guild_id": "1225608134878302329", - "id": "1225630862393999442", - "embeds": [], - "channel_id": "1225608134878302332", - "timestamp": "2024-04-05T02:19:28.715000+00:00" + "type": 0, + "mention_roles": [], + "edited_timestamp": null, + "content": "**海贼王,在赶海! --v 6.0** - <@975372485971312700> (relaxed)", + "tts": false, + "referenced_message": null, + "mentions": [ + { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:07:43.807000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:09:06.489349+00:00", + "communication_disabled_until": null, + "roles": [ + "1234355760184561747" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "guild_id": "1234355413420347402", + "id": "1234381975335342122", + "embeds": [], + "channel_id": "1234380679576424448", + "timestamp": "2024-04-29T05:53:16.628000+00:00" + } } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/2.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/2.json index 2643136a2..6c706557b 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/2.json +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/2.json @@ -1,44 +1,94 @@ { - "mention_everyone": false, - "pinned": false, - "components": [], - "attachments": [], - "interaction_metadata": { - "user_id": "972721304891453450", - "name": "imagine", - "authorizing_integration_owners": { - "0": "1225608134878302329" + "op": 0, + "s": 30, + "t": "MESSAGE_UPDATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [], + "interaction_metadata": { + "user_id": "975372485971312700", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1234355413420347402" + }, + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } }, - "id": "1225630717426274377", - "type": 2 - }, - "author": { - "global_name": null, - "bot": true, - "avatar_decoration_data": null, - "public_flags": 589824, - "id": "936929561302675456", - "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", - "username": "Midjourney Bot", - "discriminator": "9282" - }, - "flags": 0, - "type": 20, - "mention_roles": [], - "nonce": "1225630715874377728", - "application_id": "936929561302675456", - "edited_timestamp": null, - "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (Waiting to start)", - "tts": false, - "webhook_id": "936929561302675456", - "mentions": [ - { - "global_name": "JVerbalu", + "author": { + "global_name": null, + "bot": true, "avatar_decoration_data": null, + "clan": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 20, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-29T05:52:42.826454+00:00", + "content": "**海贼王,在赶海! --v 6.0** - <@975372485971312700> (0%) (relaxed)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:07:43.807000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:09:06.489349+00:00", + "communication_disabled_until": null, + "roles": [ + "1234355760184561747" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "interaction": { + "name": "imagine", "member": { "premium_since": null, "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", + "joined_at": "2024-04-29T04:07:43.807000+00:00", "communication_disabled_until": null, "roles": [], "pending": false, @@ -47,57 +97,24 @@ "mute": false, "avatar": null }, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - } - ], - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:35.840941+00:00", - "communication_disabled_until": null, - "roles": [ - "1225608242688819214" - ], - "pending": false, - "flags": 0, - "deaf": false, - "mute": false, - "avatar": null - }, - "interaction": { - "name": "imagine", - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", - "communication_disabled_until": null, - "roles": [], - "pending": false, - "flags": 0, - "deaf": false, - "mute": false, - "avatar": null + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } }, - "id": "1225630717426274377", - "type": 2, - "user": { - "global_name": "JVerbalu", - "avatar_decoration_data": null, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - } - }, - "guild_id": "1225608134878302329", - "position": 0, - "id": "1225630724431024259", - "embeds": [], - "channel_id": "1225608134878302332", - "timestamp": "2024-04-05T02:18:55.822000+00:00" + "guild_id": "1234355413420347402", + "position": 0, + "id": "1234381516130357379", + "embeds": [], + "channel_id": "1234380679576424448", + "timestamp": "2024-04-29T05:51:27.145000+00:00" + } } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/3.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/3.json index 0f6d35cc1..f375044f9 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/3.json +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/3.json @@ -1,43 +1,94 @@ { - "mention_everyone": false, - "pinned": false, - "components": [], - "attachments": [], - "interaction_metadata": { - "user_id": "972721304891453450", - "name": "imagine", - "authorizing_integration_owners": { - "0": "1225608134878302329" + "op": 0, + "s": 31, + "t": "MESSAGE_UPDATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [], + "interaction_metadata": { + "user_id": "975372485971312700", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1234355413420347402" + }, + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } }, - "id": "1225630717426274377", - "type": 2 - }, - "author": { - "global_name": null, - "bot": true, - "avatar_decoration_data": null, - "public_flags": 589824, - "id": "936929561302675456", - "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", - "username": "Midjourney Bot", - "discriminator": "9282" - }, - "flags": 0, - "type": 20, - "mention_roles": [], - "application_id": "936929561302675456", - "edited_timestamp": "2024-04-05T02:18:59.141254+00:00", - "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (0%) (fast, stealth)", - "tts": false, - "webhook_id": "936929561302675456", - "mentions": [ - { - "global_name": "JVerbalu", + "author": { + "global_name": null, + "bot": true, "avatar_decoration_data": null, + "clan": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 20, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-29T05:52:48.793794+00:00", + "content": "**海贼王,在赶海! --v 6.0** - <@975372485971312700> (10%) (relaxed)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:07:43.807000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:09:06.489349+00:00", + "communication_disabled_until": null, + "roles": [ + "1234355760184561747" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "interaction": { + "name": "imagine", "member": { "premium_since": null, "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", + "joined_at": "2024-04-29T04:07:43.807000+00:00", "communication_disabled_until": null, "roles": [], "pending": false, @@ -46,57 +97,24 @@ "mute": false, "avatar": null }, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - } - ], - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:35.840941+00:00", - "communication_disabled_until": null, - "roles": [ - "1225608242688819214" - ], - "pending": false, - "flags": 0, - "deaf": false, - "mute": false, - "avatar": null - }, - "interaction": { - "name": "imagine", - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", - "communication_disabled_until": null, - "roles": [], - "pending": false, - "flags": 0, - "deaf": false, - "mute": false, - "avatar": null + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } }, - "id": "1225630717426274377", - "type": 2, - "user": { - "global_name": "JVerbalu", - "avatar_decoration_data": null, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - } - }, - "guild_id": "1225608134878302329", - "position": 0, - "id": "1225630724431024259", - "embeds": [], - "channel_id": "1225608134878302332", - "timestamp": "2024-04-05T02:18:55.822000+00:00" + "guild_id": "1234355413420347402", + "position": 0, + "id": "1234381516130357379", + "embeds": [], + "channel_id": "1234380679576424448", + "timestamp": "2024-04-29T05:51:27.145000+00:00" + } } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/4.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/4.json index d41eb22c2..0aa8fbfed 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/4.json +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/4.json @@ -1,43 +1,94 @@ { - "mention_everyone": false, - "pinned": false, - "components": [], - "attachments": [], - "interaction_metadata": { - "user_id": "972721304891453450", - "name": "imagine", - "authorizing_integration_owners": { - "0": "1225608134878302329" + "op": 0, + "s": 32, + "t": "MESSAGE_UPDATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [], + "interaction_metadata": { + "user_id": "975372485971312700", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1234355413420347402" + }, + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } }, - "id": "1225630717426274377", - "type": 2 - }, - "author": { - "global_name": null, - "bot": true, - "avatar_decoration_data": null, - "public_flags": 589824, - "id": "936929561302675456", - "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", - "username": "Midjourney Bot", - "discriminator": "9282" - }, - "flags": 0, - "type": 20, - "mention_roles": [], - "application_id": "936929561302675456", - "edited_timestamp": "2024-04-05T02:19:02.665459+00:00", - "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (10%) (fast, stealth)", - "tts": false, - "webhook_id": "936929561302675456", - "mentions": [ - { - "global_name": "JVerbalu", + "author": { + "global_name": null, + "bot": true, "avatar_decoration_data": null, + "clan": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 20, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-29T05:52:48.976941+00:00", + "content": "**海贼王,在赶海! --v 6.0** - <@975372485971312700> (20%) (relaxed)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:07:43.807000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:09:06.489349+00:00", + "communication_disabled_until": null, + "roles": [ + "1234355760184561747" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "interaction": { + "name": "imagine", "member": { "premium_since": null, "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", + "joined_at": "2024-04-29T04:07:43.807000+00:00", "communication_disabled_until": null, "roles": [], "pending": false, @@ -46,57 +97,24 @@ "mute": false, "avatar": null }, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - } - ], - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:35.840941+00:00", - "communication_disabled_until": null, - "roles": [ - "1225608242688819214" - ], - "pending": false, - "flags": 0, - "deaf": false, - "mute": false, - "avatar": null - }, - "interaction": { - "name": "imagine", - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", - "communication_disabled_until": null, - "roles": [], - "pending": false, - "flags": 0, - "deaf": false, - "mute": false, - "avatar": null + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } }, - "id": "1225630717426274377", - "type": 2, - "user": { - "global_name": "JVerbalu", - "avatar_decoration_data": null, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - } - }, - "guild_id": "1225608134878302329", - "position": 0, - "id": "1225630724431024259", - "embeds": [], - "channel_id": "1225608134878302332", - "timestamp": "2024-04-05T02:18:55.822000+00:00" + "guild_id": "1234355413420347402", + "position": 0, + "id": "1234381516130357379", + "embeds": [], + "channel_id": "1234380679576424448", + "timestamp": "2024-04-29T05:51:27.145000+00:00" + } } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/5.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/5.json index 7503abd10..5cffb7280 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/5.json +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/5.json @@ -1,43 +1,94 @@ { - "mention_everyone": false, - "pinned": false, - "components": [], - "attachments": [], - "interaction_metadata": { - "user_id": "972721304891453450", - "name": "imagine", - "authorizing_integration_owners": { - "0": "1225608134878302329" + "op": 0, + "s": 33, + "t": "MESSAGE_UPDATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [], + "interaction_metadata": { + "user_id": "975372485971312700", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1234355413420347402" + }, + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } }, - "id": "1225630717426274377", - "type": 2 - }, - "author": { - "global_name": null, - "bot": true, - "avatar_decoration_data": null, - "public_flags": 589824, - "id": "936929561302675456", - "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", - "username": "Midjourney Bot", - "discriminator": "9282" - }, - "flags": 0, - "type": 20, - "mention_roles": [], - "application_id": "936929561302675456", - "edited_timestamp": "2024-04-05T02:19:05.339248+00:00", - "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (17%) (fast, stealth)", - "tts": false, - "webhook_id": "936929561302675456", - "mentions": [ - { - "global_name": "JVerbalu", + "author": { + "global_name": null, + "bot": true, "avatar_decoration_data": null, + "clan": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 20, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-29T05:52:54.993089+00:00", + "content": "**海贼王,在赶海! --v 6.0** - <@975372485971312700> (22%) (relaxed)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:07:43.807000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:09:06.489349+00:00", + "communication_disabled_until": null, + "roles": [ + "1234355760184561747" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "interaction": { + "name": "imagine", "member": { "premium_since": null, "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", + "joined_at": "2024-04-29T04:07:43.807000+00:00", "communication_disabled_until": null, "roles": [], "pending": false, @@ -46,57 +97,24 @@ "mute": false, "avatar": null }, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - } - ], - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:35.840941+00:00", - "communication_disabled_until": null, - "roles": [ - "1225608242688819214" - ], - "pending": false, - "flags": 0, - "deaf": false, - "mute": false, - "avatar": null - }, - "interaction": { - "name": "imagine", - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", - "communication_disabled_until": null, - "roles": [], - "pending": false, - "flags": 0, - "deaf": false, - "mute": false, - "avatar": null + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } }, - "id": "1225630717426274377", - "type": 2, - "user": { - "global_name": "JVerbalu", - "avatar_decoration_data": null, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - } - }, - "guild_id": "1225608134878302329", - "position": 0, - "id": "1225630724431024259", - "embeds": [], - "channel_id": "1225608134878302332", - "timestamp": "2024-04-05T02:18:55.822000+00:00" + "guild_id": "1234355413420347402", + "position": 0, + "id": "1234381516130357379", + "embeds": [], + "channel_id": "1234380679576424448", + "timestamp": "2024-04-29T05:51:27.145000+00:00" + } } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/6.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/6.json index 61dad1272..4e126e880 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/6.json +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/6.json @@ -1,43 +1,94 @@ { - "mention_everyone": false, - "pinned": false, - "components": [], - "attachments": [], - "interaction_metadata": { - "user_id": "972721304891453450", - "name": "imagine", - "authorizing_integration_owners": { - "0": "1225608134878302329" + "op": 0, + "s": 34, + "t": "MESSAGE_UPDATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [], + "interaction_metadata": { + "user_id": "975372485971312700", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1234355413420347402" + }, + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } }, - "id": "1225630717426274377", - "type": 2 - }, - "author": { - "global_name": null, - "bot": true, - "avatar_decoration_data": null, - "public_flags": 589824, - "id": "936929561302675456", - "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", - "username": "Midjourney Bot", - "discriminator": "9282" - }, - "flags": 0, - "type": 20, - "mention_roles": [], - "application_id": "936929561302675456", - "edited_timestamp": "2024-04-05T02:19:08.810399+00:00", - "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (25%) (fast, stealth)", - "tts": false, - "webhook_id": "936929561302675456", - "mentions": [ - { - "global_name": "JVerbalu", + "author": { + "global_name": null, + "bot": true, "avatar_decoration_data": null, + "clan": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 20, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-29T05:52:55.667426+00:00", + "content": "**海贼王,在赶海! --v 6.0** - <@975372485971312700> (32%) (relaxed)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:07:43.807000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:09:06.489349+00:00", + "communication_disabled_until": null, + "roles": [ + "1234355760184561747" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "interaction": { + "name": "imagine", "member": { "premium_since": null, "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", + "joined_at": "2024-04-29T04:07:43.807000+00:00", "communication_disabled_until": null, "roles": [], "pending": false, @@ -46,57 +97,24 @@ "mute": false, "avatar": null }, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - } - ], - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:35.840941+00:00", - "communication_disabled_until": null, - "roles": [ - "1225608242688819214" - ], - "pending": false, - "flags": 0, - "deaf": false, - "mute": false, - "avatar": null - }, - "interaction": { - "name": "imagine", - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", - "communication_disabled_until": null, - "roles": [], - "pending": false, - "flags": 0, - "deaf": false, - "mute": false, - "avatar": null + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } }, - "id": "1225630717426274377", - "type": 2, - "user": { - "global_name": "JVerbalu", - "avatar_decoration_data": null, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - } - }, - "guild_id": "1225608134878302329", - "position": 0, - "id": "1225630724431024259", - "embeds": [], - "channel_id": "1225608134878302332", - "timestamp": "2024-04-05T02:18:55.822000+00:00" + "guild_id": "1234355413420347402", + "position": 0, + "id": "1234381516130357379", + "embeds": [], + "channel_id": "1234380679576424448", + "timestamp": "2024-04-29T05:51:27.145000+00:00" + } } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/7.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/7.json index a21f527aa..38d670093 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/7.json +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/7.json @@ -1,43 +1,94 @@ { - "mention_everyone": false, - "pinned": false, - "components": [], - "attachments": [], - "interaction_metadata": { - "user_id": "972721304891453450", - "name": "imagine", - "authorizing_integration_owners": { - "0": "1225608134878302329" + "op": 0, + "s": 35, + "t": "MESSAGE_UPDATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [], + "interaction_metadata": { + "user_id": "975372485971312700", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1234355413420347402" + }, + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } }, - "id": "1225630717426274377", - "type": 2 - }, - "author": { - "global_name": null, - "bot": true, - "avatar_decoration_data": null, - "public_flags": 589824, - "id": "936929561302675456", - "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", - "username": "Midjourney Bot", - "discriminator": "9282" - }, - "flags": 0, - "type": 20, - "mention_roles": [], - "application_id": "936929561302675456", - "edited_timestamp": "2024-04-05T02:19:12.017944+00:00", - "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (32%) (fast, stealth)", - "tts": false, - "webhook_id": "936929561302675456", - "mentions": [ - { - "global_name": "JVerbalu", + "author": { + "global_name": null, + "bot": true, "avatar_decoration_data": null, + "clan": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 20, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-29T05:53:01.235104+00:00", + "content": "**海贼王,在赶海! --v 6.0** - <@975372485971312700> (35%) (relaxed)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:07:43.807000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:09:06.489349+00:00", + "communication_disabled_until": null, + "roles": [ + "1234355760184561747" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "interaction": { + "name": "imagine", "member": { "premium_since": null, "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", + "joined_at": "2024-04-29T04:07:43.807000+00:00", "communication_disabled_until": null, "roles": [], "pending": false, @@ -46,57 +97,24 @@ "mute": false, "avatar": null }, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - } - ], - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:35.840941+00:00", - "communication_disabled_until": null, - "roles": [ - "1225608242688819214" - ], - "pending": false, - "flags": 0, - "deaf": false, - "mute": false, - "avatar": null - }, - "interaction": { - "name": "imagine", - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", - "communication_disabled_until": null, - "roles": [], - "pending": false, - "flags": 0, - "deaf": false, - "mute": false, - "avatar": null + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } }, - "id": "1225630717426274377", - "type": 2, - "user": { - "global_name": "JVerbalu", - "avatar_decoration_data": null, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - } - }, - "guild_id": "1225608134878302329", - "position": 0, - "id": "1225630724431024259", - "embeds": [], - "channel_id": "1225608134878302332", - "timestamp": "2024-04-05T02:18:55.822000+00:00" + "guild_id": "1234355413420347402", + "position": 0, + "id": "1234381516130357379", + "embeds": [], + "channel_id": "1234380679576424448", + "timestamp": "2024-04-29T05:51:27.145000+00:00" + } } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/8.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/8.json index 48decf5f6..c6d1b735b 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/8.json +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/8.json @@ -1,43 +1,107 @@ { - "mention_everyone": false, - "pinned": false, - "components": [], - "attachments": [], - "interaction_metadata": { - "user_id": "972721304891453450", - "name": "imagine", - "authorizing_integration_owners": { - "0": "1225608134878302329" + "op": 0, + "s": 36, + "t": "MESSAGE_UPDATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [ + { + "filename": "5d32f4e8-8d2f-4bef-82d8-bf517e3c3660_grid_0.webp", + "size": 43912, + "content_type": "image/webp", + "width": 512, + "placeholder_version": 1, + "proxy_url": "https://media.discordapp.net/attachments/1234380679576424448/1234381927348436992/5d32f4e8-8d2f-4bef-82d8-bf517e3c3660_grid_0.webp?ex=66308741&is=662f35c1&hm=eb4abbb4ede30b588e02eba7c18203177dcea82612ee981bde696346f1d887ac&", + "placeholder": "WpcRLxZwanaXh4d4h6d2aIeG92d6hbAH", + "id": "1234381927348436992", + "url": "https://cdn.discordapp.com/attachments/1234380679576424448/1234381927348436992/5d32f4e8-8d2f-4bef-82d8-bf517e3c3660_grid_0.webp?ex=66308741&is=662f35c1&hm=eb4abbb4ede30b588e02eba7c18203177dcea82612ee981bde696346f1d887ac&", + "height": 512 + } + ], + "interaction_metadata": { + "user_id": "975372485971312700", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1234355413420347402" + }, + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } }, - "id": "1225630717426274377", - "type": 2 - }, - "author": { - "global_name": null, - "bot": true, - "avatar_decoration_data": null, - "public_flags": 589824, - "id": "936929561302675456", - "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", - "username": "Midjourney Bot", - "discriminator": "9282" - }, - "flags": 0, - "type": 20, - "mention_roles": [], - "application_id": "936929561302675456", - "edited_timestamp": "2024-04-05T02:19:15.043965+00:00", - "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (35%) (fast, stealth)", - "tts": false, - "webhook_id": "936929561302675456", - "mentions": [ - { - "global_name": "JVerbalu", + "author": { + "global_name": null, + "bot": true, "avatar_decoration_data": null, + "clan": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 20, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-29T05:53:05.164746+00:00", + "content": "**海贼王,在赶海! --v 6.0** - <@975372485971312700> (35%) (relaxed)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:07:43.807000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:09:06.489349+00:00", + "communication_disabled_until": null, + "roles": [ + "1234355760184561747" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "interaction": { + "name": "imagine", "member": { "premium_since": null, "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", + "joined_at": "2024-04-29T04:07:43.807000+00:00", "communication_disabled_until": null, "roles": [], "pending": false, @@ -46,57 +110,24 @@ "mute": false, "avatar": null }, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - } - ], - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:35.840941+00:00", - "communication_disabled_until": null, - "roles": [ - "1225608242688819214" - ], - "pending": false, - "flags": 0, - "deaf": false, - "mute": false, - "avatar": null - }, - "interaction": { - "name": "imagine", - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", - "communication_disabled_until": null, - "roles": [], - "pending": false, - "flags": 0, - "deaf": false, - "mute": false, - "avatar": null + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } }, - "id": "1225630717426274377", - "type": 2, - "user": { - "global_name": "JVerbalu", - "avatar_decoration_data": null, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - } - }, - "guild_id": "1225608134878302329", - "position": 0, - "id": "1225630724431024259", - "embeds": [], - "channel_id": "1225608134878302332", - "timestamp": "2024-04-05T02:18:55.822000+00:00" + "guild_id": "1234355413420347402", + "position": 0, + "id": "1234381516130357379", + "embeds": [], + "channel_id": "1234380679576424448", + "timestamp": "2024-04-29T05:51:27.145000+00:00" + } } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/9.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/9.json index 10a28991d..4c260889b 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/9.json +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/9.json @@ -1,56 +1,107 @@ { - "mention_everyone": false, - "pinned": false, - "components": [], - "attachments": [ - { - "filename": "8f23f288-6028-468b-8056-1e4adef73985_grid_0.webp", - "size": 30752, - "content_type": "image/webp", - "width": 512, - "placeholder_version": 1, - "proxy_url": "https://media.discordapp.net/attachments/1225608134878302332/1225630819515764806/8f23f288-6028-468b-8056-1e4adef73985_grid_0.webp?ex=6621d4a6&is=660f5fa6&hm=d46f487fce290539acae4e83322345b35f658c2ec40fb6f015a698dac9e84bb7&", - "placeholder": "HBgSFwJ/hYpEl3iGd3iId3h3R/k0gF4E", - "id": "1225630819515764806", - "url": "https://cdn.discordapp.com/attachments/1225608134878302332/1225630819515764806/8f23f288-6028-468b-8056-1e4adef73985_grid_0.webp?ex=6621d4a6&is=660f5fa6&hm=d46f487fce290539acae4e83322345b35f658c2ec40fb6f015a698dac9e84bb7&", - "height": 512 - } - ], - "interaction_metadata": { - "user_id": "972721304891453450", - "name": "imagine", - "authorizing_integration_owners": { - "0": "1225608134878302329" + "op": 0, + "s": 37, + "t": "MESSAGE_UPDATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [ + { + "filename": "5d32f4e8-8d2f-4bef-82d8-bf517e3c3660_grid_0.webp", + "size": 27876, + "content_type": "image/webp", + "width": 512, + "placeholder_version": 1, + "proxy_url": "https://media.discordapp.net/attachments/1234380679576424448/1234381937288679506/5d32f4e8-8d2f-4bef-82d8-bf517e3c3660_grid_0.webp?ex=66308743&is=662f35c3&hm=ccebcb830d6e76127164767721ebf18ec3bc1e9acf8d61481b5f755e89caf8b8&", + "placeholder": "G7cJFwqCeYiHeId5h/h2eHmU9xeHc7AG", + "id": "1234381937288679506", + "url": "https://cdn.discordapp.com/attachments/1234380679576424448/1234381937288679506/5d32f4e8-8d2f-4bef-82d8-bf517e3c3660_grid_0.webp?ex=66308743&is=662f35c3&hm=ccebcb830d6e76127164767721ebf18ec3bc1e9acf8d61481b5f755e89caf8b8&", + "height": 512 + } + ], + "interaction_metadata": { + "user_id": "975372485971312700", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1234355413420347402" + }, + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } }, - "id": "1225630717426274377", - "type": 2 - }, - "author": { - "global_name": null, - "bot": true, - "avatar_decoration_data": null, - "public_flags": 589824, - "id": "936929561302675456", - "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", - "username": "Midjourney Bot", - "discriminator": "9282" - }, - "flags": 0, - "type": 20, - "mention_roles": [], - "application_id": "936929561302675456", - "edited_timestamp": "2024-04-05T02:19:18.460823+00:00", - "content": "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (45%) (fast, stealth)", - "tts": false, - "webhook_id": "936929561302675456", - "mentions": [ - { - "global_name": "JVerbalu", + "author": { + "global_name": null, + "bot": true, "avatar_decoration_data": null, + "clan": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 20, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-29T05:53:07.496257+00:00", + "content": "**海贼王,在赶海! --v 6.0** - <@975372485971312700> (55%) (relaxed)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:07:43.807000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:09:06.489349+00:00", + "communication_disabled_until": null, + "roles": [ + "1234355760184561747" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "interaction": { + "name": "imagine", "member": { "premium_since": null, "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", + "joined_at": "2024-04-29T04:07:43.807000+00:00", "communication_disabled_until": null, "roles": [], "pending": false, @@ -59,57 +110,24 @@ "mute": false, "avatar": null }, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - } - ], - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:35.840941+00:00", - "communication_disabled_until": null, - "roles": [ - "1225608242688819214" - ], - "pending": false, - "flags": 0, - "deaf": false, - "mute": false, - "avatar": null - }, - "interaction": { - "name": "imagine", - "member": { - "premium_since": null, - "nick": null, - "joined_at": "2024-04-05T00:49:10.062000+00:00", - "communication_disabled_until": null, - "roles": [], - "pending": false, - "flags": 0, - "deaf": false, - "mute": false, - "avatar": null + "id": "1234381513597128715", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } }, - "id": "1225630717426274377", - "type": 2, - "user": { - "global_name": "JVerbalu", - "avatar_decoration_data": null, - "public_flags": 0, - "id": "972721304891453450", - "avatar": "3646118d04fd12dfd301c4fd17afd801", - "username": "jverbalu4990", - "discriminator": "0" - } - }, - "guild_id": "1225608134878302329", - "position": 0, - "id": "1225630724431024259", - "embeds": [], - "channel_id": "1225608134878302332", - "timestamp": "2024-04-05T02:18:55.822000+00:00" + "guild_id": "1234355413420347402", + "position": 0, + "id": "1234381516130357379", + "embeds": [], + "channel_id": "1234380679576424448", + "timestamp": "2024-04-29T05:51:27.145000+00:00" + } } \ No newline at end of file From 330fd52b3e2ffc2f6045b736b05ddd2f5762864a Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 14:46:57 +0800 Subject: [PATCH 187/684] =?UTF-8?q?=E3=80=90=E6=B7=BB=E5=8A=A0=E3=80=91mid?= =?UTF-8?q?journey=20=E5=A2=9E=E5=8A=A0=20imagine=20=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/AiImageController.java | 17 +++-- .../module/ai/service/AiImageService.java | 10 +++ .../ai/service/impl/AiImageServiceImpl.java | 62 +++++++++++++++++-- 3 files changed, 79 insertions(+), 10 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java index f4a20e5fa..aefdf14f4 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java @@ -1,14 +1,17 @@ package cn.iocoder.yudao.module.ai.controller; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.ai.service.AiImageService; import cn.iocoder.yudao.module.ai.vo.AiImageDallDrawingReq; +import cn.iocoder.yudao.module.ai.vo.AiImageMidjourneyReq; +import cn.iocoder.yudao.module.ai.vo.AiImageMidjourneyRes; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; @@ -30,10 +33,16 @@ public class AiImageController { private final AiImageService aiImageService; @Operation(summary = "dall2/dall3绘画", description = "openAi dall3是付费的!") - @GetMapping("/dallDrawing") - public SseEmitter dallDrawing(@Validated @ModelAttribute AiImageDallDrawingReq req) { + @PostMapping("/dallDrawing") + public SseEmitter dallDrawing(@Validated @RequestBody AiImageDallDrawingReq req) { Utf8SseEmitter sseEmitter = new Utf8SseEmitter(); aiImageService.dallDrawing(req, sseEmitter); return sseEmitter; } + + @Operation(summary = "midjourney", description = "midjourney图片绘画流程:1、提交任务 2、获取完成的任务 3、选择对应功能 4、获取最终结果") + @PostMapping("/midjourney") + public CommonResult midjourney(@Validated @RequestBody AiImageMidjourneyReq req) { + return CommonResult.success(aiImageService.midjourney(req)); + } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java index 05e512d24..f4395e398 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java @@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; import cn.iocoder.yudao.module.ai.vo.AiImageDallDrawingReq; +import cn.iocoder.yudao.module.ai.vo.AiImageMidjourneyReq; +import cn.iocoder.yudao.module.ai.vo.AiImageMidjourneyRes; /** * ai 作图 @@ -19,4 +21,12 @@ public interface AiImageService { * @param sseEmitter */ void dallDrawing(AiImageDallDrawingReq req, Utf8SseEmitter sseEmitter); + + /** + * midjourney 图片生成 + * + * @param req + * @return + */ + AiImageMidjourneyRes midjourney(AiImageMidjourneyReq req); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java index cdb95c78c..d87e2d9f3 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java @@ -8,17 +8,26 @@ import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageClient; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageModelEnum; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageOptions; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageStyleEnum; +import cn.iocoder.yudao.framework.ai.midjourney.api.MidjourneyInteractionsApi; +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyWebSocketStarter; +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.WssNotify; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; import cn.iocoder.yudao.module.ai.dal.dataobject.AiImageDO; import cn.iocoder.yudao.module.ai.enums.AiChatDrawingStatusEnum; import cn.iocoder.yudao.module.ai.mapper.AiImageMapper; import cn.iocoder.yudao.module.ai.service.AiImageService; import cn.iocoder.yudao.module.ai.vo.AiImageDallDrawingReq; +import cn.iocoder.yudao.module.ai.vo.AiImageMidjourneyReq; +import cn.iocoder.yudao.module.ai.vo.AiImageMidjourneyRes; +import jakarta.annotation.PostConstruct; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.MediaType; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.io.IOException; @@ -36,6 +45,24 @@ public class AiImageServiceImpl implements AiImageService { private final AiImageMapper aiImageMapper; private final OpenAiImageClient openAiImageClient; + private final MidjourneyWebSocketStarter midjourneyWebSocketStarter; + private final MidjourneyInteractionsApi midjourneyInteractionsApi; + + @PostConstruct + public void startMidjourney() { + log.info("midjourney web socket starter..."); + midjourneyWebSocketStarter.start(new WssNotify() { + @Override + public void notify(int code, String message) { + log.info("code: {}, message: {}", code, message); + if (message.contains("Authentication failed")) { + // TODO 芋艿,这里看怎么处理,token无效的时候会认证失败! + // 认证失败 + log.error("midjourney socket 认证失败,检查token是否失效!"); + } + } + }); + } @Override public void dallDrawing(AiImageDallDrawingReq req, Utf8SseEmitter sseEmitter) { @@ -55,15 +82,33 @@ public class AiImageServiceImpl implements AiImageService { // 发送信息 sendSseEmitter(sseEmitter, imageGeneration); // 保存数据库 - doSave(req, imageGeneration.getOutput().getUrl(), AiChatDrawingStatusEnum.COMPLETE, null); + doSave(req.getPrompt(), req.getSize(), req.getModal(), + imageGeneration.getOutput().getUrl(), AiChatDrawingStatusEnum.COMPLETE, null); } catch (AiException aiException) { // 保存数据库 - doSave(req, null, AiChatDrawingStatusEnum.FAIL, aiException.getMessage()); + doSave(req.getPrompt(), req.getSize(), req.getModal(), + null, AiChatDrawingStatusEnum.FAIL, aiException.getMessage()); // 发送错误信息 sendSseEmitter(sseEmitter, aiException.getMessage()); } } + @Override + @Transactional(rollbackFor = Exception.class) + public AiImageMidjourneyRes midjourney(AiImageMidjourneyReq req) { + // 保存数据库 + doSave(req.getPrompt(), null, "midjoureny", + null, AiChatDrawingStatusEnum.SUBMIT, null); + // 提交 midjourney 任务 + Boolean imagine = midjourneyInteractionsApi.imagine(req.getPrompt()); + if (!imagine) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MIDJOURNEY_IMAGINE_FAIL); + } + // + + return null; + } + private static void sendSseEmitter(Utf8SseEmitter sseEmitter, Object object) { try { sseEmitter.send(object, MediaType.APPLICATION_JSON); @@ -75,14 +120,19 @@ public class AiImageServiceImpl implements AiImageService { } } - private void doSave(AiImageDallDrawingReq req, String imageUrl, AiChatDrawingStatusEnum drawingStatusEnum, String drawingError) { + private void doSave(String prompt, + String size, + String model, + String imageUrl, + AiChatDrawingStatusEnum drawingStatusEnum, + String drawingError) { // 保存数据库 Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); AiImageDO aiImageDO = new AiImageDO(); aiImageDO.setId(null); - aiImageDO.setPrompt(req.getPrompt()); - aiImageDO.setSize(req.getSize()); - aiImageDO.setModal(req.getModal()); + aiImageDO.setPrompt(prompt); + aiImageDO.setSize(size); + aiImageDO.setModal(model); aiImageDO.setUserId(loginUserId); aiImageDO.setDrawingImageUrl(imageUrl); aiImageDO.setDrawingStatus(drawingStatusEnum.getStatus()); From 0581f5a7a506656eca305db542aa71ff825f968c Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 14:47:18 +0800 Subject: [PATCH 188/684] =?UTF-8?q?=E3=80=90=E6=B7=BB=E5=8A=A0=E3=80=91?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BB=BB=E5=8A=A1=E6=8F=90=E4=BA=A4=E7=8A=B6?= =?UTF-8?q?=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iocoder/yudao/module/ai/enums/AiChatDrawingStatusEnum.java | 1 + 1 file changed, 1 insertion(+) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatDrawingStatusEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatDrawingStatusEnum.java index fef37e13d..e32cb94fa 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatDrawingStatusEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatDrawingStatusEnum.java @@ -14,6 +14,7 @@ import lombok.Getter; @Getter public enum AiChatDrawingStatusEnum { + SUBMIT("submit", "提交任务"), COMPLETE("complete", "完成"), FAIL("fail", "失败"), From 0d8ce9373a7d9b8817db903e2155926a92707b33 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 14:47:59 +0800 Subject: [PATCH 189/684] =?UTF-8?q?=E3=80=90=E5=88=9B=E5=BB=BA=E3=80=91Mid?= =?UTF-8?q?journey=20req=20=E5=92=8C=20res?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/vo/AiImageMidjourneyReq.java | 21 +++++++++++++++++++ .../module/ai/vo/AiImageMidjourneyRes.java | 16 ++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageMidjourneyReq.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageMidjourneyRes.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageMidjourneyReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageMidjourneyReq.java new file mode 100644 index 000000000..279541377 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageMidjourneyReq.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.ai.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * midjourney req + * + * @author fansili + * @time 2024/4/28 17:42 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class AiImageMidjourneyReq { + + @Schema(description = "提示词") + private String prompt; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageMidjourneyRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageMidjourneyRes.java new file mode 100644 index 000000000..569047cd8 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageMidjourneyRes.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.ai.vo; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * midjourney + * + * @author fansili + * @time 2024/4/28 17:42 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class AiImageMidjourneyRes { +} From 6bd1d943eb3fe63b126f748db71fa67bfda493de Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 14:48:20 +0800 Subject: [PATCH 190/684] =?UTF-8?q?=E3=80=90=E5=88=9B=E5=BB=BA=E3=80=91?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20midjourney=20imagine=20=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5!=20=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index 8609df6a9..5839f11f1 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -24,11 +24,11 @@ public interface ErrorCodeConstants { ErrorCode AI_CHAT_CONTINUE_NOT_EXIST = new ErrorCode(1_022_000_020, "chat对话不存在!"); ErrorCode AI_CHAT_CONVERSATION_NOT_YOURS = new ErrorCode(1_022_000_021, "这条chat对话不是你的!"); - ErrorCode AI_CHAT_ROLE_NOT_EXIST = new ErrorCode(1_022_000_040, "chatRole不存在!"); + ErrorCode AI_MIDJOURNEY_IMAGINE_FAIL = new ErrorCode(1_022_000_040, "midjourney imagine 操作失败!"); + ErrorCode AI_CHAT_ROLE_NOT_EXIST = new ErrorCode(1_022_000_060, "chatRole不存在!"); - - ErrorCode AI_MODAL_NOT_EXIST = new ErrorCode(1_022_000_060, "ai模型不存在!"); + ErrorCode AI_MODAL_NOT_EXIST = new ErrorCode(1_022_000_080, "ai模型不存在!"); } From 80787d1dcca7e3cabc5c483e318ef0db3668be37 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 14:49:09 +0800 Subject: [PATCH 191/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91Mid?= =?UTF-8?q?journeyMessageListener=20=E5=A2=9E=E5=8A=A0=20message=20handler?= =?UTF-8?q?=20=E5=9B=9E=E8=B0=83=EF=BC=8C=E7=94=A8=E4=BA=8E=E5=A4=84?= =?UTF-8?q?=E7=90=86=E4=B8=9A=E5=8A=A1=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../webSocket/MidjourneyMessageHandler.java | 15 +++++++++++++++ .../listener/MidjourneyMessageListener.java | 17 ++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MidjourneyMessageHandler.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MidjourneyMessageHandler.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MidjourneyMessageHandler.java new file mode 100644 index 000000000..d5522fc82 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MidjourneyMessageHandler.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.framework.ai.midjourney.webSocket; + +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyMessage; + +/** + * message handler + * + * @author fansili + * @time 2024/4/29 14:29 + * @since 1.0 + */ +public interface MidjourneyMessageHandler { + + void messageHandler(MidjourneyMessage midjourneyMessage); +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java index a044f3613..e85c4e8f7 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java @@ -4,13 +4,13 @@ package cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.util.StrUtil; -import cn.hutool.json.JSONUtil; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyMessage; import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyConstants; import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyGennerateStatusEnum; import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyMessageTypeEnum; import cn.iocoder.yudao.framework.ai.midjourney.util.MidjourneyUtil; +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyMessageHandler; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.utils.data.DataObject; @@ -21,11 +21,18 @@ import java.util.List; public class MidjourneyMessageListener { private MidjourneyConfig midjourneyConfig; + private MidjourneyMessageHandler midjourneyMessageHandler = null; public MidjourneyMessageListener(MidjourneyConfig midjourneyConfig) { this.midjourneyConfig = midjourneyConfig; } + public MidjourneyMessageListener(MidjourneyConfig midjourneyConfig, + MidjourneyMessageHandler midjourneyMessageHandler) { + this.midjourneyConfig = midjourneyConfig; + this.midjourneyMessageHandler = midjourneyMessageHandler; + } + public void onMessage(DataObject raw) { MidjourneyMessageTypeEnum messageType = MidjourneyMessageTypeEnum.of(raw.getString("t")); if (messageType == null || MidjourneyMessageTypeEnum.DELETE == messageType) { @@ -35,7 +42,6 @@ public class MidjourneyMessageListener { if (ignoreAndLogMessage(data, messageType)) { return; } - // 转换几个重要的信息 MidjourneyMessage mjMessage = new MidjourneyMessage(); mjMessage.setId(data.getString(MidjourneyConstants.MSG_ID)); @@ -56,9 +62,10 @@ public class MidjourneyMessageListener { } // 转换状态 convertGenerateStatus(mjMessage); - // - log.info("message 信息 {}", JSONUtil.toJsonPrettyStr(mjMessage)); - System.err.println(JSONUtil.toJsonPrettyStr(mjMessage)); + // message handler 调用 + if (midjourneyMessageHandler != null) { + midjourneyMessageHandler.messageHandler(mjMessage); + } } private void convertGenerateStatus(MidjourneyMessage mjMessage) { From ab0a49a1a7aec7b35b49166a076eb4288e66bb1f Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 14:50:13 +0800 Subject: [PATCH 192/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91Mid?= =?UTF-8?q?journey=20=E8=87=AA=E5=8A=A8=E9=85=8D=E7=BD=AE=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20messageHanlder?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/config/YudaoAiAutoConfiguration.java | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index fa69ee56a..6eedb5997 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -15,11 +15,15 @@ import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageApi; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageClient; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageOptions; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyMessage; import cn.iocoder.yudao.framework.ai.midjourney.api.MidjourneyInteractionsApi; +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyMessageHandler; import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyWebSocketStarter; import cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener.MidjourneyMessageListener; +import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.ApplicationContext; @@ -37,6 +41,7 @@ import java.util.Map; * @time 2024/4/12 16:29 * @since 1.0 */ +@Slf4j @AutoConfiguration @EnableConfigurationProperties(YudaoAiProperties.class) public class YudaoAiAutoConfiguration { @@ -116,15 +121,29 @@ public class YudaoAiAutoConfiguration { ); } + @Bean + @ConditionalOnMissingBean(value = MidjourneyMessageHandler.class) + public MidjourneyMessageHandler defaultMidjourneyMessageHandler() { + // 如果没有实现 MidjourneyMessageHandler 默认注入一个 + return new MidjourneyMessageHandler() { + @Override + public void messageHandler(MidjourneyMessage midjourneyMessage) { + log.info("default midjourney message: {}", midjourneyMessage); + } + }; + } + @Bean @ConditionalOnProperty(value = "yudao.ai.midjourney.enable", havingValue = "true") - public MidjourneyWebSocketStarter midjourneyWebSocketStarter(ApplicationContext applicationContext, YudaoAiProperties yudaoAiProperties) { + public MidjourneyWebSocketStarter midjourneyWebSocketStarter(ApplicationContext applicationContext, + MidjourneyMessageHandler midjourneyMessageHandler, + YudaoAiProperties yudaoAiProperties) { // 获取 midjourneyProperties YudaoAiProperties.MidjourneyProperties midjourneyProperties = yudaoAiProperties.getMidjourney(); // 获取 midjourneyConfig MidjourneyConfig midjourneyConfig = getMidjourneyConfig(applicationContext, midjourneyProperties); // 创建 socket messageListener - MidjourneyMessageListener messageListener = new MidjourneyMessageListener(midjourneyConfig); + MidjourneyMessageListener messageListener = new MidjourneyMessageListener(midjourneyConfig, midjourneyMessageHandler); // 创建 MidjourneyWebSocketStarter return new MidjourneyWebSocketStarter(midjourneyProperties.getWssUrl(), null, midjourneyConfig, messageListener); } From 8bf5480bbf3ab240b6e0d76750b7786f47f0bf0d Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 14:51:05 +0800 Subject: [PATCH 193/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=BC=BA=E3=80=91Mid?= =?UTF-8?q?journeyWebSocket=20token=E6=97=A0=E6=95=88=E4=BC=9A=E8=AE=A4?= =?UTF-8?q?=E8=AF=81=E5=A4=B1=E8=B4=A5=EF=BC=8C=E5=A2=9E=E5=8A=A0=20wss=20?= =?UTF-8?q?=E9=80=9A=E7=9F=A5=E5=9B=9E=E8=B0=83=EF=BC=8C=E7=BB=99=E4=B8=9A?= =?UTF-8?q?=E5=8A=A1=E6=96=B9=E6=B3=95=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../webSocket/MidjourneyWebSocketStarter.java | 7 ++++++- .../ai/midjourney/webSocket/WssNotify.java | 13 +++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/WssNotify.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MidjourneyWebSocketStarter.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MidjourneyWebSocketStarter.java index e7ff41cc5..ddf7f3f7b 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MidjourneyWebSocketStarter.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MidjourneyWebSocketStarter.java @@ -56,6 +56,7 @@ public class MidjourneyWebSocketStarter implements WebSocketStarter { * 链接成功的 session */ private WebSocketSession webSocketSession = null; + private WssNotify wssNotify = null; public MidjourneyWebSocketStarter(String wssServer, String resumeWss, @@ -68,7 +69,8 @@ public class MidjourneyWebSocketStarter implements WebSocketStarter { } @Override - public void start() { + public void start(WssNotify wssNotify) { + this.wssNotify = wssNotify; start(false); } @@ -178,6 +180,9 @@ public class MidjourneyWebSocketStarter implements WebSocketStarter { private void notifyWssLock(int code, String reason) { System.err.println("notifyWssLock: " + code + " - " + reason); + if (wssNotify != null) { + wssNotify.notify(code, reason); + } } /** diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/WssNotify.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/WssNotify.java new file mode 100644 index 000000000..33c8a29e8 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/WssNotify.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.framework.ai.midjourney.webSocket; + +/** + * 通知信息 + * + * @author fansili + * @time 2024/4/29 14:21 + * @since 1.0 + */ +public interface WssNotify { + + void notify(int code, String message); +} From e43f7cbbcdba7fff6ee8d8bea4bac1824fb10227 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 14:51:48 +0800 Subject: [PATCH 194/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=BC=BA=E3=80=91Web?= =?UTF-8?q?SocketStarter=20=E5=A2=9E=E5=8A=A0=20WssNotify=20=E5=9B=9E?= =?UTF-8?q?=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ai/midjourney/webSocket/WebSocketStarter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/WebSocketStarter.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/WebSocketStarter.java index 88e283244..5a438aacc 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/WebSocketStarter.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/WebSocketStarter.java @@ -3,6 +3,6 @@ package cn.iocoder.yudao.framework.ai.midjourney.webSocket; public interface WebSocketStarter { - void start() throws Exception; + void start(WssNotify wssNotify) throws Exception; } From f5387d9d5a56cbcc1dbe9ab17a775f61de39f7f7 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 14:52:21 +0800 Subject: [PATCH 195/684] =?UTF-8?q?=E3=80=90=E6=B7=BB=E5=8A=A0=E3=80=91YuD?= =?UTF-8?q?aoMidjourneyMessageHandler=20=E5=A4=84=E7=90=86Midjourney=20?= =?UTF-8?q?=E4=B8=9A=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../YuDaoMidjourneyMessageHandler.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java new file mode 100644 index 000000000..5e065bbfd --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.ai.service.midjourneyHandler; + +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyMessage; +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyMessageHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * yudao message handler + * + * @author fansili + * @time 2024/4/29 14:34 + * @since 1.0 + */ +@Component +@Slf4j +public class YuDaoMidjourneyMessageHandler implements MidjourneyMessageHandler { + + @Override + public void messageHandler(MidjourneyMessage midjourneyMessage) { + log.info("yudao-midjourney-midjourney-message-handler", midjourneyMessage); + } +} From 59a289f18e53593c648ca94855f043f98d8bc4f3 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 14:52:42 +0800 Subject: [PATCH 196/684] =?UTF-8?q?=E5=A4=84=E7=90=86todo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ai/midjourney/api/MidjourneyInteractions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractions.java index 4077912a5..76549239a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractions.java @@ -73,7 +73,7 @@ public abstract class MidjourneyInteractions { */ protected HashMap getDefaultParams() { HashMap requestParams = Maps.newHashMap(); - // TODO @fansili:感觉参数的组装,可以搞成一个公用的方法;就是 config + 入参的感觉; + // TODO done @fansili:感觉参数的组装,可以搞成一个公用的方法;就是 config + 入参的感觉; requestParams.put("guild_id", midjourneyConfig.getGuildId()); requestParams.put("channel_id", midjourneyConfig.getChannelId()); requestParams.put("session_id", midjourneyConfig.getSessionId()); From 01552d30a6f05d3d405e941c2f43bdc064de1a63 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 14:53:00 +0800 Subject: [PATCH 197/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91mj?= =?UTF-8?q?=20=E6=B5=8B=E8=AF=95=E5=A2=9E=E5=8A=A0=20WssNotify?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ai/midjourney/MidjourneyWebSocketTests.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyWebSocketTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyWebSocketTests.java index a0d672873..cf90b17d8 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyWebSocketTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyWebSocketTests.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.framework.ai.midjourney; import cn.hutool.core.io.FileUtil; +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.WssNotify; import cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener.MidjourneyMessageListener; import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyWebSocketStarter; import org.junit.Before; @@ -38,7 +39,12 @@ public class MidjourneyWebSocketTests { var webSocketStarter = new MidjourneyWebSocketStarter(wssUrl, null, midjourneyConfig, messageListener); try { - webSocketStarter.start(); + webSocketStarter.start(new WssNotify() { + @Override + public void notify(int code, String message) { + + } + }); } catch (Exception e) { throw new RuntimeException(e); } From 3cc3695ec0602f37564e6ea7362175d25c6d477a Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 14:53:31 +0800 Subject: [PATCH 198/684] =?UTF-8?q?=E3=80=90=E6=B5=8B=E8=AF=95=E3=80=91?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=20midjourney=20=E6=8F=90=E4=BA=A4=E7=BB=98?= =?UTF-8?q?=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/http/image.http | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http index 069ebf1ba..a5282df16 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http @@ -1,5 +1,24 @@ -### chat call -GET {{baseUrl}}/ai/image/dallDrawing?modal=dall-e-2&size=256x256&prompt=中国长城 +### chat dallDrawing + +POST {{baseUrl}}/ai/image/dallDrawing +Content-Type: application/json Authorization: {{token}} +{ + "modal": "dall-e-3", + "size": "1024x1024", + "style": "vivid", + "prompt": "中国长城" +} + + +### chat midjourney + +POST {{baseUrl}}/ai/image/midjourney +Content-Type: application/json +Authorization: {{token}} + +{ + "prompt": "Mona Lisa, eating on a seat under a tree, wearing white clothes, smiling at the sky" +} \ No newline at end of file From cf3c1458672a30b804d38d3febdb297fae1d902c Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 14:54:11 +0800 Subject: [PATCH 199/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91?= =?UTF-8?q?=E6=8F=90=E4=BB=B7=20midjourney=20=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-server/src/main/resources/application-local.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index ffc9970c9..dd191ce9a 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -262,9 +262,9 @@ yudao: style: vivid midjourney: enable: true - token: OTcyNzIxMzA0ODkxNDUzNDUw.G_vMOz.BO_Q0sXAD80u5ZKIHPNYDTRX_FgeKL3cKFc53I - guild-id: 1225608134878302329 - channel-id: 1225608134878302332 + token: OTc1MzcyNDg1OTcxMzEyNzAw.G2iiSo.OqW9vToC5dokiyb1QOWnCwRPsYpOjLyNcf9--M + guild-id: 1234355413420347402 + channel-id: 1234380679576424448 captcha: enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试; security: From 27d6ba1e7f9a74fcf67dd4be1203d9179f35cb04 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 21:07:56 +0800 Subject: [PATCH 200/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91?= =?UTF-8?q?=E6=89=8B=E6=9C=BAmj=E5=BC=82=E5=B8=B8=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=EF=BC=8C=E5=88=B0=E5=90=8E=E6=9C=9F=E7=BB=9F=E4=B8=80=E5=A4=84?= =?UTF-8?q?=E7=90=86=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MessageUpdate-1.json | 86 +++++++ .../imageGenerationProcess/nonce错误信息.json | 239 ++++++++++++++++++ .../imageGenerationProcess/图片放大2倍.json | 72 ++++++ .../并发队列满提示.json | 82 ++++++ .../imageGenerationProcess/队列满.json | 94 +++++++ 5 files changed, 573 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/MessageUpdate-1.json create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/nonce错误信息.json create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/图片放大2倍.json create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/并发队列满提示.json create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/队列满.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/MessageUpdate-1.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/MessageUpdate-1.json new file mode 100644 index 000000000..5c21ebfaf --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/MessageUpdate-1.json @@ -0,0 +1,86 @@ +{ + "op": 0, + "s": 47, + "t": "MESSAGE_UPDATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [ + { + "filename": "97b1c75b-41c2-4dfe-bb7d-e61fbea8f1c7_grid_0.webp", + "size": 71390, + "content_type": "image/webp", + "width": 512, + "ephemeral": true, + "placeholder_version": 1, + "proxy_url": "https://media.discordapp.net/ephemeral-attachments/1234380679576424448/1234437493542359114/97b1c75b-41c2-4dfe-bb7d-e61fbea8f1c7_grid_0.webp?ex=6630bb01&is=662f6981&hm=60e610be44d3ae5fec8f1cbfb791997a627901d132a24e4364ac663362ab9a30&", + "placeholder": "XQgKBYJ8H3aDh3eHiAeIecB0Bsl2", + "id": "1234437493542359114", + "url": "https://cdn.discordapp.com/ephemeral-attachments/1234380679576424448/1234437493542359114/97b1c75b-41c2-4dfe-bb7d-e61fbea8f1c7_grid_0.webp?ex=6630bb01&is=662f6981&hm=60e610be44d3ae5fec8f1cbfb791997a627901d132a24e4364ac663362ab9a30&", + "height": 340 + } + ], + "interaction_metadata": { + "user_id": "975372485971312700", + "interacted_message_id": "1234433732761620500", + "authorizing_integration_owners": { + "0": "1234355413420347402" + }, + "id": "1234436261440126977", + "type": 3, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + }, + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "clan": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 64, + "type": 19, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-29T09:33:53.172018+00:00", + "content": "**A girl from China, creator of ancient Chinese clothing, dances on the square --ar 3:2** - Pan Right by <@975372485971312700> (35%) (relaxed)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + ], + "position": 0, + "message_reference": { + "guild_id": "1234355413420347402", + "message_id": "1234433732761620500", + "type": 0, + "channel_id": "1234380679576424448" + }, + "id": "1234436266045608016", + "embeds": [], + "channel_id": "1234380679576424448", + "timestamp": "2024-04-29T09:29:00.542000+00:00" + } +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/nonce错误信息.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/nonce错误信息.json new file mode 100644 index 000000000..5c3ae931f --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/nonce错误信息.json @@ -0,0 +1,239 @@ +{ + "op": 0, + "s": 24, + "t": "MESSAGE_UPDATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [ + { + "components": [ + { + "emoji": { + "name": "upscale_1", + "id": "940147353879478324" + }, + "custom_id": "MJ::JOB::upsample_v6_2x_subtle::1::519cd956-d02e-4ae2-b62d-17c499dbbe3f::SOLO", + "style": 2, + "label": "Upscale (Subtle)", + "type": 2 + }, + { + "emoji": { + "name": "upscale_1", + "id": "940147353879478324" + }, + "custom_id": "MJ::JOB::upsample_v6_2x_creative::1::519cd956-d02e-4ae2-b62d-17c499dbbe3f::SOLO", + "style": 2, + "label": "Upscale (Creative)", + "type": 2 + }, + { + "emoji": { + "name": "🪄" + }, + "custom_id": "MJ::JOB::low_variation::1::519cd956-d02e-4ae2-b62d-17c499dbbe3f::SOLO", + "style": 2, + "label": "Vary (Subtle)", + "type": 2 + }, + { + "emoji": { + "name": "🪄" + }, + "custom_id": "MJ::JOB::high_variation::1::519cd956-d02e-4ae2-b62d-17c499dbbe3f::SOLO", + "style": 2, + "label": "Vary (Strong)", + "type": 2 + }, + { + "emoji": { + "name": "🖌️" + }, + "custom_id": "MJ::Inpaint::1::519cd956-d02e-4ae2-b62d-17c499dbbe3f::SOLO", + "style": 2, + "label": "Vary (Region)", + "type": 2 + } + ], + "type": 1 + }, + { + "components": [ + { + "emoji": { + "name": "🔍" + }, + "custom_id": "MJ::Outpaint::50::1::519cd956-d02e-4ae2-b62d-17c499dbbe3f::SOLO", + "style": 4, + "label": "Zoom Out 2x", + "type": 2 + }, + { + "emoji": { + "name": "🔍" + }, + "custom_id": "MJ::Outpaint::75::1::519cd956-d02e-4ae2-b62d-17c499dbbe3f::SOLO", + "style": 2, + "label": "Zoom Out 1.5x", + "type": 2 + }, + { + "emoji": { + "name": "🔍" + }, + "custom_id": "MJ::CustomZoom::519cd956-d02e-4ae2-b62d-17c499dbbe3f", + "style": 2, + "label": "Custom Zoom", + "type": 2 + } + ], + "type": 1 + }, + { + "components": [ + { + "emoji": { + "name": "⬅️" + }, + "custom_id": "MJ::JOB::pan_left::1::519cd956-d02e-4ae2-b62d-17c499dbbe3f::SOLO", + "style": 2, + "type": 2 + }, + { + "emoji": { + "name": "➡️" + }, + "custom_id": "MJ::JOB::pan_right::1::519cd956-d02e-4ae2-b62d-17c499dbbe3f::SOLO", + "style": 2, + "type": 2 + }, + { + "emoji": { + "name": "⬆️" + }, + "custom_id": "MJ::JOB::pan_up::1::519cd956-d02e-4ae2-b62d-17c499dbbe3f::SOLO", + "style": 2, + "type": 2 + }, + { + "emoji": { + "name": "⬇️" + }, + "custom_id": "MJ::JOB::pan_down::1::519cd956-d02e-4ae2-b62d-17c499dbbe3f::SOLO", + "style": 2, + "type": 2 + } + ], + "type": 1 + }, + { + "components": [ + { + "emoji": { + "name": "❤️" + }, + "custom_id": "MJ::BOOKMARK::519cd956-d02e-4ae2-b62d-17c499dbbe3f", + "style": 2, + "type": 2 + }, + { + "style": 5, + "label": "Web", + "type": 2, + "url": "https://www.midjourney.com/app/jobs/519cd956-d02e-4ae2-b62d-17c499dbbe3f/" + } + ], + "type": 1 + } + ], + "attachments": [ + { + "filename": "andrakosq9211_A_girl_from_China_creator_of_ancient_Chinese_clot_519cd956-d02e-4ae2-b62d-17c499dbbe3f.png", + "size": 2014189, + "content_type": "image/png", + "width": 1024, + "placeholder_version": 1, + "proxy_url": "https://media.discordapp.net/attachments/1234380679576424448/1234433732341927976/andrakosq9211_A_girl_from_China_creator_of_ancient_Chinese_clot_519cd956-d02e-4ae2-b62d-17c499dbbe3f.png?ex=6630b780&is=662f6600&hm=8f273f74c29274431ec9b02bc4778a37ee944aa5360d10875cbbe512847b71c2&", + "placeholder": "YwgKDwKIWGiAiYd4iGh4d4h4mKz5uZwP", + "id": "1234433732341927976", + "url": "https://cdn.discordapp.com/attachments/1234380679576424448/1234433732341927976/andrakosq9211_A_girl_from_China_creator_of_ancient_Chinese_clot_519cd956-d02e-4ae2-b62d-17c499dbbe3f.png?ex=6630b780&is=662f6600&hm=8f273f74c29274431ec9b02bc4778a37ee944aa5360d10875cbbe512847b71c2&", + "height": 1024 + } + ], + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "clan": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 19, + "mention_roles": [], + "edited_timestamp": "2024-04-29T09:19:12.812177+00:00", + "content": "**A girl from China, creator of ancient Chinese clothing, dances on the square** - Image #3 <@975372485971312700>", + "tts": false, + "mentions": [ + { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:07:43.807000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:09:06.489349+00:00", + "communication_disabled_until": null, + "roles": [ + "1234355760184561747" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "guild_id": "1234355413420347402", + "position": 0, + "message_reference": { + "guild_id": "1234355413420347402", + "message_id": "1234433346940043294", + "type": 0, + "channel_id": "1234380679576424448" + }, + "id": "1234433732761620500", + "embeds": [ + { + "color": 16711680, + "description": "Hey <@975372485971312700>\nYour job queue is full. Please wait for a job to finish first, then resubmit this one.\n*[Please check the bottom of the channel for more information.](https://discord.com/channels/1234355413420347402/1234380679576424448/1234433798599606315)*", + "type": "rich", + "url": "https://discord.com/channels/1234355413420347402/1234380679576424448/1234433798599606315" + } + ], + "channel_id": "1234380679576424448", + "timestamp": "2024-04-29T09:18:56.560000+00:00" + } +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/图片放大2倍.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/图片放大2倍.json new file mode 100644 index 000000000..d8d9cb194 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/图片放大2倍.json @@ -0,0 +1,72 @@ +{ + "op": 0, + "s": 119, + "t": "MESSAGE_UPDATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [], + "interaction_metadata": { + "user_id": "975372485971312700", + "interacted_message_id": "1234430088515293194", + "authorizing_integration_owners": { + "0": "1234355413420347402" + }, + "id": "1234430127618658305", + "type": 3, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + }, + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "clan": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 64, + "type": 19, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-29T09:06:37.616666+00:00", + "content": "**A girl from China, creator of ancient Chinese clothing, dances on the square** - Zoom Out by <@975372485971312700> (22%) (relaxed)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + ], + "position": 0, + "message_reference": { + "guild_id": "1234355413420347402", + "message_id": "1234430088515293194", + "type": 0, + "channel_id": "1234380679576424448" + }, + "id": "1234430128721887272", + "embeds": [], + "channel_id": "1234380679576424448", + "timestamp": "2024-04-29T09:04:37.290000+00:00" + } +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/并发队列满提示.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/并发队列满提示.json new file mode 100644 index 000000000..c9f25ab2c --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/并发队列满提示.json @@ -0,0 +1,82 @@ +{ + "op": 0, + "s": 5, + "t": "MESSAGE_CREATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [], + "attachments": [], + "interaction_metadata": { + "user_id": "975372485971312700", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1234355413420347402" + }, + "id": "1234425115912179745", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + }, + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "clan": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 64, + "type": 20, + "mention_roles": [], + "nonce": "1234425114066419712", + "application_id": "936929561302675456", + "edited_timestamp": null, + "content": "", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [], + "interaction": { + "name": "imagine", + "id": "1234425115912179745", + "type": 2, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + }, + "position": 0, + "id": "1234425117380182102", + "embeds": [ + { + "content_scan_version": 0, + "color": 16239475, + "footer": { + "text": "/imagine Cartoon car" + }, + "description": "You have reached the maximum allowed number of concurrent jobs. Don't worry, this job will start as soon as another one finishes!", + "type": "rich", + "title": "Job queued" + } + ], + "channel_id": "1234380679576424448", + "timestamp": "2024-04-29T08:44:42.493000+00:00" + } +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/队列满.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/队列满.json new file mode 100644 index 000000000..7f7c75dc2 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/队列满.json @@ -0,0 +1,94 @@ +{ + "op": 0, + "s": 34, + "t": "MESSAGE_CREATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [ + { + "components": [ + { + "custom_id": "MJ::Job::Retry::64a7ec94-9607-492e-99ac-8550a4e7faf2", + "style": 2, + "label": "Resubmit", + "type": 2 + } + ], + "type": 1 + } + ], + "attachments": [], + "interaction_metadata": { + "user_id": "976067621160108072", + "name": "imagine", + "authorizing_integration_owners": { + "0": "1234483730148626542" + }, + "id": "1234491017005105172", + "type": 2, + "user": { + "global_name": "Sequoiab", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "976067621160108072", + "avatar": "2ef47ed59695ff8bcdc2254f5189b70c", + "username": "sequoiab2281", + "discriminator": "0" + } + }, + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "clan": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 64, + "type": 20, + "mention_roles": [], + "nonce": "1234491015356743680", + "application_id": "936929561302675456", + "edited_timestamp": null, + "content": "", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [], + "interaction": { + "name": "imagine", + "id": "1234491017005105172", + "type": 2, + "user": { + "global_name": "Sequoiab", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "976067621160108072", + "avatar": "2ef47ed59695ff8bcdc2254f5189b70c", + "username": "sequoiab2281", + "discriminator": "0" + } + }, + "position": 0, + "id": "1234491019211575376", + "embeds": [ + { + "content_scan_version": 0, + "color": 16711680, + "footer": { + "text": "/imagine Doctor Strange vs. Ultraman --v 6" + }, + "description": "Your job queue is full. Please wait for a job to finish first, then resubmit this one.", + "type": "rich", + "title": "Queue full" + } + ], + "channel_id": "1234490728575533057", + "timestamp": "2024-04-29T13:06:34.714000+00:00" + } +} \ No newline at end of file From d2c7dafdc98eac850ee47394a67bca11aa201824 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 22:02:38 +0800 Subject: [PATCH 201/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91Mid?= =?UTF-8?q?journey=20=E5=A2=9E=E5=8A=A0md=E6=96=87=E4=BB=B6=E5=AF=B9?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E4=BD=93=E8=BF=9B=E8=A1=8C=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../imageGenerationProcess/readme.md | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/readme.md diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/readme.md b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/readme.md new file mode 100644 index 000000000..0802bee85 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/readme.md @@ -0,0 +1,45 @@ + +# Midjourney 消息体解析 + +```text + +{ + "op": 0, + "s": 346, + "t": "MESSAGE_CREATE", // 消息类型 + "d": { + "id": "1234498661476601907", // 唯一id + "mention_everyone": false, + "pinned": false, + "channel_id": "1234380679576424448", // 频道id用来只区分自己频道 + "flags": 64, // flags 未知 + "type": 20, // 初步理解是用于区分消息类型 + "mention_roles": [], + "nonce": "18", // 重点,我们传过去的唯一id,用于区分不同的绘画 + "application_id": "936929561302675456", + "edited_timestamp": null, + "content": "", // 消息内容 + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [], + "components": [], // U1、U2等操作 + "attachments": [], // 生成的图片附件 + "embeds": [] // 重点异常、提示、错误 都是在这个里面,这个里面有信息这个任务就不正常 + } +} +``` + +说明: +- t: 是消息类型(处理 create、和update) + - MESSAGE_CREATE:会增加一条新的信息出来 + - MESSAGE_UPDATE:不会增加新的信息,在原来的信息上更新展示,比如进度条 10% 30%... + - MESSAGE_DELETE 没啥用 +- components:可以理解为可以操作的按钮 + - 情况1:正常只有图片完成才有对于操作 + - 情况2:异常情况可以 submit 当前任务 +- attachments: 附件,在图片生成到50%左右就会开始有模糊的图片,这里面就会有照片的地址 +- content:正常的消息内容在这里面,一般会是一串字符串,一般有 prompt、版本、进度、状态/生成类型 + - 内容示例:**海贼王,在赶海! --v 6.0** - <@975372485971312700> (0%) (relaxed) + - 内容示例:**海贼王,在赶海! --v 6.0** - <@975372485971312700> (35%) (relaxed) +- embeds: <重点> 只有错误、警告、封号、异常里面才有信息,可以优先判断这里面有没有内容,就知道是否正常! + From 60f66c59cb1f1487b5c293be29e7168ac9165738 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 22:08:23 +0800 Subject: [PATCH 202/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91mj?= =?UTF-8?q?=20Cancel=20Job=E6=8C=89=E9=92=AE=E7=9A=84=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E4=BD=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Cancel Job按钮的消息体.json | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/Cancel Job按钮的消息体.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/Cancel Job按钮的消息体.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/Cancel Job按钮的消息体.json new file mode 100644 index 000000000..186bd1311 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/Cancel Job按钮的消息体.json @@ -0,0 +1,84 @@ +{ + "op": 0, + "s": 1112, + "t": "MESSAGE_UPDATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [ + { + "components": [ + { + "custom_id": "MJ::CancelJob::ByJobid::a58fcee9-ec89-4471-aff3-088615fc78f2", + "style": 4, + "label": "Cancel Job", + "type": 2 + } + ], + "type": 1 + } + ], + "attachments": [], + "interaction_metadata": { + "user_id": "975372485971312700", + "interacted_message_id": "1234503859578081381", + "authorizing_integration_owners": { + "0": "1234355413420347402" + }, + "id": "1234506142236020767", + "type": 3, + "user": { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + }, + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "clan": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 64, + "type": 19, + "mention_roles": [], + "application_id": "936929561302675456", + "edited_timestamp": "2024-04-29T14:06:46.866376+00:00", + "content": "**A girl from China, creator of ancient Chinese clothing, dances on the square --v 6.0 --ar 3:2** - Variations (Strong) by <@975372485971312700> (0%) (relaxed)", + "tts": false, + "webhook_id": "936929561302675456", + "mentions": [ + { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + ], + "position": 0, + "message_reference": { + "guild_id": "1234355413420347402", + "message_id": "1234503859578081381", + "type": 0, + "channel_id": "1234380679576424448" + }, + "id": "1234506143943102605", + "embeds": [], + "channel_id": "1234380679576424448", + "timestamp": "2024-04-29T14:06:40.731000+00:00" + } +} \ No newline at end of file From ae934e84e8fd8245ac3194ecfe931f8697f15171 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 22:09:02 +0800 Subject: [PATCH 203/684] =?UTF-8?q?=E3=80=90=E6=B7=BB=E5=8A=A0=E3=80=91?= =?UTF-8?q?=E7=AD=89=E5=BE=85=E3=80=81=E8=BF=9B=E8=A1=8C=E4=B8=AD=20?= =?UTF-8?q?=E7=8A=B6=E6=80=81=EF=BC=8C=E8=AE=B0=E5=BD=95mj=E7=9A=84?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iocoder/yudao/module/ai/enums/AiChatDrawingStatusEnum.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatDrawingStatusEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatDrawingStatusEnum.java index e32cb94fa..2fcd90ee4 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatDrawingStatusEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatDrawingStatusEnum.java @@ -15,6 +15,8 @@ import lombok.Getter; public enum AiChatDrawingStatusEnum { SUBMIT("submit", "提交任务"), + WAITING("waiting", "等待"), + IN_PROGRESS("in_progress", "进行中"), COMPLETE("complete", "完成"), FAIL("fail", "失败"), From 03b4460eae5144eb1e6cdbc29a3b405517cce013 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 22:10:12 +0800 Subject: [PATCH 204/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91?= =?UTF-8?q?=E5=AF=B9=E6=8E=A5=20Midjourney=EF=BC=8C=E5=A2=9E=E5=8A=A0nonce?= =?UTF-8?q?=E4=BC=A0=E9=80=92=EF=BC=8C=E6=9B=B4=E6=96=B0Midjourney=20image?= =?UTF-8?q?=20=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/AiImageController.java | 6 +-- .../module/ai/service/AiImageService.java | 2 +- .../ai/service/impl/AiImageServiceImpl.java | 12 ++--- .../YuDaoMidjourneyMessageHandler.java | 51 ++++++++++++++++++- .../ai/midjourney/MidjourneyMessage.java | 47 +++++++++++++++++ .../api/MidjourneyInteractionsApi.java | 4 +- .../constants/MidjourneyConstants.java | 8 +++ .../listener/MidjourneyMessageListener.java | 25 ++++++++- 8 files changed, 140 insertions(+), 15 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java index aefdf14f4..622778861 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java @@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.ai.service.AiImageService; import cn.iocoder.yudao.module.ai.vo.AiImageDallDrawingReq; import cn.iocoder.yudao.module.ai.vo.AiImageMidjourneyReq; -import cn.iocoder.yudao.module.ai.vo.AiImageMidjourneyRes; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; @@ -42,7 +41,8 @@ public class AiImageController { @Operation(summary = "midjourney", description = "midjourney图片绘画流程:1、提交任务 2、获取完成的任务 3、选择对应功能 4、获取最终结果") @PostMapping("/midjourney") - public CommonResult midjourney(@Validated @RequestBody AiImageMidjourneyReq req) { - return CommonResult.success(aiImageService.midjourney(req)); + public CommonResult midjourney(@Validated @RequestBody AiImageMidjourneyReq req) { + aiImageService.midjourney(req); + return CommonResult.success(null); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java index f4395e398..997c9a6d7 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java @@ -28,5 +28,5 @@ public interface AiImageService { * @param req * @return */ - AiImageMidjourneyRes midjourney(AiImageMidjourneyReq req); + void midjourney(AiImageMidjourneyReq req); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java index d87e2d9f3..73e97c9c5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java @@ -95,18 +95,15 @@ public class AiImageServiceImpl implements AiImageService { @Override @Transactional(rollbackFor = Exception.class) - public AiImageMidjourneyRes midjourney(AiImageMidjourneyReq req) { + public void midjourney(AiImageMidjourneyReq req) { // 保存数据库 - doSave(req.getPrompt(), null, "midjoureny", + AiImageDO aiImageDO = doSave(req.getPrompt(), null, "midjoureny", null, AiChatDrawingStatusEnum.SUBMIT, null); // 提交 midjourney 任务 - Boolean imagine = midjourneyInteractionsApi.imagine(req.getPrompt()); + Boolean imagine = midjourneyInteractionsApi.imagine(aiImageDO.getId(), req.getPrompt()); if (!imagine) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MIDJOURNEY_IMAGINE_FAIL); } - // - - return null; } private static void sendSseEmitter(Utf8SseEmitter sseEmitter, Object object) { @@ -120,7 +117,7 @@ public class AiImageServiceImpl implements AiImageService { } } - private void doSave(String prompt, + private AiImageDO doSave(String prompt, String size, String model, String imageUrl, @@ -138,5 +135,6 @@ public class AiImageServiceImpl implements AiImageService { aiImageDO.setDrawingStatus(drawingStatusEnum.getStatus()); aiImageDO.setDrawingError(drawingError); aiImageMapper.insert(aiImageDO); + return aiImageDO; } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java index 5e065bbfd..a5d9fa80a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java @@ -1,7 +1,15 @@ package cn.iocoder.yudao.module.ai.service.midjourneyHandler; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyMessage; +import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyGennerateStatusEnum; import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyMessageHandler; +import cn.iocoder.yudao.module.ai.dal.dataobject.AiImageDO; +import cn.iocoder.yudao.module.ai.enums.AiChatDrawingStatusEnum; +import cn.iocoder.yudao.module.ai.mapper.AiImageMapper; +import com.alibaba.fastjson2.JSON; +import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -14,10 +22,51 @@ import org.springframework.stereotype.Component; */ @Component @Slf4j +@AllArgsConstructor public class YuDaoMidjourneyMessageHandler implements MidjourneyMessageHandler { + private final AiImageMapper aiImageMapper; + @Override public void messageHandler(MidjourneyMessage midjourneyMessage) { - log.info("yudao-midjourney-midjourney-message-handler", midjourneyMessage); + log.info("yudao-midjourney-midjourney-message-handler {}", JSON.toJSONString(midjourneyMessage)); + if (midjourneyMessage.getContent() != null) { + log.info("进度id {} 状态 {} 进度 {}", + midjourneyMessage.getNonce(), + midjourneyMessage.getGenerateStatus(), + midjourneyMessage.getContent().getProgress()); + } + // + updateImage(midjourneyMessage); + } + + private void updateImage(MidjourneyMessage midjourneyMessage) { + // Nonce 不存在不更新 + if (StrUtil.isBlank(midjourneyMessage.getNonce())) { + return; + } + // 获取id + Long aiImageId = Long.valueOf(midjourneyMessage.getNonce()); + // 获取生成 url + String imageUrl = null; + if (CollUtil.isNotEmpty(midjourneyMessage.getAttachments())) { + imageUrl = midjourneyMessage.getAttachments().get(0).getUrl(); + } + // 转换状态 + AiChatDrawingStatusEnum drawingStatusEnum = null; + String generateStatus = midjourneyMessage.getGenerateStatus(); + if (MidjourneyGennerateStatusEnum.COMPLETED.getStatus().equals(generateStatus)) { + drawingStatusEnum = AiChatDrawingStatusEnum.COMPLETE; + } else if (MidjourneyGennerateStatusEnum.IN_PROGRESS.getStatus().equals(generateStatus)) { + drawingStatusEnum = AiChatDrawingStatusEnum.IN_PROGRESS; + } else if (MidjourneyGennerateStatusEnum.WAITING.getStatus().equals(generateStatus)) { + drawingStatusEnum = AiChatDrawingStatusEnum.WAITING; + } + aiImageMapper.updateById( + new AiImageDO() + .setId(aiImageId) + .setDrawingImageUrl(imageUrl) + .setDrawingStatus(drawingStatusEnum == null ? null : drawingStatusEnum.getStatus()) + ); } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyMessage.java index f52ba9337..3ee83be1e 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyMessage.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyMessage.java @@ -14,6 +14,10 @@ public class MidjourneyMessage { * id是一个重要的字段,在同时生成多个的时候,可以区分生成信息 */ private String id; + /** + * 提交id(nonce 可能会不存在,系统提示的时候,这个为空) + */ + private String nonce; /** * 现在已知: * 0:我们发送的消息,和指令 @@ -45,6 +49,14 @@ public class MidjourneyMessage { * {@link MidjourneyGennerateStatusEnum} */ private String generateStatus; + /** + * 一般用于提示信息 + * - 错误 + * - 并发队列满了 + * - 账号违规了、敏感词 + * - 账号被封 + */ + private List embeds; @Data @Accessors(chain = true) @@ -123,4 +135,39 @@ public class MidjourneyMessage { private String progress; private String status; } + + /** + * embed 用于警告、提示、错误 + */ + @Data + @Accessors(chain = true) + public static class Embed { + + // 内容扫描版本号 + private int contentScanVersion; + + // 颜色值,这里用Java的Color类来表示,注意实际使用中可能需要自定义方法来从int转换为Color对象 + private String color; + + // 页脚信息,包含文本 + private Footer footer; + + // 描述信息 + private String description; + + // 消息类型,这里是富文本类型(这个区分不同提示类型) + private String type; + + // 标题 + private String title; + + // Footer类,作为嵌套类存在,用来表示footer部分的JSON对象 + @Data + @Accessors(chain = true) + public static class Footer { + // 页脚文本 + private String text; + } + + } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractionsApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractionsApi.java index e0b2334eb..8edeb22da 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractionsApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractionsApi.java @@ -38,11 +38,13 @@ public class MidjourneyInteractionsApi extends MidjourneyInteractions { this.url = midjourneyConfig.getServerUrl().concat(midjourneyConfig.getApiInteractions()); } - public Boolean imagine(String prompt) { + public Boolean imagine(Long id, String prompt) { + String nonce = String.valueOf(id); // 获取请求模板 String requestTemplate = midjourneyConfig.getRequestTemplates().get("imagine"); // 设置参数 HashMap requestParams = getDefaultParams(); + requestParams.put("nonce", nonce); requestParams.put("prompt", prompt); // 解析 template 参数占位符 String requestBody = MidjourneyUtil.parseTemplate(requestTemplate, requestParams); diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyConstants.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyConstants.java index ee180a0f4..29387a27b 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyConstants.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyConstants.java @@ -6,6 +6,10 @@ public final class MidjourneyConstants { * 消息 - 编号 */ public static final String MSG_ID = "id"; + /** + * 用于区分操作唯一性 + */ + public static final String MSG_NONCE = "nonce"; /** * 消息 - 类型 * 现在已知: @@ -32,6 +36,10 @@ public final class MidjourneyConstants { * 附件(生成中比较模糊的图片) */ public static final String MSG_ATTACHMENTS = "attachments"; + /** + * 一般用于提示 + */ + public static final String MSG_EMBEDS = "embeds"; // diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java index e85c4e8f7..0d196faf9 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java @@ -42,12 +42,14 @@ public class MidjourneyMessageListener { if (ignoreAndLogMessage(data, messageType)) { return; } + log.info("socket message: {}", raw); // 转换几个重要的信息 MidjourneyMessage mjMessage = new MidjourneyMessage(); - mjMessage.setId(data.getString(MidjourneyConstants.MSG_ID)); + mjMessage.setId(getString(data, MidjourneyConstants.MSG_ID, "")); + mjMessage.setNonce(getString(data, MidjourneyConstants.MSG_NONCE, "")); mjMessage.setType(data.getInt(MidjourneyConstants.MSG_TYPE)); mjMessage.setRawData(StrUtil.str(raw.toJson(), "UTF-8")); - mjMessage.setContent(MidjourneyUtil.parseContent(data.getString(MidjourneyConstants.MSG_CONTENT))); + mjMessage.setContent(MidjourneyUtil.parseContent(data.getString(MidjourneyConstants.MSG_CONTENT))); // 转换 components if (!data.getArray(MidjourneyConstants.MSG_COMPONENTS).isEmpty()) { String componentsJson = StrUtil.str(data.getArray(MidjourneyConstants.MSG_COMPONENTS).toJson(), "UTF-8"); @@ -60,6 +62,12 @@ public class MidjourneyMessageListener { List attachments = JsonUtils.parseArray(attachmentsJson, MidjourneyMessage.Attachment.class); mjMessage.setAttachments(attachments); } + // 转换 embeds 提示信息 + if (!data.getArray(MidjourneyConstants.MSG_EMBEDS).isEmpty()) { + String embedJson = StrUtil.str(data.getArray(MidjourneyConstants.MSG_EMBEDS).toJson(), "UTF-8"); + List embeds = JsonUtils.parseArray(embedJson, MidjourneyMessage.Embed.class); + mjMessage.setEmbeds(embeds); + } // 转换状态 convertGenerateStatus(mjMessage); // message handler 调用 @@ -68,7 +76,20 @@ public class MidjourneyMessageListener { } } + private String getString(DataObject data, String key, String defaultValue) { + if (!data.hasKey(key)) { + return defaultValue; + } + return data.getString(key); + } + private void convertGenerateStatus(MidjourneyMessage mjMessage) { + // + // tip:提示、警告、异常 content是没有内容的 + // tip: 一般错误信息在 Embeds 只要 Embeds有值,content就没信息。 + if (CollUtil.isNotEmpty(mjMessage.getEmbeds())) { + return; + } if (mjMessage.getType() == 20 && mjMessage.getContent().getStatus().contains("Waiting")) { mjMessage.setGenerateStatus(MidjourneyGennerateStatusEnum.WAITING.getStatus()); } else if (mjMessage.getType() == 20 && !StrUtil.isBlank(mjMessage.getContent().getProgress())) { From b3bc2d7a5ff39420d2675c2985f859c7eed23dc0 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 22:11:31 +0800 Subject: [PATCH 205/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=8D=E8=83=BD=E8=A7=A3=E6=9E=90=E7=9A=84?= =?UTF-8?q?content?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/framework/ai/midjourney/util/MidjourneyUtil.java | 1 + 1 file changed, 1 insertion(+) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MidjourneyUtil.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MidjourneyUtil.java index 92c7d42e0..7e4c94e2b 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MidjourneyUtil.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MidjourneyUtil.java @@ -31,6 +31,7 @@ public class MidjourneyUtil { // 南极应该是什么样子? // "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (32%) (fast, stealth)", // "**南极应该是什么样子? --v 6.0 --style raw** - <@972721304891453450> (fast, stealth)" + // Upscaling image #3 with **A girl from China, creator of ancient Chinese clothing, dances on the square** - <@975372485971312700> (Waiting to start) MidjourneyMessage.Content mjContent = new MidjourneyMessage.Content(); if (CharSequenceUtil.isBlank(content)) { return null; From 6b3020c04ab192d87b390bb987fef49d26c11082 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 22:11:55 +0800 Subject: [PATCH 206/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E6=B7=BB=E5=8A=A0nonce=E5=85=BC=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ai/midjourney/MidjourneyInteractionsTests.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java index 0ecf54f8b..bfc5aaa85 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.framework.ai.midjourney; import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.IdUtil; import cn.iocoder.yudao.framework.ai.midjourney.api.MidjourneyInteractionsApi; import cn.iocoder.yudao.framework.ai.midjourney.api.req.AttachmentsReq; import cn.iocoder.yudao.framework.ai.midjourney.api.req.DescribeReq; @@ -39,7 +40,7 @@ public class MidjourneyInteractionsTests { @Test public void mjImageTest() { MidjourneyInteractionsApi mjImagineInteractions = new MidjourneyInteractionsApi(midjourneyConfig); - mjImagineInteractions.imagine("童话里应该是什么样子?"); + mjImagineInteractions.imagine(IdUtil.getSnowflakeNextId(), "童话里应该是什么样子?"); } From 1fde659099e6c6d234d8991fb74c70d0fc6dd8e5 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 29 Apr 2024 22:25:59 +0800 Subject: [PATCH 207/684] =?UTF-8?q?=E3=80=90=E6=B7=BB=E5=8A=A0=E3=80=91=20?= =?UTF-8?q?=E6=82=A8=E7=9A=84=E5=B7=A5=E4=BD=9C=E9=98=9F=E5=88=97=E5=B7=B2?= =?UTF-8?q?=E6=BB=A1=E3=80=82=E8=AF=B7=E5=85=88=E7=AD=89=E5=BE=85=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A=E5=AE=8C=E6=88=90=EF=BC=8C=E7=84=B6=E5=90=8E=E9=87=8D?= =?UTF-8?q?=E6=96=B0=E6=8F=90=E4=BA=A4=E6=AD=A4=E4=BD=9C=E4=B8=9A=E3=80=82?= =?UTF-8?q?=20json=20=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...满。请先等待作业完成,然后重新提交此作业。.json | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/您的工作队列已满。请先等待作业完成,然后重新提交此作业。.json diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/您的工作队列已满。请先等待作业完成,然后重新提交此作业。.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/您的工作队列已满。请先等待作业完成,然后重新提交此作业。.json new file mode 100644 index 000000000..79fef4c6f --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/您的工作队列已满。请先等待作业完成,然后重新提交此作业。.json @@ -0,0 +1,165 @@ +{ + "op": 0, + "s": 1861, + "t": "MESSAGE_UPDATE", + "d": { + "mention_everyone": false, + "pinned": false, + "components": [ + { + "components": [ + { + "custom_id": "MJ::JOB::upsample::1::a58fcee9-ec89-4471-aff3-088615fc78f2", + "style": 2, + "label": "U1", + "type": 2 + }, + { + "custom_id": "MJ::JOB::upsample::2::a58fcee9-ec89-4471-aff3-088615fc78f2", + "style": 2, + "label": "U2", + "type": 2 + }, + { + "custom_id": "MJ::JOB::upsample::3::a58fcee9-ec89-4471-aff3-088615fc78f2", + "style": 2, + "label": "U3", + "type": 2 + }, + { + "custom_id": "MJ::JOB::upsample::4::a58fcee9-ec89-4471-aff3-088615fc78f2", + "style": 2, + "label": "U4", + "type": 2 + }, + { + "emoji": { + "name": "🔄" + }, + "custom_id": "MJ::JOB::reroll::0::a58fcee9-ec89-4471-aff3-088615fc78f2::SOLO", + "style": 1, + "type": 2 + } + ], + "type": 1 + }, + { + "components": [ + { + "custom_id": "MJ::JOB::variation::1::a58fcee9-ec89-4471-aff3-088615fc78f2", + "style": 2, + "label": "V1", + "type": 2 + }, + { + "custom_id": "MJ::JOB::variation::2::a58fcee9-ec89-4471-aff3-088615fc78f2", + "style": 2, + "label": "V2", + "type": 2 + }, + { + "custom_id": "MJ::JOB::variation::3::a58fcee9-ec89-4471-aff3-088615fc78f2", + "style": 2, + "label": "V3", + "type": 2 + }, + { + "custom_id": "MJ::JOB::variation::4::a58fcee9-ec89-4471-aff3-088615fc78f2", + "style": 2, + "label": "V4", + "type": 2 + } + ], + "type": 1 + } + ], + "attachments": [ + { + "filename": "andrakosq9211_A_girl_from_China_creator_of_ancient_Chinese_clot_a58fcee9-ec89-4471-aff3-088615fc78f2.png", + "size": 8558317, + "content_type": "image/png", + "width": 2688, + "placeholder_version": 1, + "proxy_url": "https://media.discordapp.net/attachments/1234380679576424448/1234506591949291592/andrakosq9211_A_girl_from_China_creator_of_ancient_Chinese_clot_a58fcee9-ec89-4471-aff3-088615fc78f2.png?ex=6630fb5b&is=662fa9db&hm=ce38fbb4da6acca7a545fadf53f1bfaa3096e04fe68d24750104a2e66719f84d&", + "placeholder": "YAgGBYBYFZeDa5eHegdnZ/3Erv7s", + "id": "1234506591949291592", + "url": "https://cdn.discordapp.com/attachments/1234380679576424448/1234506591949291592/andrakosq9211_A_girl_from_China_creator_of_ancient_Chinese_clot_a58fcee9-ec89-4471-aff3-088615fc78f2.png?ex=6630fb5b&is=662fa9db&hm=ce38fbb4da6acca7a545fadf53f1bfaa3096e04fe68d24750104a2e66719f84d&", + "height": 1792 + } + ], + "author": { + "global_name": null, + "bot": true, + "avatar_decoration_data": null, + "clan": null, + "public_flags": 589824, + "id": "936929561302675456", + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76", + "username": "Midjourney Bot", + "discriminator": "9282" + }, + "flags": 0, + "type": 19, + "mention_roles": [], + "edited_timestamp": "2024-04-29T14:16:39.564000+00:00", + "content": "**A girl from China, creator of ancient Chinese clothing, dances on the square --v 6.0 --ar 3:2** - Variations (Strong) by <@975372485971312700> (relaxed)", + "tts": false, + "mentions": [ + { + "global_name": "禁止挂软件刷图,逮到删服务器,踢设备,永久拉黑!!!", + "avatar_decoration_data": null, + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:07:43.807000+00:00", + "communication_disabled_until": null, + "roles": [], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "clan": null, + "public_flags": 0, + "id": "975372485971312700", + "avatar": "90ab939feddeaea32e23d066ce66d0e6", + "username": "andrakosq9211", + "discriminator": "0" + } + ], + "member": { + "premium_since": null, + "nick": null, + "joined_at": "2024-04-29T04:09:06.489349+00:00", + "communication_disabled_until": null, + "roles": [ + "1234355760184561747" + ], + "pending": false, + "flags": 0, + "deaf": false, + "mute": false, + "avatar": null + }, + "guild_id": "1234355413420347402", + "position": 0, + "message_reference": { + "guild_id": "1234355413420347402", + "message_id": "1234503859578081381", + "type": 0, + "channel_id": "1234380679576424448" + }, + "id": "1234506592565596251", + "embeds": [ + { + "color": 16711680, + "description": "Hey <@975372485971312700>\nYour job queue is full. Please wait for a job to finish first, then resubmit this one.\n*[Please check the bottom of the channel for more information.](https://discord.com/channels/1234355413420347402/1234380679576424448/1234508653562826822)*", + "type": "rich", + "url": "https://discord.com/channels/1234355413420347402/1234380679576424448/1234508653562826822" + } + ], + "channel_id": "1234380679576424448", + "timestamp": "2024-04-29T14:08:27.691000+00:00" + } +} \ No newline at end of file From 3afd2cba0cd5e46e04a0dc9f20449f1adbaa83e0 Mon Sep 17 00:00:00 2001 From: scholar <1145227973@qq.com> Date: Sat, 4 May 2024 22:24:23 +0800 Subject: [PATCH 208/684] =?UTF-8?q?=E5=AE=8C=E6=88=90todo=E9=83=A8?= =?UTF-8?q?=E5=88=86=EF=BC=8C=E4=BC=98=E5=8C=96=E7=8E=AF=E6=AF=94=E5=90=8C?= =?UTF-8?q?=E6=AF=94=E6=95=B0=E6=8D=AE=E7=9A=84=E8=AE=A1=E7=AE=97=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CrmStatisticsPerformanceServiceImpl.java | 119 +++++++++--------- 1 file changed, 57 insertions(+), 62 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java index c93951f81..b8fa94c7a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java @@ -55,16 +55,15 @@ public class CrmStatisticsPerformanceServiceImpl implements CrmStatisticsPerform } /** - * 获得员工业绩数据 - * + * 获得员工业绩数据,并通过如下方法拿到对应的lastYearCount,lastMonthCount + * 比如说,构造2024 年的CrmStatisticsPerformanceRespVO,获得 2023-01 到 2024-12的月统计数据即可 + * 可以数据 group by 年-月,2023-01 到 2024-12的,然后聚合出 CrmStatisticsPerformanceRespVO * @param performanceReqVO 参数 * @param performanceFunction 员工业绩统计方法 * @return 员工业绩数据 */ - private List getPerformance(CrmStatisticsPerformanceReqVO performanceReqVO, Function> performanceFunction) { - - List performanceRespVOList; + private List getPerformance(CrmStatisticsPerformanceReqVO performanceReqVO, + Function> performanceFunction) { // 1. 获得用户编号数组 final List userIds = getUserIds(performanceReqVO); @@ -72,75 +71,71 @@ public class CrmStatisticsPerformanceServiceImpl implements CrmStatisticsPerform return Collections.emptyList(); } performanceReqVO.setUserIds(userIds); + // 2. 获得业绩数据 - List performance = performanceFunction.apply(performanceReqVO); + List performanceList = performanceFunction.apply(performanceReqVO); // 获取查询的年份 String currentYear = LocalDateTimeUtil.format(performanceReqVO.getTimes()[0],"yyyy"); + Map currentYearMap = new TreeMap<>();//查询当年的map数据 + Map lastYearMap = new TreeMap<>();//前一年的map数据 - // 构造查询当年和前一年,每年12个月的年月组合 - List allMonths = new ArrayList<>(); - for (int year = Integer.parseInt(currentYear)-1; year <= Integer.parseInt(currentYear); year++) { - for (int month = 1; month <= 12; month++) { - allMonths.add(String.format("%d%02d", year, month)); - } + for (int month = 1; month <= 12; month++) { + //根据数据库的月销售数据查询结果,构造查询当年的map数据 + String currentYearKey = String.format("%d%02d", Integer.parseInt(currentYear), month); + buildYearMapData(performanceList, currentYearMap, currentYearKey); + + //根据数据库的月销售数据查询结果,构造查询前一年的map数据 + String lastYearKey = String.format("%d%02d", Integer.parseInt(currentYear)-1, month); + buildYearMapData(performanceList, lastYearMap, lastYearKey); } - - List computedList = new ArrayList<>(); + //根据构造好的map数据,计算查询当年的环比和同比数据,并构造好返回的respVOList List respVOList = new ArrayList<>(); - - // 生成computedList基础数据 - // 构造完整的2*12个月的数据,如果某月数据缺失,需要补上0,一年12个月不能有缺失 - for (String month : allMonths) { - CrmStatisticsPerformanceRespVO foundData = performance.stream() - .filter(data -> data.getTime().equals(month)) - .findFirst() - .orElse(null); - - if (foundData != null) { - computedList.add(foundData); - } else { - CrmStatisticsPerformanceRespVO missingData = new CrmStatisticsPerformanceRespVO(); - missingData.setTime(month); - missingData.setCurrentMonthCount(BigDecimal.ZERO); - missingData.setLastMonthCount(BigDecimal.ZERO); - missingData.setLastYearCount(BigDecimal.ZERO); - computedList.add(missingData); + for (int key : currentYearMap.keySet()) { + BigDecimal lastYearCount = lastYearMap.get(key-100).getCurrentMonthCount(); + BigDecimal lastMonthCount; + if (key % 100 > 1) {//2-12月份的前一个月数据 + lastMonthCount = currentYearMap.get(key-1).getCurrentMonthCount(); + } else {//1月份的前一个月数据 + lastMonthCount = lastYearMap.get(key-89).getCurrentMonthCount(); } + + currentYearMap.get(key).setLastYearCount(lastYearCount); + currentYearMap.get(key).setLastMonthCount(lastMonthCount); + + respVOList.add(currentYearMap.get(key)); } - //根据查询年份和前一年的数据,计算查询年份的同比环比数据 - for (CrmStatisticsPerformanceRespVO currentData : computedList) { - String currentMonth = currentData.getTime(); - // 根据当年和前一年的月销售数据,计算currentYear的完整数据 - if (currentMonth.startsWith(currentYear)) { - // 计算 LastMonthCount - int currentIndex = computedList.indexOf(currentData); - if (currentIndex > 0) { - CrmStatisticsPerformanceRespVO lastMonthData = computedList.get(currentIndex - 1); - currentData.setLastMonthCount(lastMonthData.getCurrentMonthCount()); - } else { - currentData.setLastMonthCount(BigDecimal.ZERO); // 第一个月的 LastMonthCount 设为0 - } - - // 计算 LastYearCount - String lastYearMonth = String.valueOf(Integer.parseInt(currentMonth) - 100); - CrmStatisticsPerformanceRespVO lastYearData = computedList.stream() - .filter(data -> data.getTime().equals(lastYearMonth)) - .findFirst() - .orElse(null); - - if (lastYearData != null) { - currentData.setLastYearCount(lastYearData.getCurrentMonthCount()); - } else { - currentData.setLastYearCount(BigDecimal.ZERO); // 如果去年同月数据不存在,设为0 - } - respVOList.add(currentData);//给前端只需要返回查询当年的数据,不需要前一年数据 - } - } return respVOList; } + /** + * 根据mapKey,添加当年和前一年的月销售记录到对应的map结构中 + * @param performanceList 数据库中查询到的月销售记录 + * @param YearDataMap 将查询到的月销售记录put到对应的map中,如果月销售记录为null,置为0 + * @param mapKey 对应的mapKey + */ + private void buildYearMapData(List performanceList, + Map YearDataMap, + String mapKey) + { + CrmStatisticsPerformanceRespVO currentYearData = performanceList.stream() + .filter(data -> data.getTime().equals(mapKey)) + .findFirst() + .orElse(null); + + if(currentYearData != null) { + YearDataMap.put(Integer.parseInt(mapKey), currentYearData); + } else { + CrmStatisticsPerformanceRespVO defaultVO = new CrmStatisticsPerformanceRespVO(); + defaultVO.setTime(mapKey); + defaultVO.setCurrentMonthCount(BigDecimal.ZERO); + defaultVO.setLastMonthCount(BigDecimal.ZERO); + defaultVO.setLastYearCount(BigDecimal.ZERO); + YearDataMap.put(Integer.parseInt(mapKey), defaultVO); + } + } + /** * 获取用户编号数组。如果用户编号为空, 则获得部门下的用户编号数组,包括子部门的所有用户编号 * From 0c0ac0b02abea90a949f78b2c5a26b51bed62723 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 6 May 2024 11:38:20 +0800 Subject: [PATCH 209/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E8=B0=83=E6=95=B4=20open=20ai=20image=20=E6=9E=9A=E4=B8=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/framework/ai/imageopenai/OpenAiImageOptions.java | 2 ++ .../ai/imageopenai/{ => enums}/OpenAiImageModelEnum.java | 2 +- .../ai/imageopenai/{ => enums}/OpenAiImageStyleEnum.java | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/{ => enums}/OpenAiImageModelEnum.java (92%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/{ => enums}/OpenAiImageStyleEnum.java (94%) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java index fd06fbe76..c2fa74890 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.framework.ai.imageopenai; import cn.iocoder.yudao.framework.ai.image.ImageOptions; +import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageModelEnum; +import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageStyleEnum; import lombok.Data; import lombok.Getter; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageModelEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/enums/OpenAiImageModelEnum.java similarity index 92% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageModelEnum.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/enums/OpenAiImageModelEnum.java index 919dd11d6..08cd2ae95 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageModelEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/enums/OpenAiImageModelEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.imageopenai; +package cn.iocoder.yudao.framework.ai.imageopenai.enums; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageStyleEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/enums/OpenAiImageStyleEnum.java similarity index 94% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageStyleEnum.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/enums/OpenAiImageStyleEnum.java index e586420a5..63feb85d3 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageStyleEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/enums/OpenAiImageStyleEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.imageopenai; +package cn.iocoder.yudao.framework.ai.imageopenai.enums; import lombok.AllArgsConstructor; import lombok.Getter; From 118158424b7cd152a2752468533af212854c3207 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 6 May 2024 15:55:43 +0800 Subject: [PATCH 210/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E8=80=83=E8=99=91=E5=88=B0=E5=89=8D=E7=AB=AF=E4=BC=A0=E5=85=A5?= =?UTF-8?q?=E7=9A=84json=E9=85=8D=E7=BD=AE=E4=B8=8D=E7=A1=AE=E5=AE=9A?= =?UTF-8?q?=EF=BC=8C=E5=85=88=E4=B8=8D=E8=BD=AC=E5=8C=96config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/convert/AiChatModalConvert.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java index cb3f644c0..c8b7f0405 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java @@ -4,12 +4,14 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO; import cn.iocoder.yudao.module.ai.vo.AiChatModalAddReq; import cn.iocoder.yudao.module.ai.vo.AiChatModalListRes; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; import org.mapstruct.factory.Mappers; import java.util.List; /** - * 聊天 对话 convert + * 聊天 modal * * @author fansili * @time 2024/4/18 16:39 @@ -29,10 +31,13 @@ public interface AiChatModalConvert { List convertAiChatModalListRes(List list); /** - * 转换 - AiChatModalDO + * 转换 - AiChatModalDO * * @param req * @return */ + @Mappings({ + @Mapping(target = "config", ignore = true) + }) AiChatModalDO convertAiChatModalDO(AiChatModalAddReq req); } From c21b5f76790e9cc05bfa0dd2545be057e96e1f94 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 6 May 2024 16:32:47 +0800 Subject: [PATCH 211/684] =?UTF-8?q?=E3=80=90=E8=B0=83=E6=95=B4=E3=80=91?= =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E6=8E=A5=E5=8F=A3=E8=AE=BE=E8=AE=A1=E8=B0=83?= =?UTF-8?q?=E6=95=B4=EF=BC=8Cai=20model?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/ErrorCodeConstants.java | 25 +++--- .../module/ai/enums/AiChatModalTypeEnum.java | 11 +++ .../ai/controller/AiChatModalController.java | 2 +- .../ai/dal/dataobject/AiChatModalDO.java | 20 ++--- .../ai/dal/vo/AiChatModalChatConfigVO.java | 35 ++++++++ .../module/ai/dal/vo/AiChatModalConfigVO.java | 28 +++++++ .../ai/dal/vo/AiChatModalDallConfigVO.java | 41 ++++++++++ .../dal/vo/AiChatModalMidjourneyConfigVO.java | 16 ++++ .../AiChatModelConfigTypeHandler.java | 75 +++++++++++++++++ .../service/impl/AiChatModalServiceImpl.java | 80 ++++++++++++++++++- .../ai/service/impl/AiImageServiceImpl.java | 5 +- .../yudao/module/ai/vo/AiChatModalAddReq.java | 22 +++-- .../module/ai/vo/AiChatModalListRes.java | 42 +++++----- .../src/main/resources/http/chat-modal.http | 34 ++++++-- .../yudao/framework/ai/AiPlatformEnum.java | 18 +++++ .../ai/config/YudaoAiProperties.java | 4 +- 16 files changed, 392 insertions(+), 66 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatModalTypeEnum.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalChatConfigVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalConfigVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalDallConfigVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalMidjourneyConfigVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/typeHandler/AiChatModelConfigTypeHandler.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index 5839f11f1..12652cb0b 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -11,24 +11,27 @@ public interface ErrorCodeConstants { // ========== 模块 ai 错误码区间 [1-022-000-000 ~ 1-023-000-000) ========== - // TODO @fansili:1)类注释不太对;2)中英文之间,有个空格;例如说 AI 模型 - ErrorCode AI_MODULE_NOT_SUPPORTED = new ErrorCode(1_022_000_000, "AI模型暂不支持!"); + // chat + ErrorCode AI_MODULE_NOT_SUPPORTED = new ErrorCode(1_022_000_000, "AI 模型暂不支持!"); ErrorCode AI_CHAT_ROLE_NOT_EXISTENT = new ErrorCode(1_022_000_001, "AI Role 不存在!");; + ErrorCode AI_CHAT_CONTINUE_CONVERSATION_ID_NOT_NULL = new ErrorCode(1_022_000_002, "chat 继续对话,对话 id 不能为空!");; + ErrorCode AI_CHAT_CONTINUE_NOT_EXIST = new ErrorCode(1_022_000_020, "chat 对话不存在!"); + ErrorCode AI_CHAT_CONVERSATION_NOT_YOURS = new ErrorCode(1_022_000_021, "这条 chat 对话不是你的!"); - - ErrorCode AI_CHAT_CONTINUE_CONVERSATION_ID_NOT_NULL = new ErrorCode(1_022_000_002, "chat 继续对话,对话id不能为空!");; - - - - ErrorCode AI_CHAT_CONTINUE_NOT_EXIST = new ErrorCode(1_022_000_020, "chat对话不存在!"); - ErrorCode AI_CHAT_CONVERSATION_NOT_YOURS = new ErrorCode(1_022_000_021, "这条chat对话不是你的!"); + // midjourney ErrorCode AI_MIDJOURNEY_IMAGINE_FAIL = new ErrorCode(1_022_000_040, "midjourney imagine 操作失败!"); - ErrorCode AI_CHAT_ROLE_NOT_EXIST = new ErrorCode(1_022_000_060, "chatRole不存在!"); + // role - ErrorCode AI_MODAL_NOT_EXIST = new ErrorCode(1_022_000_080, "ai模型不存在!"); + ErrorCode AI_CHAT_ROLE_NOT_EXIST = new ErrorCode(1_022_000_060, "chatRole 不存在!"); + // modal + + ErrorCode AI_MODAL_NOT_EXIST = new ErrorCode(1_022_000_080, "AI 模型不存在!"); + ErrorCode AI_MODAL_CONFIG_PARAMS_INCORRECT = new ErrorCode(1_022_000_081, "AI 模型 config 参数不正确! {} "); + ErrorCode AI_MODAL_NOT_SUPPORTED_MODAL = new ErrorCode(1_022_000_082, "AI 模型不支持的 modal! {} "); + ErrorCode AI_MODAL_PLATFORM_PARAMS_INCORRECT = new ErrorCode(1_022_000_083, "AI 平台参数不正确! {} "); } diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatModalTypeEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatModalTypeEnum.java new file mode 100644 index 000000000..0cf6c6ab1 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatModalTypeEnum.java @@ -0,0 +1,11 @@ +package cn.iocoder.yudao.module.ai.enums; + +/** + * 枚举 + * + * @author fansili + * @time 2024/5/6 11:48 + * @since 1.0 + */ +public enum AiChatModalTypeEnum { +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java index 9530f23b9..cbbb23049 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java @@ -30,7 +30,7 @@ public class AiChatModalController { private final AiChatModalService aiChatModalService; - @Operation(summary = "ai模型 - 模型照片上传") + @Operation(summary = "ai模型 - 模型列表") @GetMapping("/modal/list") public PageResult list(@ModelAttribute AiChatModalListReq req) { return aiChatModalService.list(req); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java index c417e5a44..43175d349 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java @@ -22,27 +22,23 @@ public class AiChatModalDO extends BaseDO { */ private Long id; /** - * 模型key + * 名字 */ - private String modelKey; + private String name; /** - * 模型类型 参考:{@link cn.iocoder.yudao.framework.ai.AiPlatformEnum} - */ - private String modelPlatform; - /** - * 模型类型 + * 类型 * {@link cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel} * {@link cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel} */ - private String modelType; + private String modal; /** - * 模型名字 + * 平台 参考:{@link cn.iocoder.yudao.framework.ai.AiPlatformEnum} */ - private String modelName; + private String platform; /** - * 模型照片 + * 图片地址 */ - private String modalImage; + private String imageUrl; /** * 禁用 0、正常 1、禁用 */ diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalChatConfigVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalChatConfigVO.java new file mode 100644 index 000000000..79cce7ad4 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalChatConfigVO.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.ai.dal.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * chat config + * + * @author fansili + * @time 2024/5/6 15:06 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class AiChatModalChatConfigVO extends AiChatModalConfigVO { + + @NotNull + @Schema(description = "在生成消息时采用的Top-K采样大小") + private Double topK; + + @NotNull + @Schema(description = "Top-P核采样方法的概率阈值") + private Double topP; + + @NotNull + @Schema(description = "温度参数,用于调整生成回复的随机性和多样性程度") + private Double temperature; + + @NotNull + @Schema(description = "最大 tokens") + private Integer maxTokens; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalConfigVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalConfigVO.java new file mode 100644 index 000000000..1b6e957d0 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalConfigVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.ai.dal.vo; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * modal config + * + * @author fansili + * @time 2024/5/6 15:06 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class AiChatModalConfigVO { + + /** + * 模型平台 (冗余,方便类型转换) + * 参考:{@link cn.iocoder.yudao.framework.ai.AiPlatformEnum} + */ + private String platform; + /** + * 模型类型(冗余,方便类型转换) + * {@link cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel} + * {@link cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel} + */ + private String type; +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalDallConfigVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalDallConfigVO.java new file mode 100644 index 000000000..c7dce40e6 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalDallConfigVO.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.ai.dal.vo; + +import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageStyleEnum; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * dall + * + * @author fansili + * @time 2024/5/6 15:06 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class AiChatModalDallConfigVO extends AiChatModalConfigVO { + // 可选字段,默认为1 + // 生成图像的数量,必须在1到10之间。对于dall-e-3模型,目前仅支持n=1。 + private Integer n = 1; + + // 可选字段,默认为standard + // 设置生成图像的质量。hd质量将创建细节更丰富、图像整体一致性更高的图片。该参数仅对dall-e-3模型有效。 + private String quality = "standard"; + + // 可选字段,默认为url + // 返回生成图像的格式。必须是url或b64_json中的一种。URL链接的有效期是从生成图像后开始计算的60分钟内有效。 + private String responseFormat = "url"; + + // 可选字段,默认为1024x1024 + // 生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。 + private String size = "1024x1024"; + + // 可选字段,默认为vivid + // 图像生成的风格。可为vivid(生动)或natural(自然)。vivid会使模型偏向生成超现实和戏剧性的图像,而natural则会让模型产出更自然、不那么超现实的图像。该参数仅对dall-e-3模型有效。 + private OpenAiImageStyleEnum style = OpenAiImageStyleEnum.VIVID; + + // 可选字段 + // 代表您的终端用户的唯一标识符,有助于OpenAI监控并检测滥用行为。了解更多信息请参考官方文档。 + private String endUserId = "UID123456"; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalMidjourneyConfigVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalMidjourneyConfigVO.java new file mode 100644 index 000000000..543c58705 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalMidjourneyConfigVO.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.ai.dal.vo; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * Midjourney Config + * + * @author fansili + * @time 2024/5/6 15:07 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class AiChatModalMidjourneyConfigVO extends AiChatModalConfigVO { +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/typeHandler/AiChatModelConfigTypeHandler.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/typeHandler/AiChatModelConfigTypeHandler.java new file mode 100644 index 000000000..b1f54eaac --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/typeHandler/AiChatModelConfigTypeHandler.java @@ -0,0 +1,75 @@ +//package cn.iocoder.yudao.module.ai.mapper.typeHandler; +// +//import cn.hutool.core.util.StrUtil; +//import cn.iocoder.yudao.framework.ai.AiPlatformEnum; +//import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +//import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO; +//import org.apache.ibatis.type.BaseTypeHandler; +//import org.apache.ibatis.type.JdbcType; +//import org.apache.ibatis.type.MappedTypes; +// +//import java.sql.CallableStatement; +//import java.sql.PreparedStatement; +//import java.sql.ResultSet; +//import java.sql.SQLException; +// +///** +// * chat modal config +// * +// * @author fansili +// * @time 2024/5/6 11:18 +// * @since 1.0 +// */ +//@MappedTypes(value = AiChatModalDO.Config.class) +//public class AiChatModelConfigTypeHandler extends BaseTypeHandler { +// +// @Override +// public void setNonNullParameter(PreparedStatement ps, int i, AiChatModalDO.Config parameter, JdbcType jdbcType) throws SQLException { +// // 将 MyCustomType 转换为数据库类型并设置到 PreparedStatement 中 +// if (parameter == null) { +// ps.setString(i, ""); +// } else { +// ps.setString(i, JsonUtils.toJsonString(parameter)); +// } +// } +// +// @Override +// public AiChatModalDO.Config getNullableResult(ResultSet rs, String columnName) throws SQLException { +// // 从 ResultSet 中获取数据库类型并转换为 MyCustomType +// String str = rs.getString(columnName); +// if (StrUtil.isBlank(str)) { +// return null; +// } +// AiChatModalDO.Config config = JsonUtils.parseObject(str, AiChatModalDO.Config.class); +// // 获取平台 +// AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(config.getModelPlatform()); +// if (AiPlatformEnum.CHAT_PLATFORM_LIST.contains(platformEnum)) { +// return JsonUtils.parseObject(str, AiChatModalDO.ChatConfig.class); +// } else if (AiPlatformEnum.OPEN_AI_DALL == platformEnum) { +// return JsonUtils.parseObject(str, AiChatModalDO.OpenAiImageConfig.class); +// } else if (AiPlatformEnum.MIDJOURNEY == platformEnum) { +// return JsonUtils.parseObject(str, AiChatModalDO.MidjourneyConfig.class); +// } +// throw new IllegalArgumentException("ai模型中config不能转换! json: " + str); +// } +// +// @Override +// public AiChatModalDO.Config getNullableResult(ResultSet rs, int columnIndex) throws SQLException { +// // 从 ResultSet 中获取数据库类型并转换为 MyCustomType +// String str = rs.getString(columnIndex); +// if (StrUtil.isBlank(str)) { +// return null; +// } +// return JsonUtils.parseObject(str, AiChatModalDO.Config.class); +// } +// +// @Override +// public AiChatModalDO.Config getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { +// // 从 CallableStatement 中获取数据库类型并转换为 MyCustomType +// String str = cs.getString(columnIndex); +// if (StrUtil.isBlank(str)) { +// return null; +// } +// return JsonUtils.parseObject(str, AiChatModalDO.Config.class); +// } +//} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java index 9e4b6e41d..cc7f505b1 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java @@ -1,23 +1,34 @@ package cn.iocoder.yudao.module.ai.service.impl; import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.validation.ValidationUtil; +import cn.iocoder.yudao.framework.ai.AiPlatformEnum; +import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatModal; +import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel; +import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.convert.AiChatModalConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO; +import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalChatConfigVO; +import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalConfigVO; +import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalDallConfigVO; import cn.iocoder.yudao.module.ai.enums.AiChatModalDisableEnum; import cn.iocoder.yudao.module.ai.mapper.AiChatModalMapper; import cn.iocoder.yudao.module.ai.service.AiChatModalService; import cn.iocoder.yudao.module.ai.vo.AiChatModalAddReq; import cn.iocoder.yudao.module.ai.vo.AiChatModalListReq; import cn.iocoder.yudao.module.ai.vo.AiChatModalListRes; +import jakarta.validation.ConstraintViolation; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.List; +import java.util.Set; /** * ai 模型 @@ -40,7 +51,7 @@ public class AiChatModalServiceImpl implements AiChatModalService { queryWrapperX.eq(AiChatModalDO::getDisable, AiChatModalDisableEnum.NO.getValue()); // search if (!StrUtil.isBlank(req.getSearch())) { - queryWrapperX.like(AiChatModalDO::getModelName, req.getSearch().trim()); + queryWrapperX.like(AiChatModalDO::getName, req.getSearch().trim()); } // 默认排序 queryWrapperX.orderByDesc(AiChatModalDO::getId); @@ -53,21 +64,38 @@ public class AiChatModalServiceImpl implements AiChatModalService { @Override public void add(AiChatModalAddReq req) { + // 校验 platform、type + validatePlatform(req.getPlatform()); + validateModal(req.getPlatform(), req.getModal()); + // 转换config + AiChatModalConfigVO aiChatModalConfigVO = convertConfig(req); + // 校验 modal config + validateModalConfig(aiChatModalConfigVO); // 转换 do AiChatModalDO insertChatModalDO = AiChatModalConvert.INSTANCE.convertAiChatModalDO(req); - // + // 设置默认属性 insertChatModalDO.setDisable(AiChatModalDisableEnum.NO.getValue()); + insertChatModalDO.setConfig(JsonUtils.toJsonString(aiChatModalConfigVO)); // 保存数据库 aiChatModalMapper.insert(insertChatModalDO); } @Override public void update(Long id, AiChatModalAddReq req) { + // 校验 platform、type + validatePlatform(req.getPlatform()); + validateModal(req.getPlatform(), req.getModal()); + // 转换config + AiChatModalConfigVO aiChatModalConfigVO = convertConfig(req); + // 校验 modal config + validateModalConfig(aiChatModalConfigVO); + // 校验模型是否存在 validateChatModalExists(id); // 转换 updateChatModalDO AiChatModalDO updateChatModalDO = AiChatModalConvert.INSTANCE.convertAiChatModalDO(req); updateChatModalDO.setId(id); + updateChatModalDO.setConfig(JsonUtils.toJsonString(aiChatModalConfigVO)); // 更新数据库 aiChatModalMapper.updateById(updateChatModalDO); } @@ -86,4 +114,52 @@ public class AiChatModalServiceImpl implements AiChatModalService { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_NOT_EXIST); } } + + private void validateModal(String platform, String modal) { + AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(platform); + try { + if (AiPlatformEnum.QIAN_WEN == platformEnum) { + QianWenChatModal.valueOfModel(modal); + } else if (AiPlatformEnum.XING_HUO == platformEnum) { + XingHuoChatModel.valueOfModel(modal); + } else if (AiPlatformEnum.YI_YAN == platformEnum) { + YiYanChatModel.valueOfModel(modal); + } else { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_NOT_SUPPORTED_MODAL, platform); + } + } catch (IllegalArgumentException e) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_CONFIG_PARAMS_INCORRECT, e.getMessage()); + } + } + + private void validatePlatform(String platform) { + try { + AiPlatformEnum.valueOfPlatform(platform); + } catch (IllegalArgumentException e) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_PLATFORM_PARAMS_INCORRECT, e.getMessage()); + } + } + + private void validateModalConfig(AiChatModalConfigVO aiChatModalConfigVO) { + Set> validate = ValidationUtil.validate(aiChatModalConfigVO); + for (ConstraintViolation constraintViolation : validate) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_CONFIG_PARAMS_INCORRECT, constraintViolation.getMessage()); + } + } + + private static AiChatModalConfigVO convertConfig(AiChatModalAddReq req) { + AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(req.getPlatform()); + AiChatModalConfigVO resVo = null; + if (AiPlatformEnum.CHAT_PLATFORM_LIST.contains(platformEnum)) { + resVo = JsonUtils.parseObject(JsonUtils.toJsonString(req.getConfig()), AiChatModalChatConfigVO.class); + } else if (AiPlatformEnum.OPEN_AI_DALL == platformEnum) { + resVo = JsonUtils.parseObject(JsonUtils.toJsonString(req.getConfig()), AiChatModalDallConfigVO.class); + } + if (resVo == null) { + throw new IllegalArgumentException("ai模型中config不能转换! json: " + req.getConfig()); + } + resVo.setType(req.getModal()); + resVo.setPlatform(req.getPlatform()); + return resVo; + } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java index 73e97c9c5..fb5ebf690 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java @@ -5,9 +5,9 @@ import cn.iocoder.yudao.framework.ai.image.ImageGeneration; import cn.iocoder.yudao.framework.ai.image.ImagePrompt; import cn.iocoder.yudao.framework.ai.image.ImageResponse; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageClient; -import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageModelEnum; +import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageModelEnum; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageOptions; -import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageStyleEnum; +import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageStyleEnum; import cn.iocoder.yudao.framework.ai.midjourney.api.MidjourneyInteractionsApi; import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyWebSocketStarter; import cn.iocoder.yudao.framework.ai.midjourney.webSocket.WssNotify; @@ -21,7 +21,6 @@ import cn.iocoder.yudao.module.ai.mapper.AiImageMapper; import cn.iocoder.yudao.module.ai.service.AiImageService; import cn.iocoder.yudao.module.ai.vo.AiImageDallDrawingReq; import cn.iocoder.yudao.module.ai.vo.AiImageMidjourneyReq; -import cn.iocoder.yudao.module.ai.vo.AiImageMidjourneyRes; import jakarta.annotation.PostConstruct; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalAddReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalAddReq.java index b20c92d5b..4145e2cd4 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalAddReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalAddReq.java @@ -6,6 +6,8 @@ import jakarta.validation.constraints.Size; import lombok.Data; import lombok.experimental.Accessors; +import java.util.Map; + /** * ai chat modal * @@ -19,18 +21,24 @@ public class AiChatModalAddReq { @NotNull @Schema(description = "模型名字") - @Size(max = 60, message = "模型名字最大60") - private String modelName; + @Size(max = 60, message = "模型名字最大60个字符") + private String name; + + @NotNull + @Size(max = 32, message = "模型平台最大32个字符") + @Schema(description = "模型平台 参考 AiPlatformEnum") + private String platform; @NotNull @Schema(description = "模型类型(qianwen、yiyan、xinghuo、openai)") - @Size(max = 32, message = "模型类型最大32") - private String modelType; + @Size(max = 32, message = "模型类型最大32个字符") + private String modal; @Schema(description = "模型照片") - private String modalImage; + @Size(max = 256, message = "模型照片地址最大256个字符") + private String imageUrl; @Schema(description = "模型配置JSON") - private String modelConfig; - +// @Size(max = 1024, message = "模型配置最大1024个字符") + private Map config; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java index 3d1701560..d05ed7d0d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.ai.vo; +import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; @@ -13,29 +15,25 @@ import lombok.experimental.Accessors; @Data @Accessors(chain = true) public class AiChatModalListRes { - /** - * 编号 - */ + + @Schema(description = "id") private Long id; - /** - * 模型名字 - */ - private String modelName; - /** - * 模型类型(qianwen、yiyan、xinghuo、openai) - */ - private String modelType; - /** - * 模型照片 - */ - private String modalImage; - /** - * 模型配置JSON - */ - private String modelConfig; - /** - * 禁用 0、正常 1、禁用 - */ + + @Schema(description = "模型平台 参考 AiPlatformEnum") + private String platform; + + @Schema(description = "模型类型 参考 YiYanChatModel、XingHuoChatModel") + private String modal; + + @Schema(description = "模型名字") + private String name; + + @Schema(description = "模型照片") + private String image; + + @Schema(description = "禁用 0、正常 1、禁用") private Integer disable; + @Schema(description = "modal 配置") + private String config; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-modal.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-modal.http index aa2949920..50c89908c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-modal.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-modal.http @@ -1,19 +1,41 @@ - ### chat call GET {{baseUrl}}/ai/chat/modal/list Authorization: {{token}} - ### chat call PUT {{baseUrl}}/ai/chat/modal Content-Type: application/json Authorization: {{token}} { - "modelName": "小红书Ai写作大模型", - "modelType": "yiyan", - "modalImage": "", - "modelConfig": "" + "name": "小红书Ai写作大模型-plus", + "modal": "ERNIE-3.5-8K", + "platform": "yiyan", + "imageUrl": "", + "config": { + "topK": 0.6, + "topP": 0.6, + "temperature": 0.86, + "maxTokens": 2048 + } +} + +### chat call +POST {{baseUrl}}/ai/chat/modal/7 +Content-Type: application/json +Authorization: {{token}} + +{ + "name": "小红书Ai写作大模型-plus", + "modal": "ERNIE-3.5-8K", + "platform": "yiyan", + "imageUrl": "", + "config": { + "topK": 0.6, + "topP": 0.6, + "temperature": 0.86, + "maxTokens": 2048 + } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java index 717ced538..752cb042d 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java @@ -1,8 +1,11 @@ package cn.iocoder.yudao.framework.ai; +import com.google.common.collect.Lists; import lombok.AllArgsConstructor; import lombok.Getter; +import java.util.List; + /** * ai 模型平台 * @@ -17,12 +20,27 @@ public enum AiPlatformEnum { YI_YAN("yiyan", "一言"), QIAN_WEN("qianwen", "千问"), XING_HUO("xinghuo", "星火"), + OPEN_AI("openai", "openAi"), + OPEN_AI_DALL("dall", "dall"), + MIDJOURNEY("midjourney", "midjourney"), ; private String platform; private String name; + public static List CHAT_PLATFORM_LIST = Lists.newArrayList( + AiPlatformEnum.YI_YAN, + AiPlatformEnum.QIAN_WEN, + AiPlatformEnum.XING_HUO, + AiPlatformEnum.OPEN_AI + ); + + public static List IMAGE_PLATFORM_LIST = Lists.newArrayList( + AiPlatformEnum.OPEN_AI_DALL, + AiPlatformEnum.MIDJOURNEY + ); + public static AiPlatformEnum valueOfPlatform(String platform) { for (AiPlatformEnum itemEnum : AiPlatformEnum.values()) { if (itemEnum.getPlatform().equals(platform)) { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java index f9dcae04a..57ef69ef6 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.framework.ai.config; import cn.iocoder.yudao.framework.ai.AiPlatformEnum; import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel; import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel; -import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageModelEnum; -import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageStyleEnum; +import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageModelEnum; +import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageStyleEnum; import lombok.Data; import lombok.experimental.Accessors; import org.springframework.boot.context.properties.ConfigurationProperties; From 3d7c994bf96ae01fdd8a810a835ed0b9254115f7 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 6 May 2024 16:38:33 +0800 Subject: [PATCH 212/684] =?UTF-8?q?=E3=80=90=E8=B0=83=E6=95=B4=E3=80=91ai?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=EF=BC=8C=E5=A2=9E=E5=8A=A0sort=E6=8E=92?= =?UTF-8?q?=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/dal/dataobject/AiChatModalDO.java | 5 +++++ .../module/ai/service/impl/AiChatModalServiceImpl.java | 2 +- .../iocoder/yudao/module/ai/vo/AiChatModalAddReq.java | 10 +++++++--- .../iocoder/yudao/module/ai/vo/AiChatModalListRes.java | 3 +++ .../src/main/resources/http/chat-modal.http | 6 ++++-- 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java index 43175d349..cb045c549 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java @@ -43,8 +43,13 @@ public class AiChatModalDO extends BaseDO { * 禁用 0、正常 1、禁用 */ private Integer disable; + /** + * 排序 + */ + private Integer sort; /** * modal 配置(json) */ private String config; + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java index cc7f505b1..b8030cc9f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java @@ -54,7 +54,7 @@ public class AiChatModalServiceImpl implements AiChatModalService { queryWrapperX.like(AiChatModalDO::getName, req.getSearch().trim()); } // 默认排序 - queryWrapperX.orderByDesc(AiChatModalDO::getId); + queryWrapperX.orderByAsc(AiChatModalDO::getSort); // 查询 PageResult aiChatModalDOPageResult = aiChatModalMapper.selectPage(req, queryWrapperX); // 转换 res diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalAddReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalAddReq.java index 4145e2cd4..6a2b143dd 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalAddReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalAddReq.java @@ -19,25 +19,29 @@ import java.util.Map; @Accessors(chain = true) public class AiChatModalAddReq { - @NotNull @Schema(description = "模型名字") @Size(max = 60, message = "模型名字最大60个字符") + @NotNull(message = "模型名字不能为空!") private String name; - @NotNull @Size(max = 32, message = "模型平台最大32个字符") @Schema(description = "模型平台 参考 AiPlatformEnum") + @NotNull(message = "平台不能为空!") private String platform; - @NotNull @Schema(description = "模型类型(qianwen、yiyan、xinghuo、openai)") @Size(max = 32, message = "模型类型最大32个字符") + @NotNull(message = "modal模型不能为空!") private String modal; @Schema(description = "模型照片") @Size(max = 256, message = "模型照片地址最大256个字符") private String imageUrl; + @Schema(description = "排序") + @NotNull(message = "sort排序不能为空!") + private Integer sort; + @Schema(description = "模型配置JSON") // @Size(max = 1024, message = "模型配置最大1024个字符") private Map config; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java index d05ed7d0d..ce99e39db 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java @@ -34,6 +34,9 @@ public class AiChatModalListRes { @Schema(description = "禁用 0、正常 1、禁用") private Integer disable; + @Schema(description = "排序 asc 排序") + private Integer sort; + @Schema(description = "modal 配置") private String config; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-modal.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-modal.http index 50c89908c..ab8aa85c6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-modal.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-modal.http @@ -10,10 +10,11 @@ Content-Type: application/json Authorization: {{token}} { - "name": "小红书Ai写作大模型-plus", - "modal": "ERNIE-3.5-8K", + "name": "小红书Ai写作大模型4.0", + "modal": "ERNIE 4.0", "platform": "yiyan", "imageUrl": "", + "sort": 100, "config": { "topK": 0.6, "topP": 0.6, @@ -32,6 +33,7 @@ Authorization: {{token}} "modal": "ERNIE-3.5-8K", "platform": "yiyan", "imageUrl": "", + "sort": 1, "config": { "topK": 0.6, "topP": 0.6, From 2b7e7763bfea8083320425e82fe807949e67356f Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 6 May 2024 17:11:30 +0800 Subject: [PATCH 213/684] =?UTF-8?q?=E3=80=90=E8=B0=83=E6=95=B4=E3=80=91?= =?UTF-8?q?=E6=A0=B9=E6=8D=AEapi=E8=B0=83=E6=95=B4ai=E8=A7=92=E8=89=B2?= =?UTF-8?q?=EF=BC=8C=E5=88=A0=E9=99=A4=E5=AF=B9modal=E5=85=B3=E8=81=94=20?= =?UTF-8?q?=E5=92=8C=20modal=20topK=20=E7=9B=B8=E5=85=B3=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E3=80=82=E7=AE=80=E5=8D=95=E6=94=B9=E4=B8=BA=E5=8F=AA=E6=98=AF?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=E8=A7=92=E8=89=B2=E7=9A=84=E9=A2=84=E8=AE=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ityEnum.java => AiChatRoleEnableEnum.java} | 10 +++--- .../module/ai/enums/AiChatRoleSourceEnum.java | 36 ------------------- .../ai/controller/AiChatRoleController.java | 8 ++--- .../ai/dal/dataobject/AiChatRoleDO.java | 33 +++-------------- .../module/ai/service/AiChatRoleService.java | 2 +- .../impl/AiChatConversationServiceImpl.java | 2 +- .../service/impl/AiChatRoleServiceImpl.java | 17 ++++----- .../yudao/module/ai/vo/AiChatRoleAddReq.java | 28 +++------------ .../yudao/module/ai/vo/AiChatRoleListRes.java | 23 +++--------- .../module/ai/vo/AiChatRoleUpdateReq.java | 28 +++------------ .../ai/vo/AiChatRoleUpdateVisibilityReq.java | 4 +-- .../src/main/resources/http/chat-role.http | 26 +++++--------- 12 files changed, 45 insertions(+), 172 deletions(-) rename yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/{AiChatRoleVisibilityEnum.java => AiChatRoleEnableEnum.java} (64%) delete mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleSourceEnum.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleVisibilityEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleEnableEnum.java similarity index 64% rename from yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleVisibilityEnum.java rename to yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleEnableEnum.java index ec7a19a2c..81b29c0e5 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleVisibilityEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleEnableEnum.java @@ -12,10 +12,10 @@ import lombok.Getter; */ @AllArgsConstructor @Getter -public enum AiChatRoleVisibilityEnum { +public enum AiChatRoleEnableEnum { - PUBLIC("public", "公开"), - PRIVATE("private", "私有的"), + OPEN("open", "公开"), + CLOSE("close", "关闭"), ; @@ -24,8 +24,8 @@ public enum AiChatRoleVisibilityEnum { private String name; - public static AiChatRoleVisibilityEnum valueOfType(String type) { - for (AiChatRoleVisibilityEnum itemEnum : AiChatRoleVisibilityEnum.values()) { + public static AiChatRoleEnableEnum valueOfType(String type) { + for (AiChatRoleEnableEnum itemEnum : AiChatRoleEnableEnum.values()) { if (itemEnum.getType().equals(type)) { return itemEnum; } diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleSourceEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleSourceEnum.java deleted file mode 100644 index 94b004456..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleSourceEnum.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * chat角色 source - * - * @author fansili - * @time 2024/4/24 16:37 - * @since 1.0 - */ -@AllArgsConstructor -@Getter -public enum AiChatRoleSourceEnum { - - SYSTEM("system", "系统"), - CUSTOMER("customer", "用户自定义"), - - - ; - - private String type; - - private String name; - - - public static AiChatRoleSourceEnum valueOfType(String type) { - for (AiChatRoleSourceEnum itemEnum : AiChatRoleSourceEnum.values()) { - if (itemEnum.getType().equals(type)) { - return itemEnum; - } - } - throw new IllegalArgumentException("Invalid MessageType value: " + type); - } -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatRoleController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatRoleController.java index 137b8bfa4..2b459cdcb 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatRoleController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatRoleController.java @@ -48,10 +48,10 @@ public class AiChatRoleController { } @Operation(summary = "chat角色 - 修改可见性") - @PostMapping("/role/{id}/update-visibility") - public CommonResult updateVisibility(@PathVariable("id") Long id, - @Validated @RequestBody AiChatRoleUpdateVisibilityReq req) { - chatRoleService.updateVisibility(id, req); + @PostMapping("/role/{id}/update-enable") + public CommonResult updateEnable(@PathVariable("id") Long id, + @Validated @RequestBody AiChatRoleUpdateVisibilityReq req) { + chatRoleService.updateEnable(id, req); return CommonResult.success(null); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatRoleDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatRoleDO.java index 4683a81fa..8ceb886e4 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatRoleDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatRoleDO.java @@ -28,25 +28,15 @@ public class AiChatRoleDO extends BaseDO { */ private Long userId; - /** - * 模型编号,关联到角色使用的特定模型 - */ - private String modelId; - /** * 角色名,角色的显示名称 */ - private String roleName; + private String name; /** * 角色介绍,详细描述角色的功能或用途 */ - private String roleIntroduce; - - /** - * 角色来源,如 system(系统预置)、customer(用户自定义) - */ - private String roleSource; + private String introduce; /** * 分类,角色所属的类别,如娱乐、创作等 @@ -54,24 +44,9 @@ public class AiChatRoleDO extends BaseDO { private String classify; /** - * 发布状态,private 表示仅自己可见,public表示公开,disable表示禁用 + * 是否开启 open、close */ - private String visibility; - - /** - * 生成时的Top-K采样候选集大小 - */ - private Double topK; - - /** - * 生成时使用的核采样方法的概率阈值 - */ - private Double topP; - - /** - * 用于控制随机性和多样性的温度参数 - */ - private Double temperature; + private String enable; /** * 角色的使用次数统计 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java index d3bd201e9..f0bab1a16 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java @@ -42,7 +42,7 @@ public interface AiChatRoleService { * @param id * @param req */ - void updateVisibility(Long id, AiChatRoleUpdateVisibilityReq req); + void updateEnable(Long id, AiChatRoleUpdateVisibilityReq req); /** * chat角色 - 删除 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java index 8e6a520c7..bc657b855 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java @@ -65,7 +65,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService AiChatRoleDO aiChatRoleDO = aiChatRoleMapper.selectById(req.getChatRoleId()); // 创建新的 Conversation AiChatConversationDO insertConversation = saveConversation(req.getTitle(), loginUserId, - req.getChatRoleId(), aiChatRoleDO.getRoleName(), AiChatConversationTypeEnum.ROLE_CHAT); + req.getChatRoleId(), aiChatRoleDO.getName(), AiChatConversationTypeEnum.ROLE_CHAT); // 转换 res return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(insertConversation); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java index 870168e2a..3ca9375b3 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java @@ -9,8 +9,7 @@ import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.convert.AiChatRoleConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatRoleDO; import cn.iocoder.yudao.module.ai.enums.AiChatRoleClassifyEnum; -import cn.iocoder.yudao.module.ai.enums.AiChatRoleSourceEnum; -import cn.iocoder.yudao.module.ai.enums.AiChatRoleVisibilityEnum; +import cn.iocoder.yudao.module.ai.enums.AiChatRoleEnableEnum; import cn.iocoder.yudao.module.ai.mapper.AiChatRoleMapper; import cn.iocoder.yudao.module.ai.service.AiChatRoleService; import cn.iocoder.yudao.module.ai.vo.*; @@ -39,7 +38,7 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { LambdaQueryWrapperX queryWrapperX = new LambdaQueryWrapperX<>(); // search 查询 if (!StrUtil.isBlank(req.getSearch())) { - queryWrapperX.eq(AiChatRoleDO::getRoleName, req.getSearch()); + queryWrapperX.eq(AiChatRoleDO::getName, req.getSearch()); } // 默认排序id desc queryWrapperX.orderByDesc(AiChatRoleDO::getId); @@ -56,8 +55,7 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { public void add(AiChatRoleAddReq req) { // 转换enum,并校验enum AiChatRoleClassifyEnum.valueOfClassify(req.getClassify()); - AiChatRoleVisibilityEnum.valueOfType(req.getVisibility()); - AiChatRoleSourceEnum.valueOfType(req.getRoleSource()); + AiChatRoleEnableEnum.valueOfType(req.getEnable()); // 转换do AiChatRoleDO insertAiChatRoleDO = AiChatRoleConvert.INSTANCE.convertAiChatRoleDO(req); insertAiChatRoleDO.setUserId(SecurityFrameworkUtils.getLoginUserId()); @@ -70,8 +68,7 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { public void update(Long id, AiChatRoleUpdateReq req) { // 转换enum,并校验enum AiChatRoleClassifyEnum.valueOfClassify(req.getClassify()); - AiChatRoleVisibilityEnum.valueOfType(req.getVisibility()); - AiChatRoleSourceEnum.valueOfType(req.getRoleSource()); + AiChatRoleEnableEnum.valueOfType(req.getEnable()); // 检查角色是否存在 validateChatRoleExists(id); // 转换do @@ -82,15 +79,15 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { @Override - public void updateVisibility(Long id, AiChatRoleUpdateVisibilityReq req) { + public void updateEnable(Long id, AiChatRoleUpdateVisibilityReq req) { // 转换enum,并校验enum - AiChatRoleVisibilityEnum.valueOfType(req.getVisibility()); + AiChatRoleEnableEnum.valueOfType(req.getEnable()); // 检查角色是否存在 validateChatRoleExists(id); // 更新 aiChatRoleMapper.updateById(new AiChatRoleDO() .setId(id) - .setVisibility(req.getVisibility()) + .setEnable(req.getEnable()) ); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleAddReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleAddReq.java index 63342c61b..15a803458 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleAddReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleAddReq.java @@ -16,39 +16,19 @@ import lombok.experimental.Accessors; @Accessors(chain = true) public class AiChatRoleAddReq extends PageParam { - @NotNull - @Schema(description = "模型编号,关联到角色使用的特定模型") - private String modelId; - @NotNull @Schema(description = "角色名,角色的显示名称") - private String roleName; + private String name; @NotNull @Schema(description = "角色介绍,详细描述角色的功能或用途") - private String roleIntroduce; - - @NotNull - @Schema(description = "角色来源,如 system(系统预置)、customer(用户自定义)") - private String roleSource; + private String introduce; @NotNull @Schema(description = "分类,角色所属的类别,如娱乐、创作等") private String classify; @NotNull - @Schema(description = "发布状态,private 表示仅自己可见,public表示公开,disable表示禁用\n") - private String visibility; - - @NotNull - @Schema(description = "生成时的Top-K采样候选集大小") - private Double topK; - - @NotNull - @Schema(description = "生成时使用的核采样方法的概率阈值") - private Double topP; - - @NotNull - @Schema(description = "用于控制随机性和多样性的温度参数") - private Double temperature; + @Schema(description = "开启状态 open、close") + private String enable; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleListRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleListRes.java index 8f582cc58..e018c43a2 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleListRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleListRes.java @@ -20,32 +20,17 @@ public class AiChatRoleListRes { @Schema(description = "用户id") private Long userId; - @Schema(description = "模型id") - private String modelId; - @Schema(description = "角色名字") - private String roleName; + private String name; @Schema(description = "角色介绍,详细描述角色的功能或用途") - private String roleIntroduce; - - @Schema(description = "角色来源,如 system(系统预置)、customer(用户自定义)") - private String roleSource; + private String introduce; @Schema(description = "分类,角色所属的类别,如娱乐、创作等") private String classify; - @Schema(description = "发布状态,0表示仅自己可见,1表示公开,2表示禁用") - private String visibility; - - @Schema(description = "生成时的Top-K采样候选集大小") - private Double topK; - - @Schema(description = "生成时使用的核采样方法的概率阈值") - private Double topP; - - @Schema(description = "用于控制随机性和多样性的温度参数") - private Double temperature; + @Schema(description = "状态 open、close") + private String enable; @Schema(description = "角色的使用次数统计") private Integer useCount; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleUpdateReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleUpdateReq.java index c6197f8d4..707c015f6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleUpdateReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleUpdateReq.java @@ -16,39 +16,19 @@ import lombok.experimental.Accessors; @Accessors(chain = true) public class AiChatRoleUpdateReq extends PageParam { - @NotNull - @Schema(description = "模型编号,关联到角色使用的特定模型") - private String modelId; - @NotNull @Schema(description = "角色名,角色的显示名称") - private String roleName; + private String name; @NotNull @Schema(description = "角色介绍,详细描述角色的功能或用途") - private String roleIntroduce; - - @NotNull - @Schema(description = "角色来源,如 system(系统预置)、customer(用户自定义)") - private String roleSource; + private String introduce; @NotNull @Schema(description = "分类,角色所属的类别,如娱乐、创作等") private String classify; @NotNull - @Schema(description = "发布状态,0表示仅自己可见,1表示公开,2表示禁用") - private String visibility; - - @NotNull - @Schema(description = "生成时的Top-K采样候选集大小") - private Double topK; - - @NotNull - @Schema(description = "生成时使用的核采样方法的概率阈值") - private Double topP; - - @NotNull - @Schema(description = "用于控制随机性和多样性的温度参数") - private Double temperature; + @Schema(description = "开启状态 open、close") + private String enable; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleUpdateVisibilityReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleUpdateVisibilityReq.java index d0d216b24..52685eb66 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleUpdateVisibilityReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleUpdateVisibilityReq.java @@ -17,6 +17,6 @@ import lombok.experimental.Accessors; public class AiChatRoleUpdateVisibilityReq extends PageParam { @NotNull - @Schema(description = "发布状态,0表示仅自己可见,1表示公开,2表示禁用") - private String visibility; + @Schema(description = "开启状态 open、close") + private String enable; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http index ae7e42c8f..8cbf517ba 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http @@ -11,41 +11,33 @@ Authorization: {{token}} { "modelId": 1, - "roleName": "小红书写作v1", - "roleIntroduce": "采用gpt3.5模型,拥有小红书优质作者写作经验。", - "roleSource": "system", + "name": "小红书写作v1", + "introduce": "采用gpt3.5模型,拥有小红书优质作者写作经验。", "classify": "writing", - "visibility": "public", - "topK": 0.2, - "topP": 0.4, - "temperature": 0.7 + "enable": "open" } ### chat update -POST {{baseUrl}}/ai/chat/role/1 +POST {{baseUrl}}/ai/chat/role/6 Content-Type: application/json Authorization: {{token}} { "modelId": 1, - "roleName": "小红书写作v1---hh😄", - "roleIntroduce": "采用gpt3.5模型,拥有小红书优质作者写作经验。", - "roleSource": "system", + "name": "小红书写作v1---hh😄", + "introduce": "采用gpt3.5模型,拥有小红书优质作者写作经验。", "classify": "writing", - "visibility": "public", - "topK": 0.2, - "topP": 0.4, - "temperature": 0.7 + "enable": "close" } ### chat update -POST {{baseUrl}}/ai/chat/role/1/update-visibility +POST {{baseUrl}}/ai/chat/role/6/update-visibility Content-Type: application/json Authorization: {{token}} { - "visibility": "private" + "enable": "open" } From c0470dcabb7ec3cd25dc0eabde7774081f73cac3 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 6 May 2024 18:21:17 +0800 Subject: [PATCH 214/684] =?UTF-8?q?=20=E3=80=90=E8=B0=83=E6=95=B4=E3=80=91?= =?UTF-8?q?=E6=A0=B9=E6=8D=AEapi=E8=AE=BE=E8=AE=A1=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E9=83=A8=E5=88=86=E5=AD=97=E6=AE=B5=EF=BC=8C=E5=92=8C=E4=B8=9A?= =?UTF-8?q?=E5=8A=A1=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/ErrorCodeConstants.java | 1 + .../AiChatConversationController.java | 12 ++- .../module/ai/convert/AiChatModalConvert.java | 11 +++ .../module/ai/convert/AiChatRoleConvert.java | 9 +++ .../dal/dataobject/AiChatConversationDO.java | 12 ++- .../module/ai/mapper/AiChatModalMapper.java | 22 ++++++ .../ai/service/AiChatConversationService.java | 9 +++ .../module/ai/service/AiChatModalService.java | 8 ++ .../module/ai/service/AiChatRoleService.java | 7 ++ .../impl/AiChatConversationServiceImpl.java | 76 ++++++++++++++----- .../service/impl/AiChatModalServiceImpl.java | 11 ++- .../service/impl/AiChatRoleServiceImpl.java | 7 ++ .../vo/AiChatConversationCreateRoleReq.java | 2 +- .../vo/AiChatConversationCreateUserReq.java | 1 + .../module/ai/vo/AiChatConversationRes.java | 11 ++- .../yudao/module/ai/vo/AiChatModalRes.java | 41 ++++++++++ .../yudao/module/ai/vo/AiChatRoleRes.java | 37 +++++++++ .../resources/http/chat-conversation.http | 16 +++- .../src/main/resources/http/chat-role.http | 6 +- 19 files changed, 266 insertions(+), 33 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalRes.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleRes.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index 12652cb0b..25b3b7109 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -33,5 +33,6 @@ public interface ErrorCodeConstants { ErrorCode AI_MODAL_CONFIG_PARAMS_INCORRECT = new ErrorCode(1_022_000_081, "AI 模型 config 参数不正确! {} "); ErrorCode AI_MODAL_NOT_SUPPORTED_MODAL = new ErrorCode(1_022_000_082, "AI 模型不支持的 modal! {} "); ErrorCode AI_MODAL_PLATFORM_PARAMS_INCORRECT = new ErrorCode(1_022_000_083, "AI 平台参数不正确! {} "); + ErrorCode AI_MODAL_DISABLE_NOT_USED = new ErrorCode(1_022_000_084, "AI 模型禁用不能使用!"); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatConversationController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatConversationController.java index e0f942042..6d5cb3154 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatConversationController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatConversationController.java @@ -32,13 +32,13 @@ public class AiChatConversationController { private final AiChatConversationService chatConversationService; @Operation(summary = "创建 - 对话普通对话") - @PostMapping("/createConversation") + @PutMapping("/createConversation") public CommonResult createConversation(@RequestBody @Validated AiChatConversationCreateUserReq req) { return CommonResult.success(chatConversationService.createConversation(req)); } @Operation(summary = "创建 - 对话角色对话") - @PostMapping("/createRoleConversation") + @PutMapping("/createRoleConversation") public CommonResult createRoleConversation(@RequestBody @Validated AiChatConversationCreateRoleReq req) { return CommonResult.success(chatConversationService.createRoleConversation(req)); } @@ -55,6 +55,14 @@ public class AiChatConversationController { return CommonResult.success(chatConversationService.listConversation(req)); } + @Operation(summary = "更新 - 更新模型") + @PostMapping("/{id}/modal") + public CommonResult updateModal(@PathVariable("id") Long id, + @RequestParam("modalId") Long modalId) { + chatConversationService.updateModal(id, modalId); + return CommonResult.success(null); + } + @Operation(summary = "删除") @DeleteMapping("/{id}") public CommonResult delete(@PathVariable("id") Long id) { diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java index c8b7f0405..52e47e05b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.ai.convert; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO; import cn.iocoder.yudao.module.ai.vo.AiChatModalAddReq; import cn.iocoder.yudao.module.ai.vo.AiChatModalListRes; +import cn.iocoder.yudao.module.ai.vo.AiChatModalRes; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Mappings; @@ -40,4 +41,14 @@ public interface AiChatModalConvert { @Mapping(target = "config", ignore = true) }) AiChatModalDO convertAiChatModalDO(AiChatModalAddReq req); + + + /** + * 转换 - AiChatModalRes + * + * @param aiChatModalDO + * @return + */ + AiChatModalRes convertAiChatModalRes(AiChatModalDO aiChatModalDO); + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java index 80977c442..bb936b998 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.convert; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatRoleDO; import cn.iocoder.yudao.module.ai.vo.AiChatRoleAddReq; +import cn.iocoder.yudao.module.ai.vo.AiChatRoleRes; import cn.iocoder.yudao.module.ai.vo.AiChatRoleUpdateReq; import cn.iocoder.yudao.module.ai.vo.AiChatRoleListRes; import org.mapstruct.Mapper; @@ -44,4 +45,12 @@ public interface AiChatRoleConvert { * @return */ AiChatRoleDO convertAiChatRoleDO(AiChatRoleUpdateReq req); + + /** + * 转换 - AiChatRoleRes + * + * @param aiChatRoleDO + * @return + */ + AiChatRoleRes convertAiChatRoleRes(AiChatRoleDO aiChatRoleDO); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatConversationDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatConversationDO.java index 7f5a142b3..1344d9956 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatConversationDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatConversationDO.java @@ -25,12 +25,18 @@ public class AiChatConversationDO extends BaseDO { private Long userId; @Schema(description = "chat角色Id") - private Long chatRoleId; + private Long roleId; @Schema(description = "chat角色名称") - private String chatRoleName; + private String roleName; - @Schema(description = "标题(有程序自动生成)") + @Schema(description = "模型id") + private Long modalId; + + @Schema(description = "使用的模型") + private String modal; + + @Schema(description = "标题") private String title; @Schema(description = "对话类型(roleChat、userChat)") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatModalMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatModalMapper.java index 118cda294..450791f41 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatModalMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatModalMapper.java @@ -1,6 +1,10 @@ package cn.iocoder.yudao.module.ai.mapper; +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; @@ -15,4 +19,22 @@ import org.springframework.stereotype.Repository; @Repository @Mapper public interface AiChatModalMapper extends BaseMapperX { + + /** + * 查询 - 第一个modal + * + * @return + */ + default AiChatModalDO selectFirstModal() { + PageResult pageResult = selectPage(new PageParam().setPageNo(1).setPageSize(1), + new LambdaQueryWrapperX() + .orderByAsc(AiChatModalDO::getSort) + ); + if (CollUtil.isEmpty(pageResult.getList())) { + return null; + } + return pageResult.getList().get(0); + } + + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java index fbae7c8c4..1a4c767a1 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java @@ -48,6 +48,15 @@ public interface AiChatConversationService { */ List listConversation(AiChatConversationListReq req); + /** + * 更新 - 更新模型 + * + * @param id + * @param modalId + * @return + */ + void updateModal(Long id, Long modalId); + /** * 删除 - 根据id * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java index 5681c1ba0..b1bf4a7d6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.vo.AiChatModalAddReq; import cn.iocoder.yudao.module.ai.vo.AiChatModalListReq; import cn.iocoder.yudao.module.ai.vo.AiChatModalListRes; +import cn.iocoder.yudao.module.ai.vo.AiChatModalRes; /** * ai modal @@ -44,4 +45,11 @@ public interface AiChatModalService { */ void delete(Long id); + /** + * 获取 - 获取 modal + * + * @param modalId + * @return + */ + AiChatModalRes getChatModal(Long modalId); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java index f0bab1a16..5c756075c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java @@ -51,4 +51,11 @@ public interface AiChatRoleService { */ void delete(Long chatRoleId); + /** + * 获取角色 + * + * @param roleId + * @return + */ + AiChatRoleRes getChatRole(Long roleId); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java index bc657b855..5906138b8 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java @@ -5,15 +5,16 @@ import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.convert.AiChatConversationConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatConversationDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatRoleDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO; import cn.iocoder.yudao.module.ai.enums.AiChatConversationTypeEnum; +import cn.iocoder.yudao.module.ai.enums.AiChatModalDisableEnum; import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; +import cn.iocoder.yudao.module.ai.mapper.AiChatModalMapper; import cn.iocoder.yudao.module.ai.mapper.AiChatRoleMapper; import cn.iocoder.yudao.module.ai.service.AiChatConversationService; -import cn.iocoder.yudao.module.ai.vo.AiChatConversationCreateRoleReq; -import cn.iocoder.yudao.module.ai.vo.AiChatConversationCreateUserReq; -import cn.iocoder.yudao.module.ai.vo.AiChatConversationListReq; -import cn.iocoder.yudao.module.ai.vo.AiChatConversationRes; +import cn.iocoder.yudao.module.ai.service.AiChatModalService; +import cn.iocoder.yudao.module.ai.service.AiChatRoleService; +import cn.iocoder.yudao.module.ai.vo.*; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; @@ -33,7 +34,10 @@ import java.util.List; public class AiChatConversationServiceImpl implements AiChatConversationService { private final AiChatRoleMapper aiChatRoleMapper; + private final AiChatModalMapper aiChatModalMapper; private final AiChatConversationMapper aiChatConversationMapper; + private final AiChatModalService aiChatModalService; + private final AiChatRoleService aiChatRoleService; @Override public AiChatConversationRes createConversation(AiChatConversationCreateUserReq req) { @@ -45,9 +49,12 @@ public class AiChatConversationServiceImpl implements AiChatConversationService if (latestConversation != null && latestConversation.getChatCount() <= 0) { return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(latestConversation); } + // 获取第一个模型 + AiChatModalDO aiChatModalDO = aiChatModalMapper.selectFirstModal(); // 创建新的 Conversation AiChatConversationDO insertConversation = saveConversation(req.getTitle(), loginUserId, - null, null, AiChatConversationTypeEnum.USER_CHAT); + null, null, AiChatConversationTypeEnum.USER_CHAT, + aiChatModalDO.getId(), aiChatModalDO.getModal()); // 转换 res return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(insertConversation); } @@ -57,43 +64,56 @@ public class AiChatConversationServiceImpl implements AiChatConversationService // 获取用户id Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 查询最新的对话 - AiChatConversationDO latestConversation = aiChatConversationMapper.selectLatestConversation(loginUserId); - // 如果有对话没有被使用过,那就返回这个 - if (latestConversation != null && latestConversation.getChatCount() <= 0) { - return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(latestConversation); - } - AiChatRoleDO aiChatRoleDO = aiChatRoleMapper.selectById(req.getChatRoleId()); +// AiChatConversationDO latestConversation = aiChatConversationMapper.selectLatestConversation(loginUserId); +// // 如果有对话没有被使用过,那就返回这个 +// if (latestConversation != null && latestConversation.getChatCount() <= 0) { +// return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(latestConversation); +// } + // 查询角色 + AiChatRoleRes chatRoleRes = aiChatRoleService.getChatRole(req.getRoleId()); + // 获取第一个模型 + AiChatModalDO aiChatModalDO = aiChatModalMapper.selectFirstModal(); // 创建新的 Conversation AiChatConversationDO insertConversation = saveConversation(req.getTitle(), loginUserId, - req.getChatRoleId(), aiChatRoleDO.getName(), AiChatConversationTypeEnum.ROLE_CHAT); + req.getRoleId(), chatRoleRes.getName(), AiChatConversationTypeEnum.ROLE_CHAT, + aiChatModalDO.getId(), aiChatModalDO.getModal()); // 转换 res return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(insertConversation); } private @NotNull AiChatConversationDO saveConversation(String title, Long userId, - Long chatRoleId, - String chatRoleName, - AiChatConversationTypeEnum typeEnum) { + Long roleId, + String roleName, + AiChatConversationTypeEnum typeEnum, + Long modalId, + String modal) { AiChatConversationDO insertConversation = new AiChatConversationDO(); insertConversation.setId(null); insertConversation.setUserId(userId); - insertConversation.setChatRoleId(chatRoleId); - insertConversation.setChatRoleName(chatRoleName); + insertConversation.setRoleId(roleId); + insertConversation.setRoleName(roleName); insertConversation.setTitle(title); insertConversation.setChatCount(0); insertConversation.setType(typeEnum.getType()); + insertConversation.setModalId(modalId); + insertConversation.setModal(modal); aiChatConversationMapper.insert(insertConversation); return insertConversation; } @Override public AiChatConversationRes getConversation(Long id) { + AiChatConversationDO aiChatConversationDO = validateExists(id); + return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(aiChatConversationDO); + } + + private @NotNull AiChatConversationDO validateExists(Long id) { AiChatConversationDO aiChatConversationDO = aiChatConversationMapper.selectById(id); if (aiChatConversationDO == null) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CHAT_CONTINUE_NOT_EXIST); } - return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(aiChatConversationDO); + return aiChatConversationDO; } @Override @@ -106,6 +126,24 @@ public class AiChatConversationServiceImpl implements AiChatConversationService return AiChatConversationConvert.INSTANCE.covnertChatConversationResList(top100Conversation); } + @Override + public void updateModal(Long id, Long modalId) { + // 校验对话是否存在 + validateExists(id); + // 获取模型 + AiChatModalRes chatModal = aiChatModalService.getChatModal(modalId); + // 判断模型是否禁用 + if (AiChatModalDisableEnum.YES.getValue().equals(chatModal.getDisable())) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_DISABLE_NOT_USED); + } + // 更新对话 + aiChatConversationMapper.updateById(new AiChatConversationDO() + .setId(id) + .setModalId(chatModal.getId()) + .setModal(chatModal.getModal()) + ); + } + @Override public void delete(Long id) { aiChatConversationMapper.deleteById(id); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java index b8030cc9f..4fc210baf 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java @@ -22,6 +22,7 @@ import cn.iocoder.yudao.module.ai.service.AiChatModalService; import cn.iocoder.yudao.module.ai.vo.AiChatModalAddReq; import cn.iocoder.yudao.module.ai.vo.AiChatModalListReq; import cn.iocoder.yudao.module.ai.vo.AiChatModalListRes; +import cn.iocoder.yudao.module.ai.vo.AiChatModalRes; import jakarta.validation.ConstraintViolation; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -108,11 +109,19 @@ public class AiChatModalServiceImpl implements AiChatModalService { aiChatModalMapper.deleteById(id); } - private void validateChatModalExists(Long id) { + @Override + public AiChatModalRes getChatModal(Long modalId) { + // 检查 modal 是否存在 + AiChatModalDO aiChatModalDO = validateChatModalExists(modalId); + return AiChatModalConvert.INSTANCE.convertAiChatModalRes(aiChatModalDO); + } + + private AiChatModalDO validateChatModalExists(Long id) { AiChatModalDO aiChatModalDO = aiChatModalMapper.selectById(id); if (aiChatModalDO == null) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_NOT_EXIST); } + return aiChatModalDO; } private void validateModal(String platform, String modal) { diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java index 3ca9375b3..fe36ee43b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java @@ -99,6 +99,13 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { aiChatRoleMapper.deleteById(chatRoleId); } + @Override + public AiChatRoleRes getChatRole(Long roleId) { + // 检查角色是否存在 + AiChatRoleDO aiChatRoleDO = validateChatRoleExists(roleId); + return AiChatRoleConvert.INSTANCE.convertAiChatRoleRes(aiChatRoleDO); + } + private AiChatRoleDO validateChatRoleExists(Long id) { AiChatRoleDO aiChatRoleDO = aiChatRoleMapper.selectById(id); if (aiChatRoleDO == null) { diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateRoleReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateRoleReq.java index 95223ce9f..0dc095bc1 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateRoleReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateRoleReq.java @@ -18,7 +18,7 @@ public class AiChatConversationCreateRoleReq { @Schema(description = "chat角色Id") @NotNull(message = "聊天角色id不能为空!") - private Long chatRoleId; + private Long roleId; @Schema(description = "标题(有程序自动生成)") @NotNull(message = "标题不能为空!") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateUserReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateUserReq.java index c8276ef80..9e3af32a0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateUserReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateUserReq.java @@ -19,4 +19,5 @@ public class AiChatConversationCreateUserReq { @Schema(description = "对话标题") @NotNull(message = "标题不能为空!") private String title; + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationRes.java index ca8254d5f..9e181bd01 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationRes.java @@ -22,10 +22,16 @@ public class AiChatConversationRes { private Long userId; @Schema(description = "chat角色Id") - private Long chatRoleId; + private Long roleId; @Schema(description = "chat角色名称") - private String chatRoleName; + private String roleName; + + @Schema(description = "模型id") + private Long modalId; + + @Schema(description = "使用的模型") + private String modal; @Schema(description = "标题(有程序自动生成)") private String title; @@ -35,4 +41,5 @@ public class AiChatConversationRes { @Schema(description = "聊天次数(有程序自动生成)") private Integer chatCount; + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalRes.java new file mode 100644 index 000000000..351da2538 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalRes.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.ai.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * modal list + * + * @author fansili + * @time 2024/4/24 19:56 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class AiChatModalRes { + + @Schema(description = "id") + private Long id; + + @Schema(description = "模型平台 参考 AiPlatformEnum") + private String platform; + + @Schema(description = "模型类型 参考 YiYanChatModel、XingHuoChatModel") + private String modal; + + @Schema(description = "模型名字") + private String name; + + @Schema(description = "模型照片") + private String image; + + @Schema(description = "禁用 0、正常 1、禁用") + private Integer disable; + + @Schema(description = "排序 asc 排序") + private Integer sort; + + @Schema(description = "modal 配置") + private String config; +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleRes.java new file mode 100644 index 000000000..a6903931c --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleRes.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.ai.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * chat 角色 + * + * @fansili + * @since v1.0 + */ +@Data +@Accessors(chain = true) +public class AiChatRoleRes { + + @Schema(description = "id") + private Long id; + + @Schema(description = "用户id") + private Long userId; + + @Schema(description = "角色名字") + private String name; + + @Schema(description = "角色介绍,详细描述角色的功能或用途") + private String introduce; + + @Schema(description = "分类,角色所属的类别,如娱乐、创作等") + private String classify; + + @Schema(description = "状态 open、close") + private String enable; + + @Schema(description = "角色的使用次数统计") + private Integer useCount; +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-conversation.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-conversation.http index 65230d9e9..15c441f34 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-conversation.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-conversation.http @@ -2,15 +2,27 @@ ### 登录 详细使用 https://www.jetbrains.com/help/idea/testing-restful-web-services.html、https://www.cnblogs.com/crazymakercircle/p/14317222.html ### 对话 - 创建对话 -POST {{baseUrl}}/ai/chat/conversation/create +PUT {{baseUrl}}/ai/chat/conversation/createConversation Content-Type: application/json Authorization: {{token}} { - "chatType": "userChat" + "title": "新增对话" } +### 对话 - 创建对话 +PUT {{baseUrl}}/ai/chat/conversation/createRoleConversation +Content-Type: application/json +Authorization: {{token}} + +{ + "roleId": 7, + "title": "新增对话" +} + + + ### 对话 - id获取 GET {{baseUrl}}/ai/chat/conversation/1781604279872581644 Authorization: {{token}} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http index 8cbf517ba..b459a5a95 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http @@ -19,14 +19,14 @@ Authorization: {{token}} ### chat update -POST {{baseUrl}}/ai/chat/role/6 +POST {{baseUrl}}/ai/chat/role/7 Content-Type: application/json Authorization: {{token}} { "modelId": 1, - "name": "小红书写作v1---hh😄", - "introduce": "采用gpt3.5模型,拥有小红书优质作者写作经验。", + "name": "小红书写作v1---hh😄❀", + "introduce": "采用gpt3.5模型,拥有小红书优质作者写作经验。0----", "classify": "writing", "enable": "close" } From e9cbee9d7ee593ad793b2a77a688616c61c7907b Mon Sep 17 00:00:00 2001 From: "zhijiantianya@gmail.com" Date: Mon, 6 May 2024 19:17:05 +0800 Subject: [PATCH 215/684] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91AI=EF=BC=9A=E8=B0=83=E6=95=B4=E8=A1=A8?= =?UTF-8?q?=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/enums/AiOpenAiModelEnum.java | 17 +-- .../chat/AiChatConversationControllerV2.java | 17 +++ .../admin/chat/vo/package-info.java | 1 + .../ai/controller/admin/package-info.java | 4 + .../ai/controller/app/package-info.java | 4 + .../module/ai/controller/package-info.java | 6 + .../ai/convert/AiChatConversationConvert.java | 2 +- .../ai/convert/AiChatMessageConvert.java | 2 +- .../module/ai/convert/AiChatModalConvert.java | 2 +- .../module/ai/convert/AiChatRoleConvert.java | 2 +- .../dal/dataobject/AiChatConversationDO.java | 47 -------- .../ai/dal/dataobject/AiChatMessageDO.java | 62 ---------- .../ai/dal/dataobject/AiChatModalDO.java | 55 --------- .../ai/dal/dataobject/AiChatRoleDO.java | 56 --------- .../dataobject/chat/AiChatConversationDO.java | 86 ++++++++++++++ .../dal/dataobject/chat/AiChatMessageDO.java | 109 ++++++++++++++++++ .../dal/dataobject/{ => image}/AiImageDO.java | 2 +- .../ai/dal/dataobject/model/AiApiKeyDO.java | 59 ++++++++++ .../dal/dataobject/model/AiChatModalDO.java | 75 ++++++++++++ .../ai/dal/dataobject/model/AiChatRoleDO.java | 82 +++++++++++++ .../ai/mapper/AiChatConversationMapper.java | 2 +- .../module/ai/mapper/AiChatMessageMapper.java | 4 +- .../module/ai/mapper/AiChatModalMapper.java | 1 - .../module/ai/mapper/AiChatRoleMapper.java | 2 +- .../yudao/module/ai/mapper/AiImageMapper.java | 2 +- .../impl/AiChatConversationServiceImpl.java | 2 - .../impl/AiChatMessageServiceImpl.java | 6 +- .../service/impl/AiChatModalServiceImpl.java | 1 - .../service/impl/AiChatRoleServiceImpl.java | 2 +- .../ai/service/impl/AiChatServiceImpl.java | 6 +- .../ai/service/impl/AiImageServiceImpl.java | 2 +- .../YuDaoMidjourneyMessageHandler.java | 2 +- .../module/ai/vo/AiChatModalListRes.java | 1 - 33 files changed, 468 insertions(+), 255 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationControllerV2.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/package-info.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/package-info.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/package-info.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/package-info.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatConversationDO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatMessageDO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatRoleDO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/{ => image}/AiImageDO.java (95%) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiApiKeyDO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModalDO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiOpenAiModelEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiOpenAiModelEnum.java index d87c980ba..993cabdcd 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiOpenAiModelEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiOpenAiModelEnum.java @@ -4,6 +4,7 @@ import lombok.AllArgsConstructor; import lombok.Getter; // TODO done @fansili:1)类注释要加下;2)author 和 time 用 javadoc,@author 和 @since;3)@AllArgsConstructor 使用这个注解,去掉构造方法;4)value 改成 model 字段,然后注释都写下哈;5)message 改成 name,然后注释都写下哈 +// TODO @fan: AiModelEnum 是不是可以缩写成这个哈;所有的模型,都写在这里枚举; /** * @author: fansili * @time: 2024/3/4 12:36 @@ -12,24 +13,18 @@ import lombok.Getter; @AllArgsConstructor public enum AiOpenAiModelEnum { - /** - * open ai 3.5模型 - */ - OPEN_AI_GPT_3_5("gpt-3.5-turbo", "GPT3.5"), - /** - * open ai 4.0 收费模型 - */ - OPEN_AI_GPT_4("gpt-4-turbo", "GPT4") + OPEN_AI_GPT_3_5("gpt-3.5-turbo", "GPT3.5"), + OPEN_AI_GPT_4("gpt-4-turbo", "GPT4") ; /** - * 模型 - 用于参数传递 + * 模型标志 - 用于参数传递 */ - private String model; + private final String model; /** * 模型名字 - 用于展示 */ - private String name; + private final String name; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationControllerV2.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationControllerV2.java new file mode 100644 index 000000000..6dfd0de12 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationControllerV2.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.ai.controller.admin.chat; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Tag(name = "管理后台 - 聊天会话") +@RestController +@RequestMapping("/ai/chat/conversation") +@Slf4j +public class AiChatConversationControllerV2 { + + public CommonResult> + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/package-info.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/package-info.java new file mode 100644 index 000000000..0e2d34fb4 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.ai.controller.admin.chat.vo; \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/package-info.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/package-info.java new file mode 100644 index 000000000..f28cc7058 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/package-info.java @@ -0,0 +1,4 @@ +/** + * TODO 芋艿:站位,无特殊作用 + */ +package cn.iocoder.yudao.module.ai.controller.admin; \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/package-info.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/package-info.java new file mode 100644 index 000000000..05b1ce233 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/app/package-info.java @@ -0,0 +1,4 @@ +/** + * TODO 芋艿:站位,无特殊作用 + */ +package cn.iocoder.yudao.module.ai.controller.app; \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/package-info.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/package-info.java new file mode 100644 index 000000000..68dfddfa3 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/package-info.java @@ -0,0 +1,6 @@ +/** + * 提供 RESTful API 给前端: + * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目 + * 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分 + */ +package cn.iocoder.yudao.module.ai.controller; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java index d6c93a1a5..012211926 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.ai.convert; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatConversationDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.vo.AiChatConversationRes; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java index 3a920a466..14f410a1e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.ai.convert; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatMessageDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import cn.iocoder.yudao.module.ai.vo.AiChatMessageListRes; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java index 52e47e05b..cd6714fdf 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.ai.convert; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; import cn.iocoder.yudao.module.ai.vo.AiChatModalAddReq; import cn.iocoder.yudao.module.ai.vo.AiChatModalListRes; import cn.iocoder.yudao.module.ai.vo.AiChatModalRes; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java index bb936b998..b056a6d06 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.ai.convert; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatRoleDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.vo.AiChatRoleAddReq; import cn.iocoder.yudao.module.ai.vo.AiChatRoleRes; import cn.iocoder.yudao.module.ai.vo.AiChatRoleUpdateReq; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatConversationDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatConversationDO.java deleted file mode 100644 index 1344d9956..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatConversationDO.java +++ /dev/null @@ -1,47 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.TableName; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * chat 交谈 - * - * @author fansili - * @time 2024/4/14 17:35 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -@TableName("ai_chat_conversation") -public class AiChatConversationDO extends BaseDO { - - @Schema(description = "id") - private Long id; - - @Schema(description = "用户id") - private Long userId; - - @Schema(description = "chat角色Id") - private Long roleId; - - @Schema(description = "chat角色名称") - private String roleName; - - @Schema(description = "模型id") - private Long modalId; - - @Schema(description = "使用的模型") - private String modal; - - @Schema(description = "标题") - private String title; - - @Schema(description = "对话类型(roleChat、userChat)") - private String type; - - @Schema(description = "聊天次数(有程序自动生成)") - private Integer chatCount; -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatMessageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatMessageDO.java deleted file mode 100644 index 5ed372ab4..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatMessageDO.java +++ /dev/null @@ -1,62 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * ai 聊天 message - * - * @fansili - * @since v1.0 - */ -@Data -@Accessors(chain = true) -@TableName("ai_chat_message") -public class AiChatMessageDO extends BaseDO { - - /** - * 编号,作为每条聊天记录的唯一标识符 - */ - private Long id; - - /** - * 聊天ID,关联到特定的会话或对话 - */ - private Long chatConversationId; - - /** - * 角色ID,用于标识发送消息的用户或系统的身份 - */ - private Long userId; - - /** - * 消息具体内容,存储用户的发言或者系统响应的文字信息 - */ - private String message; - - /** - * 消息类型,枚举值可能包括'system'(系统消息)、'user'(用户消息)和'assistant'(助手消息) - */ - private String messageType; - - /** - * 在生成消息时采用的Top-K采样大小, - * 表示模型生成回复时考虑的候选项集合的大小 - */ - private Double topK; - - /** - * Top-P核采样方法的概率阈值, - * 在语言模型生成过程中控制采样的过滤标准 - */ - private Double topP; - - /** - * 温度参数,用于调整生成回复的随机性和多样性程度, - * 较低的温度值会使输出更收敛于高频词汇,较高的则增加多样性 - */ - private Double temperature; - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java deleted file mode 100644 index cb045c549..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatModalDO.java +++ /dev/null @@ -1,55 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * ai 模型 - * - * @author fansili - * @time 2024/4/24 19:39 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -@TableName("ai_chat_modal") -public class AiChatModalDO extends BaseDO { - - /** - * 编号 - */ - private Long id; - /** - * 名字 - */ - private String name; - /** - * 类型 - * {@link cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel} - * {@link cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel} - */ - private String modal; - /** - * 平台 参考:{@link cn.iocoder.yudao.framework.ai.AiPlatformEnum} - */ - private String platform; - /** - * 图片地址 - */ - private String imageUrl; - /** - * 禁用 0、正常 1、禁用 - */ - private Integer disable; - /** - * 排序 - */ - private Integer sort; - /** - * modal 配置(json) - */ - private String config; - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatRoleDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatRoleDO.java deleted file mode 100644 index 8ceb886e4..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiChatRoleDO.java +++ /dev/null @@ -1,56 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * ai 聊天角色 - * - * @fansili - * @since v1.0 - */ -@Data -@Accessors(chain = true) -@TableName("ai_chat_role") -public class AiChatRoleDO extends BaseDO { - /** - * 编号,表示聊天角色在数据库中的唯一标识符 - */ - @TableId(type = IdType.AUTO) - private Long id; - - /** - * 用户ID,关联到使用该聊天角色的用户 - */ - private Long userId; - - /** - * 角色名,角色的显示名称 - */ - private String name; - - /** - * 角色介绍,详细描述角色的功能或用途 - */ - private String introduce; - - /** - * 分类,角色所属的类别,如娱乐、创作等 - */ - private String classify; - - /** - * 是否开启 open、close - */ - private String enable; - - /** - * 角色的使用次数统计 - */ - private Integer useCount; - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java new file mode 100644 index 000000000..4ac977011 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.ai.dal.dataobject.chat; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; +import cn.iocoder.yudao.module.ai.enums.AiOpenAiModelEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * AI Chat 会话 DO + * + * 用户每次发起 Chat 聊天时,会创建一个 {@link AiChatConversationDO} 对象,将它的消息关联在一起 + * + * @author fansili + * @since 2024/4/14 17:35 + */ +@TableName("ai_chat_conversation") +@KeySequence("ai_chat_conversation_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class AiChatConversationDO extends BaseDO { + + /** + * ID 编号,自增 + */ + @TableId + private Long id; + + /** + * 用户编号 + * + * 关联 AdminUserDO 的 userId 字段 + */ + private Long userId; + + /** + * 标题 + * + * 默认由系统自动生成,可用户手动修改 + */ + private String title; + + /** + * 角色编号 + * + * 关联 {@link AiChatRoleDO#getId()} + */ + private Long roleId; + /** + * 模型标志 + * + * 枚举 {@link AiOpenAiModelEnum} + */ + private String model; + + /** + * 模型编号 + * + * 关联 {@link AiChatModalDO#getId()} 字段 + */ + private Long modelId; + + // ========== 会话配置 ========== + + /** + * 温度参数 + * + * 用于调整生成回复的随机性和多样性程度:较低的温度值会使输出更收敛于高频词汇,较高的则增加多样性 + */ + private Double temperature; + /** + * 上下文数量 + */ + private Integer contextCount; + /** + * 单条回复的 Token 数量 + */ + private Integer maxTokens; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java new file mode 100644 index 000000000..096fff429 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java @@ -0,0 +1,109 @@ +package cn.iocoder.yudao.module.ai.dal.dataobject.chat; + +import cn.iocoder.yudao.framework.ai.chat.messages.MessageType; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; +import cn.iocoder.yudao.module.ai.enums.AiOpenAiModelEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * AI Chat 消息 DO + * + * @since 2024/4/14 17:35 + * @since 2024/4/14 17:35 + */ +@TableName("ai_chat_message") +@KeySequence("ai_chat_conversation_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class AiChatMessageDO extends BaseDO { + + /** + * 编号,作为每条聊天记录的唯一标识符 + */ + private Long id; + + /** + * 会话编号 + * + * 关联 {@link AiChatConversationDO#getId()} + */ + private Long conversationId; + + /** + * 消息类型 + * + * 也等价于 OpenAPI 的 role 字段 + * + * 枚举 {@link MessageType} + */ + private String type; + /** + * 用户编号 + * + * 仅当 user 发送时非空 + * + * 关联 AdminUserDO 的 userId 字段 + */ + private Long userId; + /** + * 角色编号 + * + * 仅当 assistant 回复时非空 + * + * 关联 {@link AiChatRoleDO#getId()} 字段 + */ + private Long roleId; + + /** + * 模型标志 + * + * 枚举 {@link AiOpenAiModelEnum} + */ + private String model; + /** + * 模型编号 + * + * 关联 {@link AiChatModalDO#getId()} 字段 + */ + private Long modelId; + + /** + * 聊天内容 + */ + private String content; + /** + * 消耗 Token 数量 + */ + private Integer usedTokens; + + // TODO 芋艿:是否作为上下文语料?use_context,待定 + + // ========== 会话配置 ========== + + /** + * 上下文数量 + * + * 冗余 {@link AiChatConversationDO#getContextCount()} + */ + private Integer contextCount; + /** + * 温度参数 + * + * 冗余 {@link AiChatConversationDO#getTemperature()} + */ + private Double temperature; + /** + * 单条回复的 Token 数量 + * + * 冗余 {@link AiChatConversationDO#getMaxTokens()} + */ + private Integer maxTokens; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiImageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java similarity index 95% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiImageDO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java index cba6e2800..190810095 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/AiImageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject; +package cn.iocoder.yudao.module.ai.dal.dataobject.image; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.IdType; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiApiKeyDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiApiKeyDO.java new file mode 100644 index 000000000..9512f4c5e --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiApiKeyDO.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.ai.dal.dataobject.model; + +import cn.iocoder.yudao.framework.ai.AiPlatformEnum; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * AI API 秘钥 DO + * + * @author 芋道源码 + */ +@TableName("ai_api_key") +@KeySequence("ai_chat_conversation_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class AiApiKeyDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 名称 + */ + private String name; + /** + * 平台 + * + * 枚举 {@link AiPlatformEnum} + */ + private String platform; + /** + * 用途 + * + * TODO 芋艿:枚举;chat、image + */ + private Integer type; + /** + * API 地址 + */ + private String url; + /** + * 状态 + * + * 枚举 {@link CommonStatusEnum} + */ + private Integer status; + + // TODO 芋艿:proxyUrl 代理地址 + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModalDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModalDO.java new file mode 100644 index 000000000..71bc7fefa --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModalDO.java @@ -0,0 +1,75 @@ +package cn.iocoder.yudao.module.ai.dal.dataobject.model; + +import cn.iocoder.yudao.framework.ai.AiPlatformEnum; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * AI 聊天模型 DO + * + * @author fansili + * @time 2024/4/24 19:39 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +@TableName("ai_chat_modal") +public class AiChatModalDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * API 秘钥编号 + * + * 关联 {@link AiApiKeyDO#getId()} + */ + private Long key_id; + /** + * 模型名称 + */ + private String name; + /** + * 模型标志 + */ + private String model; + /** + * 平台 + * + * 枚举 {@link AiPlatformEnum} + */ + private String platform; + + /** + * 排序值 + */ + private Integer sort; + /** + * 状态 + * + * 枚举 {@link CommonStatusEnum} + */ + private Integer status; + + // ========== 会话配置 ========== + + /** + * 温度参数 + * + * 用于调整生成回复的随机性和多样性程度:较低的温度值会使输出更收敛于高频词汇,较高的则增加多样性 + */ + private Double temperature; + /** + * 单条回复的 Token 数量 + */ + private Integer maxTokens; + + // TODO 芋艿:到底使用 max_context、还是 contextCount,待定!一个是轮次,一个是长度数量;貌似轮次更常用一点; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java new file mode 100644 index 000000000..c098e42e0 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.module.ai.dal.dataobject.model; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * ai 聊天角色 + * + * @fansili + * @since v1.0 + */ +@Data +@Accessors(chain = true) +@TableName("ai_chat_role") +public class AiChatRoleDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 角色名称 + */ + private String name; + /** + * 角色头像 + */ + private String avatar; + /** + * 角色分类 + */ + private String category; + /** + * 角色描述 + */ + private String description; + /** + * 角色欢迎语 + */ + private String welcomeMessage; + + /** + * 用户编号 + * + * 关联 AdminUserDO 的 userId 字段 + */ + private Long userId; + + /** + * 模型编号 + * + * 关联 {@link AiChatModalDO#getId()} 字段 + */ + private String modelId; + + /** + * 是否公开 + * + * true - 公开;false - 私有 + */ + private Boolean publicStatus; + + /** + * 排序值 + */ + private Integer sort; + /** + * 状态 + * + * 枚举 {@link CommonStatusEnum} + */ + private Integer status; + + // TODO 芋艿:要不要加一个 context,内置的上下文 + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java index 6da3fdc5b..1d10db144 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java @@ -5,7 +5,7 @@ import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatConversationDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java index cdac20ad6..7227d6fc5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.ai.mapper; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatMessageDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; @@ -24,7 +24,7 @@ public interface AiChatMessageMapper extends BaseMapperX { */ default int deleteByConversationAndId(Long chatConversationId, Long id) { return this.delete(new LambdaQueryWrapperX() - .eq(AiChatMessageDO::getChatConversationId, chatConversationId) + .eq(AiChatMessageDO::getConversationId, chatConversationId) .eq(AiChatMessageDO::getId, id) ); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatModalMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatModalMapper.java index 450791f41..7eb5f218e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatModalMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatModalMapper.java @@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatRoleMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatRoleMapper.java index 9f415cadf..e96c60810 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatRoleMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatRoleMapper.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.ai.mapper; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatRoleDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiImageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiImageMapper.java index 42cde4c58..dfad53d62 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiImageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiImageMapper.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.ai.mapper; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiImageDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java index 5906138b8..160f8b7b1 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java @@ -4,8 +4,6 @@ import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.convert.AiChatConversationConvert; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatConversationDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO; import cn.iocoder.yudao.module.ai.enums.AiChatConversationTypeEnum; import cn.iocoder.yudao.module.ai.enums.AiChatModalDisableEnum; import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatMessageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatMessageServiceImpl.java index 576fff3f5..ae691daee 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatMessageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatMessageServiceImpl.java @@ -6,8 +6,8 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatConversationDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatMessageDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.mapper.AiChatMessageMapper; import cn.iocoder.yudao.module.ai.service.AiChatMessageService; @@ -38,7 +38,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { public PageResult list(AiChatMessageReq req) { // 查询 LambdaQueryWrapperX queryWrapperX = new LambdaQueryWrapperX<>(); - queryWrapperX.eq(AiChatMessageDO::getChatConversationId, req.getChatConversationId()); + queryWrapperX.eq(AiChatMessageDO::getConversationId, req.getChatConversationId()); // 默认排序 queryWrapperX.orderByDesc(AiChatMessageDO::getId); PageResult pageResult = aiChatMessageMapper.selectPage(req, queryWrapperX); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java index 4fc210baf..59de1b6e9 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java @@ -12,7 +12,6 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.convert.AiChatModalConvert; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO; import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalChatConfigVO; import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalConfigVO; import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalDallConfigVO; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java index fe36ee43b..5ca5af4fa 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java @@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.convert.AiChatRoleConvert; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatRoleDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.enums.AiChatRoleClassifyEnum; import cn.iocoder.yudao.module.ai.enums.AiChatRoleEnableEnum; import cn.iocoder.yudao.module.ai.mapper.AiChatRoleMapper; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index ed2f02697..d6159b89f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -10,7 +10,7 @@ import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.config.AiChatClientFactory; import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatMessageDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.mapper.AiChatMessageMapper; import cn.iocoder.yudao.module.ai.mapper.AiChatRoleMapper; @@ -89,7 +89,7 @@ public class AiChatServiceImpl implements AiChatService { aiChatMessageMapper.insert( new AiChatMessageDO() .setId(null) - .setChatConversationId(chatConversationId) + .setConversationId(chatConversationId) .setUserId(loginUserId) .setMessage(req.getPrompt()) .setMessageType(MessageType.USER.getValue()) @@ -107,7 +107,7 @@ public class AiChatServiceImpl implements AiChatService { aiChatMessageMapper.insert( new AiChatMessageDO() .setId(null) - .setChatConversationId(chatConversationId) + .setConversationId(chatConversationId) .setUserId(loginUserId) .setMessage(systemPrompts) .setMessageType(MessageType.SYSTEM.getValue()) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java index fb5ebf690..ca23eb786 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java @@ -15,7 +15,7 @@ import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiImageDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.enums.AiChatDrawingStatusEnum; import cn.iocoder.yudao.module.ai.mapper.AiImageMapper; import cn.iocoder.yudao.module.ai.service.AiImageService; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java index a5d9fa80a..68f639765 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java @@ -5,7 +5,7 @@ import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyMessage; import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyGennerateStatusEnum; import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyMessageHandler; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiImageDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.enums.AiChatDrawingStatusEnum; import cn.iocoder.yudao.module.ai.mapper.AiImageMapper; import com.alibaba.fastjson2.JSON; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java index ce99e39db..31d5e86f1 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.ai.vo; -import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; From 2df0babc36cad69f579e9dcefa0d938f855ad3d5 Mon Sep 17 00:00:00 2001 From: "zhijiantianya@gmail.com" Date: Mon, 6 May 2024 21:47:29 +0800 Subject: [PATCH 216/684] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91AI=EF=BC=9A=E8=B0=83=E6=95=B4=20conversation?= =?UTF-8?q?=20=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AiChatConversationController.java | 72 ------------------- .../chat/AiChatConversationController.java | 64 +++++++++++++++++ .../chat/AiChatConversationControllerV2.java | 17 ----- .../AiChatConversationCreateReqVO.java | 17 +++++ .../AiChatConversationRespVO.java | 39 ++++++++++ .../AiChatConversationUpdateReqVO.java | 33 +++++++++ .../admin/chat/vo/message/package-info.java | 1 + .../admin/chat/vo/package-info.java | 1 - .../controller/admin/image/package-info.java | 4 ++ .../ai/controller/admin/package-info.java | 4 -- .../ai/convert/AiChatConversationConvert.java | 6 +- .../dataobject/chat/AiChatConversationDO.java | 28 ++++---- .../dal/dataobject/chat/AiChatMessageDO.java | 14 ++-- .../dal/dataobject/model/AiChatModalDO.java | 24 ++++--- .../ai/dal/dataobject/model/AiChatRoleDO.java | 32 ++++++--- .../ai/service/AiChatConversationService.java | 14 ++-- .../impl/AiChatConversationServiceImpl.java | 10 +-- .../ai/service/impl/AiChatServiceImpl.java | 10 +-- .../vo/AiChatConversationCreateRoleReq.java | 26 ------- .../vo/AiChatConversationCreateUserReq.java | 23 ------ .../ai/vo/AiChatConversationListReq.java | 20 ------ .../module/ai/vo/AiChatConversationRes.java | 45 ------------ 22 files changed, 237 insertions(+), 267 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatConversationController.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationControllerV2.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateReqVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateReqVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/package-info.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/package-info.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/package-info.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/package-info.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateRoleReq.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateUserReq.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationListReq.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationRes.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatConversationController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatConversationController.java deleted file mode 100644 index 6d5cb3154..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatConversationController.java +++ /dev/null @@ -1,72 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.ai.service.AiChatConversationService; -import cn.iocoder.yudao.module.ai.vo.AiChatConversationCreateRoleReq; -import cn.iocoder.yudao.module.ai.vo.AiChatConversationCreateUserReq; -import cn.iocoder.yudao.module.ai.vo.AiChatConversationListReq; -import cn.iocoder.yudao.module.ai.vo.AiChatConversationRes; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * ia 模块 - * - * @author fansili - * @time 2024/4/13 17:44 - * @since 1.0 - */ -@Tag(name = "A2-聊天-对话") -@RestController -@RequestMapping("/ai/chat/conversation") -@Slf4j -@AllArgsConstructor -public class AiChatConversationController { - - private final AiChatConversationService chatConversationService; - - @Operation(summary = "创建 - 对话普通对话") - @PutMapping("/createConversation") - public CommonResult createConversation(@RequestBody @Validated AiChatConversationCreateUserReq req) { - return CommonResult.success(chatConversationService.createConversation(req)); - } - - @Operation(summary = "创建 - 对话角色对话") - @PutMapping("/createRoleConversation") - public CommonResult createRoleConversation(@RequestBody @Validated AiChatConversationCreateRoleReq req) { - return CommonResult.success(chatConversationService.createRoleConversation(req)); - } - - @Operation(summary = "获取 - 获取对话") - @GetMapping("/{id}") - public CommonResult getConversation(@PathVariable("id") Long id) { - return CommonResult.success(chatConversationService.getConversation(id)); - } - - @Operation(summary = "获取 - 获取对话list") - @GetMapping("/list") - public CommonResult> listConversation(@ModelAttribute @Validated AiChatConversationListReq req) { - return CommonResult.success(chatConversationService.listConversation(req)); - } - - @Operation(summary = "更新 - 更新模型") - @PostMapping("/{id}/modal") - public CommonResult updateModal(@PathVariable("id") Long id, - @RequestParam("modalId") Long modalId) { - chatConversationService.updateModal(id, modalId); - return CommonResult.success(null); - } - - @Operation(summary = "删除") - @DeleteMapping("/{id}") - public CommonResult delete(@PathVariable("id") Long id) { - chatConversationService.delete(id); - return CommonResult.success(null); - } -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java new file mode 100644 index 000000000..f8a7d8d1b --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.ai.controller.admin.chat; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateReqVO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 聊天会话") +@RestController +@RequestMapping("/ai/chat/conversation") +@Slf4j +public class AiChatConversationController { + + // TODO @fan:实现一下 + @PostMapping("/create") + @Operation(summary = "创建聊天会话") + @PreAuthorize("@ss.hasPermission('ai:chat-conversation:create')") + public CommonResult createConversation(@RequestBody @Valid AiChatConversationCreateReqVO createReqVO) { + return success(1L); + } + + // TODO @fan:实现一下 + @PutMapping("/update") + @Operation(summary = "更新聊天会话") + @PreAuthorize("@ss.hasPermission('ai:chat-conversation:create')") + public CommonResult updateConversation(@RequestBody @Valid AiChatConversationUpdateReqVO updateReqVO) { + return success(true); + } + + // TODO @fan:实现一下 + @GetMapping("/list") + @Operation(summary = "获得聊天会话列表") + public CommonResult> getConversationList() { + return success(null); + } + + // TODO @fan:实现一下 + @GetMapping("/get") + @Operation(summary = "获得聊天会话") + @Parameter(name = "id", required = true, description = "会话编号", example = "1024") + public CommonResult getConversation(@RequestParam("id") Long id) { + return success(null); + } + + // TODO @fan:实现一下 + @DeleteMapping("/delete") + @Operation(summary = "删除聊天会话") + @Parameter(name = "id", required = true, description = "会话编号", example = "1024") + public CommonResult deleteConversation(@RequestParam("id") Long id) { + return success(null); + } + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationControllerV2.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationControllerV2.java deleted file mode 100644 index 6dfd0de12..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationControllerV2.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.extern.slf4j.Slf4j; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@Tag(name = "管理后台 - 聊天会话") -@RestController -@RequestMapping("/ai/chat/conversation") -@Slf4j -public class AiChatConversationControllerV2 { - - public CommonResult> - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateReqVO.java new file mode 100644 index 000000000..b1e119659 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateReqVO.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; + +@Schema(description = "管理后台 - AI 聊天会话创建 Request VO") +@Data +public class AiChatConversationCreateReqVO { + + @Schema(description = "角色编号", example = "666") + private Long roleId; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java new file mode 100644 index 000000000..720736f21 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.experimental.Accessors; + +@Schema(description = "管理后台 - AI 聊天会话 Response VO") +@Data +public class AiChatConversationRespVO { + + @Schema(description = "会话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") + private Long userId; + + @Schema(description = "会话标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是一个标题") + private String title; + + @Schema(description = "是否置顶", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean pinned; + + @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long modelId; + + @Schema(description = "模型标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "ERNIE-Bot-turbo-0922") + private String model; + + @Schema(description = "温度参数", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.8") + private Double temperature; + + @Schema(description = "单条回复的最大 Token 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096") + private Integer maxTokens; + + @Schema(description = "上下文的最大 Message 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Integer maxContexts; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateReqVO.java new file mode 100644 index 000000000..e8bdabb19 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - AI 聊天会话更新 Request VO") +@Data +public class AiChatConversationUpdateReqVO { + + @Schema(description = "会话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "会话编号不能为空") + private Long id; + + @Schema(description = "会话标题", example = "我是一个标题") + private String title; + + @Schema(description = "是否置顶", example = "true") + private Boolean pinned; + + @Schema(description = "模型编号", example = "1") + private Long modelId; + + @Schema(description = "温度参数", example = "0.8") + private Double temperature; + + @Schema(description = "单条回复的最大 Token 数量", example = "4096") + private Integer maxTokens; + + @Schema(description = "上下文的最大 Message 数量", example = "10") + private Integer maxContexts; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/package-info.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/package-info.java new file mode 100644 index 000000000..5fee7106d --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message; \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/package-info.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/package-info.java deleted file mode 100644 index 0e2d34fb4..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo; \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/package-info.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/package-info.java new file mode 100644 index 000000000..9bc6965a1 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/package-info.java @@ -0,0 +1,4 @@ +/** + * TODO 芋艿:站位,无特殊作用 + */ +package cn.iocoder.yudao.module.ai.controller.admin.image; \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/package-info.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/package-info.java deleted file mode 100644 index f28cc7058..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * TODO 芋艿:站位,无特殊作用 - */ -package cn.iocoder.yudao.module.ai.controller.admin; \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java index 012211926..af1a0bb21 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.ai.convert; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; -import cn.iocoder.yudao.module.ai.vo.AiChatConversationRes; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -25,7 +25,7 @@ public interface AiChatConversationConvert { * @param top100Conversation * @return */ - List covnertChatConversationResList(List top100Conversation); + List covnertChatConversationResList(List top100Conversation); /** * 转换 - 单个 ChatConversationRes @@ -33,5 +33,5 @@ public interface AiChatConversationConvert { * @param aiChatConversationDO * @return */ - AiChatConversationRes covnertChatConversationRes(AiChatConversationDO aiChatConversationDO); + AiChatConversationRespVO covnertChatConversationRes(AiChatConversationDO aiChatConversationDO); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java index 4ac977011..9a436b988 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java @@ -40,11 +40,15 @@ public class AiChatConversationDO extends BaseDO { private Long userId; /** - * 标题 + * 会话标题 * * 默认由系统自动生成,可用户手动修改 */ private String title; + /** + * 是否置顶 + */ + private Boolean pinned; /** * 角色编号 @@ -52,12 +56,6 @@ public class AiChatConversationDO extends BaseDO { * 关联 {@link AiChatRoleDO#getId()} */ private Long roleId; - /** - * 模型标志 - * - * 枚举 {@link AiOpenAiModelEnum} - */ - private String model; /** * 模型编号 @@ -65,6 +63,12 @@ public class AiChatConversationDO extends BaseDO { * 关联 {@link AiChatModalDO#getId()} 字段 */ private Long modelId; + /** + * 模型标志 + * + * 枚举 {@link AiOpenAiModelEnum} + */ + private String model; // ========== 会话配置 ========== @@ -75,12 +79,12 @@ public class AiChatConversationDO extends BaseDO { */ private Double temperature; /** - * 上下文数量 - */ - private Integer contextCount; - /** - * 单条回复的 Token 数量 + * 单条回复的最大 Token 数量 */ private Integer maxTokens; + /** + * 上下文的最大 Message 数量 + */ + private Integer maxContexts; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java index 096fff429..4d44e82a0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java @@ -87,12 +87,6 @@ public class AiChatMessageDO extends BaseDO { // ========== 会话配置 ========== - /** - * 上下文数量 - * - * 冗余 {@link AiChatConversationDO#getContextCount()} - */ - private Integer contextCount; /** * 温度参数 * @@ -100,10 +94,16 @@ public class AiChatMessageDO extends BaseDO { */ private Double temperature; /** - * 单条回复的 Token 数量 + * 单条回复的最大 Token 数量 * * 冗余 {@link AiChatConversationDO#getMaxTokens()} */ private Integer maxTokens; + /** + * 上下文的最大 Message 数量 + * + * 冗余 {@link AiChatConversationDO#getMaxContexts()} + */ + private Integer maxContexts; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModalDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModalDO.java index 71bc7fefa..a35fa0e69 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModalDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModalDO.java @@ -3,21 +3,25 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.model; import cn.iocoder.yudao.framework.ai.AiPlatformEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; +import lombok.*; import lombok.experimental.Accessors; /** * AI 聊天模型 DO * * @author fansili - * @time 2024/4/24 19:39 - * @since 1.0 + * @since 2024/4/24 19:39 */ +@TableName("ai_chat_model") +@KeySequence("ai_chat_model_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @Data -@Accessors(chain = true) -@TableName("ai_chat_modal") +@EqualsAndHashCode(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor public class AiChatModalDO extends BaseDO { /** @@ -30,7 +34,7 @@ public class AiChatModalDO extends BaseDO { * * 关联 {@link AiApiKeyDO#getId()} */ - private Long key_id; + private Long keyId; /** * 模型名称 */ @@ -66,10 +70,12 @@ public class AiChatModalDO extends BaseDO { */ private Double temperature; /** - * 单条回复的 Token 数量 + * 单条回复的最大 Token 数量 */ private Integer maxTokens; - - // TODO 芋艿:到底使用 max_context、还是 contextCount,待定!一个是轮次,一个是长度数量;貌似轮次更常用一点; + /** + * 上下文的最大 Message 数量 + */ + private Integer maxContexts; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java index c098e42e0..bb48f524d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java @@ -1,22 +1,30 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.model; +import cn.iocoder.yudao.framework.ai.chat.messages.MessageType; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; +import com.baomidou.mybatisplus.annotation.*; +import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler; +import lombok.*; import lombok.experimental.Accessors; +import java.io.Serializable; +import java.util.List; + /** - * ai 聊天角色 + * AI 聊天角色 DO * - * @fansili - * @since v1.0 + * @author fansili + * @since 2024/4/24 19:39 */ +@TableName(value = "ai_chat_role", autoResultMap = true) +@KeySequence("ai_chat_role_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @Data -@Accessors(chain = true) -@TableName("ai_chat_role") +@EqualsAndHashCode(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor public class AiChatRoleDO extends BaseDO { /** @@ -44,6 +52,10 @@ public class AiChatRoleDO extends BaseDO { * 角色欢迎语 */ private String welcomeMessage; + /** + * 角色设定(消息) + */ + private String systemMessage; /** * 用户编号 @@ -77,6 +89,4 @@ public class AiChatRoleDO extends BaseDO { */ private Integer status; - // TODO 芋艿:要不要加一个 context,内置的上下文 - } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java index 1a4c767a1..86592e5e8 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java @@ -1,9 +1,7 @@ package cn.iocoder.yudao.module.ai.service; -import cn.iocoder.yudao.module.ai.vo.AiChatConversationCreateRoleReq; -import cn.iocoder.yudao.module.ai.vo.AiChatConversationCreateUserReq; -import cn.iocoder.yudao.module.ai.vo.AiChatConversationListReq; -import cn.iocoder.yudao.module.ai.vo.AiChatConversationRes; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import java.util.List; @@ -21,7 +19,7 @@ public interface AiChatConversationService { * @param req * @return */ - AiChatConversationRes createConversation(AiChatConversationCreateUserReq req); + AiChatConversationRespVO createConversation(AiChatConversationCreateUserReq req); /** * 对话 - 创建role对话 @@ -29,7 +27,7 @@ public interface AiChatConversationService { * @param req * @return */ - AiChatConversationRes createRoleConversation(AiChatConversationCreateRoleReq req); + AiChatConversationRespVO createRoleConversation(AiChatConversationCreateReqVO req); /** @@ -38,7 +36,7 @@ public interface AiChatConversationService { * @param id * @return */ - AiChatConversationRes getConversation(Long id); + AiChatConversationRespVO getConversation(Long id); /** * 获取 - 对话列表 @@ -46,7 +44,7 @@ public interface AiChatConversationService { * @param req * @return */ - List listConversation(AiChatConversationListReq req); + List listConversation(AiChatConversationListReq req); /** * 更新 - 更新模型 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java index 160f8b7b1..1a8425cc5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java @@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.ai.service.impl; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import cn.iocoder.yudao.module.ai.convert.AiChatConversationConvert; import cn.iocoder.yudao.module.ai.enums.AiChatConversationTypeEnum; import cn.iocoder.yudao.module.ai.enums.AiChatModalDisableEnum; @@ -38,7 +40,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService private final AiChatRoleService aiChatRoleService; @Override - public AiChatConversationRes createConversation(AiChatConversationCreateUserReq req) { + public AiChatConversationRespVO createConversation(AiChatConversationCreateUserReq req) { // 获取用户id Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 查询最新的对话 @@ -58,7 +60,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService } @Override - public AiChatConversationRes createRoleConversation(AiChatConversationCreateRoleReq req) { + public AiChatConversationRespVO createRoleConversation(AiChatConversationCreateReqVO req) { // 获取用户id Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 查询最新的对话 @@ -101,7 +103,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService } @Override - public AiChatConversationRes getConversation(Long id) { + public AiChatConversationRespVO getConversation(Long id) { AiChatConversationDO aiChatConversationDO = validateExists(id); return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(aiChatConversationDO); } @@ -115,7 +117,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService } @Override - public List listConversation(AiChatConversationListReq req) { + public List listConversation(AiChatConversationListReq req) { // 获取用户id Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 查询前100对话 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index d6159b89f..c70b56aa0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -16,7 +16,7 @@ import cn.iocoder.yudao.module.ai.mapper.AiChatMessageMapper; import cn.iocoder.yudao.module.ai.mapper.AiChatRoleMapper; import cn.iocoder.yudao.module.ai.service.AiChatConversationService; import cn.iocoder.yudao.module.ai.service.AiChatService; -import cn.iocoder.yudao.module.ai.vo.AiChatConversationRes; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import cn.iocoder.yudao.module.ai.vo.AiChatReq; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -58,7 +58,7 @@ public class AiChatServiceImpl implements AiChatService { // 获取 client 类型 AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(req.getModal()); // 获取对话信息 - AiChatConversationRes conversationRes = chatConversationService.getConversation(req.getConversationId()); + AiChatConversationRespVO conversationRes = chatConversationService.getConversation(req.getConversationId()); // 保存 chat message saveChatMessage(req, conversationRes, loginUserId); String content = null; @@ -83,7 +83,7 @@ public class AiChatServiceImpl implements AiChatService { return content; } - private void saveChatMessage(AiChatReq req, AiChatConversationRes conversationRes, Long loginUserId) { + private void saveChatMessage(AiChatReq req, AiChatConversationRespVO conversationRes, Long loginUserId) { Long chatConversationId = conversationRes.getId(); // 增加 chat message 记录 aiChatMessageMapper.insert( @@ -101,7 +101,7 @@ public class AiChatServiceImpl implements AiChatService { aiChatConversationMapper.updateIncrChatCount(req.getConversationId()); } - public void saveSystemChatMessage(AiChatReq req, AiChatConversationRes conversationRes, Long loginUserId, String systemPrompts) { + public void saveSystemChatMessage(AiChatReq req, AiChatConversationRespVO conversationRes, Long loginUserId, String systemPrompts) { Long chatConversationId = conversationRes.getId(); // 增加 chat message 记录 aiChatMessageMapper.insert( @@ -133,7 +133,7 @@ public class AiChatServiceImpl implements AiChatService { // 获取 client 类型 AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(req.getModal()); // 获取对话信息 - AiChatConversationRes conversationRes = chatConversationService.getConversation(req.getConversationId()); + AiChatConversationRespVO conversationRes = chatConversationService.getConversation(req.getConversationId()); // 创建 chat 需要的 Prompt Prompt prompt = new Prompt(req.getPrompt()); req.setTopK(req.getTopK()); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateRoleReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateRoleReq.java deleted file mode 100644 index 0dc095bc1..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateRoleReq.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.module.ai.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * 聊天对话 - * - * @author fansili - * @time 2024/4/18 16:24 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatConversationCreateRoleReq { - - @Schema(description = "chat角色Id") - @NotNull(message = "聊天角色id不能为空!") - private Long roleId; - - @Schema(description = "标题(有程序自动生成)") - @NotNull(message = "标题不能为空!") - private String title; -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateUserReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateUserReq.java deleted file mode 100644 index 9e3af32a0..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationCreateUserReq.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.yudao.module.ai.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * 聊天对话 - * - * @author fansili - * @time 2024/4/18 16:24 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatConversationCreateUserReq { - - @Schema(description = "对话标题") - @NotNull(message = "标题不能为空!") - private String title; - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationListReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationListReq.java deleted file mode 100644 index 208bf67a2..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationListReq.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.ai.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * 聊天对话 list req - * - * @author fansili - * @time 2024/4/18 16:24 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatConversationListReq { - - @Schema(description = "查询根据title") - private String search; -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationRes.java deleted file mode 100644 index 9e181bd01..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatConversationRes.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.iocoder.yudao.module.ai.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * 聊天对话 res - * - * @author fansili - * @time 2024/4/18 16:24 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatConversationRes { - - @Schema(description = "id") - private Long id; - - @Schema(description = "用户id") - private Long userId; - - @Schema(description = "chat角色Id") - private Long roleId; - - @Schema(description = "chat角色名称") - private String roleName; - - @Schema(description = "模型id") - private Long modalId; - - @Schema(description = "使用的模型") - private String modal; - - @Schema(description = "标题(有程序自动生成)") - private String title; - - @Schema(description = "对话类型(roleChat、userChat)") - private String type; - - @Schema(description = "聊天次数(有程序自动生成)") - private Integer chatCount; - -} From aea7cc000b4ca9d1c40fb58b45df91ad73e53260 Mon Sep 17 00:00:00 2001 From: "zhijiantianya@gmail.com" Date: Mon, 6 May 2024 22:28:56 +0800 Subject: [PATCH 217/684] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91AI=EF=BC=9A=E8=B0=83=E6=95=B4=20message=20?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/AiChatController.java | 50 --------------- .../controller/AiChatMessageController.java | 44 ------------- .../admin/chat/AiChatMessageController.java | 62 +++++++++++++++++++ .../chat/vo/message/AiChatMessageRespVO.java | 37 +++++++++++ .../vo/message/AiChatMessageSendReqVO.java | 22 +++++++ .../admin/chat/vo/message/package-info.java | 1 - .../ai/convert/AiChatMessageConvert.java | 4 +- .../dal/dataobject/chat/AiChatMessageDO.java | 2 +- .../iocoder/yudao/module/ai/dal/pageinfo.java | 7 --- .../ai/service/AiChatMessageService.java | 5 +- .../module/ai/service/AiChatService.java | 6 +- .../impl/AiChatMessageServiceImpl.java | 7 +-- .../ai/service/impl/AiChatServiceImpl.java | 10 +-- .../module/ai/vo/AiChatMessageDeleteReq.java | 28 --------- .../module/ai/vo/AiChatMessageListRes.java | 42 ------------- .../yudao/module/ai/vo/AiChatMessageReq.java | 24 ------- .../iocoder/yudao/module/ai/vo/AiChatReq.java | 48 -------------- .../yudao/module/ai/vo/AiChatReqVO.java | 21 ------- 18 files changed, 137 insertions(+), 283 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatController.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatMessageController.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendReqVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/package-info.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/pageinfo.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatMessageDeleteReq.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatMessageListRes.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatMessageReq.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatReq.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatReqVO.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatController.java deleted file mode 100644 index 09b83fcad..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatController.java +++ /dev/null @@ -1,50 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.ai.service.AiChatService; -import cn.iocoder.yudao.module.ai.vo.AiChatReq; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.MediaType; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; - -/** - * ia 模块 - * - * @author fansili - * @time 2024/4/13 17:44 - * @since 1.0 - */ -@Tag(name = "A1-AI聊天") -@RestController -@RequestMapping("/ai") -@Slf4j -@AllArgsConstructor -public class AiChatController { - - @Autowired - private final AiChatService chatService; - - @Operation(summary = "聊天-chat", description = "这个一般等待时间比较久,需要全部完成才会返回!") - @GetMapping("/chat") - public CommonResult chat(@Validated @ModelAttribute AiChatReq req) { - return CommonResult.success(chatService.chat(req)); - } - - // TODO @芋艿:调用这个方法异常,Unable to handle the Spring Security Exception because the response is already committed. - @Operation(summary = "聊天-stream", description = "这里跟通义千问一样采用的是 Server-Sent Events (SSE) 通讯模式") - @GetMapping(value = "/chatStream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) - public SseEmitter chatStream(@Validated @ModelAttribute AiChatReq req) { - Utf8SseEmitter sseEmitter = new Utf8SseEmitter(); - chatService.chatStream(req, sseEmitter); - return sseEmitter; - } -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatMessageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatMessageController.java deleted file mode 100644 index ecfb6c865..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatMessageController.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.ai.service.AiChatMessageService; -import cn.iocoder.yudao.module.ai.vo.AiChatMessageListRes; -import cn.iocoder.yudao.module.ai.vo.AiChatMessageReq; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -/** - * chat message - * - * @author fansili - * @time 2024/4/24 17:22 - * @since 1.0 - */ -@Tag(name = "A3-聊天-对话") -@RestController -@RequestMapping("/ai/chat/message") -@Slf4j -@AllArgsConstructor -public class AiChatMessageController { - - private final AiChatMessageService chatMessageService; - - @Operation(summary = "聊天记录", description = "查询个人的聊天记录") - @GetMapping("/list") - public PageResult list(@Validated @ModelAttribute AiChatMessageReq req) { - return chatMessageService.list(req); - } - - @Operation(summary = "聊天记录 - 删除", description = "删除记录") - @DeleteMapping("/{chatConversationId}/{id}") - public CommonResult delete(@PathVariable("chatConversationId") Long chatConversationId, - @PathVariable("id") Long id) { - chatMessageService.delete(chatConversationId, id); - return CommonResult.success(null); - } -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java new file mode 100644 index 000000000..473f1c856 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.ai.controller.admin.chat; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; +import cn.iocoder.yudao.module.ai.service.AiChatService; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.MediaType; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +// TODO @芋艿:权限标识; +@Tag(name = "管理后台 - 聊天消息") +@RestController +@RequestMapping("/ai/chat/message") +@Slf4j +public class AiChatMessageController { + @Resource + private AiChatService chatService; + + @Operation(summary = "发送消息(段式)", description = "一次性返回,响应较慢") + @PostMapping("/send") + public CommonResult sendMessage(@Validated @ModelAttribute AiChatMessageSendReqVO sendReqVO) { + // TODO @fan:使用 static import;这样就 success 就行了; + return success(null); + } + + // TODO @芋艿:调用这个方法异常,Unable to handle the Spring Security Exception because the response is already committed.;可以再试试 + // TODO @fan:要不要使用 Flux 来返回;可以使用 Flux + @Operation(summary = "发送消息(流式)", description = "流式返回,响应较快") + @PostMapping(value = "/send-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) + public SseEmitter sendMessageStream(@Validated @ModelAttribute AiChatMessageSendReqVO sendReqVO) { + Utf8SseEmitter sseEmitter = new Utf8SseEmitter(); + chatService.chatStream(sendReqVO, sseEmitter); + return sseEmitter; + } + + @Operation(summary = "获得指定会话的消息列表") + @GetMapping("/list-by-conversation-id") + @Parameter(name = "conversationId", required = true, description = "会话编号", example = "1024") + public CommonResult> getMessageListByConversationId(@RequestParam("conversationId") Long conversationId) { + return success(null); + } + + @Operation(summary = "删除消息") + @DeleteMapping("/delete") + @Parameter(name = "id", required = true, description = "消息编号", example = "1024") + public CommonResult delete(@RequestParam("id") Long id) { + return success(null); + } + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java new file mode 100644 index 000000000..d5f830d17 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - AI 聊天消息 Response VO") +@Data +public class AiChatMessageRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "会话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") + private Long conversationId; + + @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "role") + private String type; // 参见 MessageType 枚举类 + + @Schema(description = "用户编号", example = "4096") + private Long userId; // 仅当 user 发送时非空 + + @Schema(description = "角色编号", example = "888") + private Long roleId; // 仅当 assistant 回复时非空 + + @Schema(description = "模型标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "gpt-3.5-turbo") + private String model; // 参见 AiOpenAiModelEnum 枚举类 + + @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "123") + private Long modelId; + + @Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,你好啊") + private String content; + + @Schema(description = "消耗 Token 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "80") + private Integer tokens; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendReqVO.java new file mode 100644 index 000000000..9592da347 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; +import lombok.experimental.Accessors; + +@Schema(description = "管理后台 - AI 聊天消息发送 Request VO") +@Data +public class AiChatMessageSendReqVO { + + @Schema(description = "聊天对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "聊天对话编号不能为空") + private Long conversationId; + + @Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "帮我写个 Java 算法") + @NotEmpty(message = "聊天内容不能为空") + private String content; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/package-info.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/package-info.java deleted file mode 100644 index 5fee7106d..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message; \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java index 14f410a1e..c84ecb404 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.ai.convert; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; -import cn.iocoder.yudao.module.ai.vo.AiChatMessageListRes; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -25,5 +25,5 @@ public interface AiChatMessageConvert { * @param list * @return */ - List convert(List list); + List convert(List list); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java index 4d44e82a0..f5a5296a7 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java @@ -81,7 +81,7 @@ public class AiChatMessageDO extends BaseDO { /** * 消耗 Token 数量 */ - private Integer usedTokens; + private Integer tokens; // TODO 芋艿:是否作为上下文语料?use_context,待定 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/pageinfo.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/pageinfo.java deleted file mode 100644 index ce4001112..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/pageinfo.java +++ /dev/null @@ -1,7 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal; - -/** - * @author fansili - * @time 2024/4/25 15:36 - * @since 1.0 - */ diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatMessageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatMessageService.java index ef1cfa468..77450c63b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatMessageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatMessageService.java @@ -1,8 +1,7 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.ai.vo.AiChatMessageListRes; -import cn.iocoder.yudao.module.ai.vo.AiChatMessageReq; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; /** * chat message @@ -19,7 +18,7 @@ public interface AiChatMessageService { * @param req * @return */ - PageResult list(AiChatMessageReq req); + PageResult list(AiChatMessageReq req); /** * message - 删除 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java index b3596e9cf..c054e41fa 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; -import cn.iocoder.yudao.module.ai.vo.AiChatReq; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; /** * 聊天 chat @@ -18,7 +18,7 @@ public interface AiChatService { * @param req * @return */ - String chat(AiChatReq req); + String chat(AiChatMessageSendReqVO req); /** * chat stream @@ -27,5 +27,5 @@ public interface AiChatService { * @param sseEmitter * @return */ - void chatStream(AiChatReq req, Utf8SseEmitter sseEmitter); + void chatStream(AiChatMessageSendReqVO req, Utf8SseEmitter sseEmitter); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatMessageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatMessageServiceImpl.java index ae691daee..ae5a594cb 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatMessageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatMessageServiceImpl.java @@ -11,8 +11,7 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.mapper.AiChatMessageMapper; import cn.iocoder.yudao.module.ai.service.AiChatMessageService; -import cn.iocoder.yudao.module.ai.vo.AiChatMessageListRes; -import cn.iocoder.yudao.module.ai.vo.AiChatMessageReq; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -35,7 +34,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { private final AiChatConversationMapper aiChatConversationMapper; @Override - public PageResult list(AiChatMessageReq req) { + public PageResult list(AiChatMessageReq req) { // 查询 LambdaQueryWrapperX queryWrapperX = new LambdaQueryWrapperX<>(); queryWrapperX.eq(AiChatMessageDO::getConversationId, req.getChatConversationId()); @@ -43,7 +42,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { queryWrapperX.orderByDesc(AiChatMessageDO::getId); PageResult pageResult = aiChatMessageMapper.selectPage(req, queryWrapperX); // 转换 res - List messageListResList = AiChatMessageConvert.INSTANCE.convert(pageResult.getList()); + List messageListResList = AiChatMessageConvert.INSTANCE.convert(pageResult.getList()); return new PageResult(messageListResList, pageResult.getTotal()); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index c70b56aa0..50f4ac0cb 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -17,7 +17,7 @@ import cn.iocoder.yudao.module.ai.mapper.AiChatRoleMapper; import cn.iocoder.yudao.module.ai.service.AiChatConversationService; import cn.iocoder.yudao.module.ai.service.AiChatService; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; -import cn.iocoder.yudao.module.ai.vo.AiChatReq; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.MediaType; @@ -53,7 +53,7 @@ public class AiChatServiceImpl implements AiChatService { * @return */ @Transactional(rollbackFor = Exception.class) - public String chat(AiChatReq req) { + public String chat(AiChatMessageSendReqVO req) { Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 获取 client 类型 AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(req.getModal()); @@ -83,7 +83,7 @@ public class AiChatServiceImpl implements AiChatService { return content; } - private void saveChatMessage(AiChatReq req, AiChatConversationRespVO conversationRes, Long loginUserId) { + private void saveChatMessage(AiChatMessageSendReqVO req, AiChatConversationRespVO conversationRes, Long loginUserId) { Long chatConversationId = conversationRes.getId(); // 增加 chat message 记录 aiChatMessageMapper.insert( @@ -101,7 +101,7 @@ public class AiChatServiceImpl implements AiChatService { aiChatConversationMapper.updateIncrChatCount(req.getConversationId()); } - public void saveSystemChatMessage(AiChatReq req, AiChatConversationRespVO conversationRes, Long loginUserId, String systemPrompts) { + public void saveSystemChatMessage(AiChatMessageSendReqVO req, AiChatConversationRespVO conversationRes, Long loginUserId, String systemPrompts) { Long chatConversationId = conversationRes.getId(); // 增加 chat message 记录 aiChatMessageMapper.insert( @@ -128,7 +128,7 @@ public class AiChatServiceImpl implements AiChatService { * @return */ @Override - public void chatStream(AiChatReq req, Utf8SseEmitter sseEmitter) { + public void chatStream(AiChatMessageSendReqVO req, Utf8SseEmitter sseEmitter) { Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 获取 client 类型 AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(req.getModal()); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatMessageDeleteReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatMessageDeleteReq.java deleted file mode 100644 index dafd7d84f..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatMessageDeleteReq.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.ai.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * chat message list req - * - * @author fansili - * @time 2024/4/14 16:12 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatMessageDeleteReq extends PageParam { - - @Schema(description = "id") - @NotNull - private Long id; - - @Schema(description = "聊天ID,关联到特定的会话或对话") - @NotNull - private Long chatConversationId; - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatMessageListRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatMessageListRes.java deleted file mode 100644 index ecfbc009c..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatMessageListRes.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.yudao.module.ai.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * 看板 message list req - * - * @author fansili - * @time 2024/4/24 17:28 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatMessageListRes { - - @Schema(description = "编号") - private Long id; - - @Schema(description = "聊天ID,关联到特定的会话或对话") - private Long chatConversationId; - - @Schema(description = "角色ID,用于标识发送消息的用户或系统的身份") - private Long userId; - - @Schema(description = "消息具体内容,存储用户的发言或者系统响应的文字信息") - private String message; - - @Schema(description = "消息类型,枚举值可能包括'system'(系统消息)、'user'(用户消息)和'assistant'(助手消息)") - private String messageType; - - @Schema(description = "在生成消息时采用的Top-K采样大小") - private Double topK; - - @Schema(description = "Top-P核采样方法的概率阈值") - private Double topP; - - @Schema(description = "温度参数,用于调整生成回复的随机性和多样性程度,") - private Double temperature; - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatMessageReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatMessageReq.java deleted file mode 100644 index 60b7e91ee..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatMessageReq.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.module.ai.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * chat message list req - * - * @author fansili - * @time 2024/4/14 16:12 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatMessageReq extends PageParam { - - @Schema(description = "聊天ID,关联到特定的会话或对话") - @NotNull - private Long chatConversationId; - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatReq.java deleted file mode 100644 index 0597f8990..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatReq.java +++ /dev/null @@ -1,48 +0,0 @@ -package cn.iocoder.yudao.module.ai.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * chat req - * - * @author fansili - * @time 2024/4/14 16:12 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatReq { - - @Schema(description = "ai模型(查看 AiClientNameEnum)") - @NotNull(message = "模型不能为空!") - @Size(max = 30, message = "模型字符最大 30个字符!") - private String modal; - - @Schema(description = "对话Id") - @NotNull(message = "对话id不能为空") - private Long conversationId; - - @Schema(description = "chat角色模板") - private Long chatRoleId; - - @NotNull(message = "提示词不能为空!") - @Size(max = 5000, message = "提示词最大5000个字符!") - @Schema(description = "填入固定值,1 issues, 2 pr") - private String prompt; - - @Schema(description = "用于控制随机性和多样性的温度参数") - private Double temperature; - - @Schema(description = "生成时,核采样方法的概率阈值。例如,取值为0.8时,仅保留累计概率之和大于等于0.8的概率分布中的token,\n" + - " * 作为随机采样的候选集。取值范围为(0,1.0),取值越大,生成的随机性越高;取值越低,生成的随机性越低。\n" + - " * 默认值为0.8。注意,取值不要大于等于1\n") - private Double topP; - - @Schema(description = "在生成消息时采用的Top-K采样大小,表示模型生成回复时考虑的候选项集合的大小") - private Double topK; - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatReqVO.java deleted file mode 100644 index f4bca2fd6..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatReqVO.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.ai.vo; - -import cn.iocoder.yudao.module.ai.enums.AiOpenAiModelEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -// TODO done @fansili 1)swagger 注释不太对;2)有了 swagger 注释,就不用类注释了 -@Data -@Schema(description = "用户 App - 上传文件 Request VO") -public class AiChatReqVO { - - @Schema(description = "提示词", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "提示词不能为空!") - private String prompt; - - @Schema(description = "AI模型", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "AI模型不能为空") - private AiOpenAiModelEnum aiModel; - -} From f9854273cc9b9d1e84729646ce5a6d71cf8bf5c1 Mon Sep 17 00:00:00 2001 From: "zhijiantianya@gmail.com" Date: Mon, 6 May 2024 22:34:49 +0800 Subject: [PATCH 218/684] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91AI=EF=BC=9A=E8=B0=83=E6=95=B4=20model=20?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{ => admin/image}/AiImageController.java | 8 +++++--- .../module/ai/controller/admin/image/package-info.java | 4 ---- .../admin/image}/vo/AiImageDallDrawingReq.java | 2 +- .../admin/image}/vo/AiImageMidjourneyReq.java | 2 +- .../admin/image}/vo/AiImageMidjourneyRes.java | 2 +- .../{ => admin/model}/AiChatModalController.java | 9 +++++---- .../{ => admin/model}/AiChatRoleController.java | 5 +++-- .../admin/model/vo/model}/AiChatModalAddReq.java | 2 +- .../admin/model/vo/model}/AiChatModalListReq.java | 2 +- .../admin/model/vo/model}/AiChatModalListRes.java | 2 +- .../admin/model/vo/model}/AiChatModalRes.java | 2 +- .../ai/controller/admin/model/vo/package-info.java | 1 + .../admin/model/vo/role}/AiChatRoleAddReq.java | 2 +- .../admin/model/vo/role}/AiChatRoleListReq.java | 2 +- .../admin/model/vo/role}/AiChatRoleListRes.java | 2 +- .../admin/model/vo/role}/AiChatRoleRes.java | 2 +- .../admin/model/vo/role}/AiChatRoleUpdateReq.java | 2 +- .../model/vo/role}/AiChatRoleUpdateVisibilityReq.java | 2 +- .../yudao/module/ai/convert/AiChatModalConvert.java | 6 +++--- .../yudao/module/ai/convert/AiChatRoleConvert.java | 8 ++++---- .../mysql}/AiChatConversationMapper.java | 2 +- .../ai/{mapper => dal/mysql}/AiChatMessageMapper.java | 2 +- .../ai/{mapper => dal/mysql}/AiChatModalMapper.java | 2 +- .../ai/{mapper => dal/mysql}/AiChatRoleMapper.java | 2 +- .../module/ai/{mapper => dal/mysql}/AiImageMapper.java | 2 +- .../vo}/typeHandler/AiChatModelConfigTypeHandler.java | 0 .../yudao/module/ai/service/AiChatModalService.java | 8 ++++---- .../yudao/module/ai/service/AiChatRoleService.java | 2 +- .../yudao/module/ai/service/AiImageService.java | 5 ++--- .../ai/service/impl/AiChatConversationServiceImpl.java | 9 +++++---- .../ai/service/impl/AiChatMessageServiceImpl.java | 4 ++-- .../module/ai/service/impl/AiChatModalServiceImpl.java | 10 +++++----- .../module/ai/service/impl/AiChatRoleServiceImpl.java | 4 ++-- .../module/ai/service/impl/AiChatServiceImpl.java | 6 +++--- .../module/ai/service/impl/AiImageServiceImpl.java | 6 +++--- .../YuDaoMidjourneyMessageHandler.java | 2 +- 36 files changed, 67 insertions(+), 66 deletions(-) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/{ => admin/image}/AiImageController.java (83%) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/package-info.java rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{ => controller/admin/image}/vo/AiImageDallDrawingReq.java (94%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{ => controller/admin/image}/vo/AiImageMidjourneyReq.java (84%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{ => controller/admin/image}/vo/AiImageMidjourneyRes.java (77%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/{ => admin/model}/AiChatModalController.java (84%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/{ => admin/model}/AiChatRoleController.java (91%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{vo => controller/admin/model/vo/model}/AiChatModalAddReq.java (95%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{vo => controller/admin/model/vo/model}/AiChatModalListReq.java (85%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{vo => controller/admin/model/vo/model}/AiChatModalListRes.java (92%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{vo => controller/admin/model/vo/model}/AiChatModalRes.java (92%) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/package-info.java rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{vo => controller/admin/model/vo/role}/AiChatRoleAddReq.java (92%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{vo => controller/admin/model/vo/role}/AiChatRoleListReq.java (84%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{vo => controller/admin/model/vo/role}/AiChatRoleListRes.java (92%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{vo => controller/admin/model/vo/role}/AiChatRoleRes.java (92%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{vo => controller/admin/model/vo/role}/AiChatRoleUpdateReq.java (92%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{vo => controller/admin/model/vo/role}/AiChatRoleUpdateVisibilityReq.java (87%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{mapper => dal/mysql}/AiChatConversationMapper.java (97%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{mapper => dal/mysql}/AiChatMessageMapper.java (94%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{mapper => dal/mysql}/AiChatModalMapper.java (95%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{mapper => dal/mysql}/AiChatRoleMapper.java (89%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{mapper => dal/mysql}/AiImageMapper.java (89%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{mapper => dal/vo}/typeHandler/AiChatModelConfigTypeHandler.java (100%) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java similarity index 83% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index 622778861..43e05dc83 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -1,9 +1,10 @@ -package cn.iocoder.yudao.module.ai.controller; +package cn.iocoder.yudao.module.ai.controller.admin.image; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; import cn.iocoder.yudao.module.ai.service.AiImageService; -import cn.iocoder.yudao.module.ai.vo.AiImageDallDrawingReq; -import cn.iocoder.yudao.module.ai.vo.AiImageMidjourneyReq; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReq; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReq; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; @@ -15,6 +16,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; +// TODO @芋艿:整理接口定义 /** * ai作图 * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/package-info.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/package-info.java deleted file mode 100644 index 9bc6965a1..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * TODO 芋艿:站位,无特殊作用 - */ -package cn.iocoder.yudao.module.ai.controller.admin.image; \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageDallDrawingReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallDrawingReq.java similarity index 94% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageDallDrawingReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallDrawingReq.java index fb62f2082..42887b7d3 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageDallDrawingReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallDrawingReq.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.vo; +package cn.iocoder.yudao.module.ai.controller.admin.image.vo; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageMidjourneyReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyReq.java similarity index 84% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageMidjourneyReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyReq.java index 279541377..a4bb622ac 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageMidjourneyReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyReq.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.vo; +package cn.iocoder.yudao.module.ai.controller.admin.image.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageMidjourneyRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyRes.java similarity index 77% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageMidjourneyRes.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyRes.java index 569047cd8..8d1a52e8c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiImageMidjourneyRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyRes.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.vo; +package cn.iocoder.yudao.module.ai.controller.admin.image.vo; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModalController.java similarity index 84% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModalController.java index cbbb23049..e90de159e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatModalController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModalController.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.module.ai.controller; +package cn.iocoder.yudao.module.ai.controller.admin.model; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.service.AiChatModalService; -import cn.iocoder.yudao.module.ai.vo.AiChatModalAddReq; -import cn.iocoder.yudao.module.ai.vo.AiChatModalListReq; -import cn.iocoder.yudao.module.ai.vo.AiChatModalListRes; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalAddReq; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListReq; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListRes; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; @@ -14,6 +14,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +// TODO @fan:调整下接口;相关 vo 的命名等等;modal => model /** * ai 模型 * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatRoleController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java similarity index 91% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatRoleController.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java index 2b459cdcb..e0b07e0e2 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/AiChatRoleController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.module.ai.controller; +package cn.iocoder.yudao.module.ai.controller.admin.model; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.*; import cn.iocoder.yudao.module.ai.service.AiChatRoleService; -import cn.iocoder.yudao.module.ai.vo.*; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; @@ -11,6 +11,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +// TODO @fan:调整下接口;相关 vo 的命名等等;modal => model /** * ai chat 角色 * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalAddReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalAddReq.java similarity index 95% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalAddReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalAddReq.java index 6a2b143dd..d750f922a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalAddReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalAddReq.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.vo; +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListReq.java similarity index 85% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListReq.java index 2aa6b931f..7a73a0c99 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListReq.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.vo; +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListRes.java similarity index 92% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListRes.java index 31d5e86f1..75e71df99 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalListRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListRes.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.vo; +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalRes.java similarity index 92% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalRes.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalRes.java index 351da2538..15879a603 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatModalRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalRes.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.vo; +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/package-info.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/package-info.java new file mode 100644 index 000000000..7fb31bb99 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.ai.controller.admin.model.vo; \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleAddReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleAddReq.java similarity index 92% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleAddReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleAddReq.java index 15a803458..f412b3e7e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleAddReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleAddReq.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.vo; +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleListReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListReq.java similarity index 84% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleListReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListReq.java index 1dd5e54ce..5662398a7 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleListReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListReq.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.vo; +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleListRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListRes.java similarity index 92% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleListRes.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListRes.java index e018c43a2..5aee6a3d2 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleListRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListRes.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.vo; +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleRes.java similarity index 92% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleRes.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleRes.java index a6903931c..6b4ec9d22 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleRes.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.vo; +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleUpdateReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdateReq.java similarity index 92% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleUpdateReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdateReq.java index 707c015f6..3a0f925ed 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleUpdateReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdateReq.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.vo; +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleUpdateVisibilityReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdateVisibilityReq.java similarity index 87% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleUpdateVisibilityReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdateVisibilityReq.java index 52685eb66..9e0c0c4ba 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/vo/AiChatRoleUpdateVisibilityReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdateVisibilityReq.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.vo; +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java index cd6714fdf..d2d6763f9 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.ai.convert; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; -import cn.iocoder.yudao.module.ai.vo.AiChatModalAddReq; -import cn.iocoder.yudao.module.ai.vo.AiChatModalListRes; -import cn.iocoder.yudao.module.ai.vo.AiChatModalRes; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalAddReq; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListRes; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRes; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Mappings; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java index b056a6d06..84c7aae81 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.ai.convert; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.vo.AiChatRoleAddReq; -import cn.iocoder.yudao.module.ai.vo.AiChatRoleRes; -import cn.iocoder.yudao.module.ai.vo.AiChatRoleUpdateReq; -import cn.iocoder.yudao.module.ai.vo.AiChatRoleListRes; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleAddReq; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleRes; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleUpdateReq; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleListRes; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatConversationMapper.java similarity index 97% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatConversationMapper.java index 1d10db144..0333be30d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatConversationMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatConversationMapper.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.mapper; +package cn.iocoder.yudao.module.ai.dal.mysql; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java similarity index 94% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java index 7227d6fc5..515e34333 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatMessageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.mapper; +package cn.iocoder.yudao.module.ai.dal.mysql; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatModalMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModalMapper.java similarity index 95% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatModalMapper.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModalMapper.java index 7eb5f218e..cc5074376 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatModalMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModalMapper.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.mapper; +package cn.iocoder.yudao.module.ai.dal.mysql; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageParam; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatRoleMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java similarity index 89% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatRoleMapper.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java index e96c60810..1ab7117b7 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiChatRoleMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.mapper; +package cn.iocoder.yudao.module.ai.dal.mysql; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiImageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiImageMapper.java similarity index 89% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiImageMapper.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiImageMapper.java index dfad53d62..ef2b6a596 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/AiImageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiImageMapper.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.mapper; +package cn.iocoder.yudao.module.ai.dal.mysql; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/typeHandler/AiChatModelConfigTypeHandler.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/typeHandler/AiChatModelConfigTypeHandler.java similarity index 100% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/mapper/typeHandler/AiChatModelConfigTypeHandler.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/typeHandler/AiChatModelConfigTypeHandler.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java index b1bf4a7d6..524859737 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.ai.vo.AiChatModalAddReq; -import cn.iocoder.yudao.module.ai.vo.AiChatModalListReq; -import cn.iocoder.yudao.module.ai.vo.AiChatModalListRes; -import cn.iocoder.yudao.module.ai.vo.AiChatModalRes; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalAddReq; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListReq; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListRes; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRes; /** * ai modal diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java index 5c756075c..96da840f8 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.ai.vo.*; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.*; /** * chat 角色 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java index 997c9a6d7..00b5ded44 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java @@ -1,9 +1,8 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; -import cn.iocoder.yudao.module.ai.vo.AiImageDallDrawingReq; -import cn.iocoder.yudao.module.ai.vo.AiImageMidjourneyReq; -import cn.iocoder.yudao.module.ai.vo.AiImageMidjourneyRes; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReq; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReq; /** * ai 作图 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java index 1a8425cc5..97221228e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java @@ -5,16 +5,17 @@ import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRes; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleRes; import cn.iocoder.yudao.module.ai.convert.AiChatConversationConvert; import cn.iocoder.yudao.module.ai.enums.AiChatConversationTypeEnum; import cn.iocoder.yudao.module.ai.enums.AiChatModalDisableEnum; -import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; -import cn.iocoder.yudao.module.ai.mapper.AiChatModalMapper; -import cn.iocoder.yudao.module.ai.mapper.AiChatRoleMapper; +import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; +import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModalMapper; +import cn.iocoder.yudao.module.ai.dal.mysql.AiChatRoleMapper; import cn.iocoder.yudao.module.ai.service.AiChatConversationService; import cn.iocoder.yudao.module.ai.service.AiChatModalService; import cn.iocoder.yudao.module.ai.service.AiChatRoleService; -import cn.iocoder.yudao.module.ai.vo.*; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatMessageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatMessageServiceImpl.java index ae5a594cb..2c86aa8a1 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatMessageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatMessageServiceImpl.java @@ -8,8 +8,8 @@ import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; -import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; -import cn.iocoder.yudao.module.ai.mapper.AiChatMessageMapper; +import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; +import cn.iocoder.yudao.module.ai.dal.mysql.AiChatMessageMapper; import cn.iocoder.yudao.module.ai.service.AiChatMessageService; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; import lombok.AllArgsConstructor; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java index 59de1b6e9..ebe16383f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java @@ -16,12 +16,12 @@ import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalChatConfigVO; import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalConfigVO; import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalDallConfigVO; import cn.iocoder.yudao.module.ai.enums.AiChatModalDisableEnum; -import cn.iocoder.yudao.module.ai.mapper.AiChatModalMapper; +import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModalMapper; import cn.iocoder.yudao.module.ai.service.AiChatModalService; -import cn.iocoder.yudao.module.ai.vo.AiChatModalAddReq; -import cn.iocoder.yudao.module.ai.vo.AiChatModalListReq; -import cn.iocoder.yudao.module.ai.vo.AiChatModalListRes; -import cn.iocoder.yudao.module.ai.vo.AiChatModalRes; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalAddReq; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListReq; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListRes; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRes; import jakarta.validation.ConstraintViolation; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java index 5ca5af4fa..fc882e020 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java @@ -6,13 +6,13 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.*; import cn.iocoder.yudao.module.ai.convert.AiChatRoleConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.enums.AiChatRoleClassifyEnum; import cn.iocoder.yudao.module.ai.enums.AiChatRoleEnableEnum; -import cn.iocoder.yudao.module.ai.mapper.AiChatRoleMapper; +import cn.iocoder.yudao.module.ai.dal.mysql.AiChatRoleMapper; import cn.iocoder.yudao.module.ai.service.AiChatRoleService; -import cn.iocoder.yudao.module.ai.vo.*; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index 50f4ac0cb..c7f6cf37a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -11,9 +11,9 @@ import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.config.AiChatClientFactory; import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; -import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; -import cn.iocoder.yudao.module.ai.mapper.AiChatMessageMapper; -import cn.iocoder.yudao.module.ai.mapper.AiChatRoleMapper; +import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; +import cn.iocoder.yudao.module.ai.dal.mysql.AiChatMessageMapper; +import cn.iocoder.yudao.module.ai.dal.mysql.AiChatRoleMapper; import cn.iocoder.yudao.module.ai.service.AiChatConversationService; import cn.iocoder.yudao.module.ai.service.AiChatService; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java index ca23eb786..16a414681 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java @@ -17,10 +17,10 @@ import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.enums.AiChatDrawingStatusEnum; -import cn.iocoder.yudao.module.ai.mapper.AiImageMapper; +import cn.iocoder.yudao.module.ai.dal.mysql.AiImageMapper; import cn.iocoder.yudao.module.ai.service.AiImageService; -import cn.iocoder.yudao.module.ai.vo.AiImageDallDrawingReq; -import cn.iocoder.yudao.module.ai.vo.AiImageMidjourneyReq; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReq; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReq; import jakarta.annotation.PostConstruct; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java index 68f639765..0910b2946 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java @@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyGennerateSta import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyMessageHandler; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.enums.AiChatDrawingStatusEnum; -import cn.iocoder.yudao.module.ai.mapper.AiImageMapper; +import cn.iocoder.yudao.module.ai.dal.mysql.AiImageMapper; import com.alibaba.fastjson2.JSON; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; From f86e24bb865ca55d0b0712beb9e318b056a32c78 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 10:04:49 +0800 Subject: [PATCH 219/684] =?UTF-8?q?=E3=80=90=E8=B0=83=E6=95=B4=E3=80=91?= =?UTF-8?q?=E8=B0=83=E6=95=B4AI=E5=AF=B9=E8=AF=9D=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/AiCommonConstants.java | 16 ++ .../yudao/module/ai/ErrorCodeConstants.java | 4 + .../chat/AiChatConversationController.java | 26 ++-- .../AiChatConversationListReqVO.java | 13 ++ .../ai/convert/AiChatConversationConvert.java | 8 + .../ai/dal/mysql/AiChatModalMapper.java | 1 + .../ai/service/AiChatConversationService.java | 30 ++-- .../module/ai/service/AiChatModalService.java | 2 +- .../impl/AiChatConversationServiceImpl.java | 145 ++++++++---------- .../service/impl/AiChatModalServiceImpl.java | 3 +- .../ai/service/impl/AiChatServiceImpl.java | 4 +- 11 files changed, 136 insertions(+), 116 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/AiCommonConstants.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationListReqVO.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/AiCommonConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/AiCommonConstants.java new file mode 100644 index 000000000..2bd71376b --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/AiCommonConstants.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.ai; + +/** + * ai 常用的常量 + * + * @author fansili + * @time 2024/5/7 09:29 + * @since 1.0 + */ +public class AiCommonConstants { + + /** + * 对话 - 默认 title + */ + public static final String CONVERSATION_DEFAULT_TITLE = "新增对话"; +} diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index 25b3b7109..c954a1667 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -15,6 +15,10 @@ public interface ErrorCodeConstants { ErrorCode AI_MODULE_NOT_SUPPORTED = new ErrorCode(1_022_000_000, "AI 模型暂不支持!"); ErrorCode AI_CHAT_ROLE_NOT_EXISTENT = new ErrorCode(1_022_000_001, "AI Role 不存在!");; + + // conversation + + ErrorCode AI_CONVERSATION_NOT_EXISTS = new ErrorCode(1_022_000_002, "AI 对话不存在!");; ErrorCode AI_CHAT_CONTINUE_CONVERSATION_ID_NOT_NULL = new ErrorCode(1_022_000_002, "chat 继续对话,对话 id 不能为空!");; ErrorCode AI_CHAT_CONTINUE_NOT_EXIST = new ErrorCode(1_022_000_020, "chat 对话不存在!"); ErrorCode AI_CHAT_CONVERSATION_NOT_YOURS = new ErrorCode(1_022_000_021, "这条 chat 对话不是你的!"); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java index f8a7d8d1b..988490a6f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java @@ -2,12 +2,15 @@ package cn.iocoder.yudao.module.ai.controller.admin.chat; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationListReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateReqVO; +import cn.iocoder.yudao.module.ai.service.AiChatConversationService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; +import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; @@ -16,33 +19,36 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +@Slf4j @Tag(name = "管理后台 - 聊天会话") @RestController @RequestMapping("/ai/chat/conversation") -@Slf4j +@AllArgsConstructor public class AiChatConversationController { - // TODO @fan:实现一下 + private final AiChatConversationService aiChatConversationService; + + // TODO done @fan:实现一下 @PostMapping("/create") @Operation(summary = "创建聊天会话") @PreAuthorize("@ss.hasPermission('ai:chat-conversation:create')") public CommonResult createConversation(@RequestBody @Valid AiChatConversationCreateReqVO createReqVO) { - return success(1L); + return success(aiChatConversationService.createConversation(createReqVO)); } - // TODO @fan:实现一下 + // TODO done @fan:实现一下 @PutMapping("/update") @Operation(summary = "更新聊天会话") @PreAuthorize("@ss.hasPermission('ai:chat-conversation:create')") public CommonResult updateConversation(@RequestBody @Valid AiChatConversationUpdateReqVO updateReqVO) { - return success(true); + return success(aiChatConversationService.updateConversation(updateReqVO)); } - // TODO @fan:实现一下 + // TODO done @fan:实现一下 @GetMapping("/list") @Operation(summary = "获得聊天会话列表") - public CommonResult> getConversationList() { - return success(null); + public CommonResult> getConversationList(@ModelAttribute AiChatConversationListReqVO listReqVO) { + return success(aiChatConversationService.listConversation(listReqVO)); } // TODO @fan:实现一下 @@ -50,7 +56,7 @@ public class AiChatConversationController { @Operation(summary = "获得聊天会话") @Parameter(name = "id", required = true, description = "会话编号", example = "1024") public CommonResult getConversation(@RequestParam("id") Long id) { - return success(null); + return success(aiChatConversationService.getConversationOfValidate(id)); } // TODO @fan:实现一下 @@ -58,7 +64,7 @@ public class AiChatConversationController { @Operation(summary = "删除聊天会话") @Parameter(name = "id", required = true, description = "会话编号", example = "1024") public CommonResult deleteConversation(@RequestParam("id") Long id) { - return success(null); + return success(aiChatConversationService.deleteConversation(id)); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationListReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationListReqVO.java new file mode 100644 index 000000000..571cf0e38 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationListReqVO.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - AI 聊天会话 Response VO") +@Data +public class AiChatConversationListReqVO { + + @Schema(description = "会话标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是一个标题") + private String title; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java index af1a0bb21..50c4b64d6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.ai.convert; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import org.mapstruct.Mapper; @@ -34,4 +35,11 @@ public interface AiChatConversationConvert { * @return */ AiChatConversationRespVO covnertChatConversationRes(AiChatConversationDO aiChatConversationDO); + + /** + * 转换 - AiChatConversationDO + * + * @param updateReqVO + */ + AiChatConversationDO convertAiChatConversationDO(AiChatConversationUpdateReqVO updateReqVO); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModalMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModalMapper.java index cc5074376..d460710da 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModalMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModalMapper.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java index 86592e5e8..663cde77a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java @@ -1,7 +1,9 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationListReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateReqVO; import java.util.List; @@ -14,29 +16,20 @@ import java.util.List; public interface AiChatConversationService { /** - * 对话 - 创建普通对话 + * 对话 - 创建对话 * * @param req * @return */ - AiChatConversationRespVO createConversation(AiChatConversationCreateUserReq req); + Long createConversation(AiChatConversationCreateReqVO req); /** - * 对话 - 创建role对话 + * 对话 - 更新对话 * - * @param req + * @param updateReqVO * @return */ - AiChatConversationRespVO createRoleConversation(AiChatConversationCreateReqVO req); - - - /** - * 获取 - 对话 - * - * @param id - * @return - */ - AiChatConversationRespVO getConversation(Long id); + Boolean updateConversation(AiChatConversationUpdateReqVO updateReqVO); /** * 获取 - 对话列表 @@ -44,22 +37,21 @@ public interface AiChatConversationService { * @param req * @return */ - List listConversation(AiChatConversationListReq req); + List listConversation(AiChatConversationListReqVO req); /** - * 更新 - 更新模型 + * 获取 - 对话 * * @param id - * @param modalId * @return */ - void updateModal(Long id, Long modalId); + AiChatConversationRespVO getConversationOfValidate(Long id); /** * 删除 - 根据id * * @param id */ - void delete(Long id); + Boolean deleteConversation(Long id); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java index 524859737..60511c8a6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java @@ -51,5 +51,5 @@ public interface AiChatModalService { * @param modalId * @return */ - AiChatModalRes getChatModal(Long modalId); + AiChatModalRes getChatModalOfValidate(Long modalId); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java index 97221228e..4f6a2cc52 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java @@ -2,17 +2,20 @@ package cn.iocoder.yudao.module.ai.service.impl; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.module.ai.AiCommonConstants; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationListReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRes; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleRes; import cn.iocoder.yudao.module.ai.convert.AiChatConversationConvert; -import cn.iocoder.yudao.module.ai.enums.AiChatConversationTypeEnum; -import cn.iocoder.yudao.module.ai.enums.AiChatModalDisableEnum; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModalMapper; -import cn.iocoder.yudao.module.ai.dal.mysql.AiChatRoleMapper; +import cn.iocoder.yudao.module.ai.enums.AiChatModalDisableEnum; import cn.iocoder.yudao.module.ai.service.AiChatConversationService; import cn.iocoder.yudao.module.ai.service.AiChatModalService; import cn.iocoder.yudao.module.ai.service.AiChatRoleService; @@ -34,119 +37,95 @@ import java.util.List; @AllArgsConstructor public class AiChatConversationServiceImpl implements AiChatConversationService { - private final AiChatRoleMapper aiChatRoleMapper; private final AiChatModalMapper aiChatModalMapper; - private final AiChatConversationMapper aiChatConversationMapper; private final AiChatModalService aiChatModalService; private final AiChatRoleService aiChatRoleService; + private final AiChatConversationMapper aiChatConversationMapper; @Override - public AiChatConversationRespVO createConversation(AiChatConversationCreateUserReq req) { + public Long createConversation(AiChatConversationCreateReqVO req) { // 获取用户id Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); - // 查询最新的对话 - AiChatConversationDO latestConversation = aiChatConversationMapper.selectLatestConversation(loginUserId); - // 如果有对话没有被使用过,那就返回这个 - if (latestConversation != null && latestConversation.getChatCount() <= 0) { - return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(latestConversation); - } - // 获取第一个模型 + // 默认使用 sort 排序第一个模型 AiChatModalDO aiChatModalDO = aiChatModalMapper.selectFirstModal(); - // 创建新的 Conversation - AiChatConversationDO insertConversation = saveConversation(req.getTitle(), loginUserId, - null, null, AiChatConversationTypeEnum.USER_CHAT, - aiChatModalDO.getId(), aiChatModalDO.getModal()); - // 转换 res - return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(insertConversation); - } - - @Override - public AiChatConversationRespVO createRoleConversation(AiChatConversationCreateReqVO req) { - // 获取用户id - Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); - // 查询最新的对话 -// AiChatConversationDO latestConversation = aiChatConversationMapper.selectLatestConversation(loginUserId); -// // 如果有对话没有被使用过,那就返回这个 -// if (latestConversation != null && latestConversation.getChatCount() <= 0) { -// return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(latestConversation); -// } // 查询角色 - AiChatRoleRes chatRoleRes = aiChatRoleService.getChatRole(req.getRoleId()); - // 获取第一个模型 - AiChatModalDO aiChatModalDO = aiChatModalMapper.selectFirstModal(); + AiChatRoleRes chatRoleRes = null; + if (req.getRoleId() != null) { + chatRoleRes = aiChatRoleService.getChatRole(req.getRoleId()); + } + Long chatRoleId = chatRoleRes != null ? chatRoleRes.getId() : null; // 创建新的 Conversation - AiChatConversationDO insertConversation = saveConversation(req.getTitle(), loginUserId, - req.getRoleId(), chatRoleRes.getName(), AiChatConversationTypeEnum.ROLE_CHAT, - aiChatModalDO.getId(), aiChatModalDO.getModal()); - // 转换 res - return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(insertConversation); + AiChatConversationDO insertConversation = saveConversation(AiCommonConstants.CONVERSATION_DEFAULT_TITLE, + loginUserId, chatRoleId, aiChatModalDO.getId(), aiChatModalDO.getModel() + ); + // 返回对话id + return insertConversation.getId(); } private @NotNull AiChatConversationDO saveConversation(String title, Long userId, Long roleId, - String roleName, - AiChatConversationTypeEnum typeEnum, Long modalId, - String modal) { + String model) { AiChatConversationDO insertConversation = new AiChatConversationDO(); insertConversation.setId(null); insertConversation.setUserId(userId); - insertConversation.setRoleId(roleId); - insertConversation.setRoleName(roleName); insertConversation.setTitle(title); - insertConversation.setChatCount(0); - insertConversation.setType(typeEnum.getType()); - insertConversation.setModalId(modalId); - insertConversation.setModal(modal); + insertConversation.setPinned(false); + + insertConversation.setRoleId(roleId); + insertConversation.setModelId(modalId); + insertConversation.setModel(model); + + insertConversation.setTemperature(null); + insertConversation.setMaxTokens(null); + insertConversation.setMaxContexts(null); aiChatConversationMapper.insert(insertConversation); return insertConversation; } @Override - public AiChatConversationRespVO getConversation(Long id) { + public Boolean updateConversation(AiChatConversationUpdateReqVO updateReqVO) { + // 校验对话是否存在 + validateExists(updateReqVO.getId()); + // 获取模型信息并验证 + AiChatModalRes chatModal = aiChatModalService.getChatModalOfValidate(updateReqVO.getModelId()); + // 校验modal是否可用 + if (AiChatModalDisableEnum.YES.getValue().equals(chatModal.getDisable())) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_DISABLE_NOT_USED); + } + // 更新对话信息 + AiChatConversationDO updateAiChatConversationDO + = AiChatConversationConvert.INSTANCE.convertAiChatConversationDO(updateReqVO); + return aiChatConversationMapper.updateById(updateAiChatConversationDO) > 0; + } + + @Override + public List listConversation(AiChatConversationListReqVO listReqVO) { + // 获取用户id + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + // 查询前100对话 + List top100Conversation + = aiChatConversationMapper.selectTop100Conversation(loginUserId, listReqVO.getTitle()); + return AiChatConversationConvert.INSTANCE.covnertChatConversationResList(top100Conversation); + } + + @Override + public AiChatConversationRespVO getConversationOfValidate(Long id) { AiChatConversationDO aiChatConversationDO = validateExists(id); return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(aiChatConversationDO); } + @Override + public Boolean deleteConversation(Long id) { + return aiChatConversationMapper.deleteById(id) > 0; + } + private @NotNull AiChatConversationDO validateExists(Long id) { AiChatConversationDO aiChatConversationDO = aiChatConversationMapper.selectById(id); if (aiChatConversationDO == null) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CHAT_CONTINUE_NOT_EXIST); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CONVERSATION_NOT_EXISTS); } return aiChatConversationDO; } - - @Override - public List listConversation(AiChatConversationListReq req) { - // 获取用户id - Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); - // 查询前100对话 - List top100Conversation - = aiChatConversationMapper.selectTop100Conversation(loginUserId, req.getSearch()); - return AiChatConversationConvert.INSTANCE.covnertChatConversationResList(top100Conversation); - } - - @Override - public void updateModal(Long id, Long modalId) { - // 校验对话是否存在 - validateExists(id); - // 获取模型 - AiChatModalRes chatModal = aiChatModalService.getChatModal(modalId); - // 判断模型是否禁用 - if (AiChatModalDisableEnum.YES.getValue().equals(chatModal.getDisable())) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_DISABLE_NOT_USED); - } - // 更新对话 - aiChatConversationMapper.updateById(new AiChatConversationDO() - .setId(id) - .setModalId(chatModal.getId()) - .setModal(chatModal.getModal()) - ); - } - - @Override - public void delete(Long id) { - aiChatConversationMapper.deleteById(id); - } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java index ebe16383f..67013bdda 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java @@ -12,6 +12,7 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.convert.AiChatModalConvert; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalChatConfigVO; import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalConfigVO; import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalDallConfigVO; @@ -109,7 +110,7 @@ public class AiChatModalServiceImpl implements AiChatModalService { } @Override - public AiChatModalRes getChatModal(Long modalId) { + public AiChatModalRes getChatModalOfValidate(Long modalId) { // 检查 modal 是否存在 AiChatModalDO aiChatModalDO = validateChatModalExists(modalId); return AiChatModalConvert.INSTANCE.convertAiChatModalRes(aiChatModalDO); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index c7f6cf37a..f833f60d9 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -58,7 +58,7 @@ public class AiChatServiceImpl implements AiChatService { // 获取 client 类型 AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(req.getModal()); // 获取对话信息 - AiChatConversationRespVO conversationRes = chatConversationService.getConversation(req.getConversationId()); + AiChatConversationRespVO conversationRes = chatConversationService.getConversationOfValidate(req.getConversationId()); // 保存 chat message saveChatMessage(req, conversationRes, loginUserId); String content = null; @@ -133,7 +133,7 @@ public class AiChatServiceImpl implements AiChatService { // 获取 client 类型 AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(req.getModal()); // 获取对话信息 - AiChatConversationRespVO conversationRes = chatConversationService.getConversation(req.getConversationId()); + AiChatConversationRespVO conversationRes = chatConversationService.getConversationOfValidate(req.getConversationId()); // 创建 chat 需要的 Prompt Prompt prompt = new Prompt(req.getPrompt()); req.setTopK(req.getTopK()); From 424210066ff3ce6f5a37d4d6da939d31cdd3eb52 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 10:45:37 +0800 Subject: [PATCH 220/684] =?UTF-8?q?=E3=80=90=E8=B0=83=E6=95=B4=E3=80=91?= =?UTF-8?q?=E8=B0=83=E6=95=B4AI=E8=81=8A=E5=A4=A9=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/ErrorCodeConstants.java | 1 + .../admin/chat/AiChatMessageController.java | 2 +- .../AiChatConversationRespVO.java | 3 + .../module/ai/service/AiChatModalService.java | 7 + .../module/ai/service/AiChatRoleService.java | 16 ++ .../module/ai/service/AiChatService.java | 5 +- .../impl/AiChatConversationServiceImpl.java | 5 +- .../service/impl/AiChatModalServiceImpl.java | 8 + .../service/impl/AiChatRoleServiceImpl.java | 20 ++- .../ai/service/impl/AiChatServiceImpl.java | 153 ++++++++++-------- 10 files changed, 139 insertions(+), 81 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index c954a1667..cf5d6e76e 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -30,6 +30,7 @@ public interface ErrorCodeConstants { // role ErrorCode AI_CHAT_ROLE_NOT_EXIST = new ErrorCode(1_022_000_060, "chatRole 不存在!"); + ErrorCode AI_CHAT_ROLE_NOT_PUBLIC = new ErrorCode(1_022_000_060, "AI 角色未公开!"); // modal diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java index 473f1c856..63e947e59 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java @@ -32,7 +32,7 @@ public class AiChatMessageController { @PostMapping("/send") public CommonResult sendMessage(@Validated @ModelAttribute AiChatMessageSendReqVO sendReqVO) { // TODO @fan:使用 static import;这样就 success 就行了; - return success(null); + return success(chatService.chat(sendReqVO)); } // TODO @芋艿:调用这个方法异常,Unable to handle the Spring Security Exception because the response is already committed.;可以再试试 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java index 720736f21..70ff21fc5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java @@ -21,6 +21,9 @@ public class AiChatConversationRespVO { @Schema(description = "是否置顶", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") private Boolean pinned; + @Schema(description = "角色编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1") + private Long roleId; + @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long modelId; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java index 60511c8a6..5740328be 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java @@ -52,4 +52,11 @@ public interface AiChatModalService { * @return */ AiChatModalRes getChatModalOfValidate(Long modalId); + + /** + * 校验 - 校验是否可用 + * + * @param chatModal + */ + void validateAvailable(AiChatModalRes chatModal); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java index 96da840f8..5f11e4ffc 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.*; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; /** * chat 角色 @@ -58,4 +59,19 @@ public interface AiChatRoleService { * @return */ AiChatRoleRes getChatRole(Long roleId); + + /** + * 校验 - 角色是否存在 + * + * @param id + * @return + */ + AiChatRoleDO validateExists(Long id); + + /** + * 校验 - 角色是否公开 + * + * @param aiChatRoleDO + */ + void validateIsPublic(AiChatRoleDO aiChatRoleDO); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java index c054e41fa..e25062e78 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; /** @@ -15,10 +16,10 @@ public interface AiChatService { /** * chat * - * @param req + * @param sendReqVO * @return */ - String chat(AiChatMessageSendReqVO req); + AiChatMessageRespVO chat(AiChatMessageSendReqVO sendReqVO); /** * chat stream diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java index 4f6a2cc52..6fbafc659 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java @@ -15,7 +15,6 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModalMapper; -import cn.iocoder.yudao.module.ai.enums.AiChatModalDisableEnum; import cn.iocoder.yudao.module.ai.service.AiChatConversationService; import cn.iocoder.yudao.module.ai.service.AiChatModalService; import cn.iocoder.yudao.module.ai.service.AiChatRoleService; @@ -91,9 +90,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService // 获取模型信息并验证 AiChatModalRes chatModal = aiChatModalService.getChatModalOfValidate(updateReqVO.getModelId()); // 校验modal是否可用 - if (AiChatModalDisableEnum.YES.getValue().equals(chatModal.getDisable())) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_DISABLE_NOT_USED); - } + aiChatModalService.validateAvailable(chatModal); // 更新对话信息 AiChatConversationDO updateAiChatConversationDO = AiChatConversationConvert.INSTANCE.convertAiChatConversationDO(updateReqVO); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java index 67013bdda..89c85f8ee 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java @@ -116,6 +116,14 @@ public class AiChatModalServiceImpl implements AiChatModalService { return AiChatModalConvert.INSTANCE.convertAiChatModalRes(aiChatModalDO); } + @Override + public void validateAvailable(AiChatModalRes chatModal) { + // 对话模型是否可用 + if (AiChatModalDisableEnum.YES.getValue().equals(chatModal.getDisable())) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_DISABLE_NOT_USED); + } + } + private AiChatModalDO validateChatModalExists(Long id) { AiChatModalDO aiChatModalDO = aiChatModalMapper.selectById(id); if (aiChatModalDO == null) { diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java index fc882e020..95ed67861 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java @@ -70,7 +70,7 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { AiChatRoleClassifyEnum.valueOfClassify(req.getClassify()); AiChatRoleEnableEnum.valueOfType(req.getEnable()); // 检查角色是否存在 - validateChatRoleExists(id); + validateExists(id); // 转换do AiChatRoleDO updateChatRole = AiChatRoleConvert.INSTANCE.convertAiChatRoleDO(req); updateChatRole.setId(id); @@ -83,7 +83,7 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { // 转换enum,并校验enum AiChatRoleEnableEnum.valueOfType(req.getEnable()); // 检查角色是否存在 - validateChatRoleExists(id); + validateExists(id); // 更新 aiChatRoleMapper.updateById(new AiChatRoleDO() .setId(id) @@ -94,7 +94,7 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { @Override public void delete(Long chatRoleId) { // 检查角色是否存在 - validateChatRoleExists(chatRoleId); + validateExists(chatRoleId); // 删除 aiChatRoleMapper.deleteById(chatRoleId); } @@ -102,15 +102,25 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { @Override public AiChatRoleRes getChatRole(Long roleId) { // 检查角色是否存在 - AiChatRoleDO aiChatRoleDO = validateChatRoleExists(roleId); + AiChatRoleDO aiChatRoleDO = validateExists(roleId); return AiChatRoleConvert.INSTANCE.convertAiChatRoleRes(aiChatRoleDO); } - private AiChatRoleDO validateChatRoleExists(Long id) { + public AiChatRoleDO validateExists(Long id) { AiChatRoleDO aiChatRoleDO = aiChatRoleMapper.selectById(id); if (aiChatRoleDO == null) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CHAT_ROLE_NOT_EXIST); } return aiChatRoleDO; } + + public void validateIsPublic(AiChatRoleDO aiChatRoleDO) { + if (aiChatRoleDO == null) { + return; + } + if (!aiChatRoleDO.getPublicStatus()) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CHAT_ROLE_NOT_PUBLIC); + } + } } + diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index f833f60d9..b5e2634de 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -10,14 +10,19 @@ import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.config.AiChatClientFactory; import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRes; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatMessageMapper; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatRoleMapper; import cn.iocoder.yudao.module.ai.service.AiChatConversationService; +import cn.iocoder.yudao.module.ai.service.AiChatModalService; +import cn.iocoder.yudao.module.ai.service.AiChatRoleService; import cn.iocoder.yudao.module.ai.service.AiChatService; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.MediaType; @@ -45,29 +50,39 @@ public class AiChatServiceImpl implements AiChatService { private final AiChatMessageMapper aiChatMessageMapper; private final AiChatConversationMapper aiChatConversationMapper; private final AiChatConversationService chatConversationService; + private final AiChatModalService aiChatModalService; + private final AiChatRoleService aiChatRoleService; - /** - * chat - * - * @param req - * @return - */ @Transactional(rollbackFor = Exception.class) - public String chat(AiChatMessageSendReqVO req) { + public AiChatMessageRespVO chat(AiChatMessageSendReqVO req) { Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + // 查询对话 + AiChatConversationRespVO conversation = chatConversationService.getConversationOfValidate(req.getConversationId()); + // 获取对话模型 + AiChatModalRes chatModal = aiChatModalService.getChatModalOfValidate(conversation.getModelId()); + // 对话模型是否可用 + aiChatModalService.validateAvailable(chatModal); + // 获取角色信息 + AiChatRoleDO aiChatRoleDO = null; + if (conversation.getRoleId() != null) { + aiChatRoleDO = aiChatRoleService.validateExists(conversation.getRoleId()); + } + // 校验角色是否公开 + aiChatRoleService.validateIsPublic(aiChatRoleDO); // 获取 client 类型 - AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(req.getModal()); - // 获取对话信息 - AiChatConversationRespVO conversationRes = chatConversationService.getConversationOfValidate(req.getConversationId()); + AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(chatModal.getModal()); // 保存 chat message - saveChatMessage(req, conversationRes, loginUserId); + insertChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(), + chatModal.getModal(), chatModal.getId(), req.getContent(), + null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); String content = null; try { // 创建 chat 需要的 Prompt - Prompt prompt = new Prompt(req.getPrompt()); - req.setTopK(req.getTopK()); - req.setTopP(req.getTopP()); - req.setTemperature(req.getTemperature()); + Prompt prompt = new Prompt(req.getContent()); + // TODO @芋艿 @范 看要不要支持这些 +// req.setTopK(req.getTopK()); +// req.setTopP(req.getTopP()); +// req.setTemperature(req.getTemperature()); // 发送 call 调用 ChatClient chatClient = aiChatClientFactory.getChatClient(platformEnum); ChatResponse call = chatClient.call(prompt); @@ -78,69 +93,66 @@ public class AiChatServiceImpl implements AiChatService { content = ExceptionUtil.getMessage(e); } finally { // 保存 chat message - saveSystemChatMessage(req, conversationRes, loginUserId, content); + insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), + chatModal.getModal(), chatModal.getId(), req.getContent(), + null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); } - return content; + return new AiChatMessageRespVO().setContent(content); } - private void saveChatMessage(AiChatMessageSendReqVO req, AiChatConversationRespVO conversationRes, Long loginUserId) { - Long chatConversationId = conversationRes.getId(); + private AiChatMessageDO insertChatMessage(Long conversationId, MessageType messageType, Long loginUserId, Long roleId, + String model, Long modelId, String content, Integer tokens, Double temperature, + Integer maxTokens, Integer maxContexts) { + AiChatMessageDO insertChatMessageDO = new AiChatMessageDO() + .setId(null) + .setConversationId(conversationId) + .setType(messageType.getValue()) + .setUserId(loginUserId) + .setRoleId(roleId) + .setModel(model) + .setModelId(modelId) + .setContent(content) + .setTokens(tokens) + + .setTemperature(temperature) + .setMaxTokens(maxTokens) + .setMaxContexts(maxContexts); // 增加 chat message 记录 - aiChatMessageMapper.insert( - new AiChatMessageDO() - .setId(null) - .setConversationId(chatConversationId) - .setUserId(loginUserId) - .setMessage(req.getPrompt()) - .setMessageType(MessageType.USER.getValue()) - .setTopK(req.getTopK()) - .setTopP(req.getTopP()) - .setTemperature(req.getTemperature()) - ); + aiChatMessageMapper.insert(insertChatMessageDO); // chat count 先+1 - aiChatConversationMapper.updateIncrChatCount(req.getConversationId()); + aiChatConversationMapper.updateIncrChatCount(conversationId); + return insertChatMessageDO; } - public void saveSystemChatMessage(AiChatMessageSendReqVO req, AiChatConversationRespVO conversationRes, Long loginUserId, String systemPrompts) { - Long chatConversationId = conversationRes.getId(); - // 增加 chat message 记录 - aiChatMessageMapper.insert( - new AiChatMessageDO() - .setId(null) - .setConversationId(chatConversationId) - .setUserId(loginUserId) - .setMessage(systemPrompts) - .setMessageType(MessageType.SYSTEM.getValue()) - .setTopK(req.getTopK()) - .setTopP(req.getTopP()) - .setTemperature(req.getTemperature()) - ); - - // chat count 先+1 - aiChatConversationMapper.updateIncrChatCount(req.getConversationId()); - } - - /** - * chat stream - * - * @param req - * @param sseEmitter - * @return - */ @Override public void chatStream(AiChatMessageSendReqVO req, Utf8SseEmitter sseEmitter) { Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); - // 获取 client 类型 - AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(req.getModal()); - // 获取对话信息 - AiChatConversationRespVO conversationRes = chatConversationService.getConversationOfValidate(req.getConversationId()); + // 查询对话 + AiChatConversationRespVO conversation = chatConversationService.getConversationOfValidate(req.getConversationId()); + // 获取对话模型 + AiChatModalRes chatModal = aiChatModalService.getChatModalOfValidate(conversation.getModelId()); + // 对话模型是否可用 + aiChatModalService.validateAvailable(chatModal); + // 获取角色信息 + AiChatRoleDO aiChatRoleDO = null; + if (conversation.getRoleId() != null) { + aiChatRoleDO = aiChatRoleService.validateExists(conversation.getRoleId()); + } + // 校验角色是否公开 + aiChatRoleService.validateIsPublic(aiChatRoleDO); // 创建 chat 需要的 Prompt - Prompt prompt = new Prompt(req.getPrompt()); - req.setTopK(req.getTopK()); - req.setTopP(req.getTopP()); - req.setTemperature(req.getTemperature()); + Prompt prompt = new Prompt(req.getContent()); +// req.setTopK(req.getTopK()); +// req.setTopP(req.getTopP()); +// req.setTemperature(req.getTemperature()); // 保存 chat message - saveChatMessage(req, conversationRes, loginUserId); + // 保存 chat message + insertChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(), + chatModal.getModal(), chatModal.getId(), req.getContent(), + null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); + + // 获取 client 类型 + AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(chatModal.getModal()); StreamingChatClient streamingChatClient = aiChatClientFactory.getStreamingChatClient(platformEnum); Flux streamResponse = streamingChatClient.stream(prompt); @@ -168,7 +180,10 @@ public class AiChatServiceImpl implements AiChatService { log.info("发送完成!"); sseEmitter.complete(); // 保存 chat message - saveSystemChatMessage(req, conversationRes, loginUserId, contentBuffer.toString()); + insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), + chatModal.getModal(), chatModal.getId(), req.getContent(), + null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); + } ); } From 8de98a15bb9314ada5ea1e47fbd2ddcce7a06baf Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 10:54:56 +0800 Subject: [PATCH 221/684] =?UTF-8?q?=E3=80=90=E8=B0=83=E6=95=B4=E3=80=91?= =?UTF-8?q?=E8=B0=83=E6=95=B4AI=E8=81=8A=E5=A4=A9=EF=BC=8Cmessage=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E3=80=81=E5=88=A0=E9=99=A4message?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/AiChatConversationController.java | 5 ++--- .../admin/chat/AiChatMessageController.java | 8 ++++---- .../ai/convert/AiChatMessageConvert.java | 10 +++++++++- .../ai/dal/mysql/AiChatMessageMapper.java | 10 ++++++++++ .../ai/service/AiChatConversationService.java | 12 ++++++++++-- .../module/ai/service/AiChatService.java | 19 +++++++++++++++++++ .../impl/AiChatConversationServiceImpl.java | 6 +++--- .../ai/service/impl/AiChatServiceImpl.java | 17 +++++++++++++++++ 8 files changed, 74 insertions(+), 13 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java index 988490a6f..7bd3c5a14 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.ai.controller.admin.chat; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationListReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateReqVO; import cn.iocoder.yudao.module.ai.service.AiChatConversationService; @@ -47,8 +46,8 @@ public class AiChatConversationController { // TODO done @fan:实现一下 @GetMapping("/list") @Operation(summary = "获得聊天会话列表") - public CommonResult> getConversationList(@ModelAttribute AiChatConversationListReqVO listReqVO) { - return success(aiChatConversationService.listConversation(listReqVO)); + public CommonResult> getConversationList() { + return success(aiChatConversationService.listConversation()); } // TODO @fan:实现一下 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java index 63e947e59..285611cbe 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java @@ -31,7 +31,7 @@ public class AiChatMessageController { @Operation(summary = "发送消息(段式)", description = "一次性返回,响应较慢") @PostMapping("/send") public CommonResult sendMessage(@Validated @ModelAttribute AiChatMessageSendReqVO sendReqVO) { - // TODO @fan:使用 static import;这样就 success 就行了; + // TODO done @fan:使用 static import;这样就 success 就行了; return success(chatService.chat(sendReqVO)); } @@ -49,14 +49,14 @@ public class AiChatMessageController { @GetMapping("/list-by-conversation-id") @Parameter(name = "conversationId", required = true, description = "会话编号", example = "1024") public CommonResult> getMessageListByConversationId(@RequestParam("conversationId") Long conversationId) { - return success(null); + return success(chatService.getMessageListByConversationId(conversationId)); } @Operation(summary = "删除消息") @DeleteMapping("/delete") @Parameter(name = "id", required = true, description = "消息编号", example = "1024") - public CommonResult delete(@RequestParam("id") Long id) { - return success(null); + public CommonResult deleteMessage(@RequestParam("id") Long id) { + return success(chatService.deleteMessage(id)); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java index c84ecb404..d067a26f3 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java @@ -20,10 +20,18 @@ public interface AiChatMessageConvert { AiChatMessageConvert INSTANCE = Mappers.getMapper(AiChatMessageConvert.class); /** - * 转换 ChatMessageListRes + * 转换 ChatMessageListRes * * @param list * @return */ List convert(List list); + + /** + * 转换 AiChatMessageRespVO + * + * @param aiChatMessageDOList + * @return + */ + List convertAiChatMessageRespVOList(List aiChatMessageDOList); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java index 515e34333..4e2100aff 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java @@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; +import java.util.List; + /** * message mapper * @@ -29,4 +31,12 @@ public interface AiChatMessageMapper extends BaseMapperX { ); } + /** + * 查询 - 根据 对话id查询 + * + * @param conversationId + */ + default List selectByConversationId(Long conversationId) { + return selectList() + } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java index 663cde77a..1abf2476f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java @@ -4,6 +4,8 @@ import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatCo import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationListReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateReqVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; +import org.jetbrains.annotations.NotNull; import java.util.List; @@ -34,10 +36,9 @@ public interface AiChatConversationService { /** * 获取 - 对话列表 * - * @param req * @return */ - List listConversation(AiChatConversationListReqVO req); + List listConversation(); /** * 获取 - 对话 @@ -54,4 +55,11 @@ public interface AiChatConversationService { */ Boolean deleteConversation(Long id); + /** + * 校验 - 是否存在 + * + * @param id + * @return + */ + AiChatConversationDO validateExists(Long id); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java index e25062e78..27ece6b14 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java @@ -4,6 +4,8 @@ import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; +import java.util.List; + /** * 聊天 chat * @@ -29,4 +31,21 @@ public interface AiChatService { * @return */ void chatStream(AiChatMessageSendReqVO req, Utf8SseEmitter sseEmitter); + + /** + * 获取 - 获取对话 message list + * + * @param conversationId + * @return + */ + List getMessageListByConversationId(Long conversationId); + + /** + * 删除 - 删除message + * + * @param id + * @return + */ + Boolean deleteMessage(Long id); + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java index 6fbafc659..5f45f27b6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java @@ -98,12 +98,12 @@ public class AiChatConversationServiceImpl implements AiChatConversationService } @Override - public List listConversation(AiChatConversationListReqVO listReqVO) { + public List listConversation() { // 获取用户id Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 查询前100对话 List top100Conversation - = aiChatConversationMapper.selectTop100Conversation(loginUserId, listReqVO.getTitle()); + = aiChatConversationMapper.selectTop100Conversation(loginUserId, null); return AiChatConversationConvert.INSTANCE.covnertChatConversationResList(top100Conversation); } @@ -118,7 +118,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService return aiChatConversationMapper.deleteById(id) > 0; } - private @NotNull AiChatConversationDO validateExists(Long id) { + public @NotNull AiChatConversationDO validateExists(Long id) { AiChatConversationDO aiChatConversationDO = aiChatConversationMapper.selectById(id); if (aiChatConversationDO == null) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CONVERSATION_NOT_EXISTS); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index b5e2634de..63ef59aa5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatCo import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRes; +import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; @@ -31,6 +32,7 @@ import org.springframework.transaction.annotation.Transactional; import reactor.core.publisher.Flux; import java.io.IOException; +import java.util.List; import java.util.function.Consumer; /** @@ -187,4 +189,19 @@ public class AiChatServiceImpl implements AiChatService { } ); } + + @Override + public List getMessageListByConversationId(Long conversationId) { + // 校验对话是否存在 + chatConversationService.validateExists(conversationId); + // 获取对话所有 message + List aiChatMessageDOList = aiChatMessageMapper.selectByConversationId(conversationId); + // 转换 AiChatMessageRespVO + return AiChatMessageConvert.INSTANCE.convertAiChatMessageRespVOList(aiChatMessageDOList); + } + + @Override + public Boolean deleteMessage(Long id) { + return aiChatMessageMapper.deleteById(id) > 0; + } } From 7fae5c0a7d5f8d04bd05db9c98d2d402865a22a3 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 11:00:49 +0800 Subject: [PATCH 222/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=B2=A1=E7=94=A8=E7=9A=84=20chat=20message?= =?UTF-8?q?=20service?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/service/AiChatMessageService.java | 30 -------- .../impl/AiChatMessageServiceImpl.java | 69 ------------------- 2 files changed, 99 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatMessageService.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatMessageServiceImpl.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatMessageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatMessageService.java deleted file mode 100644 index 77450c63b..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatMessageService.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.module.ai.service; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; - -/** - * chat message - * - * @author fansili - * @time 2024/4/24 17:25 - * @since 1.0 - */ -public interface AiChatMessageService { - - /** - * message - 列表 - * - * @param req - * @return - */ - PageResult list(AiChatMessageReq req); - - /** - * message - 删除 - * - * @param chatConversationId - * @param id - */ - void delete(Long chatConversationId, Long id); -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatMessageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatMessageServiceImpl.java deleted file mode 100644 index 2c86aa8a1..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatMessageServiceImpl.java +++ /dev/null @@ -1,69 +0,0 @@ -package cn.iocoder.yudao.module.ai.service.impl; - -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; -import cn.iocoder.yudao.module.ai.ErrorCodeConstants; -import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; -import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; -import cn.iocoder.yudao.module.ai.dal.mysql.AiChatMessageMapper; -import cn.iocoder.yudao.module.ai.service.AiChatMessageService; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.util.List; - -/** - * chat message - * - * @author fansili - * @time 2024/4/24 17:25 - * @since 1.0 - */ -@AllArgsConstructor -@Service -@Slf4j -public class AiChatMessageServiceImpl implements AiChatMessageService { - - private final AiChatMessageMapper aiChatMessageMapper; - private final AiChatConversationMapper aiChatConversationMapper; - - @Override - public PageResult list(AiChatMessageReq req) { - // 查询 - LambdaQueryWrapperX queryWrapperX = new LambdaQueryWrapperX<>(); - queryWrapperX.eq(AiChatMessageDO::getConversationId, req.getChatConversationId()); - // 默认排序 - queryWrapperX.orderByDesc(AiChatMessageDO::getId); - PageResult pageResult = aiChatMessageMapper.selectPage(req, queryWrapperX); - // 转换 res - List messageListResList = AiChatMessageConvert.INSTANCE.convert(pageResult.getList()); - return new PageResult(messageListResList, pageResult.getTotal()); - } - - @Override - public void delete(Long chatConversationId, Long id) { - // 获取登录用户 - Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); - // 校验 ChatConversation - validateChatConversation(chatConversationId, loginUserId); - // 删除 - aiChatMessageMapper.deleteByConversationAndId(chatConversationId, id); - } - - private AiChatConversationDO validateChatConversation(Long chatConversationId, Long loginUserId) { - AiChatConversationDO aiChatConversationDO = aiChatConversationMapper.selectById(chatConversationId); - if (aiChatConversationDO == null) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CHAT_CONTINUE_NOT_EXIST); - } - if (!aiChatConversationDO.getUserId().equals(loginUserId)) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CHAT_CONVERSATION_NOT_YOURS); - } - return aiChatConversationDO; - } -} From c124681c3affd61bf9839a266b6bfc7c19cd2d6f Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 11:01:20 +0800 Subject: [PATCH 223/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E5=AF=B9=E8=AF=9D=20message=20=E5=88=97?= =?UTF-8?q?=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/dal/mysql/AiChatMessageMapper.java | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java index 4e2100aff..5f6083fdb 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java @@ -18,25 +18,16 @@ import java.util.List; @Mapper public interface AiChatMessageMapper extends BaseMapperX { - /** - * 删除 - 根据 Conversation 和 id - * - * @param chatConversationId - * @param id - */ - default int deleteByConversationAndId(Long chatConversationId, Long id) { - return this.delete(new LambdaQueryWrapperX() - .eq(AiChatMessageDO::getConversationId, chatConversationId) - .eq(AiChatMessageDO::getId, id) - ); - } - /** * 查询 - 根据 对话id查询 * * @param conversationId */ default List selectByConversationId(Long conversationId) { - return selectList() + return this.selectList( + new LambdaQueryWrapperX() + .eq(AiChatMessageDO::getConversationId, conversationId) + .orderByAsc(AiChatMessageDO::getId) + ); } } From f0a1666e84609aeec284427cbec33042e97aee35 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 11:34:20 +0800 Subject: [PATCH 224/684] =?UTF-8?q?=E3=80=90=E8=B0=83=E6=95=B4=E3=80=91?= =?UTF-8?q?=E8=B0=83=E6=95=B4AI=E8=A7=92=E8=89=B2=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...yEnum.java => AiChatRoleCategoryEnum.java} | 12 ++-- .../module/ai/enums/AiChatRoleEnableEnum.java | 36 ----------- .../admin/model/AiChatRoleController.java | 26 ++++---- ...oleAddReq.java => AiChatRoleAddReqVO.java} | 32 +++++++--- ...=> AiChatRoleUpdatePublicStatusReqVO.java} | 11 +++- .../model/vo/role/AiChatRoleUpdateReq.java | 34 ---------- .../model/vo/role/AiChatRoleUpdateReqVO.java | 62 +++++++++++++++++++ .../module/ai/convert/AiChatRoleConvert.java | 8 +-- .../module/ai/service/AiChatRoleService.java | 8 +-- .../service/impl/AiChatRoleServiceImpl.java | 41 ++++++------ 10 files changed, 142 insertions(+), 128 deletions(-) rename yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/{AiChatRoleClassifyEnum.java => AiChatRoleCategoryEnum.java} (62%) delete mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleEnableEnum.java rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/{AiChatRoleAddReq.java => AiChatRoleAddReqVO.java} (50%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/{AiChatRoleUpdateVisibilityReq.java => AiChatRoleUpdatePublicStatusReqVO.java} (62%) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdateReq.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdateReqVO.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleClassifyEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleCategoryEnum.java similarity index 62% rename from yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleClassifyEnum.java rename to yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleCategoryEnum.java index 2221ef737..3ca923de9 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleClassifyEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleCategoryEnum.java @@ -12,7 +12,7 @@ import lombok.Getter; */ @AllArgsConstructor @Getter -public enum AiChatRoleClassifyEnum { +public enum AiChatRoleCategoryEnum { WRITING("writing", "写作"), @@ -21,17 +21,17 @@ public enum AiChatRoleClassifyEnum { ; - private String classify; + private String category; private String name; - public static AiChatRoleClassifyEnum valueOfClassify(String classify) { - for (AiChatRoleClassifyEnum itemEnum : AiChatRoleClassifyEnum.values()) { - if (itemEnum.getClassify().equals(classify)) { + public static AiChatRoleCategoryEnum valueOfCategory(String category) { + for (AiChatRoleCategoryEnum itemEnum : AiChatRoleCategoryEnum.values()) { + if (itemEnum.getCategory().equals(category)) { return itemEnum; } } - throw new IllegalArgumentException("Invalid MessageType value: " + classify); + throw new IllegalArgumentException("Invalid MessageType value: " + category); } } diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleEnableEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleEnableEnum.java deleted file mode 100644 index 81b29c0e5..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleEnableEnum.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * chat角色 可见范围 - * - * @author fansili - * @time 2024/4/24 16:44 - * @since 1.0 - */ -@AllArgsConstructor -@Getter -public enum AiChatRoleEnableEnum { - - OPEN("open", "公开"), - CLOSE("close", "关闭"), - - ; - - private String type; - - private String name; - - - public static AiChatRoleEnableEnum valueOfType(String type) { - for (AiChatRoleEnableEnum itemEnum : AiChatRoleEnableEnum.values()) { - if (itemEnum.getType().equals(type)) { - return itemEnum; - } - } - throw new IllegalArgumentException("Invalid MessageType value: " + type); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java index e0b07e0e2..64a06632a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java @@ -20,7 +20,7 @@ import org.springframework.web.bind.annotation.*; */ @Tag(name = "A4-chat角色") @RestController -@RequestMapping("/ai/chat") +@RequestMapping("/ai/chat/role") @Slf4j @AllArgsConstructor public class AiChatRoleController { @@ -28,37 +28,35 @@ public class AiChatRoleController { private final AiChatRoleService chatRoleService; @Operation(summary = "chat角色 - 角色列表") - @GetMapping("/role/list") + @GetMapping("/list") public PageResult list(@Validated @ModelAttribute AiChatRoleListReq req) { return chatRoleService.list(req); } @Operation(summary = "chat角色 - 添加") - @PutMapping("/role") - public CommonResult add(@Validated @RequestBody AiChatRoleAddReq req) { + @PutMapping("/add") + public CommonResult add(@Validated @RequestBody AiChatRoleAddReqVO req) { chatRoleService.add(req); return CommonResult.success(null); } @Operation(summary = "chat角色 - 修改") - @PostMapping("/role/{id}") - public CommonResult update(@PathVariable("id") Long id, - @Validated @RequestBody AiChatRoleUpdateReq req) { - chatRoleService.update(id, req); + @PostMapping("/update") + public CommonResult update(@Validated @RequestBody AiChatRoleUpdateReqVO req) { + chatRoleService.update(req); return CommonResult.success(null); } @Operation(summary = "chat角色 - 修改可见性") - @PostMapping("/role/{id}/update-enable") - public CommonResult updateEnable(@PathVariable("id") Long id, - @Validated @RequestBody AiChatRoleUpdateVisibilityReq req) { - chatRoleService.updateEnable(id, req); + @PostMapping("/update-public-status") + public CommonResult updatePublicStatus(@Validated @RequestBody AiChatRoleUpdatePublicStatusReqVO req) { + chatRoleService.updatePublicStatus(req); return CommonResult.success(null); } @Operation(summary = "chat角色 - 删除") - @DeleteMapping("/role/{id}") - public CommonResult delete(@PathVariable("id") Long id) { + @DeleteMapping("/delete") + public CommonResult delete(@RequestParam("id") Long id) { chatRoleService.delete(id); return CommonResult.success(null); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleAddReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleAddReqVO.java similarity index 50% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleAddReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleAddReqVO.java index f412b3e7e..f03137df8 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleAddReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleAddReqVO.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role; -import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -14,21 +13,40 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class AiChatRoleAddReq extends PageParam { +public class AiChatRoleAddReqVO { @NotNull @Schema(description = "角色名,角色的显示名称") private String name; - @NotNull - @Schema(description = "角色介绍,详细描述角色的功能或用途") - private String introduce; + @Schema(description = "头像") + private String avatar; @NotNull @Schema(description = "分类,角色所属的类别,如娱乐、创作等") - private String classify; + private String category; + + @NotNull + @Schema(description = "角色描述") + private String description; + + @Schema(description = "角色欢迎语") + private String welcomeMessage; + + @NotNull + @Schema(description = "角色设定(消息)") + private String systemMessage; + + @NotNull + @Schema(description = "模型编号") + private Long modelId; @NotNull @Schema(description = "开启状态 open、close") - private String enable; + private Boolean publicStatus; + + @NotNull + @Schema(description = "排序") + private Integer sort; + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdateVisibilityReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdatePublicStatusReqVO.java similarity index 62% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdateVisibilityReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdatePublicStatusReqVO.java index 9e0c0c4ba..c61b6d964 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdateVisibilityReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdatePublicStatusReqVO.java @@ -14,9 +14,14 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class AiChatRoleUpdateVisibilityReq extends PageParam { +public class AiChatRoleUpdatePublicStatusReqVO extends PageParam { - @NotNull + + @NotNull(message = "角色编号不能为空") + @Schema(description = "角色编号") + private Long id; + + @NotNull(message = "开启状态不能为空") @Schema(description = "开启状态 open、close") - private String enable; + private Boolean publicStatus; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdateReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdateReq.java deleted file mode 100644 index 3a0f925ed..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdateReq.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * chat 角色 - 更新 - * - * @fansili - * @since v1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatRoleUpdateReq extends PageParam { - - @NotNull - @Schema(description = "角色名,角色的显示名称") - private String name; - - @NotNull - @Schema(description = "角色介绍,详细描述角色的功能或用途") - private String introduce; - - @NotNull - @Schema(description = "分类,角色所属的类别,如娱乐、创作等") - private String classify; - - @NotNull - @Schema(description = "开启状态 open、close") - private String enable; -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdateReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdateReqVO.java new file mode 100644 index 000000000..d578b2f74 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdateReqVO.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * chat 角色 - 更新 + * + * @fansili + * @since v1.0 + */ +@Data +@Accessors(chain = true) +public class AiChatRoleUpdateReqVO extends PageParam { + + + @NotNull(message = "角色编号不能为空") + @Schema(description = "角色编号") + private Long id; + + @NotNull + @Schema(description = "角色名,角色的显示名称") + private String name; + + @Schema(description = "头像") + private String avatar; + + @NotNull + @Schema(description = "分类,角色所属的类别,如娱乐、创作等") + private String category; + + @NotNull + @Schema(description = "角色描述") + private String description; + + @Schema(description = "角色欢迎语") + private String welcomeMessage; + + @NotNull + @Schema(description = "角色设定(消息)") + private String systemMessage; + + @NotNull + @Schema(description = "模型编号") + private Long modelId; + + @NotNull + @Schema(description = "开启状态 open、close") + private Boolean publicStatus; + + @NotNull + @Schema(description = "排序") + private Integer sort; + + @NotNull + @Schema(description = "状态") + private Integer status; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java index 84c7aae81..86ed30e22 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.ai.convert; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleAddReq; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleAddReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleRes; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleUpdateReq; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleUpdateReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleListRes; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -36,7 +36,7 @@ public interface AiChatRoleConvert { * @param req * @return */ - AiChatRoleDO convertAiChatRoleDO(AiChatRoleAddReq req); + AiChatRoleDO convertAiChatRoleDO(AiChatRoleAddReqVO req); /** * 转换 - AiChatRoleDO @@ -44,7 +44,7 @@ public interface AiChatRoleConvert { * @param req * @return */ - AiChatRoleDO convertAiChatRoleDO(AiChatRoleUpdateReq req); + AiChatRoleDO convertAiChatRoleDO(AiChatRoleUpdateReqVO req); /** * 转换 - AiChatRoleRes diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java index 5f11e4ffc..2ad696fb0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java @@ -26,24 +26,22 @@ public interface AiChatRoleService { * @param req * @return */ - void add(AiChatRoleAddReq req); + void add(AiChatRoleAddReqVO req); /** * chat角色 - 修改 * - * @param id * @param req */ - void update(Long id, AiChatRoleUpdateReq req); + void update(AiChatRoleUpdateReqVO req); /** * chat角色 - 修改可见性 * - * @param id * @param req */ - void updateEnable(Long id, AiChatRoleUpdateVisibilityReq req); + void updatePublicStatus(AiChatRoleUpdatePublicStatusReqVO req); /** * chat角色 - 删除 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java index 95ed67861..b3e645e37 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.ai.service.impl; import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; @@ -9,9 +10,9 @@ import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.*; import cn.iocoder.yudao.module.ai.convert.AiChatRoleConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.enums.AiChatRoleClassifyEnum; -import cn.iocoder.yudao.module.ai.enums.AiChatRoleEnableEnum; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatRoleMapper; +import cn.iocoder.yudao.module.ai.enums.AiChatRoleCategoryEnum; +import cn.iocoder.yudao.module.ai.service.AiChatModalService; import cn.iocoder.yudao.module.ai.service.AiChatRoleService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -31,6 +32,7 @@ import java.util.List; public class AiChatRoleServiceImpl implements AiChatRoleService { private final AiChatRoleMapper aiChatRoleMapper; + private final AiChatModalService aiChatModalService; @Override public PageResult list(AiChatRoleListReq req) { @@ -52,42 +54,43 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { } @Override - public void add(AiChatRoleAddReq req) { + public void add(AiChatRoleAddReqVO req) { // 转换enum,并校验enum - AiChatRoleClassifyEnum.valueOfClassify(req.getClassify()); - AiChatRoleEnableEnum.valueOfType(req.getEnable()); + AiChatRoleCategoryEnum.valueOfCategory(req.getCategory()); + // 校验模型是否存在 + aiChatModalService.validateExists(req.getModelId()); // 转换do AiChatRoleDO insertAiChatRoleDO = AiChatRoleConvert.INSTANCE.convertAiChatRoleDO(req); insertAiChatRoleDO.setUserId(SecurityFrameworkUtils.getLoginUserId()); - insertAiChatRoleDO.setUseCount(0); + insertAiChatRoleDO.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 保存 aiChatRoleMapper.insert(insertAiChatRoleDO); } @Override - public void update(Long id, AiChatRoleUpdateReq req) { - // 转换enum,并校验enum - AiChatRoleClassifyEnum.valueOfClassify(req.getClassify()); - AiChatRoleEnableEnum.valueOfType(req.getEnable()); + public void update(AiChatRoleUpdateReqVO req) { // 检查角色是否存在 - validateExists(id); + validateExists(req.getId()); + // 转换enum,并校验enum + AiChatRoleCategoryEnum.valueOfCategory(req.getCategory()); + // 校验模型是否存在 + aiChatModalService.validateExists(req.getModelId()); // 转换do AiChatRoleDO updateChatRole = AiChatRoleConvert.INSTANCE.convertAiChatRoleDO(req); - updateChatRole.setId(id); + updateChatRole.setId(req.getId()); aiChatRoleMapper.updateById(updateChatRole); } @Override - public void updateEnable(Long id, AiChatRoleUpdateVisibilityReq req) { - // 转换enum,并校验enum - AiChatRoleEnableEnum.valueOfType(req.getEnable()); + public void updatePublicStatus(AiChatRoleUpdatePublicStatusReqVO req) { // 检查角色是否存在 - validateExists(id); + validateExists(req.getId()); // 更新 - aiChatRoleMapper.updateById(new AiChatRoleDO() - .setId(id) - .setEnable(req.getEnable()) + aiChatRoleMapper.updateById( + new AiChatRoleDO() + .setId(req.getId()) + .setPublicStatus(req.getPublicStatus()) ); } From 929f3597fdfb00da67dfbf821379267e27fd9859 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 11:47:58 +0800 Subject: [PATCH 225/684] =?UTF-8?q?=E3=80=90=E8=B0=83=E6=95=B4=E3=80=91?= =?UTF-8?q?=E8=B0=83=E6=95=B4Ai=20model?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/enums/AiChatModalDisableEnum.java | 26 ------ .../admin/model/AiChatModalController.java | 36 +++----- ...alAddReq.java => AiChatModalAddReqVO.java} | 36 ++++---- ...ListReq.java => AiChatModalListReqVO.java} | 2 +- .../admin/model/vo/model/AiChatModalRes.java | 35 +++++--- .../vo/model/AiChatModalUpdateReqVO.java | 63 +++++++++++++ .../module/ai/convert/AiChatModalConvert.java | 11 +-- .../module/ai/service/AiChatModalService.java | 19 ++-- .../service/impl/AiChatModalServiceImpl.java | 90 ++++--------------- .../ai/service/impl/AiChatServiceImpl.java | 12 +-- 10 files changed, 163 insertions(+), 167 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatModalDisableEnum.java rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/{AiChatModalAddReq.java => AiChatModalAddReqVO.java} (62%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/{AiChatModalListReq.java => AiChatModalListReqVO.java} (88%) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalUpdateReqVO.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatModalDisableEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatModalDisableEnum.java deleted file mode 100644 index 5b780ec6e..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatModalDisableEnum.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * ai modal disable - * - * @author fansili - * @time 2024/4/24 20:15 - * @since 1.0 - */ -@AllArgsConstructor -@Getter -public enum AiChatModalDisableEnum { - - NO(0, "未禁用"), - YES(1, "禁用"), - - - ; - - private Integer value; - - private String name; -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModalController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModalController.java index e90de159e..5b96aeec9 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModalController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModalController.java @@ -2,19 +2,19 @@ package cn.iocoder.yudao.module.ai.controller.admin.model; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.ai.service.AiChatModalService; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalAddReq; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListReq; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalAddReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListRes; +import cn.iocoder.yudao.module.ai.service.AiChatModalService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; // TODO @fan:调整下接口;相关 vo 的命名等等;modal => model + /** * ai 模型 * @@ -24,7 +24,7 @@ import org.springframework.web.multipart.MultipartFile; */ @Tag(name = "A6-AI模型") @RestController -@RequestMapping("/ai/chat") +@RequestMapping("/ai/chat/modal") @Slf4j @AllArgsConstructor public class AiChatModalController { @@ -32,37 +32,29 @@ public class AiChatModalController { private final AiChatModalService aiChatModalService; @Operation(summary = "ai模型 - 模型列表") - @GetMapping("/modal/list") - public PageResult list(@ModelAttribute AiChatModalListReq req) { + @GetMapping("/list") + public PageResult list(@ModelAttribute AiChatModalListReqVO req) { return aiChatModalService.list(req); } @Operation(summary = "ai模型 - 添加") - @PutMapping("/modal") - public CommonResult add(@RequestBody @Validated AiChatModalAddReq req) { + @PutMapping("/add") + public CommonResult add(@RequestBody @Validated AiChatModalAddReqVO req) { aiChatModalService.add(req); return CommonResult.success(null); } - @Operation(summary = "ai模型 - 模型照片上传") - @PostMapping("/modal/{id}/updateImage") - public CommonResult updateImage(@PathVariable("id") Long id, - MultipartFile file) { - // todo yunai 文件上传这里放哪里 - return CommonResult.success(null); - } - @Operation(summary = "ai模型 - 修改") - @PostMapping("/modal/{id}") - public CommonResult update(@PathVariable Long id, - @RequestBody @Validated AiChatModalAddReq req) { + @PostMapping("/update") + public CommonResult update(@RequestParam("id") Long id, + @RequestBody @Validated AiChatModalAddReqVO req) { aiChatModalService.update(id, req); return CommonResult.success(null); } @Operation(summary = "ai模型 - 删除") - @DeleteMapping("/modal/{id}") - public CommonResult delete(@PathVariable Long id) { + @DeleteMapping("/delete") + public CommonResult delete(@RequestParam("id") Long id) { aiChatModalService.delete(id); return CommonResult.success(null); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalAddReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalAddReqVO.java similarity index 62% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalAddReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalAddReqVO.java index d750f922a..e9bc9242e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalAddReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalAddReqVO.java @@ -6,8 +6,6 @@ import jakarta.validation.constraints.Size; import lombok.Data; import lombok.experimental.Accessors; -import java.util.Map; - /** * ai chat modal * @@ -17,32 +15,40 @@ import java.util.Map; */ @Data @Accessors(chain = true) -public class AiChatModalAddReq { +public class AiChatModalAddReqVO { + + @Schema(description = "API 秘钥编号") + @Size(max = 32, message = "API 秘钥编号最大32个字符") + @NotNull(message = "API 秘钥编号不能为空!") + private Long keyId; @Schema(description = "模型名字") @Size(max = 60, message = "模型名字最大60个字符") @NotNull(message = "模型名字不能为空!") private String name; + @Schema(description = "模型类型(qianwen、yiyan、xinghuo、openai)") + @Size(max = 32, message = "模型类型最大32个字符") + @NotNull(message = "model模型不能为空!") + private String model; + @Size(max = 32, message = "模型平台最大32个字符") @Schema(description = "模型平台 参考 AiPlatformEnum") @NotNull(message = "平台不能为空!") private String platform; - @Schema(description = "模型类型(qianwen、yiyan、xinghuo、openai)") - @Size(max = 32, message = "模型类型最大32个字符") - @NotNull(message = "modal模型不能为空!") - private String modal; - - @Schema(description = "模型照片") - @Size(max = 256, message = "模型照片地址最大256个字符") - private String imageUrl; - @Schema(description = "排序") @NotNull(message = "sort排序不能为空!") private Integer sort; - @Schema(description = "模型配置JSON") -// @Size(max = 1024, message = "模型配置最大1024个字符") - private Map config; + // ========== 会话配置 ========== + + @Schema(description = "温度参数") + private Integer temperature; + + @Schema(description = "单条回复的最大 Token 数量") + private Integer maxTokens; + + @Schema(description = "上下文的最大 Message 数量") + private Integer maxContexts; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListReqVO.java similarity index 88% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListReqVO.java index 7a73a0c99..a589db4b5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListReqVO.java @@ -14,7 +14,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class AiChatModalListReq extends PageParam { +public class AiChatModalListReqVO extends PageParam { @Schema(description = "名字搜搜") private String search; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalRes.java index 15879a603..61ed35abd 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalRes.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Size; import lombok.Data; import lombok.experimental.Accessors; @@ -15,27 +16,35 @@ import lombok.experimental.Accessors; @Accessors(chain = true) public class AiChatModalRes { - @Schema(description = "id") + @Schema(description = "编号") private Long id; - @Schema(description = "模型平台 参考 AiPlatformEnum") - private String platform; - - @Schema(description = "模型类型 参考 YiYanChatModel、XingHuoChatModel") - private String modal; + @Schema(description = "API 秘钥编号") + private Long keyId; @Schema(description = "模型名字") private String name; - @Schema(description = "模型照片") - private String image; + @Schema(description = "模型类型(qianwen、yiyan、xinghuo、openai)") + private String model; - @Schema(description = "禁用 0、正常 1、禁用") - private Integer disable; + @Size(max = 32, message = "模型平台最大32个字符") + private String platform; - @Schema(description = "排序 asc 排序") + @Schema(description = "排序") private Integer sort; - @Schema(description = "modal 配置") - private String config; + @Schema(description = "状态") + private Integer status; + + // ========== 会话配置 ========== + + @Schema(description = "温度参数") + private Integer temperature; + + @Schema(description = "单条回复的最大 Token 数量") + private Integer maxTokens; + + @Schema(description = "上下文的最大 Message 数量") + private Integer maxContexts; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalUpdateReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalUpdateReqVO.java new file mode 100644 index 000000000..4e9fd898c --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalUpdateReqVO.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * ai chat modal + * + * @author fansili + * @time 2024/4/24 19:47 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class AiChatModalUpdateReqVO { + + @Schema(description = "编号") + @Size(max = 32, message = "编号最大32个字符") + @NotNull(message = "编号不能为空") + private Long id; + + @Schema(description = "API 秘钥编号") + @Size(max = 32, message = "API 秘钥编号最大32个字符") + @NotNull(message = "API 秘钥编号不能为空!") + private Long keyId; + + @Schema(description = "模型名字") + @Size(max = 60, message = "模型名字最大60个字符") + @NotNull(message = "模型名字不能为空!") + private String name; + + @Schema(description = "模型类型(qianwen、yiyan、xinghuo、openai)") + @Size(max = 32, message = "模型类型最大32个字符") + @NotNull(message = "model模型不能为空!") + private String model; + + @Size(max = 32, message = "模型平台最大32个字符") + @Schema(description = "模型平台 参考 AiPlatformEnum") + @NotNull(message = "平台不能为空!") + private String platform; + + @Schema(description = "排序") + @NotNull(message = "sort排序不能为空!") + private Integer sort; + + @Schema(description = "状态") + @NotNull(message = "状态不能为空!") + private Integer status; + + // ========== 会话配置 ========== + + @Schema(description = "温度参数") + private Integer temperature; + + @Schema(description = "单条回复的最大 Token 数量") + private Integer maxTokens; + + @Schema(description = "上下文的最大 Message 数量") + private Integer maxContexts; +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java index d2d6763f9..04a9352ab 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java @@ -1,12 +1,10 @@ package cn.iocoder.yudao.module.ai.convert; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalAddReq; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalAddReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListRes; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRes; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.Mappings; import org.mapstruct.factory.Mappers; import java.util.List; @@ -37,10 +35,7 @@ public interface AiChatModalConvert { * @param req * @return */ - @Mappings({ - @Mapping(target = "config", ignore = true) - }) - AiChatModalDO convertAiChatModalDO(AiChatModalAddReq req); + AiChatModalDO convertAiChatModalDO(AiChatModalAddReqVO req); /** diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java index 5740328be..2f52b8ab1 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java @@ -1,10 +1,11 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalAddReq; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListReq; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalAddReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListRes; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRes; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; /** * ai modal @@ -21,14 +22,14 @@ public interface AiChatModalService { * @param req * @return */ - PageResult list(AiChatModalListReq req); + PageResult list(AiChatModalListReqVO req); /** * ai modal - 添加 * * @param req */ - void add(AiChatModalAddReq req); + void add(AiChatModalAddReqVO req); /** * ai modal - 更新 @@ -36,7 +37,7 @@ public interface AiChatModalService { * @param id * @param req */ - void update(Long id, AiChatModalAddReq req); + void update(Long id, AiChatModalAddReqVO req); /** * ai modal - 删除 @@ -53,6 +54,14 @@ public interface AiChatModalService { */ AiChatModalRes getChatModalOfValidate(Long modalId); + /** + * 校验 - 是否存在 + * + * @param id + * @return + */ + AiChatModalDO validateExists(Long id); + /** * 校验 - 校验是否可用 * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java index 89c85f8ee..1702df4a6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java @@ -3,26 +3,20 @@ package cn.iocoder.yudao.module.ai.service.impl; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.validation.ValidationUtil; import cn.iocoder.yudao.framework.ai.AiPlatformEnum; -import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatModal; -import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel; -import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; -import cn.iocoder.yudao.module.ai.convert.AiChatModalConvert; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; -import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalChatConfigVO; -import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalConfigVO; -import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalDallConfigVO; -import cn.iocoder.yudao.module.ai.enums.AiChatModalDisableEnum; -import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModalMapper; -import cn.iocoder.yudao.module.ai.service.AiChatModalService; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalAddReq; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListReq; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalAddReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListRes; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRes; +import cn.iocoder.yudao.module.ai.convert.AiChatModalConvert; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; +import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModalMapper; +import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalConfigVO; +import cn.iocoder.yudao.module.ai.service.AiChatModalService; import jakarta.validation.ConstraintViolation; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -46,10 +40,10 @@ public class AiChatModalServiceImpl implements AiChatModalService { private final AiChatModalMapper aiChatModalMapper; @Override - public PageResult list(AiChatModalListReq req) { + public PageResult list(AiChatModalListReqVO req) { LambdaQueryWrapperX queryWrapperX = new LambdaQueryWrapperX<>(); // 查询的都是未禁用的模型 - queryWrapperX.eq(AiChatModalDO::getDisable, AiChatModalDisableEnum.NO.getValue()); + queryWrapperX.eq(AiChatModalDO::getStatus, CommonStatusEnum.ENABLE.getStatus()); // search if (!StrUtil.isBlank(req.getSearch())) { queryWrapperX.like(AiChatModalDO::getName, req.getSearch().trim()); @@ -64,39 +58,26 @@ public class AiChatModalServiceImpl implements AiChatModalService { } @Override - public void add(AiChatModalAddReq req) { + public void add(AiChatModalAddReqVO req) { // 校验 platform、type validatePlatform(req.getPlatform()); - validateModal(req.getPlatform(), req.getModal()); - // 转换config - AiChatModalConfigVO aiChatModalConfigVO = convertConfig(req); - // 校验 modal config - validateModalConfig(aiChatModalConfigVO); // 转换 do AiChatModalDO insertChatModalDO = AiChatModalConvert.INSTANCE.convertAiChatModalDO(req); // 设置默认属性 - insertChatModalDO.setDisable(AiChatModalDisableEnum.NO.getValue()); - insertChatModalDO.setConfig(JsonUtils.toJsonString(aiChatModalConfigVO)); + insertChatModalDO.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 保存数据库 aiChatModalMapper.insert(insertChatModalDO); } @Override - public void update(Long id, AiChatModalAddReq req) { - // 校验 platform、type + public void update(Long id, AiChatModalAddReqVO req) { + // 校验 platform validatePlatform(req.getPlatform()); - validateModal(req.getPlatform(), req.getModal()); - // 转换config - AiChatModalConfigVO aiChatModalConfigVO = convertConfig(req); - // 校验 modal config - validateModalConfig(aiChatModalConfigVO); - // 校验模型是否存在 - validateChatModalExists(id); + validateExists(id); // 转换 updateChatModalDO AiChatModalDO updateChatModalDO = AiChatModalConvert.INSTANCE.convertAiChatModalDO(req); updateChatModalDO.setId(id); - updateChatModalDO.setConfig(JsonUtils.toJsonString(aiChatModalConfigVO)); // 更新数据库 aiChatModalMapper.updateById(updateChatModalDO); } @@ -104,7 +85,7 @@ public class AiChatModalServiceImpl implements AiChatModalService { @Override public void delete(Long id) { // 检查 modal 是否存在 - validateChatModalExists(id); + validateExists(id); // 删除 delete aiChatModalMapper.deleteById(id); } @@ -112,19 +93,19 @@ public class AiChatModalServiceImpl implements AiChatModalService { @Override public AiChatModalRes getChatModalOfValidate(Long modalId) { // 检查 modal 是否存在 - AiChatModalDO aiChatModalDO = validateChatModalExists(modalId); + AiChatModalDO aiChatModalDO = validateExists(modalId); return AiChatModalConvert.INSTANCE.convertAiChatModalRes(aiChatModalDO); } @Override public void validateAvailable(AiChatModalRes chatModal) { // 对话模型是否可用 - if (AiChatModalDisableEnum.YES.getValue().equals(chatModal.getDisable())) { + if (CommonStatusEnum.ENABLE.getStatus().equals(chatModal.getStatus())) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_DISABLE_NOT_USED); } } - private AiChatModalDO validateChatModalExists(Long id) { + public AiChatModalDO validateExists(Long id) { AiChatModalDO aiChatModalDO = aiChatModalMapper.selectById(id); if (aiChatModalDO == null) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_NOT_EXIST); @@ -132,23 +113,6 @@ public class AiChatModalServiceImpl implements AiChatModalService { return aiChatModalDO; } - private void validateModal(String platform, String modal) { - AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(platform); - try { - if (AiPlatformEnum.QIAN_WEN == platformEnum) { - QianWenChatModal.valueOfModel(modal); - } else if (AiPlatformEnum.XING_HUO == platformEnum) { - XingHuoChatModel.valueOfModel(modal); - } else if (AiPlatformEnum.YI_YAN == platformEnum) { - YiYanChatModel.valueOfModel(modal); - } else { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_NOT_SUPPORTED_MODAL, platform); - } - } catch (IllegalArgumentException e) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_CONFIG_PARAMS_INCORRECT, e.getMessage()); - } - } - private void validatePlatform(String platform) { try { AiPlatformEnum.valueOfPlatform(platform); @@ -163,20 +127,4 @@ public class AiChatModalServiceImpl implements AiChatModalService { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_CONFIG_PARAMS_INCORRECT, constraintViolation.getMessage()); } } - - private static AiChatModalConfigVO convertConfig(AiChatModalAddReq req) { - AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(req.getPlatform()); - AiChatModalConfigVO resVo = null; - if (AiPlatformEnum.CHAT_PLATFORM_LIST.contains(platformEnum)) { - resVo = JsonUtils.parseObject(JsonUtils.toJsonString(req.getConfig()), AiChatModalChatConfigVO.class); - } else if (AiPlatformEnum.OPEN_AI_DALL == platformEnum) { - resVo = JsonUtils.parseObject(JsonUtils.toJsonString(req.getConfig()), AiChatModalDallConfigVO.class); - } - if (resVo == null) { - throw new IllegalArgumentException("ai模型中config不能转换! json: " + req.getConfig()); - } - resVo.setType(req.getModal()); - resVo.setPlatform(req.getPlatform()); - return resVo; - } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index 63ef59aa5..575e7889b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -72,10 +72,10 @@ public class AiChatServiceImpl implements AiChatService { // 校验角色是否公开 aiChatRoleService.validateIsPublic(aiChatRoleDO); // 获取 client 类型 - AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(chatModal.getModal()); + AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(chatModal.getModel()); // 保存 chat message insertChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(), - chatModal.getModal(), chatModal.getId(), req.getContent(), + chatModal.getModel(), chatModal.getId(), req.getContent(), null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); String content = null; try { @@ -96,7 +96,7 @@ public class AiChatServiceImpl implements AiChatService { } finally { // 保存 chat message insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), - chatModal.getModal(), chatModal.getId(), req.getContent(), + chatModal.getModel(), chatModal.getId(), req.getContent(), null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); } return new AiChatMessageRespVO().setContent(content); @@ -150,11 +150,11 @@ public class AiChatServiceImpl implements AiChatService { // 保存 chat message // 保存 chat message insertChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(), - chatModal.getModal(), chatModal.getId(), req.getContent(), + chatModal.getModel(), chatModal.getId(), req.getContent(), null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); // 获取 client 类型 - AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(chatModal.getModal()); + AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(chatModal.getModel()); StreamingChatClient streamingChatClient = aiChatClientFactory.getStreamingChatClient(platformEnum); Flux streamResponse = streamingChatClient.stream(prompt); @@ -183,7 +183,7 @@ public class AiChatServiceImpl implements AiChatService { sseEmitter.complete(); // 保存 chat message insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), - chatModal.getModal(), chatModal.getId(), req.getContent(), + chatModal.getModel(), chatModal.getId(), req.getContent(), null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); } From 53f4ad43d83baab204bb361288c7d9261842be05 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 11:49:15 +0800 Subject: [PATCH 226/684] =?UTF-8?q?=E3=80=90=E8=B0=83=E6=95=B4=E3=80=91?= =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D=20modal=20req=20=E5=92=8Cres?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0vo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/model/AiChatModalController.java | 4 ++-- ...tModalListRes.java => AiChatModalListRespVO.java} | 2 +- .../{AiChatModalRes.java => AiChatModalRespVO.java} | 2 +- .../yudao/module/ai/convert/AiChatModalConvert.java | 8 ++++---- .../yudao/module/ai/service/AiChatModalService.java | 10 +++++----- .../service/impl/AiChatConversationServiceImpl.java | 5 ++--- .../ai/service/impl/AiChatModalServiceImpl.java | 12 ++++++------ .../module/ai/service/impl/AiChatServiceImpl.java | 6 +++--- 8 files changed, 24 insertions(+), 25 deletions(-) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/{AiChatModalListRes.java => AiChatModalListRespVO.java} (96%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/{AiChatModalRes.java => AiChatModalRespVO.java} (97%) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModalController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModalController.java index 5b96aeec9..929a9e343 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModalController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModalController.java @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalAddReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListRes; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListRespVO; import cn.iocoder.yudao.module.ai.service.AiChatModalService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -33,7 +33,7 @@ public class AiChatModalController { @Operation(summary = "ai模型 - 模型列表") @GetMapping("/list") - public PageResult list(@ModelAttribute AiChatModalListReqVO req) { + public PageResult list(@ModelAttribute AiChatModalListReqVO req) { return aiChatModalService.list(req); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListRespVO.java similarity index 96% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListRes.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListRespVO.java index 75e71df99..2249a2c00 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListRespVO.java @@ -13,7 +13,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class AiChatModalListRes { +public class AiChatModalListRespVO { @Schema(description = "id") private Long id; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalRespVO.java similarity index 97% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalRes.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalRespVO.java index 61ed35abd..28a439733 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalRespVO.java @@ -14,7 +14,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class AiChatModalRes { +public class AiChatModalRespVO { @Schema(description = "编号") private Long id; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java index 04a9352ab..a0604f1d6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.ai.convert; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalAddReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListRes; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRes; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRespVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -27,7 +27,7 @@ public interface AiChatModalConvert { * @param list * @return */ - List convertAiChatModalListRes(List list); + List convertAiChatModalListRes(List list); /** * 转换 - AiChatModalDO @@ -44,6 +44,6 @@ public interface AiChatModalConvert { * @param aiChatModalDO * @return */ - AiChatModalRes convertAiChatModalRes(AiChatModalDO aiChatModalDO); + AiChatModalRespVO convertAiChatModalRes(AiChatModalDO aiChatModalDO); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java index 2f52b8ab1..ba16b8e17 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalAddReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListRes; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRes; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRespVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; /** @@ -22,7 +22,7 @@ public interface AiChatModalService { * @param req * @return */ - PageResult list(AiChatModalListReqVO req); + PageResult list(AiChatModalListReqVO req); /** * ai modal - 添加 @@ -52,7 +52,7 @@ public interface AiChatModalService { * @param modalId * @return */ - AiChatModalRes getChatModalOfValidate(Long modalId); + AiChatModalRespVO getChatModalOfValidate(Long modalId); /** * 校验 - 是否存在 @@ -67,5 +67,5 @@ public interface AiChatModalService { * * @param chatModal */ - void validateAvailable(AiChatModalRes chatModal); + void validateAvailable(AiChatModalRespVO chatModal); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java index 5f45f27b6..34332959f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java @@ -5,10 +5,9 @@ import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.AiCommonConstants; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationListReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRes; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRespVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleRes; import cn.iocoder.yudao.module.ai.convert.AiChatConversationConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; @@ -88,7 +87,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService // 校验对话是否存在 validateExists(updateReqVO.getId()); // 获取模型信息并验证 - AiChatModalRes chatModal = aiChatModalService.getChatModalOfValidate(updateReqVO.getModelId()); + AiChatModalRespVO chatModal = aiChatModalService.getChatModalOfValidate(updateReqVO.getModelId()); // 校验modal是否可用 aiChatModalService.validateAvailable(chatModal); // 更新对话信息 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java index 1702df4a6..2e1c37503 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java @@ -10,8 +10,8 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalAddReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListRes; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRes; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRespVO; import cn.iocoder.yudao.module.ai.convert.AiChatModalConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModalMapper; @@ -40,7 +40,7 @@ public class AiChatModalServiceImpl implements AiChatModalService { private final AiChatModalMapper aiChatModalMapper; @Override - public PageResult list(AiChatModalListReqVO req) { + public PageResult list(AiChatModalListReqVO req) { LambdaQueryWrapperX queryWrapperX = new LambdaQueryWrapperX<>(); // 查询的都是未禁用的模型 queryWrapperX.eq(AiChatModalDO::getStatus, CommonStatusEnum.ENABLE.getStatus()); @@ -53,7 +53,7 @@ public class AiChatModalServiceImpl implements AiChatModalService { // 查询 PageResult aiChatModalDOPageResult = aiChatModalMapper.selectPage(req, queryWrapperX); // 转换 res - List resList = AiChatModalConvert.INSTANCE.convertAiChatModalListRes(aiChatModalDOPageResult.getList()); + List resList = AiChatModalConvert.INSTANCE.convertAiChatModalListRes(aiChatModalDOPageResult.getList()); return new PageResult<>(resList, aiChatModalDOPageResult.getTotal()); } @@ -91,14 +91,14 @@ public class AiChatModalServiceImpl implements AiChatModalService { } @Override - public AiChatModalRes getChatModalOfValidate(Long modalId) { + public AiChatModalRespVO getChatModalOfValidate(Long modalId) { // 检查 modal 是否存在 AiChatModalDO aiChatModalDO = validateExists(modalId); return AiChatModalConvert.INSTANCE.convertAiChatModalRes(aiChatModalDO); } @Override - public void validateAvailable(AiChatModalRes chatModal) { + public void validateAvailable(AiChatModalRespVO chatModal) { // 对话模型是否可用 if (CommonStatusEnum.ENABLE.getStatus().equals(chatModal.getStatus())) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_DISABLE_NOT_USED); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index 575e7889b..7fc13cac6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -13,7 +13,7 @@ import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRes; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRespVO; import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; @@ -61,7 +61,7 @@ public class AiChatServiceImpl implements AiChatService { // 查询对话 AiChatConversationRespVO conversation = chatConversationService.getConversationOfValidate(req.getConversationId()); // 获取对话模型 - AiChatModalRes chatModal = aiChatModalService.getChatModalOfValidate(conversation.getModelId()); + AiChatModalRespVO chatModal = aiChatModalService.getChatModalOfValidate(conversation.getModelId()); // 对话模型是否可用 aiChatModalService.validateAvailable(chatModal); // 获取角色信息 @@ -132,7 +132,7 @@ public class AiChatServiceImpl implements AiChatService { // 查询对话 AiChatConversationRespVO conversation = chatConversationService.getConversationOfValidate(req.getConversationId()); // 获取对话模型 - AiChatModalRes chatModal = aiChatModalService.getChatModalOfValidate(conversation.getModelId()); + AiChatModalRespVO chatModal = aiChatModalService.getChatModalOfValidate(conversation.getModelId()); // 对话模型是否可用 aiChatModalService.validateAvailable(chatModal); // 获取角色信息 From f438e68dc9659bf1253a39fd2b9b052c3a997dd1 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 11:49:49 +0800 Subject: [PATCH 227/684] =?UTF-8?q?=E3=80=90=E8=B0=83=E6=95=B4=E3=80=91?= =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D=20role=20req=20=E5=92=8Cres?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0vo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/admin/model/AiChatRoleController.java | 2 +- .../{AiChatRoleListReq.java => AiChatRoleListReqVO.java} | 2 +- .../{AiChatRoleListRes.java => AiChatRoleListRespVO.java} | 2 +- .../vo/role/{AiChatRoleRes.java => AiChatRoleRespVO.java} | 2 +- .../yudao/module/ai/convert/AiChatRoleConvert.java | 8 ++++---- .../yudao/module/ai/service/AiChatRoleService.java | 4 ++-- .../ai/service/impl/AiChatConversationServiceImpl.java | 4 ++-- .../module/ai/service/impl/AiChatRoleServiceImpl.java | 6 +++--- 8 files changed, 15 insertions(+), 15 deletions(-) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/{AiChatRoleListReq.java => AiChatRoleListReqVO.java} (88%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/{AiChatRoleListRes.java => AiChatRoleListRespVO.java} (95%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/{AiChatRoleRes.java => AiChatRoleRespVO.java} (96%) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java index 64a06632a..1aab42600 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java @@ -29,7 +29,7 @@ public class AiChatRoleController { @Operation(summary = "chat角色 - 角色列表") @GetMapping("/list") - public PageResult list(@Validated @ModelAttribute AiChatRoleListReq req) { + public PageResult list(@Validated @ModelAttribute AiChatRoleListReqVO req) { return chatRoleService.list(req); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListReqVO.java similarity index 88% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListReqVO.java index 5662398a7..247154a4c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListReqVO.java @@ -13,7 +13,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class AiChatRoleListReq extends PageParam { +public class AiChatRoleListReqVO extends PageParam { @Schema(description = "查询") private String search; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListRespVO.java similarity index 95% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListRes.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListRespVO.java index 5aee6a3d2..f66d5a6ea 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListRespVO.java @@ -12,7 +12,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class AiChatRoleListRes { +public class AiChatRoleListRespVO { @Schema(description = "id") private Long id; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleRespVO.java similarity index 96% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleRes.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleRespVO.java index 6b4ec9d22..a28dd4f4c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleRes.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleRespVO.java @@ -12,7 +12,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class AiChatRoleRes { +public class AiChatRoleRespVO { @Schema(description = "id") private Long id; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java index 86ed30e22..269b4a6ee 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java @@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.ai.convert; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleAddReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleRes; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleRespVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleUpdateReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleListRes; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleListRespVO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -28,7 +28,7 @@ public interface AiChatRoleConvert { * @param roleList * @return */ - List convertChatRoleListRes(List roleList); + List convertChatRoleListRes(List roleList); /** * 转换 - AiChatRoleDO @@ -52,5 +52,5 @@ public interface AiChatRoleConvert { * @param aiChatRoleDO * @return */ - AiChatRoleRes convertAiChatRoleRes(AiChatRoleDO aiChatRoleDO); + AiChatRoleRespVO convertAiChatRoleRes(AiChatRoleDO aiChatRoleDO); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java index 2ad696fb0..96d722100 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java @@ -18,7 +18,7 @@ public interface AiChatRoleService { * @param req * @return */ - PageResult list(AiChatRoleListReq req); + PageResult list(AiChatRoleListReqVO req); /** * chat角色 - 添加 @@ -56,7 +56,7 @@ public interface AiChatRoleService { * @param roleId * @return */ - AiChatRoleRes getChatRole(Long roleId); + AiChatRoleRespVO getChatRole(Long roleId); /** * 校验 - 角色是否存在 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java index 34332959f..228ab75e1 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java @@ -8,7 +8,7 @@ import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatCo import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleRes; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleRespVO; import cn.iocoder.yudao.module.ai.convert.AiChatConversationConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; @@ -47,7 +47,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService // 默认使用 sort 排序第一个模型 AiChatModalDO aiChatModalDO = aiChatModalMapper.selectFirstModal(); // 查询角色 - AiChatRoleRes chatRoleRes = null; + AiChatRoleRespVO chatRoleRes = null; if (req.getRoleId() != null) { chatRoleRes = aiChatRoleService.getChatRole(req.getRoleId()); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java index b3e645e37..5264ea2a2 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java @@ -35,7 +35,7 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { private final AiChatModalService aiChatModalService; @Override - public PageResult list(AiChatRoleListReq req) { + public PageResult list(AiChatRoleListReqVO req) { // 查询条件 LambdaQueryWrapperX queryWrapperX = new LambdaQueryWrapperX<>(); // search 查询 @@ -49,7 +49,7 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { Long total = aiChatRoleDOPageResult.getTotal(); List roleList = aiChatRoleDOPageResult.getList(); // 换货res - List chatRoleListResList = AiChatRoleConvert.INSTANCE.convertChatRoleListRes(roleList); + List chatRoleListResList = AiChatRoleConvert.INSTANCE.convertChatRoleListRes(roleList); return new PageResult<>(chatRoleListResList, total); } @@ -103,7 +103,7 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { } @Override - public AiChatRoleRes getChatRole(Long roleId) { + public AiChatRoleRespVO getChatRole(Long roleId) { // 检查角色是否存在 AiChatRoleDO aiChatRoleDO = validateExists(roleId); return AiChatRoleConvert.INSTANCE.convertAiChatRoleRes(aiChatRoleDO); From 4ccaad792122d376419c751881892ace8023369c Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 11:50:39 +0800 Subject: [PATCH 228/684] =?UTF-8?q?=E3=80=90=E8=B0=83=E6=95=B4=E3=80=91?= =?UTF-8?q?=E5=88=A0=E9=99=A4=20package-info=20=E5=8D=A0=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/controller/admin/model/vo/package-info.java | 1 - 1 file changed, 1 deletion(-) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/package-info.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/package-info.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/package-info.java deleted file mode 100644 index 7fb31bb99..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo; \ No newline at end of file From fb82dd2ffd7be5525185b1b1ead0235f1be9b584 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 11:59:17 +0800 Subject: [PATCH 229/684] =?UTF-8?q?=E3=80=90=E8=B0=83=E6=95=B4=E3=80=91?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=B2=A1=E7=94=A8=E7=9A=84=20enum?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/enums/AiChatModalTypeEnum.java | 11 ------ .../yudao/module/ai/enums/AiChatTypeEnum.java | 34 ------------------- 2 files changed, 45 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatModalTypeEnum.java delete mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatTypeEnum.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatModalTypeEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatModalTypeEnum.java deleted file mode 100644 index 0cf6c6ab1..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatModalTypeEnum.java +++ /dev/null @@ -1,11 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums; - -/** - * 枚举 - * - * @author fansili - * @time 2024/5/6 11:48 - * @since 1.0 - */ -public enum AiChatModalTypeEnum { -} diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatTypeEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatTypeEnum.java deleted file mode 100644 index 6ee7fabf6..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatTypeEnum.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 聊天类型 - * - * @author fansili - * @time 2024/4/14 17:58 - * @since 1.0 - */ -@AllArgsConstructor -@Getter -public enum AiChatTypeEnum { - - ROLE_CHAT("roleChat", "角色模板聊天"), - USER_CHAT("userChat", "用户普通聊天"), - - ; - - private String type; - - private String name; - - public static AiChatTypeEnum valueOfType(String type) { - for (AiChatTypeEnum itemEnum : AiChatTypeEnum.values()) { - if (itemEnum.getType().equals(type)) { - return itemEnum; - } - } - throw new IllegalArgumentException("Invalid MessageType value: " + type); - } -} From 794d4c3195434a530230c56a14d7755cefd2c175 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 12:06:20 +0800 Subject: [PATCH 230/684] =?UTF-8?q?=E3=80=90=E8=B0=83=E6=95=B4=E3=80=91?= =?UTF-8?q?=E5=90=88=E5=B9=B6=20AI=20=E6=A8=A1=E5=9E=8B=E5=88=B0=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=20enums=E9=87=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/enums/AiModelEnum.java | 67 +++++++++++++++++++ .../module/ai/enums/AiOpenAiModelEnum.java | 30 --------- 2 files changed, 67 insertions(+), 30 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiModelEnum.java delete mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiOpenAiModelEnum.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiModelEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiModelEnum.java new file mode 100644 index 000000000..3d30d27cb --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiModelEnum.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.ai.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +// TODO done @fansili:1)类注释要加下;2)author 和 time 用 javadoc,@author 和 @since;3)@AllArgsConstructor 使用这个注解,去掉构造方法;4)value 改成 model 字段,然后注释都写下哈;5)message 改成 name,然后注释都写下哈 +// TODO @fan: AiModelEnum 是不是可以缩写成这个哈;所有的模型,都写在这里枚举; +/** + * @author: fansili + * @time: 2024/3/4 12:36 + */ +@Getter +@AllArgsConstructor +public enum AiModelEnum { + + // open ai + OPEN_AI_GPT_3_5( "GPT3.5", "gpt-3.5-turbo",null), + OPEN_AI_GPT_4("GPT4", "gpt-4-turbo",null), + + // 千问付费模型 + QWEN_TURBO("通义千问超大规模语言模型", "qwen-turbo", null), + QWEN_PLUS("通义千问超大规模语言模型增强版", "qwen-plus", null), + QWEN_MAX("通义千问千亿级别超大规模语言模型", "qwen-max", null), + QWEN_MAX_0403("通义千问千亿级别超大规模语言模型-0403", "qwen-max-0403", null), + QWEN_MAX_0107("通义千问千亿级别超大规模语言模型-0107", "qwen-max-0107", null), + QWEN_MAX_1201("通义千问千亿级别超大规模语言模型-1201", "qwen-max-1201", null), + QWEN_MAX_LONGCONTEXT("通义千问千亿级别超大规模语言模型-28k tokens", "qwen-max-longcontext", null), + + // 千问开源模型 + // https://help.aliyun.com/document_detail/2666503.html?spm=a2c4g.2701795.0.0.26eb34dfKzcWN4 + QWEN_72B_CHAT("通义千问1.5对外开源的72B规模参数量的经过人类指令对齐的chat模型", "qwen-72b-chat", null), + + // 一言模型 + ERNIE4_0("ERNIE 4.0", "ERNIE 4.0", "/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions_pro"), + ERNIE4_3_5_8K("ERNIE-3.5-8K", "ERNIE-3.5-8K", "/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions"), + ERNIE4_3_5_8K_0205("ERNIE-3.5-8K-0205", "ERNIE-3.5-8K-0205", "/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-3.5-8k-0205"), + + ERNIE4_3_5_8K_1222("ERNIE-3.5-8K-1222", "ERNIE-3.5-8K-1222", "/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-3.5-8k-1222"), + ERNIE4_BOT_8K("ERNIE-Bot-8K", "ERNIE-Bot-8K", "/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie_bot_8k"), + ERNIE4_3_5_4K_0205("ERNIE-3.5-4K-0205", "ERNIE-3.5-4K-0205", "/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-3.5-4k-0205"), + +// 文档地址:https://www.xfyun.cn/doc/spark/Web.html#_1-%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E +// general指向V1.5版本; +// generalv2指向V2版本; +// generalv3指向V3版本; +// generalv3.5指向V3.5版本; + + XING_HUO_1_5("星火大模型1.5", "general", "/v1.1/chat"), + XING_HUO_2_0("星火大模型2.0", "generalv2", "/v2.1/chat"), + XING_HUO_3_0("星火大模型3.0", "generalv3", "/v3.1/chat"), + XING_HUO_3_5("星火大模型3.5", "generalv3.5", "/v3.5/chat"), + ; + + /** + * 模型名字 - 用于展示 + */ + private final String name; + /** + * 模型标志 - 用于参数传递 + */ + private final String model; + /** + * uri地址 + */ + private final String uri; + +} diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiOpenAiModelEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiOpenAiModelEnum.java deleted file mode 100644 index 993cabdcd..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiOpenAiModelEnum.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -// TODO done @fansili:1)类注释要加下;2)author 和 time 用 javadoc,@author 和 @since;3)@AllArgsConstructor 使用这个注解,去掉构造方法;4)value 改成 model 字段,然后注释都写下哈;5)message 改成 name,然后注释都写下哈 -// TODO @fan: AiModelEnum 是不是可以缩写成这个哈;所有的模型,都写在这里枚举; -/** - * @author: fansili - * @time: 2024/3/4 12:36 - */ -@Getter -@AllArgsConstructor -public enum AiOpenAiModelEnum { - - - OPEN_AI_GPT_3_5("gpt-3.5-turbo", "GPT3.5"), - OPEN_AI_GPT_4("gpt-4-turbo", "GPT4") - ; - - /** - * 模型标志 - 用于参数传递 - */ - private final String model; - /** - * 模型名字 - 用于展示 - */ - private final String name; - -} From 893d394a0af3f81526224aef6f36f78b6967849c Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 12:06:55 +0800 Subject: [PATCH 231/684] =?UTF-8?q?=E3=80=90=E8=B0=83=E6=95=B4=E3=80=91?= =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D=E4=B8=BA=20AiModelEnum=20=E5=90=88?= =?UTF-8?q?=E5=B9=B6=E6=88=90=E4=B8=80=E4=B8=AA=20ai=E6=9E=9A=E4=B8=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/dal/dataobject/chat/AiChatConversationDO.java | 4 ++-- .../yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java index 9a436b988..21bc0c0bf 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.chat; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.enums.AiOpenAiModelEnum; +import cn.iocoder.yudao.module.ai.enums.AiModelEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -66,7 +66,7 @@ public class AiChatConversationDO extends BaseDO { /** * 模型标志 * - * 枚举 {@link AiOpenAiModelEnum} + * 枚举 {@link AiModelEnum} */ private String model; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java index f5a5296a7..33489ae67 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.ai.chat.messages.MessageType; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.enums.AiOpenAiModelEnum; +import cn.iocoder.yudao.module.ai.enums.AiModelEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; @@ -64,7 +64,7 @@ public class AiChatMessageDO extends BaseDO { /** * 模型标志 * - * 枚举 {@link AiOpenAiModelEnum} + * 枚举 {@link AiModelEnum} */ private String model; /** From 46b5f17bbc3830cdf67d6e0159b2a9af72e53a7d Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 14:43:07 +0800 Subject: [PATCH 232/684] =?UTF-8?q?=E3=80=90=E8=B0=83=E6=95=B4=E3=80=91mod?= =?UTF-8?q?al=20=E4=BF=AE=E6=94=B9=E4=B8=BA=20model?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...roller.java => AiChatModelController.java} | 28 +++++----- ...AddReqVO.java => AiChatModelAddReqVO.java} | 3 +- ...stReqVO.java => AiChatModelListReqVO.java} | 2 +- ...RespVO.java => AiChatModelListRespVO.java} | 2 +- ...alConvert.java => AiChatModelConvert.java} | 16 +++--- ...{AiChatModalDO.java => AiChatModelDO.java} | 5 +- ...odalMapper.java => AiChatModelMapper.java} | 12 ++--- ...alService.java => AiChatModelService.java} | 18 +++---- .../service/impl/AiChatModalServiceImpl.java | 54 +++++++++---------- 9 files changed, 69 insertions(+), 71 deletions(-) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/{AiChatModalController.java => AiChatModelController.java} (73%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/{AiChatModalAddReqVO.java => AiChatModelAddReqVO.java} (93%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/{AiChatModalListReqVO.java => AiChatModelListReqVO.java} (88%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/{AiChatModalListRespVO.java => AiChatModelListRespVO.java} (96%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/{AiChatModalConvert.java => AiChatModelConvert.java} (68%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/{AiChatModalDO.java => AiChatModelDO.java} (93%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/{AiChatModalMapper.java => AiChatModelMapper.java} (74%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/{AiChatModalService.java => AiChatModelService.java} (79%) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModalController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java similarity index 73% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModalController.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java index 929a9e343..16da3a7ac 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModalController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.ai.controller.admin.model; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalAddReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListRespVO; -import cn.iocoder.yudao.module.ai.service.AiChatModalService; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelAddReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelListReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelListRespVO; +import cn.iocoder.yudao.module.ai.service.AiChatModelService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; @@ -24,38 +24,38 @@ import org.springframework.web.bind.annotation.*; */ @Tag(name = "A6-AI模型") @RestController -@RequestMapping("/ai/chat/modal") +@RequestMapping("/ai/chat/model") @Slf4j @AllArgsConstructor -public class AiChatModalController { +public class AiChatModelController { - private final AiChatModalService aiChatModalService; + private final AiChatModelService aiChatModelService; @Operation(summary = "ai模型 - 模型列表") @GetMapping("/list") - public PageResult list(@ModelAttribute AiChatModalListReqVO req) { - return aiChatModalService.list(req); + public PageResult list(@ModelAttribute AiChatModelListReqVO req) { + return aiChatModelService.list(req); } @Operation(summary = "ai模型 - 添加") @PutMapping("/add") - public CommonResult add(@RequestBody @Validated AiChatModalAddReqVO req) { - aiChatModalService.add(req); + public CommonResult add(@RequestBody @Validated AiChatModelAddReqVO req) { + aiChatModelService.add(req); return CommonResult.success(null); } @Operation(summary = "ai模型 - 修改") @PostMapping("/update") public CommonResult update(@RequestParam("id") Long id, - @RequestBody @Validated AiChatModalAddReqVO req) { - aiChatModalService.update(id, req); + @RequestBody @Validated AiChatModelAddReqVO req) { + aiChatModelService.update(id, req); return CommonResult.success(null); } @Operation(summary = "ai模型 - 删除") @DeleteMapping("/delete") public CommonResult delete(@RequestParam("id") Long id) { - aiChatModalService.delete(id); + aiChatModelService.delete(id); return CommonResult.success(null); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalAddReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelAddReqVO.java similarity index 93% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalAddReqVO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelAddReqVO.java index e9bc9242e..569760fab 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalAddReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelAddReqVO.java @@ -15,10 +15,9 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class AiChatModalAddReqVO { +public class AiChatModelAddReqVO { @Schema(description = "API 秘钥编号") - @Size(max = 32, message = "API 秘钥编号最大32个字符") @NotNull(message = "API 秘钥编号不能为空!") private Long keyId; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListReqVO.java similarity index 88% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListReqVO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListReqVO.java index a589db4b5..7e3cfff13 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListReqVO.java @@ -14,7 +14,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class AiChatModalListReqVO extends PageParam { +public class AiChatModelListReqVO extends PageParam { @Schema(description = "名字搜搜") private String search; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListRespVO.java similarity index 96% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListRespVO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListRespVO.java index 2249a2c00..8a2bc5bc3 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalListRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListRespVO.java @@ -13,7 +13,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class AiChatModalListRespVO { +public class AiChatModelListRespVO { @Schema(description = "id") private Long id; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModelConvert.java similarity index 68% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModelConvert.java index a0604f1d6..666f7a23b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModalConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModelConvert.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.ai.convert; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalAddReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelAddReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelListRespVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRespVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -17,9 +17,9 @@ import java.util.List; * @since 1.0 */ @Mapper -public interface AiChatModalConvert { +public interface AiChatModelConvert { - AiChatModalConvert INSTANCE = Mappers.getMapper(AiChatModalConvert.class); + AiChatModelConvert INSTANCE = Mappers.getMapper(AiChatModelConvert.class); /** * 转换 - AiChatModalListRes @@ -27,7 +27,7 @@ public interface AiChatModalConvert { * @param list * @return */ - List convertAiChatModalListRes(List list); + List convertAiChatModalListRes(List list); /** * 转换 - AiChatModalDO @@ -35,7 +35,7 @@ public interface AiChatModalConvert { * @param req * @return */ - AiChatModalDO convertAiChatModalDO(AiChatModalAddReqVO req); + AiChatModelDO convertAiChatModalDO(AiChatModelAddReqVO req); /** @@ -44,6 +44,6 @@ public interface AiChatModalConvert { * @param aiChatModalDO * @return */ - AiChatModalRespVO convertAiChatModalRes(AiChatModalDO aiChatModalDO); + AiChatModalRespVO convertAiChatModalRes(AiChatModelDO aiChatModalDO); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModalDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModelDO.java similarity index 93% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModalDO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModelDO.java index a35fa0e69..420de6fe1 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModalDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModelDO.java @@ -7,7 +7,6 @@ import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; -import lombok.experimental.Accessors; /** * AI 聊天模型 DO @@ -22,7 +21,7 @@ import lombok.experimental.Accessors; @Builder @NoArgsConstructor @AllArgsConstructor -public class AiChatModalDO extends BaseDO { +public class AiChatModelDO extends BaseDO { /** * 编号 @@ -76,6 +75,6 @@ public class AiChatModalDO extends BaseDO { /** * 上下文的最大 Message 数量 */ - private Integer maxContexts; + private Integer i; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModalMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java similarity index 74% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModalMapper.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java index d460710da..46d66ff5f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModalMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; @@ -18,17 +18,17 @@ import org.springframework.stereotype.Repository; */ @Repository @Mapper -public interface AiChatModalMapper extends BaseMapperX { +public interface AiChatModelMapper extends BaseMapperX { /** * 查询 - 第一个modal * * @return */ - default AiChatModalDO selectFirstModal() { - PageResult pageResult = selectPage(new PageParam().setPageNo(1).setPageSize(1), - new LambdaQueryWrapperX() - .orderByAsc(AiChatModalDO::getSort) + default AiChatModelDO selectFirstModal() { + PageResult pageResult = selectPage(new PageParam().setPageNo(1).setPageSize(1), + new LambdaQueryWrapperX() + .orderByAsc(AiChatModelDO::getSort) ); if (CollUtil.isEmpty(pageResult.getList())) { return null; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModelService.java similarity index 79% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModelService.java index ba16b8e17..b685d2694 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModalService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModelService.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalAddReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelAddReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelListReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelListRespVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRespVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; /** * ai modal @@ -14,7 +14,7 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; * @time 2024/4/24 19:42 * @since 1.0 */ -public interface AiChatModalService { +public interface AiChatModelService { /** * ai modal - 列表 @@ -22,14 +22,14 @@ public interface AiChatModalService { * @param req * @return */ - PageResult list(AiChatModalListReqVO req); + PageResult list(AiChatModelListReqVO req); /** * ai modal - 添加 * * @param req */ - void add(AiChatModalAddReqVO req); + void add(AiChatModelAddReqVO req); /** * ai modal - 更新 @@ -37,7 +37,7 @@ public interface AiChatModalService { * @param id * @param req */ - void update(Long id, AiChatModalAddReqVO req); + void update(Long id, AiChatModelAddReqVO req); /** * ai modal - 删除 @@ -60,7 +60,7 @@ public interface AiChatModalService { * @param id * @return */ - AiChatModalDO validateExists(Long id); + AiChatModelDO validateExists(Long id); /** * 校验 - 校验是否可用 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java index 2e1c37503..7a40846a4 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java @@ -8,15 +8,15 @@ import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalAddReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalListRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelAddReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelListReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelListRespVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRespVO; -import cn.iocoder.yudao.module.ai.convert.AiChatModalConvert; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; -import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModalMapper; +import cn.iocoder.yudao.module.ai.convert.AiChatModelConvert; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; +import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModelMapper; import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalConfigVO; -import cn.iocoder.yudao.module.ai.service.AiChatModalService; +import cn.iocoder.yudao.module.ai.service.AiChatModelService; import jakarta.validation.ConstraintViolation; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -35,51 +35,51 @@ import java.util.Set; @AllArgsConstructor @Service @Slf4j -public class AiChatModalServiceImpl implements AiChatModalService { +public class AiChatModalServiceImpl implements AiChatModelService { - private final AiChatModalMapper aiChatModalMapper; + private final AiChatModelMapper aiChatModelMapper; @Override - public PageResult list(AiChatModalListReqVO req) { - LambdaQueryWrapperX queryWrapperX = new LambdaQueryWrapperX<>(); + public PageResult list(AiChatModelListReqVO req) { + LambdaQueryWrapperX queryWrapperX = new LambdaQueryWrapperX<>(); // 查询的都是未禁用的模型 - queryWrapperX.eq(AiChatModalDO::getStatus, CommonStatusEnum.ENABLE.getStatus()); + queryWrapperX.eq(AiChatModelDO::getStatus, CommonStatusEnum.ENABLE.getStatus()); // search if (!StrUtil.isBlank(req.getSearch())) { - queryWrapperX.like(AiChatModalDO::getName, req.getSearch().trim()); + queryWrapperX.like(AiChatModelDO::getName, req.getSearch().trim()); } // 默认排序 - queryWrapperX.orderByAsc(AiChatModalDO::getSort); + queryWrapperX.orderByAsc(AiChatModelDO::getSort); // 查询 - PageResult aiChatModalDOPageResult = aiChatModalMapper.selectPage(req, queryWrapperX); + PageResult aiChatModalDOPageResult = aiChatModelMapper.selectPage(req, queryWrapperX); // 转换 res - List resList = AiChatModalConvert.INSTANCE.convertAiChatModalListRes(aiChatModalDOPageResult.getList()); + List resList = AiChatModelConvert.INSTANCE.convertAiChatModalListRes(aiChatModalDOPageResult.getList()); return new PageResult<>(resList, aiChatModalDOPageResult.getTotal()); } @Override - public void add(AiChatModalAddReqVO req) { + public void add(AiChatModelAddReqVO req) { // 校验 platform、type validatePlatform(req.getPlatform()); // 转换 do - AiChatModalDO insertChatModalDO = AiChatModalConvert.INSTANCE.convertAiChatModalDO(req); + AiChatModelDO insertChatModalDO = AiChatModelConvert.INSTANCE.convertAiChatModalDO(req); // 设置默认属性 insertChatModalDO.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 保存数据库 - aiChatModalMapper.insert(insertChatModalDO); + aiChatModelMapper.insert(insertChatModalDO); } @Override - public void update(Long id, AiChatModalAddReqVO req) { + public void update(Long id, AiChatModelAddReqVO req) { // 校验 platform validatePlatform(req.getPlatform()); // 校验模型是否存在 validateExists(id); // 转换 updateChatModalDO - AiChatModalDO updateChatModalDO = AiChatModalConvert.INSTANCE.convertAiChatModalDO(req); + AiChatModelDO updateChatModalDO = AiChatModelConvert.INSTANCE.convertAiChatModalDO(req); updateChatModalDO.setId(id); // 更新数据库 - aiChatModalMapper.updateById(updateChatModalDO); + aiChatModelMapper.updateById(updateChatModalDO); } @Override @@ -87,14 +87,14 @@ public class AiChatModalServiceImpl implements AiChatModalService { // 检查 modal 是否存在 validateExists(id); // 删除 delete - aiChatModalMapper.deleteById(id); + aiChatModelMapper.deleteById(id); } @Override public AiChatModalRespVO getChatModalOfValidate(Long modalId) { // 检查 modal 是否存在 - AiChatModalDO aiChatModalDO = validateExists(modalId); - return AiChatModalConvert.INSTANCE.convertAiChatModalRes(aiChatModalDO); + AiChatModelDO aiChatModalDO = validateExists(modalId); + return AiChatModelConvert.INSTANCE.convertAiChatModalRes(aiChatModalDO); } @Override @@ -105,8 +105,8 @@ public class AiChatModalServiceImpl implements AiChatModalService { } } - public AiChatModalDO validateExists(Long id) { - AiChatModalDO aiChatModalDO = aiChatModalMapper.selectById(id); + public AiChatModelDO validateExists(Long id) { + AiChatModelDO aiChatModalDO = aiChatModelMapper.selectById(id); if (aiChatModalDO == null) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_NOT_EXIST); } From a0e06cc0b7aa97cf869409d1ae513b5143766759 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 15:24:18 +0800 Subject: [PATCH 233/684] =?UTF-8?q?=E3=80=90=E8=B0=83=E6=95=B4=E3=80=91?= =?UTF-8?q?=E8=B0=83=E6=95=B4modal=20list=20=E8=BF=94=E5=9B=9E=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=EF=BC=8C=E5=92=8Cupdate=20req?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/model/AiChatModelController.java | 6 +- .../model/vo/model/AiChatModelListRespVO.java | 41 ++++++++----- .../vo/model/AiChatModelUpdateReqVO.java | 57 +++++++++++++++++++ .../module/ai/convert/AiChatModelConvert.java | 10 +++- .../dal/dataobject/model/AiChatModelDO.java | 2 +- .../module/ai/service/AiChatModelService.java | 8 +-- .../service/impl/AiChatModalServiceImpl.java | 11 ++-- 7 files changed, 103 insertions(+), 32 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelUpdateReqVO.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java index 16da3a7ac..010d143cc 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelAddReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelListReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelListRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelUpdateReqVO; import cn.iocoder.yudao.module.ai.service.AiChatModelService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -46,9 +47,8 @@ public class AiChatModelController { @Operation(summary = "ai模型 - 修改") @PostMapping("/update") - public CommonResult update(@RequestParam("id") Long id, - @RequestBody @Validated AiChatModelAddReqVO req) { - aiChatModelService.update(id, req); + public CommonResult update(@RequestBody @Validated AiChatModelUpdateReqVO req) { + aiChatModelService.update(req); return CommonResult.success(null); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListRespVO.java index 8a2bc5bc3..59a8900a6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListRespVO.java @@ -1,5 +1,9 @@ package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; +import cn.iocoder.yudao.framework.ai.AiPlatformEnum; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; +import com.baomidou.mybatisplus.annotation.TableId; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; @@ -15,27 +19,36 @@ import lombok.experimental.Accessors; @Accessors(chain = true) public class AiChatModelListRespVO { - @Schema(description = "id") + @Schema(description = "编号") private Long id; - @Schema(description = "模型平台 参考 AiPlatformEnum") - private String platform; + @Schema(description = "API 秘钥编号") + private Long keyId; - @Schema(description = "模型类型 参考 YiYanChatModel、XingHuoChatModel") - private String modal; - - @Schema(description = "模型名字") + @Schema(description = "模型名称") private String name; - @Schema(description = "模型照片") - private String image; + @Schema(description = "模型标志") + private String model; - @Schema(description = "禁用 0、正常 1、禁用") - private Integer disable; + @Schema(description = "平台") + private String platform; - @Schema(description = "排序 asc 排序") + @Schema(description = "排序值") private Integer sort; - @Schema(description = "modal 配置") - private String config; + @Schema(description = "状态") + private Integer status; + + // ========== 会话配置 ========== + + @Schema(description = "温度参数") + private Double temperature; + + @Schema(description = "单条回复的最大 Token 数量") + private Integer maxTokens; + + @Schema(description = "上下文的最大 Message 数量") + private Integer maxContexts; + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelUpdateReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelUpdateReqVO.java new file mode 100644 index 000000000..577e998e9 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelUpdateReqVO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * ai chat modal + * + * @author fansili + * @time 2024/4/24 19:47 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class AiChatModelUpdateReqVO { + + @Schema(description = "编号") + @NotNull(message = "编号不能为空") + private Long id; + + @Schema(description = "API 秘钥编号") + @NotNull(message = "API 秘钥编号不能为空!") + private Long keyId; + + @Schema(description = "模型名字") + @Size(max = 60, message = "模型名字最大60个字符") + @NotNull(message = "模型名字不能为空!") + private String name; + + @Schema(description = "模型类型(qianwen、yiyan、xinghuo、openai)") + @Size(max = 32, message = "模型类型最大32个字符") + @NotNull(message = "model模型不能为空!") + private String model; + + @Size(max = 32, message = "模型平台最大32个字符") + @Schema(description = "模型平台 参考 AiPlatformEnum") + @NotNull(message = "平台不能为空!") + private String platform; + + @Schema(description = "排序") + @NotNull(message = "sort排序不能为空!") + private Integer sort; + + // ========== 会话配置 ========== + + @Schema(description = "温度参数") + private Integer temperature; + + @Schema(description = "单条回复的最大 Token 数量") + private Integer maxTokens; + + @Schema(description = "上下文的最大 Message 数量") + private Integer maxContexts; +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModelConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModelConvert.java index 666f7a23b..d6d57b5ef 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModelConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModelConvert.java @@ -1,8 +1,9 @@ package cn.iocoder.yudao.module.ai.convert; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRespVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelAddReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelListRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelUpdateReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -37,6 +38,13 @@ public interface AiChatModelConvert { */ AiChatModelDO convertAiChatModalDO(AiChatModelAddReqVO req); + /** + * 转换 - AiChatModalDO + * + * @param req + * @return + */ + AiChatModelDO convertAiChatModalDO(AiChatModelUpdateReqVO req); /** * 转换 - AiChatModalRes diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModelDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModelDO.java index 420de6fe1..8c86127c3 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModelDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModelDO.java @@ -75,6 +75,6 @@ public class AiChatModelDO extends BaseDO { /** * 上下文的最大 Message 数量 */ - private Integer i; + private Integer maxContexts; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModelService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModelService.java index b685d2694..07a902dd8 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModelService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModelService.java @@ -1,10 +1,7 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelAddReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelListReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelListRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.*; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; /** @@ -34,10 +31,9 @@ public interface AiChatModelService { /** * ai modal - 更新 * - * @param id * @param req */ - void update(Long id, AiChatModelAddReqVO req); + void update(AiChatModelUpdateReqVO req); /** * ai modal - 删除 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java index 7a40846a4..c831ab723 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java @@ -8,10 +8,7 @@ import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelAddReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelListReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelListRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.*; import cn.iocoder.yudao.module.ai.convert.AiChatModelConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModelMapper; @@ -70,14 +67,14 @@ public class AiChatModalServiceImpl implements AiChatModelService { } @Override - public void update(Long id, AiChatModelAddReqVO req) { + public void update(AiChatModelUpdateReqVO req) { // 校验 platform validatePlatform(req.getPlatform()); // 校验模型是否存在 - validateExists(id); + validateExists(req.getId()); // 转换 updateChatModalDO AiChatModelDO updateChatModalDO = AiChatModelConvert.INSTANCE.convertAiChatModalDO(req); - updateChatModalDO.setId(id); + updateChatModalDO.setId(req.getId()); // 更新数据库 aiChatModelMapper.updateById(updateChatModalDO); } From 3e91032eaffac2d708ac6ec3458bdfee63a038c4 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 15:25:34 +0800 Subject: [PATCH 234/684] =?UTF-8?q?=E3=80=90=E8=B0=83=E6=95=B4=E3=80=91AI?= =?UTF-8?q?=20=E5=AF=B9=E8=AF=9D=E5=BC=95=E5=85=A5=E7=9A=84=20modal=20?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=BA=20model?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/dal/dataobject/chat/AiChatConversationDO.java | 4 ++-- .../service/impl/AiChatConversationServiceImpl.java | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java index 21bc0c0bf..a4651323c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.chat; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.enums.AiModelEnum; import com.baomidou.mybatisplus.annotation.KeySequence; @@ -60,7 +60,7 @@ public class AiChatConversationDO extends BaseDO { /** * 模型编号 * - * 关联 {@link AiChatModalDO#getId()} 字段 + * 关联 {@link AiChatModelDO#getId()} 字段 */ private Long modelId; /** diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java index 228ab75e1..dc5205011 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java @@ -11,11 +11,11 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRes import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleRespVO; import cn.iocoder.yudao.module.ai.convert.AiChatConversationConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; -import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModalMapper; +import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModelMapper; import cn.iocoder.yudao.module.ai.service.AiChatConversationService; -import cn.iocoder.yudao.module.ai.service.AiChatModalService; +import cn.iocoder.yudao.module.ai.service.AiChatModelService; import cn.iocoder.yudao.module.ai.service.AiChatRoleService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -35,8 +35,8 @@ import java.util.List; @AllArgsConstructor public class AiChatConversationServiceImpl implements AiChatConversationService { - private final AiChatModalMapper aiChatModalMapper; - private final AiChatModalService aiChatModalService; + private final AiChatModelMapper aiChatModalMapper; + private final AiChatModelService aiChatModalService; private final AiChatRoleService aiChatRoleService; private final AiChatConversationMapper aiChatConversationMapper; @@ -45,7 +45,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService // 获取用户id Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 默认使用 sort 排序第一个模型 - AiChatModalDO aiChatModalDO = aiChatModalMapper.selectFirstModal(); + AiChatModelDO aiChatModalDO = aiChatModalMapper.selectFirstModal(); // 查询角色 AiChatRoleRespVO chatRoleRes = null; if (req.getRoleId() != null) { From b091498040b989ebc5a2afb72539ee47d2430220 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 15:38:01 +0800 Subject: [PATCH 235/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E4=BC=98=E5=8C=96AI=20=E8=A7=92=E8=89=B2=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E8=BF=94=E5=9B=9E=E4=BF=A1=E6=81=AF=20=E5=92=8C=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E6=A8=A1=E5=9E=8Bid=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/vo/role/AiChatRoleAddReqVO.java | 2 +- .../model/vo/role/AiChatRoleListRespVO.java | 41 +++++++++++++------ .../ai/dal/dataobject/model/AiChatRoleDO.java | 13 ++---- .../service/impl/AiChatRoleServiceImpl.java | 4 +- 4 files changed, 34 insertions(+), 26 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleAddReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleAddReqVO.java index f03137df8..f069caf97 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleAddReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleAddReqVO.java @@ -42,7 +42,7 @@ public class AiChatRoleAddReqVO { private Long modelId; @NotNull - @Schema(description = "开启状态 open、close") + @Schema(description = "开启状态 0、open 1、close") private Boolean publicStatus; @NotNull diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListRespVO.java index f66d5a6ea..3eee736be 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListRespVO.java @@ -14,24 +14,39 @@ import lombok.experimental.Accessors; @Accessors(chain = true) public class AiChatRoleListRespVO { - @Schema(description = "id") + @Schema(description = "编号", example = "1") private Long id; - @Schema(description = "用户id") - private Long userId; - - @Schema(description = "角色名字") + @Schema(description = "角色名称", example = "小红书写作") private String name; - @Schema(description = "角色介绍,详细描述角色的功能或用途") - private String introduce; + @Schema(description = "角色头像", example = "http://...") + private String avatar; - @Schema(description = "分类,角色所属的类别,如娱乐、创作等") - private String classify; + @Schema(description = "角色分类", example = "writing") + private String category; - @Schema(description = "状态 open、close") - private String enable; + @Schema(description = "角色描述", example = "角色描述") + private String description; - @Schema(description = "角色的使用次数统计") - private Integer useCount; + @Schema(description = "角色欢迎语", example = "欢迎...") + private String welcomeMessage; + + @Schema(description = "角色设定(消息)", example = "你是拥有丰富的小红书写作经验作者xxxx") + private String systemMessage; + + @Schema(description = "用户编号", example = "1") + private Long userId; + + @Schema(description = "模型编号", example = "1") + private Long modelId; + + @Schema(description = "是否公开 true - 公开;false - 私有", example = "true") + private Boolean publicStatus; + + @Schema(description = "排序值 asc", example = "1") + private Integer sort; + + @Schema(description = "状态 0、开启 1、关闭", example = "1") + private Integer status; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java index bb48f524d..51cf67c86 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java @@ -1,16 +1,9 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.model; -import cn.iocoder.yudao.framework.ai.chat.messages.MessageType; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.*; -import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler; import lombok.*; -import lombok.experimental.Accessors; - -import java.io.Serializable; -import java.util.List; /** * AI 聊天角色 DO @@ -67,12 +60,12 @@ public class AiChatRoleDO extends BaseDO { /** * 模型编号 * - * 关联 {@link AiChatModalDO#getId()} 字段 + * 关联 {@link AiChatModelDO#getId()} 字段 */ - private String modelId; + private Long modelId; /** - * 是否公开 + * 是否公开 true - 公开;false - 私有 * * true - 公开;false - 私有 */ diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java index 5264ea2a2..cc432fe41 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java @@ -12,7 +12,7 @@ import cn.iocoder.yudao.module.ai.convert.AiChatRoleConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatRoleMapper; import cn.iocoder.yudao.module.ai.enums.AiChatRoleCategoryEnum; -import cn.iocoder.yudao.module.ai.service.AiChatModalService; +import cn.iocoder.yudao.module.ai.service.AiChatModelService; import cn.iocoder.yudao.module.ai.service.AiChatRoleService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -32,7 +32,7 @@ import java.util.List; public class AiChatRoleServiceImpl implements AiChatRoleService { private final AiChatRoleMapper aiChatRoleMapper; - private final AiChatModalService aiChatModalService; + private final AiChatModelService aiChatModalService; @Override public PageResult list(AiChatRoleListReqVO req) { From fd6ce5a627c885f3fd0be4f11db5840d34a24919 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 15:38:47 +0800 Subject: [PATCH 236/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E4=BF=AE=E6=94=B9http=20=E8=AF=B7=E6=B1=82=E5=9C=B0=E5=9D=80?= =?UTF-8?q?=E5=92=8C=E8=AF=B7=E6=B1=82=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/http/chat-modal.http | 33 +++++--------- .../src/main/resources/http/chat-role.http | 44 +++++++++++-------- 2 files changed, 37 insertions(+), 40 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-modal.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-modal.http index ab8aa85c6..8a58fa990 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-modal.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-modal.http @@ -1,43 +1,32 @@ ### chat call -GET {{baseUrl}}/ai/chat/modal/list +GET {{baseUrl}}/admin-api/ai/chat/model/list Authorization: {{token}} ### chat call -PUT {{baseUrl}}/ai/chat/modal +PUT {{baseUrl}}/admin-api/ai/chat/model/add Content-Type: application/json Authorization: {{token}} { + "keyId": "1", "name": "小红书Ai写作大模型4.0", - "modal": "ERNIE 4.0", + "model": "ERNIE 4.0", "platform": "yiyan", - "imageUrl": "", - "sort": 100, - "config": { - "topK": 0.6, - "topP": 0.6, - "temperature": 0.86, - "maxTokens": 2048 - } + "sort": 100 } ### chat call -POST {{baseUrl}}/ai/chat/modal/7 +POST {{baseUrl}}/admin-api/ai/chat/model/update Content-Type: application/json Authorization: {{token}} { - "name": "小红书Ai写作大模型-plus", - "modal": "ERNIE-3.5-8K", + "id": 9, + "keyId": "1", + "name": "小红书Ai写作大模型3.5 8k", + "model": "ERNIE-3.5-8K", "platform": "yiyan", - "imageUrl": "", - "sort": 1, - "config": { - "topK": 0.6, - "topP": 0.6, - "temperature": 0.86, - "maxTokens": 2048 - } + "sort": 100 } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http index b459a5a95..87502e313 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http @@ -1,50 +1,58 @@ ### chat角色 - list -GET {{baseUrl}}/ai/chat/role/list?pageNo=1&pageSize=20&search= +GET {{baseUrl}}/admin-api/ai/chat/role/list?pageNo=1&pageSize=20&search= Authorization: {{token}} - ### chat add -PUT {{baseUrl}}/ai/chat/role +PUT {{baseUrl}}/admin-api/ai/chat/role/add Content-Type: application/json Authorization: {{token}} { - "modelId": 1, + "modelId": 9, "name": "小红书写作v1", - "introduce": "采用gpt3.5模型,拥有小红书优质作者写作经验。", - "classify": "writing", - "enable": "open" + "avatar": "http://baidu.com", + "category": "writing", + "description": "采用gpt3.5模型,拥有小红书优质作者写作经验。", + "welcomeMessage": "欢迎使用小红书写作模型!", + "systemMessage": "你是一名优秀的小红书人文、风光作者,你热爱旅游,每去往一个城市你都会用美妙的文字抒写着这座城市的大街小巷,描述着这座城市的美好。", + "publicStatus": 0, + "sort": 0 } ### chat update -POST {{baseUrl}}/ai/chat/role/7 +POST {{baseUrl}}/admin-api/ai/chat/role/update Content-Type: application/json Authorization: {{token}} { - "modelId": 1, - "name": "小红书写作v1---hh😄❀", - "introduce": "采用gpt3.5模型,拥有小红书优质作者写作经验。0----", - "classify": "writing", - "enable": "close" + "id": 8, + "modelId": 9, + "name": "小红书写作v2", + "avatar": "http://baidu.com", + "category": "writing", + "description": "采用gpt3.5模型,拥有小红书优质作者写作经验。", + "welcomeMessage": "欢迎使用小红书写作模型!", + "systemMessage": "你是一名优秀的小红书人文、风光作者,你热爱旅游,每去往一个城市你都会用美妙的文字抒写着这座城市的大街小巷,描述着这座城市的美好。", + "publicStatus": 0, + "sort": 0, + "status": 0 } ### chat update -POST {{baseUrl}}/ai/chat/role/6/update-visibility +POST {{baseUrl}}/admin-api/ai/chat/role/update-public-status Content-Type: application/json Authorization: {{token}} { - "enable": "open" + "id": "8", + "publicStatus": true } - ### chat update -DELETE {{baseUrl}}/ai/chat/role/1 -Content-Type: application/json +DELETE {{baseUrl}}/admin-api/ai/chat/role/delete?id=8 Authorization: {{token}} From 9ad977bdb9c7b72250c4d47b100d60ef5afc9a9a Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 15:39:13 +0800 Subject: [PATCH 237/684] =?UTF-8?q?=E3=80=90=E8=B0=83=E6=95=B4=E3=80=91mes?= =?UTF-8?q?sage=20=E4=BF=AE=E6=94=B9=E5=BC=95=E5=85=A5=E7=9A=84modal?= =?UTF-8?q?=E6=94=B9=E4=B8=BAmodel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java | 4 ++-- .../yudao/module/ai/service/impl/AiChatServiceImpl.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java index 33489ae67..7e57f7ea0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.chat; import cn.iocoder.yudao.framework.ai.chat.messages.MessageType; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModalDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.enums.AiModelEnum; import com.baomidou.mybatisplus.annotation.KeySequence; @@ -70,7 +70,7 @@ public class AiChatMessageDO extends BaseDO { /** * 模型编号 * - * 关联 {@link AiChatModalDO#getId()} 字段 + * 关联 {@link AiChatModelDO#getId()} 字段 */ private Long modelId; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index 7fc13cac6..3241a144d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -21,7 +21,7 @@ import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatMessageMapper; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatRoleMapper; import cn.iocoder.yudao.module.ai.service.AiChatConversationService; -import cn.iocoder.yudao.module.ai.service.AiChatModalService; +import cn.iocoder.yudao.module.ai.service.AiChatModelService; import cn.iocoder.yudao.module.ai.service.AiChatRoleService; import cn.iocoder.yudao.module.ai.service.AiChatService; import lombok.AllArgsConstructor; @@ -52,7 +52,7 @@ public class AiChatServiceImpl implements AiChatService { private final AiChatMessageMapper aiChatMessageMapper; private final AiChatConversationMapper aiChatConversationMapper; private final AiChatConversationService chatConversationService; - private final AiChatModalService aiChatModalService; + private final AiChatModelService aiChatModalService; private final AiChatRoleService aiChatRoleService; @Transactional(rollbackFor = Exception.class) From bd3e65898befa518d825c5d74757e90a457425a1 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 16:22:58 +0800 Subject: [PATCH 238/684] =?UTF-8?q?=E3=80=90=E6=B5=8B=E8=AF=95=E3=80=91AI?= =?UTF-8?q?=E5=AF=B9=E8=AF=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/http/chat-conversation.http | 44 +++++++------------ 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-conversation.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-conversation.http index 15c441f34..275ed56c3 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-conversation.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-conversation.http @@ -1,39 +1,27 @@ ### 登录 详细使用 https://www.jetbrains.com/help/idea/testing-restful-web-services.html、https://www.cnblogs.com/crazymakercircle/p/14317222.html -### 对话 - 创建对话 -PUT {{baseUrl}}/ai/chat/conversation/createConversation -Content-Type: application/json -Authorization: {{token}} - -{ - "title": "新增对话" -} - - -### 对话 - 创建对话 -PUT {{baseUrl}}/ai/chat/conversation/createRoleConversation -Content-Type: application/json -Authorization: {{token}} - -{ - "roleId": 7, - "title": "新增对话" -} - - - -### 对话 - id获取 -GET {{baseUrl}}/ai/chat/conversation/1781604279872581644 -Authorization: {{token}} - ### 对话 - list -GET {{baseUrl}}/ai/chat/conversation/list +GET {{baseUrl}}/admin-api/ai/chat/conversation/list +Authorization: {{token}} + + +### 对话 - 创建对话 +POST {{baseUrl}}/admin-api/ai/chat/conversation/create +Content-Type: application/json +Authorization: {{token}} + +{ + "roleId": "9" +} + +### 对话 - id获取 +GET {{baseUrl}}/admin-api/ai/chat/conversation/get?id=1781604279872581647 Authorization: {{token}} ### 对话 - 删除 -DELETE {{baseUrl}}/ai/chat/conversation/1781604279872581644 +DELETE {{baseUrl}}/admin-api/ai/chat/conversation/delete?id=1781604279872581647 Authorization: {{token}} From 708d66e8cf0647cb4c7afa2743794a478c8b9bce Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 16:47:25 +0800 Subject: [PATCH 239/684] =?UTF-8?q?=E3=80=90=E6=B5=8B=E8=AF=95=E3=80=91cha?= =?UTF-8?q?t=20=E8=81=8A=E5=A4=A9(send=E3=80=81send-stream)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/chat/AiChatMessageController.java | 4 +-- .../service/impl/AiChatModalServiceImpl.java | 2 +- .../ai/service/impl/AiChatServiceImpl.java | 13 ++++---- .../src/main/resources/http/chat-message.http | 25 ++++++++++++++-- .../src/main/resources/http/chat.http | 30 ------------------- 5 files changed, 31 insertions(+), 43 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java index 285611cbe..a36f871a6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java @@ -30,7 +30,7 @@ public class AiChatMessageController { @Operation(summary = "发送消息(段式)", description = "一次性返回,响应较慢") @PostMapping("/send") - public CommonResult sendMessage(@Validated @ModelAttribute AiChatMessageSendReqVO sendReqVO) { + public CommonResult sendMessage(@Validated @RequestBody AiChatMessageSendReqVO sendReqVO) { // TODO done @fan:使用 static import;这样就 success 就行了; return success(chatService.chat(sendReqVO)); } @@ -39,7 +39,7 @@ public class AiChatMessageController { // TODO @fan:要不要使用 Flux 来返回;可以使用 Flux @Operation(summary = "发送消息(流式)", description = "流式返回,响应较快") @PostMapping(value = "/send-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) - public SseEmitter sendMessageStream(@Validated @ModelAttribute AiChatMessageSendReqVO sendReqVO) { + public SseEmitter sendMessageStream(@Validated @RequestBody AiChatMessageSendReqVO sendReqVO) { Utf8SseEmitter sseEmitter = new Utf8SseEmitter(); chatService.chatStream(sendReqVO, sseEmitter); return sseEmitter; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java index c831ab723..0aec7a94c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java @@ -97,7 +97,7 @@ public class AiChatModalServiceImpl implements AiChatModelService { @Override public void validateAvailable(AiChatModalRespVO chatModal) { // 对话模型是否可用 - if (CommonStatusEnum.ENABLE.getStatus().equals(chatModal.getStatus())) { + if (!CommonStatusEnum.ENABLE.getStatus().equals(chatModal.getStatus())) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_DISABLE_NOT_USED); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index 3241a144d..ba1b4b679 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -19,7 +19,6 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatMessageMapper; -import cn.iocoder.yudao.module.ai.dal.mysql.AiChatRoleMapper; import cn.iocoder.yudao.module.ai.service.AiChatConversationService; import cn.iocoder.yudao.module.ai.service.AiChatModelService; import cn.iocoder.yudao.module.ai.service.AiChatRoleService; @@ -48,7 +47,6 @@ import java.util.function.Consumer; public class AiChatServiceImpl implements AiChatService { private final AiChatClientFactory aiChatClientFactory; - private final AiChatRoleMapper aiChatRoleMapper; private final AiChatMessageMapper aiChatMessageMapper; private final AiChatConversationMapper aiChatConversationMapper; private final AiChatConversationService chatConversationService; @@ -72,7 +70,7 @@ public class AiChatServiceImpl implements AiChatService { // 校验角色是否公开 aiChatRoleService.validateIsPublic(aiChatRoleDO); // 获取 client 类型 - AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(chatModal.getModel()); + AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(chatModal.getPlatform()); // 保存 chat message insertChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(), chatModal.getModel(), chatModal.getId(), req.getContent(), @@ -90,13 +88,12 @@ public class AiChatServiceImpl implements AiChatService { ChatResponse call = chatClient.call(prompt); content = call.getResult().getOutput().getContent(); // 更新 conversation - } catch (Exception e) { content = ExceptionUtil.getMessage(e); } finally { // 保存 chat message insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), - chatModal.getModel(), chatModal.getId(), req.getContent(), + chatModal.getModel(), chatModal.getId(), content, null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); } return new AiChatMessageRespVO().setContent(content); @@ -154,7 +151,7 @@ public class AiChatServiceImpl implements AiChatService { null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); // 获取 client 类型 - AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(chatModal.getModel()); + AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(chatModal.getPlatform()); StreamingChatClient streamingChatClient = aiChatClientFactory.getStreamingChatClient(platformEnum); Flux streamResponse = streamingChatClient.stream(prompt); @@ -166,7 +163,7 @@ public class AiChatServiceImpl implements AiChatService { String content = chatResponse.getResults().get(0).getOutput().getContent(); try { contentBuffer.append(content); - sseEmitter.send(content, MediaType.APPLICATION_JSON); + sseEmitter.send(new AiChatMessageRespVO().setContent(content), MediaType.APPLICATION_JSON); } catch (IOException e) { log.error("发送异常{}", ExceptionUtil.getMessage(e)); // 如果不是因为关闭而抛出异常,则重新连接 @@ -183,7 +180,7 @@ public class AiChatServiceImpl implements AiChatService { sseEmitter.complete(); // 保存 chat message insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), - chatModal.getModel(), chatModal.getId(), req.getContent(), + chatModal.getModel(), chatModal.getId(), contentBuffer.toString(), null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-message.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-message.http index b39eda5ff..b357ab66e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-message.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-message.http @@ -1,10 +1,31 @@ +### chat call +POST {{baseUrl}}/admin-api/ai/chat/message/send +Content-Type: application/json +Authorization: {{token}} + +{ + "conversationId": "1781604279872581649", + "content": "中国好看吗?" +} + + +### chat call +POST {{baseUrl}}/admin-api/ai/chat/message/send-stream +Content-Type: application/json +Authorization: {{token}} + +{ + "conversationId": "1781604279872581649", + "content": "苹果是什么颜色?" +} + ### message list -GET {{baseUrl}}/ai/chat/message/list?chatConversationId=1781604279872581644 +GET {{baseUrl}}/admin-api/ai/chat/message/list-by-conversation-id?conversationId=1781604279872581649 Authorization: {{token}} ### message delete -DELETE {{baseUrl}}/ai/chat/message/1781604279872581644/8 +DELETE {{baseUrl}}/admin-api/ai/chat/message/delete?id=50 Authorization: {{token}} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http deleted file mode 100644 index 829b74f45..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http +++ /dev/null @@ -1,30 +0,0 @@ - - -### 登录 - -POST {{baseUrl}}/admin-api/system/auth/login -Content-Type: application/json -tenant-id: 1 - -{ - "username": "admin", - "password": "123456", - "captchaVerification": "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==", - "socialCode": "1024", - "socialState": "9b2ffbc1-7425-4155-9894-9d5c08541d62", - "socialCodeValid": true -} - -### chat call -GET {{baseUrl}}/ai/chat?modal=qianwen&conversationId=1781604279872581644&prompt=中国好看吗? -Authorization: {{token}} - - - -### chat call -GET {{baseUrl}}/ai/chatStream?conversationId=1781604279872581644&prompt=苹果是什么颜色?&modal=yiYan3_5_8k -Authorization: {{token}} - - - - From 5579620140c7036c35bf270b2ca40ba98a7de7b7 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 17:22:23 +0800 Subject: [PATCH 240/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E8=81=8A=E5=A4=A9=20event=20stream=20=E6=94=B9=E4=B8=BA=20flex?= =?UTF-8?q?=20=E8=BF=94=E5=9B=9E=E6=9B=B4=E5=8A=A0=E7=9A=84=E4=BC=98?= =?UTF-8?q?=E9=9B=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/controller/Utf8SseEmitter.java | 26 ------- .../admin/chat/AiChatMessageController.java | 11 ++- .../admin/image/AiImageController.java | 13 ++-- .../module/ai/service/AiChatService.java | 7 +- .../module/ai/service/AiImageService.java | 4 +- .../ai/service/impl/AiChatServiceImpl.java | 71 +++++++++---------- .../ai/service/impl/AiImageServiceImpl.java | 40 +++++------ .../src/main/resources/application-local.yaml | 8 ++- 8 files changed, 71 insertions(+), 109 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/Utf8SseEmitter.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/Utf8SseEmitter.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/Utf8SseEmitter.java deleted file mode 100644 index d23f4e9b1..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/Utf8SseEmitter.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller; - -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.http.server.ServerHttpResponse; -import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; - -import java.nio.charset.StandardCharsets; - -/** - * 解决中文乱码 - * - * @author fansili - * @time 2024/4/14 15:13 - * @since 1.0 - */ -public class Utf8SseEmitter extends SseEmitter { - - @Override - protected void extendResponse(ServerHttpResponse outputMessage) { - super.extendResponse(outputMessage); - - HttpHeaders headers = outputMessage.getHeaders(); - headers.setContentType(new MediaType(MediaType.TEXT_EVENT_STREAM, StandardCharsets.UTF_8)); - } -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java index a36f871a6..82392ed27 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java @@ -1,10 +1,9 @@ package cn.iocoder.yudao.module.ai.controller.admin.chat; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; -import cn.iocoder.yudao.module.ai.service.AiChatService; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; +import cn.iocoder.yudao.module.ai.service.AiChatService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -13,7 +12,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.http.MediaType; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; +import reactor.core.publisher.Flux; import java.util.List; @@ -39,10 +38,8 @@ public class AiChatMessageController { // TODO @fan:要不要使用 Flux 来返回;可以使用 Flux @Operation(summary = "发送消息(流式)", description = "流式返回,响应较快") @PostMapping(value = "/send-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) - public SseEmitter sendMessageStream(@Validated @RequestBody AiChatMessageSendReqVO sendReqVO) { - Utf8SseEmitter sseEmitter = new Utf8SseEmitter(); - chatService.chatStream(sendReqVO, sseEmitter); - return sseEmitter; + public Flux sendMessageStream(@Validated @RequestBody AiChatMessageSendReqVO sendReqVO) { + return chatService.chatStream(sendReqVO); } @Operation(summary = "获得指定会话的消息列表") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index 43e05dc83..274391777 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -1,10 +1,9 @@ package cn.iocoder.yudao.module.ai.controller.admin.image; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; -import cn.iocoder.yudao.module.ai.service.AiImageService; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReq; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReq; +import cn.iocoder.yudao.module.ai.service.AiImageService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; @@ -14,7 +13,6 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; // TODO @芋艿:整理接口定义 /** @@ -35,10 +33,11 @@ public class AiImageController { @Operation(summary = "dall2/dall3绘画", description = "openAi dall3是付费的!") @PostMapping("/dallDrawing") - public SseEmitter dallDrawing(@Validated @RequestBody AiImageDallDrawingReq req) { - Utf8SseEmitter sseEmitter = new Utf8SseEmitter(); - aiImageService.dallDrawing(req, sseEmitter); - return sseEmitter; + public void dallDrawing(@Validated @RequestBody AiImageDallDrawingReq req) { +// Utf8SseEmitter sseEmitter = new Utf8SseEmitter(); +// aiImageService.dallDrawing(req, sseEmitter); +// return sseEmitter; + } @Operation(summary = "midjourney", description = "midjourney图片绘画流程:1、提交任务 2、获取完成的任务 3、选择对应功能 4、获取最终结果") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java index 27ece6b14..a5e97ce5f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.ai.service; -import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; +import reactor.core.publisher.Flux; import java.util.List; @@ -26,11 +26,10 @@ public interface AiChatService { /** * chat stream * - * @param req - * @param sseEmitter + * @param sendReqVO * @return */ - void chatStream(AiChatMessageSendReqVO req, Utf8SseEmitter sseEmitter); + Flux chatStream(AiChatMessageSendReqVO sendReqVO); /** * 获取 - 获取对话 message list diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java index 00b5ded44..cf95483d2 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.ai.service; -import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReq; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReq; @@ -17,9 +16,8 @@ public interface AiImageService { * ai绘画 - dall2/dall3 绘画 * * @param req - * @param sseEmitter */ - void dallDrawing(AiImageDallDrawingReq req, Utf8SseEmitter sseEmitter); + void dallDrawing(AiImageDallDrawingReq req); /** * midjourney 图片生成 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index ba1b4b679..90649f417 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -9,7 +9,6 @@ import cn.iocoder.yudao.framework.ai.chat.messages.MessageType; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.config.AiChatClientFactory; -import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; @@ -25,13 +24,12 @@ import cn.iocoder.yudao.module.ai.service.AiChatRoleService; import cn.iocoder.yudao.module.ai.service.AiChatService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import reactor.core.publisher.Flux; -import java.io.IOException; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; /** @@ -76,6 +74,7 @@ public class AiChatServiceImpl implements AiChatService { chatModal.getModel(), chatModal.getId(), req.getContent(), null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); String content = null; + int tokens = 0; try { // 创建 chat 需要的 Prompt Prompt prompt = new Prompt(req.getContent()); @@ -87,6 +86,7 @@ public class AiChatServiceImpl implements AiChatService { ChatClient chatClient = aiChatClientFactory.getChatClient(platformEnum); ChatResponse call = chatClient.call(prompt); content = call.getResult().getOutput().getContent(); + tokens = call.getResults().size(); // 更新 conversation } catch (Exception e) { content = ExceptionUtil.getMessage(e); @@ -94,7 +94,7 @@ public class AiChatServiceImpl implements AiChatService { // 保存 chat message insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), chatModal.getModel(), chatModal.getId(), content, - null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); + tokens, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); } return new AiChatMessageRespVO().setContent(content); } @@ -123,8 +123,7 @@ public class AiChatServiceImpl implements AiChatService { return insertChatMessageDO; } - @Override - public void chatStream(AiChatMessageSendReqVO req, Utf8SseEmitter sseEmitter) { + public Flux chatStream(AiChatMessageSendReqVO req) { Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 查询对话 AiChatConversationRespVO conversation = chatConversationService.getConversationOfValidate(req.getConversationId()); @@ -144,47 +143,43 @@ public class AiChatServiceImpl implements AiChatService { // req.setTopK(req.getTopK()); // req.setTopP(req.getTopP()); // req.setTemperature(req.getTemperature()); - // 保存 chat message // 保存 chat message insertChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(), chatModal.getModel(), chatModal.getId(), req.getContent(), null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); - // 获取 client 类型 AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(chatModal.getPlatform()); StreamingChatClient streamingChatClient = aiChatClientFactory.getStreamingChatClient(platformEnum); Flux streamResponse = streamingChatClient.stream(prompt); - + // 转换 flex AiChatMessageRespVO StringBuffer contentBuffer = new StringBuffer(); - streamResponse.subscribe( - new Consumer() { - @Override - public void accept(ChatResponse chatResponse) { - String content = chatResponse.getResults().get(0).getOutput().getContent(); - try { - contentBuffer.append(content); - sseEmitter.send(new AiChatMessageRespVO().setContent(content), MediaType.APPLICATION_JSON); - } catch (IOException e) { - log.error("发送异常{}", ExceptionUtil.getMessage(e)); - // 如果不是因为关闭而抛出异常,则重新连接 - sseEmitter.completeWithError(e); - } - } - }, - error -> { - // - log.error("subscribe错误 {}", ExceptionUtil.getMessage(error)); - }, - () -> { - log.info("发送完成!"); - sseEmitter.complete(); - // 保存 chat message - insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), - chatModal.getModel(), chatModal.getId(), contentBuffer.toString(), - null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); - + AtomicInteger tokens = new AtomicInteger(0); + return streamResponse.map(res -> { + AiChatMessageRespVO aiChatMessageRespVO = new AiChatMessageRespVO(); + aiChatMessageRespVO.setContent(res.getResult().getOutput().getContent()); + contentBuffer.append(res.getResult().getOutput().getContent()); + tokens.incrementAndGet(); + return aiChatMessageRespVO; } - ); + ).doOnComplete(new Runnable() { + @Override + public void run() { + log.info("发送完成!"); + // 保存 chat message + insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), + chatModal.getModel(), chatModal.getId(), contentBuffer.toString(), + tokens.get(), conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); + } + }).doOnError(new Consumer() { + @Override + public void accept(Throwable throwable) { + log.error("发送错误 {}!", throwable.getMessage()); + // 保存 chat message + insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), + chatModal.getModel(), chatModal.getId(), throwable.getMessage(), + tokens.get(), conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); + } + }); } @Override @@ -194,7 +189,7 @@ public class AiChatServiceImpl implements AiChatService { // 获取对话所有 message List aiChatMessageDOList = aiChatMessageMapper.selectByConversationId(conversationId); // 转换 AiChatMessageRespVO - return AiChatMessageConvert.INSTANCE.convertAiChatMessageRespVOList(aiChatMessageDOList); + return AiChatMessageConvert.INSTANCE.convertAiChatMessageRespVOList(aiChatMessageDOList); } @Override diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java index 16a414681..5bacf9da5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java @@ -5,8 +5,8 @@ import cn.iocoder.yudao.framework.ai.image.ImageGeneration; import cn.iocoder.yudao.framework.ai.image.ImagePrompt; import cn.iocoder.yudao.framework.ai.image.ImageResponse; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageClient; -import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageModelEnum; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageOptions; +import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageModelEnum; import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageStyleEnum; import cn.iocoder.yudao.framework.ai.midjourney.api.MidjourneyInteractionsApi; import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyWebSocketStarter; @@ -14,22 +14,18 @@ import cn.iocoder.yudao.framework.ai.midjourney.webSocket.WssNotify; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; -import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; -import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; -import cn.iocoder.yudao.module.ai.enums.AiChatDrawingStatusEnum; -import cn.iocoder.yudao.module.ai.dal.mysql.AiImageMapper; -import cn.iocoder.yudao.module.ai.service.AiImageService; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReq; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReq; +import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; +import cn.iocoder.yudao.module.ai.dal.mysql.AiImageMapper; +import cn.iocoder.yudao.module.ai.enums.AiChatDrawingStatusEnum; +import cn.iocoder.yudao.module.ai.service.AiImageService; import jakarta.annotation.PostConstruct; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.io.IOException; - /** * ai 作图 * @@ -64,7 +60,7 @@ public class AiImageServiceImpl implements AiImageService { } @Override - public void dallDrawing(AiImageDallDrawingReq req, Utf8SseEmitter sseEmitter) { + public void dallDrawing(AiImageDallDrawingReq req) { // 获取 model OpenAiImageModelEnum openAiImageModelEnum = OpenAiImageModelEnum.valueOfModel(req.getModal()); OpenAiImageStyleEnum openAiImageStyleEnum = OpenAiImageStyleEnum.valueOfStyle(req.getStyle()); @@ -79,7 +75,7 @@ public class AiImageServiceImpl implements AiImageService { // 发送 ImageGeneration imageGeneration = imageResponse.getResult(); // 发送信息 - sendSseEmitter(sseEmitter, imageGeneration); +// sendSseEmitter(sseEmitter, imageGeneration); // 保存数据库 doSave(req.getPrompt(), req.getSize(), req.getModal(), imageGeneration.getOutput().getUrl(), AiChatDrawingStatusEnum.COMPLETE, null); @@ -88,7 +84,7 @@ public class AiImageServiceImpl implements AiImageService { doSave(req.getPrompt(), req.getSize(), req.getModal(), null, AiChatDrawingStatusEnum.FAIL, aiException.getMessage()); // 发送错误信息 - sendSseEmitter(sseEmitter, aiException.getMessage()); +// sendSseEmitter(sseEmitter, aiException.getMessage()); } } @@ -105,16 +101,16 @@ public class AiImageServiceImpl implements AiImageService { } } - private static void sendSseEmitter(Utf8SseEmitter sseEmitter, Object object) { - try { - sseEmitter.send(object, MediaType.APPLICATION_JSON); - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - // 发送 complete - sseEmitter.complete(); - } - } +// private static void sendSseEmitter(Utf8SseEmitter sseEmitter, Object object) { +// try { +// sseEmitter.send(object, MediaType.APPLICATION_JSON); +// } catch (IOException e) { +// throw new RuntimeException(e); +// } finally { +// // 发送 complete +// sseEmitter.complete(); +// } +// } private AiImageDO doSave(String prompt, String size, diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index dd191ce9a..135b3df81 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -2,7 +2,6 @@ server: port: 48080 --- #################### 数据库相关配置 #################### - spring: # 数据源配置项 autoconfigure: @@ -79,7 +78,12 @@ spring: port: 6379 # 端口 database: 0 # 数据库索引 # password: dev # 密码,建议生产环境开启 - +server: + servlet: + encoding: + enabled: true + charset: UTF-8 + force: true --- #################### 定时任务相关配置 #################### # Quartz 配置项,对应 QuartzProperties 配置类 From 6e3f34b0dbfc57d448c535d05fb12857e94dcc74 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 18:00:30 +0800 Subject: [PATCH 241/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E9=87=8D=E6=96=B0=E9=80=82=E9=85=8D=20dall2=E5=92=8Cdall3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/image/AiImageController.java | 14 +++--- ...gReq.java => AiImageDallDrawingReqVO.java} | 4 +- .../image/vo/AiImageDallDrawingRespVO.java | 45 +++++++++++++++++++ .../module/ai/convert/AiImageConvert.java | 27 +++++++++++ .../module/ai/service/AiImageService.java | 5 ++- .../ai/service/impl/AiImageServiceImpl.java | 30 ++++++++----- .../src/main/resources/http/image.http | 2 +- 7 files changed, 104 insertions(+), 23 deletions(-) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/{AiImageDallDrawingReq.java => AiImageDallDrawingReqVO.java} (88%) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallDrawingRespVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index 274391777..982d43080 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -1,7 +1,8 @@ package cn.iocoder.yudao.module.ai.controller.admin.image; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReq; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingRespVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReq; import cn.iocoder.yudao.module.ai.service.AiImageService; import io.swagger.v3.oas.annotations.Operation; @@ -14,6 +15,8 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + // TODO @芋艿:整理接口定义 /** * ai作图 @@ -33,17 +36,14 @@ public class AiImageController { @Operation(summary = "dall2/dall3绘画", description = "openAi dall3是付费的!") @PostMapping("/dallDrawing") - public void dallDrawing(@Validated @RequestBody AiImageDallDrawingReq req) { -// Utf8SseEmitter sseEmitter = new Utf8SseEmitter(); -// aiImageService.dallDrawing(req, sseEmitter); -// return sseEmitter; - + public AiImageDallDrawingRespVO dallDrawing(@Validated @RequestBody AiImageDallDrawingReqVO req) { + return aiImageService.dallDrawing(req); } @Operation(summary = "midjourney", description = "midjourney图片绘画流程:1、提交任务 2、获取完成的任务 3、选择对应功能 4、获取最终结果") @PostMapping("/midjourney") public CommonResult midjourney(@Validated @RequestBody AiImageMidjourneyReq req) { aiImageService.midjourney(req); - return CommonResult.success(null); + return success(null); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallDrawingReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallDrawingReqVO.java similarity index 88% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallDrawingReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallDrawingReqVO.java index 42887b7d3..3973eb2e9 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallDrawingReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallDrawingReqVO.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.controller.admin.image.vo; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; import lombok.Data; import lombok.experimental.Accessors; @@ -14,10 +15,11 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class AiImageDallDrawingReq { +public class AiImageDallDrawingReqVO { @Schema(description = "提示词") @NotNull(message = "提示词不能为空!") + @Size(max = 1200, message = "提示词最大1200") private String prompt; @Schema(description = "模型") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallDrawingRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallDrawingRespVO.java new file mode 100644 index 000000000..7e480a8f0 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallDrawingRespVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.ai.controller.admin.image.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * dall2/dall2 绘画 + * + * @author fansili + * @time 2024/4/25 16:24 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class AiImageDallDrawingRespVO { + + + @Schema(description = "提示词") + @NotNull(message = "提示词不能为空!") + @Size(max = 1200, message = "提示词最大1200") + private String prompt; + + @Schema(description = "模型") + @NotNull(message = "模型不能为空") + private String modal; + + @Schema(description = "风格") + private String style; + + @Schema(description = "图片size 1024x1024 ...") + private String size; + + @Schema(description = "可以访问图像的URL。") + private String url; + + @Schema(description = "图片base64。") + private String base64; + + @Schema(description = "错误信息。") + private String errorMessage; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java new file mode 100644 index 000000000..5f2d18564 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.ai.convert; + +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingRespVO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * ai image convert + * + * @author fansili + * @time 2024/4/18 16:39 + * @since 1.0 + */ +@Mapper +public interface AiImageConvert { + + AiImageConvert INSTANCE = Mappers.getMapper(AiImageConvert.class); + + /** + * 转换 - AiImageDallDrawingRespVO + * + * @param req + * @return + */ + AiImageDallDrawingRespVO convertAiImageDallDrawingRespVO(AiImageDallDrawingReqVO req); +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java index cf95483d2..04768757a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.ai.service; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReq; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingRespVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReq; /** @@ -17,7 +18,7 @@ public interface AiImageService { * * @param req */ - void dallDrawing(AiImageDallDrawingReq req); + AiImageDallDrawingRespVO dallDrawing(AiImageDallDrawingReqVO req); /** * midjourney 图片生成 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java index 5bacf9da5..90aaf0322 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java @@ -14,8 +14,10 @@ import cn.iocoder.yudao.framework.ai.midjourney.webSocket.WssNotify; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReq; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingRespVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReq; +import cn.iocoder.yudao.module.ai.convert.AiImageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiImageMapper; import cn.iocoder.yudao.module.ai.enums.AiChatDrawingStatusEnum; @@ -60,31 +62,35 @@ public class AiImageServiceImpl implements AiImageService { } @Override - public void dallDrawing(AiImageDallDrawingReq req) { + public AiImageDallDrawingRespVO dallDrawing(AiImageDallDrawingReqVO req) { // 获取 model OpenAiImageModelEnum openAiImageModelEnum = OpenAiImageModelEnum.valueOfModel(req.getModal()); OpenAiImageStyleEnum openAiImageStyleEnum = OpenAiImageStyleEnum.valueOfStyle(req.getStyle()); - // - OpenAiImageOptions openAiImageOptions = new OpenAiImageOptions(); - openAiImageOptions.setModel(openAiImageModelEnum); - openAiImageOptions.setStyle(openAiImageStyleEnum); - openAiImageOptions.setSize(req.getSize()); - ImageResponse imageResponse; + // 转换 AiImageDallDrawingRespVO + AiImageDallDrawingRespVO respVO = AiImageConvert.INSTANCE.convertAiImageDallDrawingRespVO(req); try { - imageResponse = openAiImageClient.call(new ImagePrompt(req.getPrompt(), openAiImageOptions)); + // 转换openai 参数 + OpenAiImageOptions openAiImageOptions = new OpenAiImageOptions(); + openAiImageOptions.setModel(openAiImageModelEnum); + openAiImageOptions.setStyle(openAiImageStyleEnum); + openAiImageOptions.setSize(req.getSize()); + ImageResponse imageResponse = openAiImageClient.call(new ImagePrompt(req.getPrompt(), openAiImageOptions)); // 发送 ImageGeneration imageGeneration = imageResponse.getResult(); - // 发送信息 -// sendSseEmitter(sseEmitter, imageGeneration); // 保存数据库 doSave(req.getPrompt(), req.getSize(), req.getModal(), imageGeneration.getOutput().getUrl(), AiChatDrawingStatusEnum.COMPLETE, null); + // 返回 flex + respVO.setUrl(imageGeneration.getOutput().getUrl()); + respVO.setBase64(imageGeneration.getOutput().getB64Json()); + return respVO; } catch (AiException aiException) { // 保存数据库 doSave(req.getPrompt(), req.getSize(), req.getModal(), null, AiChatDrawingStatusEnum.FAIL, aiException.getMessage()); // 发送错误信息 -// sendSseEmitter(sseEmitter, aiException.getMessage()); + respVO.setErrorMessage(aiException.getMessage()); + return respVO; } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http index a5282df16..dda3f04f9 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http @@ -1,7 +1,7 @@ ### chat dallDrawing -POST {{baseUrl}}/ai/image/dallDrawing +POST {{baseUrl}}/admin-api/ai/image/dallDrawing Content-Type: application/json Authorization: {{token}} From 1a7446b914d6a32dfc241ba641732f35bbe06558 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 7 May 2024 18:17:17 +0800 Subject: [PATCH 242/684] =?UTF-8?q?=E3=80=90=E5=AE=9A=E4=B9=89=E3=80=91?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=20midjourney=20=E7=9B=B8=E5=85=B3=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E6=93=8D=E4=BD=9Capi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/image/AiImageController.java | 35 +++++++++++++++---- ...q.java => AiImageMidjourneyListReqVO.java} | 6 ++-- .../image/vo/AiImageMidjourneyListRespVO.java | 18 ++++++++++ .../image/vo/AiImageMidjourneyReqVO.java | 29 +++++++++++++++ .../module/ai/service/AiImageService.java | 4 +-- .../ai/service/impl/AiImageServiceImpl.java | 4 +-- 6 files changed, 81 insertions(+), 15 deletions(-) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/{AiImageMidjourneyReq.java => AiImageMidjourneyListReqVO.java} (71%) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyListRespVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyReqVO.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index 982d43080..c4d6aa816 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -3,17 +3,14 @@ package cn.iocoder.yudao.module.ai.controller.admin.image; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReq; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReqVO; import cn.iocoder.yudao.module.ai.service.AiImageService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -40,10 +37,34 @@ public class AiImageController { return aiImageService.dallDrawing(req); } - @Operation(summary = "midjourney", description = "midjourney图片绘画流程:1、提交任务 2、获取完成的任务 3、选择对应功能 4、获取最终结果") + @Operation(summary = "midjourney绘画", description = "midjourney图片绘画流程:1、提交任务 2、获取完成的任务 3、选择对应功能 4、获取最终结果") @PostMapping("/midjourney") - public CommonResult midjourney(@Validated @RequestBody AiImageMidjourneyReq req) { + public CommonResult midjourney(@Validated @RequestBody AiImageMidjourneyReqVO req) { aiImageService.midjourney(req); return success(null); } + + @Operation(summary = "midjourney绘画操作", description = "一般有选择图片、放大、换一批...") + @PostMapping("/midjourney-operate") + public CommonResult midjourneyOperate(@Validated @RequestBody AiImageMidjourneyReqVO req) { + return success(null); + } + + @Operation(summary = "获取midjourney绘画列表", description = "获取 Midjourney 绘画列表") + @GetMapping("/get-midjourney-list") + public CommonResult getMidjourneyList(@Validated @RequestBody AiImageMidjourneyReqVO req) { + return success(null); + } + + @Operation(summary = "取消 midjourney 绘画", description = "取消 midjourney 绘画") + @PostMapping("/cancel-midjourney") + public CommonResult cancelMidjourney(@RequestParam("id") Long id) { + return success(null); + } + + @Operation(summary = "删除绘画记录", description = "") + @DeleteMapping("/delete") + public CommonResult delete(@RequestParam("id") Long id) { + return success(null); + } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyReq.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyListReqVO.java similarity index 71% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyReq.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyListReqVO.java index a4bb622ac..6328c46fe 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyReq.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyListReqVO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.ai.controller.admin.image.vo; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; @@ -13,9 +14,6 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class AiImageMidjourneyReq { - - @Schema(description = "提示词") - private String prompt; +public class AiImageMidjourneyListReqVO extends PageParam { } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyListRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyListRespVO.java new file mode 100644 index 000000000..27269a2af --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyListRespVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.ai.controller.admin.image.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * midjourney req + * + * @author fansili + * @time 2024/4/28 17:42 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class AiImageMidjourneyListRespVO extends PageParam { + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyReqVO.java new file mode 100644 index 000000000..e6cb0dcec --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyReqVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.ai.controller.admin.image.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * midjourney req + * + * @author fansili + * @time 2024/4/28 17:42 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class AiImageMidjourneyReqVO { + + @Schema(description = "提示词") + private String prompt; + + @Schema(description = "绘画比例 1:1、3:4、4:3、9:16、16:9") + private String size; + + @Schema(description = "风格") + private String style; + + @Schema(description = "参考图") + private String referImage; +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java index 04768757a..d9ef9758d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.ai.service; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReq; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReqVO; /** * ai 作图 @@ -26,5 +26,5 @@ public interface AiImageService { * @param req * @return */ - void midjourney(AiImageMidjourneyReq req); + void midjourney(AiImageMidjourneyReqVO req); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java index 90aaf0322..49a257073 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java @@ -16,7 +16,7 @@ import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReq; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReqVO; import cn.iocoder.yudao.module.ai.convert.AiImageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiImageMapper; @@ -96,7 +96,7 @@ public class AiImageServiceImpl implements AiImageService { @Override @Transactional(rollbackFor = Exception.class) - public void midjourney(AiImageMidjourneyReq req) { + public void midjourney(AiImageMidjourneyReqVO req) { // 保存数据库 AiImageDO aiImageDO = doSave(req.getPrompt(), null, "midjoureny", null, AiChatDrawingStatusEnum.SUBMIT, null); From 52c86cd290d22bea92dcddf9ea6569b5c6c9d056 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 7 May 2024 23:08:38 +0800 Subject: [PATCH 243/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91CRM?= =?UTF-8?q?=EF=BC=9A=E5=91=98=E5=B7=A5=E4=B8=9A=E7=BB=A9=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 4 +- .../CrmStatisticsPerformanceServiceImpl.java | 91 ++++++------------- yudao-server/pom.xml | 20 ++-- 3 files changed, 38 insertions(+), 77 deletions(-) diff --git a/pom.xml b/pom.xml index e770c0359..b1bc573e8 100644 --- a/pom.xml +++ b/pom.xml @@ -16,12 +16,12 @@ yudao-module-system yudao-module-infra - + yudao-module-bpm - + yudao-module-crm diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java index 6679a4500..77b14a268 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.crm.service.statistics; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; -import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceReqVO; import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceRespVO; @@ -11,16 +11,19 @@ import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; - import java.math.BigDecimal; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; import java.util.function.Function; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; /** * CRM 员工业绩分析 Service 实现类 @@ -56,9 +59,11 @@ public class CrmStatisticsPerformanceServiceImpl implements CrmStatisticsPerform } /** - * 获得员工业绩数据,并通过如下方法拿到对应的lastYearCount,lastMonthCount - * 比如说,构造2024 年的CrmStatisticsPerformanceRespVO,获得 2023-01 到 2024-12的月统计数据即可 - * 可以数据 group by 年-月,2023-01 到 2024-12的,然后聚合出 CrmStatisticsPerformanceRespVO + * 获得员工业绩数据 + * + * 1. 获得今年 + 去年的数据 + * 2. 遍历今年的月份,逐个拼接去年的月份数据 + * * @param performanceReqVO 参数 * @param performanceFunction 员工业绩统计方法 * @return 员工业绩数据 @@ -67,7 +72,7 @@ public class CrmStatisticsPerformanceServiceImpl implements CrmStatisticsPerform Function> performanceFunction) { // 1. 获得用户编号数组 - final List userIds = getUserIds(performanceReqVO); + List userIds = getUserIds(performanceReqVO); if (CollUtil.isEmpty(userIds)) { return Collections.emptyList(); } @@ -75,66 +80,22 @@ public class CrmStatisticsPerformanceServiceImpl implements CrmStatisticsPerform // 2. 获得业绩数据 List performanceList = performanceFunction.apply(performanceReqVO); + Map performanceMap = convertMap(performanceList, CrmStatisticsPerformanceRespVO::getTime, + CrmStatisticsPerformanceRespVO::getCurrentMonthCount); - // 获取查询的年份 - String currentYear = LocalDateTimeUtil.format(performanceReqVO.getTimes()[0],"yyyy"); - Map currentYearMap = new TreeMap<>();//查询当年的map数据 - Map lastYearMap = new TreeMap<>();//前一年的map数据 - + // 3. 组装数据返回 + List result = new ArrayList<>(); + int year = DateUtil.thisYear(); for (int month = 1; month <= 12; month++) { - //根据数据库的月销售数据查询结果,构造查询当年的map数据 - String currentYearKey = String.format("%d%02d", Integer.parseInt(currentYear), month); - buildYearMapData(performanceList, currentYearMap, currentYearKey); - - //根据数据库的月销售数据查询结果,构造查询前一年的map数据 - String lastYearKey = String.format("%d%02d", Integer.parseInt(currentYear)-1, month); - buildYearMapData(performanceList, lastYearMap, lastYearKey); - } - //根据构造好的map数据,计算查询当年的环比和同比数据,并构造好返回的respVOList - List respVOList = new ArrayList<>(); - for (int key : currentYearMap.keySet()) { - BigDecimal lastYearCount = lastYearMap.get(key-100).getCurrentMonthCount(); - BigDecimal lastMonthCount; - if (key % 100 > 1) {//2-12月份的前一个月数据 - lastMonthCount = currentYearMap.get(key-1).getCurrentMonthCount(); - } else {//1月份的前一个月数据 - lastMonthCount = lastYearMap.get(key-89).getCurrentMonthCount(); - } - - currentYearMap.get(key).setLastYearCount(lastYearCount); - currentYearMap.get(key).setLastMonthCount(lastMonthCount); - - respVOList.add(currentYearMap.get(key)); - } - - return respVOList; - } - - /** - * 根据mapKey,添加当年和前一年的月销售记录到对应的map结构中 - * @param performanceList 数据库中查询到的月销售记录 - * @param YearDataMap 将查询到的月销售记录put到对应的map中,如果月销售记录为null,置为0 - * @param mapKey 对应的mapKey - */ - private void buildYearMapData(List performanceList, - Map YearDataMap, - String mapKey) - { - CrmStatisticsPerformanceRespVO currentYearData = performanceList.stream() - .filter(data -> data.getTime().equals(mapKey)) - .findFirst() - .orElse(null); - - if(currentYearData != null) { - YearDataMap.put(Integer.parseInt(mapKey), currentYearData); - } else { - CrmStatisticsPerformanceRespVO defaultVO = new CrmStatisticsPerformanceRespVO(); - defaultVO.setTime(mapKey); - defaultVO.setCurrentMonthCount(BigDecimal.ZERO); - defaultVO.setLastMonthCount(BigDecimal.ZERO); - defaultVO.setLastYearCount(BigDecimal.ZERO); - YearDataMap.put(Integer.parseInt(mapKey), defaultVO); + String currentMonth = String.format("%d%02d", year, month); + String lastMonth = month == 1 ? String.format("%d%02d", year - 1, 12) : String.format("%d%02d", year, month - 1); + String lastYear = String.format("%d%02d", year - 1, month); + result.add(new CrmStatisticsPerformanceRespVO().setTime(currentMonth) + .setCurrentMonthCount(performanceMap.getOrDefault(currentMonth, BigDecimal.ZERO)) + .setLastMonthCount(performanceMap.getOrDefault(lastMonth, BigDecimal.ZERO)) + .setLastYearCount(performanceMap.getOrDefault(lastYear, BigDecimal.ZERO))); } + return result; } /** diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index bc850b590..ade54c068 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -46,11 +46,11 @@ - - - - - + + cn.iocoder.boot + yudao-module-bpm-biz + ${revision} + @@ -88,11 +88,11 @@ - - - - - + + cn.iocoder.boot + yudao-module-crm-biz + ${revision} + From e8cf40a82a0db2b136fd481971b719415442dfd3 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 8 May 2024 15:07:49 +0800 Subject: [PATCH 244/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=911?= =?UTF-8?q?=E3=80=81mj=20components=20=E7=9B=B8=E5=85=B3=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E6=8F=90=E4=BA=A4=202=E3=80=81=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0ai=20image=20=E5=88=97=E8=A1=A8=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/ErrorCodeConstants.java | 9 +- ...num.java => AiImageDrawingStatusEnum.java} | 6 +- .../admin/image/AiImageController.java | 20 +-- ...yListRespVO.java => AiImageListReqVO.java} | 2 +- ...yListReqVO.java => AiImageListRespVO.java} | 3 +- .../vo/AiImageMidjourneyOperateReqVO.java | 31 +++++ .../vo/AiImageMidjourneyOperationsVO.java | 30 ++++ .../module/ai/convert/AiImageConvert.java | 12 ++ .../ai/dal/dataobject/image/AiImageDO.java | 23 +++- .../module/ai/service/AiImageService.java | 23 +++- .../ai/service/impl/AiImageServiceImpl.java | 128 ++++++++++++++---- .../YuDaoMidjourneyMessageHandler.java | 10 +- 12 files changed, 240 insertions(+), 57 deletions(-) rename yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/{AiChatDrawingStatusEnum.java => AiImageDrawingStatusEnum.java} (76%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/{AiImageMidjourneyListRespVO.java => AiImageListReqVO.java} (83%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/{AiImageMidjourneyListReqVO.java => AiImageListRespVO.java} (72%) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyOperateReqVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyOperationsVO.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index cf5d6e76e..fde06746e 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -14,29 +14,26 @@ public interface ErrorCodeConstants { // chat ErrorCode AI_MODULE_NOT_SUPPORTED = new ErrorCode(1_022_000_000, "AI 模型暂不支持!"); - ErrorCode AI_CHAT_ROLE_NOT_EXISTENT = new ErrorCode(1_022_000_001, "AI Role 不存在!");; // conversation ErrorCode AI_CONVERSATION_NOT_EXISTS = new ErrorCode(1_022_000_002, "AI 对话不存在!");; - ErrorCode AI_CHAT_CONTINUE_CONVERSATION_ID_NOT_NULL = new ErrorCode(1_022_000_002, "chat 继续对话,对话 id 不能为空!");; - ErrorCode AI_CHAT_CONTINUE_NOT_EXIST = new ErrorCode(1_022_000_020, "chat 对话不存在!"); - ErrorCode AI_CHAT_CONVERSATION_NOT_YOURS = new ErrorCode(1_022_000_021, "这条 chat 对话不是你的!"); // midjourney ErrorCode AI_MIDJOURNEY_IMAGINE_FAIL = new ErrorCode(1_022_000_040, "midjourney imagine 操作失败!"); + ErrorCode AI_MIDJOURNEY_OPERATION_NOT_EXISTS = new ErrorCode(1_022_000_040, "midjourney 操作不存在!"); + ErrorCode AI_MIDJOURNEY_MESSAGE_ID_INCORRECT = new ErrorCode(1_022_000_040, "midjourney message id 不正确!"); // role - ErrorCode AI_CHAT_ROLE_NOT_EXIST = new ErrorCode(1_022_000_060, "chatRole 不存在!"); + ErrorCode AI_CHAT_ROLE_NOT_EXIST = new ErrorCode(1_022_000_060, "AI 角色不存在!"); ErrorCode AI_CHAT_ROLE_NOT_PUBLIC = new ErrorCode(1_022_000_060, "AI 角色未公开!"); // modal ErrorCode AI_MODAL_NOT_EXIST = new ErrorCode(1_022_000_080, "AI 模型不存在!"); ErrorCode AI_MODAL_CONFIG_PARAMS_INCORRECT = new ErrorCode(1_022_000_081, "AI 模型 config 参数不正确! {} "); - ErrorCode AI_MODAL_NOT_SUPPORTED_MODAL = new ErrorCode(1_022_000_082, "AI 模型不支持的 modal! {} "); ErrorCode AI_MODAL_PLATFORM_PARAMS_INCORRECT = new ErrorCode(1_022_000_083, "AI 平台参数不正确! {} "); ErrorCode AI_MODAL_DISABLE_NOT_USED = new ErrorCode(1_022_000_084, "AI 模型禁用不能使用!"); diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatDrawingStatusEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageDrawingStatusEnum.java similarity index 76% rename from yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatDrawingStatusEnum.java rename to yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageDrawingStatusEnum.java index 2fcd90ee4..c38b17756 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatDrawingStatusEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageDrawingStatusEnum.java @@ -12,7 +12,7 @@ import lombok.Getter; */ @AllArgsConstructor @Getter -public enum AiChatDrawingStatusEnum { +public enum AiImageDrawingStatusEnum { SUBMIT("submit", "提交任务"), WAITING("waiting", "等待"), @@ -27,8 +27,8 @@ public enum AiChatDrawingStatusEnum { private String name; - public static AiChatDrawingStatusEnum valueOfStatus(String status) { - for (AiChatDrawingStatusEnum itemEnum : AiChatDrawingStatusEnum.values()) { + public static AiImageDrawingStatusEnum valueOfStatus(String status) { + for (AiImageDrawingStatusEnum itemEnum : AiImageDrawingStatusEnum.values()) { if (itemEnum.getStatus().equals(status)) { return itemEnum; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index c4d6aa816..7f0620ab2 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -1,9 +1,8 @@ package cn.iocoder.yudao.module.ai.controller.admin.image; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReqVO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; import cn.iocoder.yudao.module.ai.service.AiImageService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -31,6 +30,12 @@ public class AiImageController { private final AiImageService aiImageService; + @Operation(summary = "获取image列表", description = "dall3、midjourney") + @GetMapping("/list") + public PageResult list(@Validated @RequestBody AiImageListReqVO req) { + return aiImageService.list(req); + } + @Operation(summary = "dall2/dall3绘画", description = "openAi dall3是付费的!") @PostMapping("/dallDrawing") public AiImageDallDrawingRespVO dallDrawing(@Validated @RequestBody AiImageDallDrawingReqVO req) { @@ -46,13 +51,8 @@ public class AiImageController { @Operation(summary = "midjourney绘画操作", description = "一般有选择图片、放大、换一批...") @PostMapping("/midjourney-operate") - public CommonResult midjourneyOperate(@Validated @RequestBody AiImageMidjourneyReqVO req) { - return success(null); - } - - @Operation(summary = "获取midjourney绘画列表", description = "获取 Midjourney 绘画列表") - @GetMapping("/get-midjourney-list") - public CommonResult getMidjourneyList(@Validated @RequestBody AiImageMidjourneyReqVO req) { + public CommonResult midjourneyOperate(@Validated @RequestBody AiImageMidjourneyOperateReqVO req) { + aiImageService.midjourneyOperate(req); return success(null); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyListRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListReqVO.java similarity index 83% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyListRespVO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListReqVO.java index 27269a2af..e75ebb4b3 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyListRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListReqVO.java @@ -13,6 +13,6 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class AiImageMidjourneyListRespVO extends PageParam { +public class AiImageListReqVO extends PageParam { } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyListReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java similarity index 72% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyListReqVO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java index 6328c46fe..9222a4ec4 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyListReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.ai.controller.admin.image.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; @@ -14,6 +13,6 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class AiImageMidjourneyListReqVO extends PageParam { +public class AiImageListRespVO extends PageParam { } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyOperateReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyOperateReqVO.java new file mode 100644 index 000000000..b49530425 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyOperateReqVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.ai.controller.admin.image.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * midjourney req + * + * @author fansili + * @time 2024/4/28 17:42 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class AiImageMidjourneyOperateReqVO { + + + @NotNull(message = "图片编号不能为空") + @Schema(description = "编号") + private String id; + + @NotNull(message = "消息编号不能为空") + @Schema(description = "消息编号") + private String messageId; + + @NotNull(message = "操作编号不能为空") + @Schema(description = "操作编号") + private String operateId; +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyOperationsVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyOperationsVO.java new file mode 100644 index 000000000..fe202d83d --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyOperationsVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.ai.controller.admin.image.vo; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * mj 保存 components 记录 + * + * "components": [ + * { + * "custom_id": "MJ::JOB::upsample::1::5d32f4e8-8d2f-4bef-82d8-bf517e3c3660", + * "style": 2, + * "label": "U1", + * "type": 2 + * }, + * ] + * + * @author fansili + * @time 2024/5/8 14:44 + * @since 1.0 + */ +@Data +@Accessors(chain = true) +public class AiImageMidjourneyOperationsVO { + + private String custom_id; + private String style; + private String label; + private String type; +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java index 5f2d18564..089af76b5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java @@ -2,9 +2,13 @@ package cn.iocoder.yudao.module.ai.convert; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageListRespVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; +import java.util.List; + /** * ai image convert * @@ -24,4 +28,12 @@ public interface AiImageConvert { * @return */ AiImageDallDrawingRespVO convertAiImageDallDrawingRespVO(AiImageDallDrawingReqVO req); + + /** + * 转换 - AiImageListRespVO + * + * @param list + * @return + */ + List convertAiImageListRespVO(List list); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java index 190810095..ea83d2181 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java @@ -29,20 +29,37 @@ public class AiImageDO extends BaseDO { @Schema(description = "提示词") private String prompt; - @Schema(description = "模型") + @Schema(description = "模型 dall2/dall3、MJ、NIJI") private String modal; @Schema(description = "生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。") private String size; + @Schema(description = "图片地址(自己服务器)") + private String imageUrl; + @Schema(description = "绘画状态:提交、排队、绘画中、绘画完成、绘画失败") private String drawingStatus; - @Schema(description = "绘画图片地址") + @Schema(description = "绘画图片地址(绘画好的服务器)") private String drawingImageUrl; @Schema(description = "绘画错误信息") - private String drawingError; + private String drawingErrorMessage; + + // ============ mj 需要字段 + + @Schema(description = "用户操作的消息编号(MJ返回)") + private String mjMessageId; + + @Schema(description = "用户操作的操作编号(MJ返回)") + private String mjOperationId; + + @Schema(description = "用户操作的操作名字(MJ返回)") + private String mjOperationName; + + @Schema(description = "mj图片生产成功保存的 components json 数组") + private String mjOperations; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java index d9ef9758d..33c4bf449 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java @@ -1,8 +1,9 @@ package cn.iocoder.yudao.module.ai.service; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReqVO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; + +import java.util.List; /** * ai 作图 @@ -13,6 +14,14 @@ import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReq */ public interface AiImageService { + /** + * ai绘画 - 列表 + * + * @param req + * @return + */ + PageResult list(AiImageListReqVO req); + /** * ai绘画 - dall2/dall3 绘画 * @@ -27,4 +36,12 @@ public interface AiImageService { * @return */ void midjourney(AiImageMidjourneyReqVO req); + + /** + * midjourney 操作(u1、u2、放大、换一批...) + * + * @param req + */ + void midjourneyOperate(AiImageMidjourneyOperateReqVO req); + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java index 49a257073..c3fb4454d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.ai.service.impl; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.exception.AiException; import cn.iocoder.yudao.framework.ai.image.ImageGeneration; import cn.iocoder.yudao.framework.ai.image.ImagePrompt; @@ -9,18 +10,20 @@ import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageOptions; import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageModelEnum; import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageStyleEnum; import cn.iocoder.yudao.framework.ai.midjourney.api.MidjourneyInteractionsApi; +import cn.iocoder.yudao.framework.ai.midjourney.api.req.ReRollReq; import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyWebSocketStarter; import cn.iocoder.yudao.framework.ai.midjourney.webSocket.WssNotify; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; import cn.iocoder.yudao.module.ai.convert.AiImageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiImageMapper; -import cn.iocoder.yudao.module.ai.enums.AiChatDrawingStatusEnum; +import cn.iocoder.yudao.module.ai.enums.AiImageDrawingStatusEnum; import cn.iocoder.yudao.module.ai.service.AiImageService; import jakarta.annotation.PostConstruct; import lombok.AllArgsConstructor; @@ -28,6 +31,9 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Collections; +import java.util.List; + /** * ai 作图 * @@ -61,6 +67,23 @@ public class AiImageServiceImpl implements AiImageService { }); } + @Override + public PageResult list(AiImageListReqVO req) { + // 获取登录用户 + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + // 查询当前用户下所有的绘画记录 + PageResult pageResult = aiImageMapper.selectPage(req, + new LambdaQueryWrapperX() + .eq(AiImageDO::getUserId, loginUserId) + .orderByDesc(AiImageDO::getId) + ); + // 转换 PageResult 返回 + PageResult result = new PageResult<>(); + result.setTotal(pageResult.getTotal()); + result.setList(AiImageConvert.INSTANCE.convertAiImageListRespVO(pageResult.getList())); + return result; + } + @Override public AiImageDallDrawingRespVO dallDrawing(AiImageDallDrawingReqVO req) { // 获取 model @@ -79,7 +102,8 @@ public class AiImageServiceImpl implements AiImageService { ImageGeneration imageGeneration = imageResponse.getResult(); // 保存数据库 doSave(req.getPrompt(), req.getSize(), req.getModal(), - imageGeneration.getOutput().getUrl(), AiChatDrawingStatusEnum.COMPLETE, null); + imageGeneration.getOutput().getUrl(), AiImageDrawingStatusEnum.COMPLETE, null, + null, null, null); // 返回 flex respVO.setUrl(imageGeneration.getOutput().getUrl()); respVO.setBase64(imageGeneration.getOutput().getB64Json()); @@ -87,7 +111,8 @@ public class AiImageServiceImpl implements AiImageService { } catch (AiException aiException) { // 保存数据库 doSave(req.getPrompt(), req.getSize(), req.getModal(), - null, AiChatDrawingStatusEnum.FAIL, aiException.getMessage()); + null, AiImageDrawingStatusEnum.FAIL, aiException.getMessage(), + null, null, null); // 发送错误信息 respVO.setErrorMessage(aiException.getMessage()); return respVO; @@ -99,7 +124,8 @@ public class AiImageServiceImpl implements AiImageService { public void midjourney(AiImageMidjourneyReqVO req) { // 保存数据库 AiImageDO aiImageDO = doSave(req.getPrompt(), null, "midjoureny", - null, AiChatDrawingStatusEnum.SUBMIT, null); + null, AiImageDrawingStatusEnum.SUBMIT, null, + null, null, null); // 提交 midjourney 任务 Boolean imagine = midjourneyInteractionsApi.imagine(aiImageDO.getId(), req.getPrompt()); if (!imagine) { @@ -107,23 +133,71 @@ public class AiImageServiceImpl implements AiImageService { } } -// private static void sendSseEmitter(Utf8SseEmitter sseEmitter, Object object) { -// try { -// sseEmitter.send(object, MediaType.APPLICATION_JSON); -// } catch (IOException e) { -// throw new RuntimeException(e); -// } finally { -// // 发送 complete -// sseEmitter.complete(); -// } -// } + @Transactional(rollbackFor = Exception.class) + @Override + public void midjourneyOperate(AiImageMidjourneyOperateReqVO req) { + // 校验是否存在 + AiImageDO aiImageDO = validateExists(req); + // 获取 midjourneyOperations + List midjourneyOperations = getMidjourneyOperations(aiImageDO); + // 校验 OperateId 是否存在 + AiImageMidjourneyOperationsVO midjourneyOperationsVO = validateMidjourneyOperationsExists(midjourneyOperations, req.getOperateId()); + // 校验 messageId + validateMessageId(aiImageDO.getMjMessageId(), req.getMessageId()); + // 获取 mjOperationName + String mjOperationName = midjourneyOperationsVO.getLabel(); + // 保存一个 image 任务记录 + doSave(aiImageDO.getPrompt(), aiImageDO.getSize(), aiImageDO.getModal(), + null, AiImageDrawingStatusEnum.SUBMIT, null, + req.getMessageId(), req.getOperateId(), mjOperationName); + // 提交操作 + midjourneyInteractionsApi.reRoll( + new ReRollReq() + .setCustomId(req.getOperateId()) + .setMessageId(req.getMessageId()) + ); + } + + private void validateMessageId(String mjMessageId, String messageId) { + if (!mjMessageId.equals(messageId)) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MIDJOURNEY_MESSAGE_ID_INCORRECT); + } + } + + private AiImageMidjourneyOperationsVO validateMidjourneyOperationsExists(List midjourneyOperations, String operateId) { + for (AiImageMidjourneyOperationsVO midjourneyOperation : midjourneyOperations) { + if (midjourneyOperation.getCustom_id().equals(operateId)) { + return midjourneyOperation; + } + } + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MIDJOURNEY_OPERATION_NOT_EXISTS); + } + + + private List getMidjourneyOperations(AiImageDO aiImageDO) { + if (StrUtil.isBlank(aiImageDO.getMjOperations())) { + return Collections.emptyList(); + } + return JsonUtils.parseArray(aiImageDO.getMjOperations(), AiImageMidjourneyOperationsVO.class); + } + + private AiImageDO validateExists(AiImageMidjourneyOperateReqVO req) { + AiImageDO aiImageDO = aiImageMapper.selectById(req.getId()); + if (aiImageDO == null) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MIDJOURNEY_IMAGINE_FAIL); + } + return aiImageDO; + } private AiImageDO doSave(String prompt, - String size, - String model, - String imageUrl, - AiChatDrawingStatusEnum drawingStatusEnum, - String drawingError) { + String size, + String model, + String drawingImageUrl, + AiImageDrawingStatusEnum drawingStatusEnum, + String drawingErrorMessage, + String mjMessageId, + String mjOperationId, + String mjOperationName) { // 保存数据库 Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); AiImageDO aiImageDO = new AiImageDO(); @@ -132,9 +206,15 @@ public class AiImageServiceImpl implements AiImageService { aiImageDO.setSize(size); aiImageDO.setModal(model); aiImageDO.setUserId(loginUserId); - aiImageDO.setDrawingImageUrl(imageUrl); + // TODO @芋艿 如何上传到自己服务器 + aiImageDO.setImageUrl(null); aiImageDO.setDrawingStatus(drawingStatusEnum.getStatus()); - aiImageDO.setDrawingError(drawingError); + aiImageDO.setDrawingImageUrl(drawingImageUrl); + aiImageDO.setDrawingErrorMessage(drawingErrorMessage); + // + aiImageDO.setMjMessageId(mjMessageId); + aiImageDO.setMjOperationId(mjOperationId); + aiImageDO.setMjOperationName(mjOperationName); aiImageMapper.insert(aiImageDO); return aiImageDO; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java index 0910b2946..3870ba0dc 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java @@ -6,7 +6,7 @@ import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyMessage; import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyGennerateStatusEnum; import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyMessageHandler; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; -import cn.iocoder.yudao.module.ai.enums.AiChatDrawingStatusEnum; +import cn.iocoder.yudao.module.ai.enums.AiImageDrawingStatusEnum; import cn.iocoder.yudao.module.ai.dal.mysql.AiImageMapper; import com.alibaba.fastjson2.JSON; import lombok.AllArgsConstructor; @@ -53,14 +53,14 @@ public class YuDaoMidjourneyMessageHandler implements MidjourneyMessageHandler { imageUrl = midjourneyMessage.getAttachments().get(0).getUrl(); } // 转换状态 - AiChatDrawingStatusEnum drawingStatusEnum = null; + AiImageDrawingStatusEnum drawingStatusEnum = null; String generateStatus = midjourneyMessage.getGenerateStatus(); if (MidjourneyGennerateStatusEnum.COMPLETED.getStatus().equals(generateStatus)) { - drawingStatusEnum = AiChatDrawingStatusEnum.COMPLETE; + drawingStatusEnum = AiImageDrawingStatusEnum.COMPLETE; } else if (MidjourneyGennerateStatusEnum.IN_PROGRESS.getStatus().equals(generateStatus)) { - drawingStatusEnum = AiChatDrawingStatusEnum.IN_PROGRESS; + drawingStatusEnum = AiImageDrawingStatusEnum.IN_PROGRESS; } else if (MidjourneyGennerateStatusEnum.WAITING.getStatus().equals(generateStatus)) { - drawingStatusEnum = AiChatDrawingStatusEnum.WAITING; + drawingStatusEnum = AiImageDrawingStatusEnum.WAITING; } aiImageMapper.updateById( new AiImageDO() From b6096b76d28d2d47596194b85c39835a822e40af Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 8 May 2024 15:10:57 +0800 Subject: [PATCH 245/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91ai?= =?UTF-8?q?=20image=20=E7=94=9F=E6=88=90=E8=AE=B0=E5=BD=95=E5=88=A0?= =?UTF-8?q?=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/admin/image/AiImageController.java | 2 ++ .../image/vo/AiImageMidjourneyOperateReqVO.java | 2 +- .../yudao/module/ai/service/AiImageService.java | 7 +++++++ .../module/ai/service/impl/AiImageServiceImpl.java | 14 +++++++++++--- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index 7f0620ab2..7df2592f9 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -59,12 +59,14 @@ public class AiImageController { @Operation(summary = "取消 midjourney 绘画", description = "取消 midjourney 绘画") @PostMapping("/cancel-midjourney") public CommonResult cancelMidjourney(@RequestParam("id") Long id) { + // @范 这里实现mj取消逻辑 return success(null); } @Operation(summary = "删除绘画记录", description = "") @DeleteMapping("/delete") public CommonResult delete(@RequestParam("id") Long id) { + aiImageService.delete(id); return success(null); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyOperateReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyOperateReqVO.java index b49530425..994c1c5f0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyOperateReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyOperateReqVO.java @@ -19,7 +19,7 @@ public class AiImageMidjourneyOperateReqVO { @NotNull(message = "图片编号不能为空") @Schema(description = "编号") - private String id; + private Long id; @NotNull(message = "消息编号不能为空") @Schema(description = "消息编号") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java index 33c4bf449..b58201056 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java @@ -44,4 +44,11 @@ public interface AiImageService { */ void midjourneyOperate(AiImageMidjourneyOperateReqVO req); + /** + * 删除 - image 记录 + * + * @param id + */ + void delete(Long id); + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java index c3fb4454d..e0d797d18 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java @@ -137,7 +137,7 @@ public class AiImageServiceImpl implements AiImageService { @Override public void midjourneyOperate(AiImageMidjourneyOperateReqVO req) { // 校验是否存在 - AiImageDO aiImageDO = validateExists(req); + AiImageDO aiImageDO = validateExists(req.getId()); // 获取 midjourneyOperations List midjourneyOperations = getMidjourneyOperations(aiImageDO); // 校验 OperateId 是否存在 @@ -158,6 +158,14 @@ public class AiImageServiceImpl implements AiImageService { ); } + @Override + public void delete(Long id) { + // 校验记录是否存在 + AiImageDO aiImageDO = validateExists(id); + // 删除记录 + aiImageMapper.deleteById(id); + } + private void validateMessageId(String mjMessageId, String messageId) { if (!mjMessageId.equals(messageId)) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MIDJOURNEY_MESSAGE_ID_INCORRECT); @@ -181,8 +189,8 @@ public class AiImageServiceImpl implements AiImageService { return JsonUtils.parseArray(aiImageDO.getMjOperations(), AiImageMidjourneyOperationsVO.class); } - private AiImageDO validateExists(AiImageMidjourneyOperateReqVO req) { - AiImageDO aiImageDO = aiImageMapper.selectById(req.getId()); + private AiImageDO validateExists(Long id) { + AiImageDO aiImageDO = aiImageMapper.selectById(id); if (aiImageDO == null) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MIDJOURNEY_IMAGINE_FAIL); } From 38a9c1a7ee0ddd718b25751fd27b1219d4e6bfd5 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 8 May 2024 15:58:03 +0800 Subject: [PATCH 246/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91mj?= =?UTF-8?q?=E5=9B=BE=E7=89=87=E5=A4=84=E7=90=86=E6=88=90=E5=8A=9F=E6=B6=88?= =?UTF-8?q?=E6=81=AF=EF=BC=8C=E5=A2=9E=E5=8A=A0component=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=EF=BC=8C=E5=A4=84=E7=90=86error=E4=BF=A1=E6=81=AF=E4=BF=9D?= =?UTF-8?q?=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/convert/AiImageConvert.java | 10 ++++ .../YuDaoMidjourneyMessageHandler.java | 59 ++++++++++++++++++- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java index 089af76b5..27bf11136 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java @@ -1,8 +1,10 @@ package cn.iocoder.yudao.module.ai.convert; +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyMessage; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingRespVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageListRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyOperationsVO; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -36,4 +38,12 @@ public interface AiImageConvert { * @return */ List convertAiImageListRespVO(List list); + + /** + * 转换 - AiImageMidjourneyOperationsVO + * + * @param component + * @return + */ + AiImageMidjourneyOperationsVO convertAiImageMidjourneyOperationsVO(MidjourneyMessage.Component component); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java index 3870ba0dc..43ca13b6a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java @@ -5,14 +5,21 @@ import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyMessage; import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyGennerateStatusEnum; import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyMessageHandler; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyOperationsVO; +import cn.iocoder.yudao.module.ai.convert.AiImageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; -import cn.iocoder.yudao.module.ai.enums.AiImageDrawingStatusEnum; import cn.iocoder.yudao.module.ai.dal.mysql.AiImageMapper; +import cn.iocoder.yudao.module.ai.enums.AiImageDrawingStatusEnum; import com.alibaba.fastjson2.JSON; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + /** * yudao message handler * @@ -45,6 +52,36 @@ public class YuDaoMidjourneyMessageHandler implements MidjourneyMessageHandler { if (StrUtil.isBlank(midjourneyMessage.getNonce())) { return; } + // 根据 Embeds 来判断是否异常 + if (CollUtil.isEmpty(midjourneyMessage.getEmbeds())) { + successHandler(midjourneyMessage); + } else { + errorHandler(midjourneyMessage); + } + } + + private void errorHandler(MidjourneyMessage midjourneyMessage) { + // image 编号 + Long aiImageId = Long.valueOf(midjourneyMessage.getNonce()); + // 获取 error message + String errorMessage = getErrorMessage(midjourneyMessage); + aiImageMapper.updateById( + new AiImageDO() + .setId(aiImageId) + .setDrawingErrorMessage(errorMessage) + .setDrawingStatus(AiImageDrawingStatusEnum.FAIL.getStatus()) + ); + } + + private String getErrorMessage(MidjourneyMessage midjourneyMessage) { + StringBuilder errorMessage = new StringBuilder(); + for (MidjourneyMessage.Embed embed : midjourneyMessage.getEmbeds()) { + errorMessage.append(embed.getDescription()); + } + return errorMessage.toString(); + } + + private void successHandler(MidjourneyMessage midjourneyMessage) { // 获取id Long aiImageId = Long.valueOf(midjourneyMessage.getNonce()); // 获取生成 url @@ -59,14 +96,32 @@ public class YuDaoMidjourneyMessageHandler implements MidjourneyMessageHandler { drawingStatusEnum = AiImageDrawingStatusEnum.COMPLETE; } else if (MidjourneyGennerateStatusEnum.IN_PROGRESS.getStatus().equals(generateStatus)) { drawingStatusEnum = AiImageDrawingStatusEnum.IN_PROGRESS; - } else if (MidjourneyGennerateStatusEnum.WAITING.getStatus().equals(generateStatus)) { + } else if (MidjourneyGennerateStatusEnum.WAITING.getStatus().equals(generateStatus)) { drawingStatusEnum = AiImageDrawingStatusEnum.WAITING; } + // 获取 midjourneyOperations + List midjourneyOperations = getMidjourneyOperationsList(midjourneyMessage); + // 更新数据库 aiImageMapper.updateById( new AiImageDO() .setId(aiImageId) .setDrawingImageUrl(imageUrl) .setDrawingStatus(drawingStatusEnum == null ? null : drawingStatusEnum.getStatus()) + .setMjMessageId(midjourneyMessage.getId()) + .setMjOperations(JsonUtils.toJsonString(midjourneyOperations)) ); } + + private List getMidjourneyOperationsList(MidjourneyMessage midjourneyMessage) { + // 为空直接返回 + if (CollUtil.isEmpty(midjourneyMessage.getComponents())) { + return Collections.emptyList(); + } + // 将 component 转成 AiImageMidjourneyOperationsVO + return midjourneyMessage.getComponents().stream() + .map(componentType -> componentType.getComponents().stream() + .map(AiImageConvert.INSTANCE::convertAiImageMidjourneyOperationsVO) + .collect(Collectors.toList())) + .toList().stream().flatMap(List::stream).toList(); + } } From b058090a77d16054a947c7ade975da9d6d9d7b3a Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 8 May 2024 18:11:18 +0800 Subject: [PATCH 247/684] =?UTF-8?q?=E3=80=90=E6=9B=B4=E6=96=B0=E3=80=91?= =?UTF-8?q?=E6=9B=B4=E6=96=B0sql=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/chat.sql | 159 ++++++++++-------- 1 file changed, 90 insertions(+), 69 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/chat.sql b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/chat.sql index 6fd87f4f4..a845056d7 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/chat.sql +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/chat.sql @@ -11,7 +11,7 @@ Target Server Version : 80034 (8.0.34) File Encoding : 65001 - Date: 28/04/2024 11:50:47 + Date: 08/05/2024 18:10:05 */ SET NAMES utf8mb4; @@ -24,24 +24,31 @@ DROP TABLE IF EXISTS `ai_chat_conversation`; CREATE TABLE `ai_chat_conversation` ( `id` bigint NOT NULL AUTO_INCREMENT, `user_id` bigint DEFAULT NULL COMMENT '用户id', - `chat_role_id` bigint DEFAULT NULL COMMENT '聊天角色', - `chat_role_name` varchar(128) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '聊天角色名称', + `role_id` bigint DEFAULT NULL COMMENT '聊天角色', `title` varchar(256) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '标题', `type` varchar(16) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '对话类型', `chat_count` int DEFAULT NULL COMMENT '聊天次数', + `model_id` bigint DEFAULT NULL COMMENT '模型id', + `model` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '模型', + `pinned` blob COMMENT '是否置顶', + `temperature` double DEFAULT NULL COMMENT '温度参数', + `max_tokens` int DEFAULT NULL COMMENT '单条回复的最大 Token 数量', + `max_contexts` int DEFAULT NULL COMMENT '上下文的最大 Message 数量', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_time` datetime DEFAULT NULL COMMENT '更新时间', `creator` bigint DEFAULT NULL COMMENT '创建用户', `updater` bigint DEFAULT NULL COMMENT '更新用户', `deleted` bit(1) DEFAULT b'0' COMMENT '删除', PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=1781604279872581645 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; +) ENGINE=InnoDB AUTO_INCREMENT=1781604279872581650 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; -- ---------------------------- -- Records of ai_chat_conversation -- ---------------------------- BEGIN; -INSERT INTO `ai_chat_conversation` (`id`, `user_id`, `chat_role_id`, `chat_role_name`, `title`, `type`, `chat_count`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (1781604279872581644, 1, NULL, NULL, '中国好看吗?', 'userChat', 32, '2024-04-20 16:59:32', '2024-04-20 16:59:32', 1, 1, b'0'); +INSERT INTO `ai_chat_conversation` (`id`, `user_id`, `role_id`, `title`, `type`, `chat_count`, `model_id`, `model`, `pinned`, `temperature`, `max_tokens`, `max_contexts`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (1781604279872581647, 1, NULL, '新增对话', NULL, NULL, 9, 'ERNIE-3.5-8K', 0x30, NULL, NULL, NULL, '2024-05-07 16:20:06', '2024-05-07 16:20:06', 1, 1, b'1'); +INSERT INTO `ai_chat_conversation` (`id`, `user_id`, `role_id`, `title`, `type`, `chat_count`, `model_id`, `model`, `pinned`, `temperature`, `max_tokens`, `max_contexts`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (1781604279872581648, 1, 9, '新增对话', NULL, NULL, 9, 'ERNIE-3.5-8K', 0x30, NULL, NULL, NULL, '2024-05-07 16:20:35', '2024-05-07 16:20:35', 1, 1, b'0'); +INSERT INTO `ai_chat_conversation` (`id`, `user_id`, `role_id`, `title`, `type`, `chat_count`, `model_id`, `model`, `pinned`, `temperature`, `max_tokens`, `max_contexts`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (1781604279872581649, 1, NULL, '新增对话', NULL, NULL, 9, 'ERNIE-3.5-8K', 0x30, NULL, NULL, NULL, '2024-05-07 16:22:37', '2024-05-07 16:22:37', 1, 1, b'0'); COMMIT; -- ---------------------------- @@ -50,83 +57,64 @@ COMMIT; DROP TABLE IF EXISTS `ai_chat_message`; CREATE TABLE `ai_chat_message` ( `id` bigint NOT NULL AUTO_INCREMENT, - `chat_conversation_id` bigint DEFAULT NULL COMMENT '对话id', + `conversation_id` bigint DEFAULT NULL COMMENT '对话id', `user_id` bigint DEFAULT NULL COMMENT '用户id', - `message` text COLLATE utf8mb4_0900_bin COMMENT '对话message', - `message_type` varchar(16) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '对话类型system、user、assistant\n', - `top_k` float DEFAULT NULL COMMENT '在生成消息时采用的Top-K采样大小', - `top_p` float DEFAULT NULL COMMENT 'Top-P核采样方法的概率阈值', - `temperature` float DEFAULT NULL COMMENT '用于调整生成回复的随机性和多样性程度', + `role_id` bigint DEFAULT NULL COMMENT '角色id', + `type` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '类型system、user、assistant\n', + `model` varchar(32) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '模型', + `model_id` bigint DEFAULT NULL COMMENT '模型id', + `content` varchar(2048) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '内容', + `tokens` int DEFAULT NULL COMMENT '消耗 Token 数量', + `temperature` double DEFAULT NULL COMMENT '用于调整生成回复的随机性和多样性程度', + `max_tokens` int DEFAULT NULL COMMENT '单条回复的最大 Token 数量', + `max_contexts` int DEFAULT NULL COMMENT '上下文的最大 Message 数量', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_time` datetime DEFAULT NULL COMMENT '更新时间', `creator` bigint DEFAULT NULL COMMENT '创建用户', `updater` bigint DEFAULT NULL COMMENT '更新用户', `deleted` bit(1) DEFAULT b'0' COMMENT '删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; +) ENGINE=InnoDB AUTO_INCREMENT=65 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; -- ---------------------------- -- Records of ai_chat_message -- ---------------------------- BEGIN; -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (1, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-20 18:22:41', '2024-04-20 18:22:41', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (2, 1781604279872581644, 1, '作为一个AI助手,我没有个人感受和偏好。但是,中国是一个拥有丰富历史、文化和自然景观的国家,有许多令人惊叹的地方,如长城、故宫、西湖、张家界、九寨沟等著名景点,吸引了无数国内外游客的喜爱。每个人对于\"好看\"的定义可能不同,但中国无疑有着独特的魅力和多样性。', 'system', NULL, NULL, NULL, '2024-04-20 18:22:44', '2024-04-20 18:22:44', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (3, 1781604279872581644, 1, '苹果是什么颜色?', 'user', NULL, NULL, NULL, '2024-04-20 18:23:05', '2024-04-20 18:23:05', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (4, 1781604279872581644, 1, '苹果的颜色可以根据品种的不同而有所差异。常见的苹果颜色有红色、黄色和青绿色。除了这些基本颜色,苹果还可能呈现出淡红色、深红色等不同的红色调。\n\n这些颜色只是影响苹果的外观,对苹果的口感和营养价值没有影响。苹果口感酸甜,营养丰富,深受人们喜爱。', 'system', NULL, NULL, NULL, '2024-04-20 18:23:11', '2024-04-20 18:23:11', NULL, NULL, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (5, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-23 10:46:48', '2024-04-23 10:46:48', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (6, 1781604279872581644, 1, '作为一个AI助手,我没有个人感受和偏好。但是,中国是一个拥有丰富历史、文化和自然景观的国家,有许多令人惊叹的地方,如长城、故宫、西湖、张家界、九寨沟等著名景点,吸引了无数国内外游客的喜爱。每个人对于\"好看\"的定义可能不同,但中国无疑有着独特的魅力和多样性。', 'system', NULL, NULL, NULL, '2024-04-23 10:46:52', '2024-04-23 10:46:52', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (7, 1781604279872581644, 1, '苹果是什么颜色?', 'user', NULL, NULL, NULL, '2024-04-23 10:46:55', '2024-04-23 10:46:55', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (8, 1781604279872581644, 1, '苹果的颜色因品种和成熟度的不同而异。常见的苹果颜色有红色、黄色和青绿色。除此之外,还有一些苹果品种可能呈现出淡红色、深红色等不同的红色调,或者带有条纹或斑点。总的来说,苹果的颜色非常多样化,但最常见的是红色、黄色和青绿色。', 'system', NULL, NULL, NULL, '2024-04-23 10:47:03', '2024-04-23 10:47:03', NULL, NULL, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (9, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-23 13:49:16', '2024-04-23 13:49:16', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (10, 1781604279872581644, 1, '作为一个AI助手,我没有个人感受和偏好。但是,中国是一个拥有丰富历史、文化和自然景观的国家,有许多令人惊叹的地方,如长城、故宫、西湖、张家界、九寨沟等著名景点,吸引了无数国内外游客的喜爱。每个人对于\"好看\"的定义可能不同,但中国无疑有着独特的魅力和多样性。', 'system', NULL, NULL, NULL, '2024-04-23 13:49:19', '2024-04-23 13:49:19', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (11, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-25 17:55:39', '2024-04-25 17:55:39', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (12, 1781604279872581644, 1, 'NoSuchBeanDefinitionException: No qualifying bean of type \'cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient\' available', 'system', NULL, NULL, NULL, '2024-04-25 17:55:39', '2024-04-25 17:55:39', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (13, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-25 17:56:12', '2024-04-25 17:56:12', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (14, 1781604279872581644, 1, 'NoSuchBeanDefinitionException: No qualifying bean of type \'cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient\' available', 'system', NULL, NULL, NULL, '2024-04-25 17:56:12', '2024-04-25 17:56:12', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (15, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-25 17:56:24', '2024-04-25 17:56:24', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (16, 1781604279872581644, 1, 'NoSuchBeanDefinitionException: No qualifying bean of type \'cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient\' available', 'system', NULL, NULL, NULL, '2024-04-25 17:56:24', '2024-04-25 17:56:24', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (17, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-25 17:56:41', '2024-04-25 17:56:41', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (18, 1781604279872581644, 1, 'NoSuchBeanDefinitionException: No qualifying bean of type \'cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient\' available', 'system', NULL, NULL, NULL, '2024-04-25 17:56:59', '2024-04-25 17:56:59', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (19, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-25 17:58:15', '2024-04-25 17:58:15', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (20, 1781604279872581644, 1, '作为一个AI助手,我没有个人感受和偏好。但是,中国是一个拥有丰富历史、文化和自然景观的国家,有许多令人惊叹的地方,如长城、故宫、西湖、张家界、九寨沟等著名景点,吸引了无数国内外游客的喜爱。每个人对于\"好看\"的定义可能不同,但中国无疑有着独特的魅力和多样性。', 'system', NULL, NULL, NULL, '2024-04-25 17:58:19', '2024-04-25 17:58:19', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (21, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-26 18:27:13', '2024-04-26 18:27:13', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (22, 1781604279872581644, 1, 'ClassCastException: class com.alibaba.dashscope.aigc.generation.models.QwenParam cannot be cast to class cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenChatCompletionRequest (com.alibaba.dashscope.aigc.generation.models.QwenParam and cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenChatCompletionRequest are in unnamed module of loader \'app\')', 'system', NULL, NULL, NULL, '2024-04-26 18:27:13', '2024-04-26 18:27:13', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (23, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-26 18:28:12', '2024-04-26 18:28:12', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (24, 1781604279872581644, 1, 'ClassCastException: class com.alibaba.dashscope.aigc.generation.models.QwenParam cannot be cast to class cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenChatCompletionRequest (com.alibaba.dashscope.aigc.generation.models.QwenParam and cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenChatCompletionRequest are in unnamed module of loader \'app\')', 'system', NULL, NULL, NULL, '2024-04-26 18:30:31', '2024-04-26 18:30:31', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (25, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-27 09:39:56', '2024-04-27 09:39:56', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (26, 1781604279872581644, 1, 'ClassCastException: class com.alibaba.dashscope.aigc.generation.models.QwenParam cannot be cast to class cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenChatCompletionRequest (com.alibaba.dashscope.aigc.generation.models.QwenParam and cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenChatCompletionRequest are in unnamed module of loader \'app\')', 'system', NULL, NULL, NULL, '2024-04-27 09:39:56', '2024-04-27 09:39:56', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (27, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-27 09:41:02', '2024-04-27 09:41:02', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (28, 1781604279872581644, 1, 'AiException: 没有找到apiKey!Can not find api-key.', 'system', NULL, NULL, NULL, '2024-04-27 09:41:02', '2024-04-27 09:41:02', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (29, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-27 09:41:58', '2024-04-27 09:41:58', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (30, 1781604279872581644, 1, 'AiException: 没有找到apiKey!Can not find api-key.', 'system', NULL, NULL, NULL, '2024-04-27 09:41:58', '2024-04-27 09:41:58', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (31, 1781604279872581644, 1, '中国好看吗?', 'user', NULL, NULL, NULL, '2024-04-27 09:42:41', '2024-04-27 09:42:41', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `chat_conversation_id`, `user_id`, `message`, `message_type`, `top_k`, `top_p`, `temperature`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (32, 1781604279872581644, 1, 'ApiException: {\"statusCode\":400,\"message\":\"parameter incremental_output only support stream call\",\"code\":\"InvalidParameter\",\"isJson\":true,\"requestId\":\"9edd3968-6eec-901d-8194-15f497ca0d3a\"}', 'system', NULL, NULL, NULL, '2024-04-27 09:42:42', '2024-04-27 09:42:42', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `conversation_id`, `user_id`, `role_id`, `type`, `model`, `model_id`, `content`, `tokens`, `temperature`, `max_tokens`, `max_contexts`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (61, 1781604279872581649, 1, NULL, 'user', 'ERNIE-3.5-8K', 9, '苹果是什么颜色?', NULL, NULL, NULL, NULL, '2024-05-07 17:18:29', '2024-05-07 17:18:29', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `conversation_id`, `user_id`, `role_id`, `type`, `model`, `model_id`, `content`, `tokens`, `temperature`, `max_tokens`, `max_contexts`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (62, 1781604279872581649, 1, NULL, 'system', 'ERNIE-3.5-8K', 9, '苹果是一种水果,其颜色可以因品种和成熟度而异。常见的苹果颜色包括:\n\n1. 红色:许多苹果品种,如红富士、红元帅等,在成熟时会呈现出鲜艳的红色。\n2. 绿色:一些苹果品种,如青苹果、青香蕉等,在成熟时保持绿色或带有绿色条纹。\n3. 黄色:金苹果、黄元帅等品种在成熟时呈黄色。\n\n此外,还有一些苹果品种在成熟时会呈现出不同的颜色组合,如红绿相间、红黄相间等。因此,苹果的颜色并不是单一的,而是根据品种和成熟度而有所不同。', 8, NULL, NULL, NULL, '2024-05-07 17:18:38', '2024-05-07 17:18:38', NULL, NULL, b'0'); +INSERT INTO `ai_chat_message` (`id`, `conversation_id`, `user_id`, `role_id`, `type`, `model`, `model_id`, `content`, `tokens`, `temperature`, `max_tokens`, `max_contexts`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (63, 1781604279872581649, 1, NULL, 'user', 'ERNIE-3.5-8K', 9, '中国好看吗?', NULL, NULL, NULL, NULL, '2024-05-07 17:18:53', '2024-05-07 17:18:53', 1, 1, b'0'); +INSERT INTO `ai_chat_message` (`id`, `conversation_id`, `user_id`, `role_id`, `type`, `model`, `model_id`, `content`, `tokens`, `temperature`, `max_tokens`, `max_contexts`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (64, 1781604279872581649, 1, NULL, 'system', 'ERNIE-3.5-8K', 9, '中国是一个拥有悠久历史、灿烂文化、广袤土地和多元民族的国家,自然景观和人文景观都非常丰富。从雄伟的长城、壮丽的黄山到神秘的西藏,从繁华的上海、历史悠久的北京到充满异域风情的云南,中国各地都有独特的魅力。\n\n此外,中国还拥有丰富多彩的非物质文化遗产,如京剧、川剧、皮影戏等传统艺术形式,以及中秋节、春节等传统节日。这些文化遗产反映了中国人民的智慧和创造力,也是中国文化的重要组成部分。\n\n因此,可以说中国非常美丽,值得人们去探索和发现它的魅力。无论是自然景观还是人文景观,中国都有着独特的魅力和吸引力。', 1, NULL, NULL, NULL, '2024-05-07 17:19:03', '2024-05-07 17:19:03', 1, 1, b'0'); COMMIT; -- ---------------------------- --- Table structure for ai_chat_modal +-- Table structure for ai_chat_model -- ---------------------------- -DROP TABLE IF EXISTS `ai_chat_modal`; -CREATE TABLE `ai_chat_modal` ( +DROP TABLE IF EXISTS `ai_chat_model`; +CREATE TABLE `ai_chat_model` ( `id` bigint NOT NULL AUTO_INCREMENT, - `model_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '模型名字\n', - `model_type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '模型类型(自己定义qianwen、yiyan、xinghuo、openai)\n', - `modal_image` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '模型照片\n', - `config` json DEFAULT NULL COMMENT 'Ai配置文件', - `disable` tinyint DEFAULT NULL COMMENT '禁用 0、正常 1、禁用\n', + `key_id` bigint DEFAULT NULL COMMENT 'API 秘钥编号', + `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '模型名字\n', + `model` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '模型类型(自己定义qianwen、yiyan、xinghuo、openai)\n', + `platform` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '平台', + `sort` int DEFAULT NULL COMMENT '排序', + `status` tinyint DEFAULT NULL COMMENT '禁用 0、正常 1、禁用\n', + `temperature` double DEFAULT NULL COMMENT '温度参数', + `max_tokens` int DEFAULT NULL COMMENT '单条回复的最大 Token 数量', + `max_contexts` int DEFAULT NULL COMMENT '上下文的最大 Message 数量', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_time` datetime DEFAULT NULL COMMENT '更新时间', `creator` bigint DEFAULT NULL COMMENT '创建用户', `updater` bigint DEFAULT NULL COMMENT '更新用户', `deleted` bit(1) DEFAULT b'0' COMMENT '删除', PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; +) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; -- ---------------------------- --- Records of ai_chat_modal +-- Records of ai_chat_model -- ---------------------------- BEGIN; -INSERT INTO `ai_chat_modal` (`id`, `model_name`, `model_type`, `modal_image`, `config`, `disable`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (1, '小红书Ai写作大模型', 'yiyan', '', NULL, 0, '2024-04-25 18:10:32', '2024-04-25 18:10:32', 1, 1, b'0'); +INSERT INTO `ai_chat_model` (`id`, `key_id`, `name`, `model`, `platform`, `sort`, `status`, `temperature`, `max_tokens`, `max_contexts`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (9, 1, '小红书Ai写作大模型3.5 8k', 'ERNIE-3.5-8K', 'yiyan', 100, 0, NULL, NULL, NULL, '2024-05-07 15:08:22', '2024-05-07 15:20:32', 1, 1, b'0'); +INSERT INTO `ai_chat_model` (`id`, `key_id`, `name`, `model`, `platform`, `sort`, `status`, `temperature`, `max_tokens`, `max_contexts`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (10, 1, '小红书Ai写作大模型4.0', 'ERNIE 4.0', 'yiyan', 100, 0, NULL, NULL, NULL, '2024-05-07 15:23:33', '2024-05-07 15:23:33', 1, 1, b'0'); COMMIT; -- ---------------------------- @@ -136,31 +124,64 @@ DROP TABLE IF EXISTS `ai_chat_role`; CREATE TABLE `ai_chat_role` ( `id` bigint NOT NULL AUTO_INCREMENT, `user_id` bigint DEFAULT NULL, - `model_id` bigint DEFAULT NULL COMMENT '模型编号,关联到角色使用的特定模型\n', - `role_name` varchar(128) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '角色名,角色的显示名称\n', - `role_introduce` varchar(256) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '角色介绍,详细描述角色的功能或用途\n', - `role_source` varchar(16) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '角色来源,如 system(系统预置)、customer(用户自定义)\n', - `classify` varchar(32) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '分类,角色所属的类别,如娱乐、创作等\n', - `visibility` varchar(16) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '发布状态,private 表示仅自己可见,public表示公开,disable表示禁用\n', - `top_k` float DEFAULT NULL COMMENT '生成时的Top-K采样候选集大小\n', - `top_p` float DEFAULT NULL COMMENT '生成时使用的核采样方法的概率阈值\n', - `temperature` float DEFAULT NULL COMMENT '用于控制随机性和多样性的温度参数\n', - `use_count` int DEFAULT NULL COMMENT '角色的使用次数统计\n', + `model_id` bigint DEFAULT NULL COMMENT '模型编号', + `name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '角色名,角色的显示名称\n', + `avatar` varchar(256) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '头像', + `category` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '分类,角色所属的类别,如娱乐、创作等\n', + `sort` int DEFAULT NULL COMMENT '排序', + `description` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '角色描述', + `welcome_message` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '角色欢迎语', + `system_message` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '角色设定(消息)', + `public_status` blob COMMENT '是否公开 true - 公开;false - 私有', + `status` tinyint DEFAULT NULL COMMENT '状态 0、开启 1、关闭', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_time` datetime DEFAULT NULL COMMENT '更新时间', `creator` bigint DEFAULT NULL COMMENT '创建用户', `updater` bigint DEFAULT NULL COMMENT '更新用户', `deleted` bit(1) DEFAULT b'0' COMMENT '删除', PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; +) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; -- ---------------------------- -- Records of ai_chat_role -- ---------------------------- BEGIN; -INSERT INTO `ai_chat_role` (`id`, `user_id`, `model_id`, `role_name`, `role_introduce`, `role_source`, `classify`, `visibility`, `top_k`, `top_p`, `temperature`, `use_count`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (1, 1, 1, '小红书写作v1---hh😄', '采用gpt3.5模型,拥有小红书优质作者写作经验。', 'system', 'writing', 'private', 0.2, 0.4, 0.7, 0, '2024-04-24 19:21:42', '2024-04-24 19:37:49', 1, 1, b'1'); -INSERT INTO `ai_chat_role` (`id`, `user_id`, `model_id`, `role_name`, `role_introduce`, `role_source`, `classify`, `visibility`, `top_k`, `top_p`, `temperature`, `use_count`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (2, 1, 1, '小红书写作v2', '采用gpt3.5模型,拥有小红书优质作者写作经验。', 'system', 'writing', 'public', 0.2, 0.4, 0.7, 0, '2024-04-24 19:22:05', '2024-04-24 19:22:05', 1, 1, b'0'); -INSERT INTO `ai_chat_role` (`id`, `user_id`, `model_id`, `role_name`, `role_introduce`, `role_source`, `classify`, `visibility`, `top_k`, `top_p`, `temperature`, `use_count`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (3, 1, 1, '小红书写作v1---', '采用gpt3.5模型,拥有小红书优质作者写作经验。', 'system', 'writing', 'public', 0.2, 0.4, 0.7, 0, '2024-04-24 19:29:38', '2024-04-24 19:29:38', 1, 1, b'0'); +INSERT INTO `ai_chat_role` (`id`, `user_id`, `model_id`, `name`, `avatar`, `category`, `sort`, `description`, `welcome_message`, `system_message`, `public_status`, `status`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (8, 1, 9, '小红书写作v2', 'http://baidu.com', 'writing', 0, '采用gpt3.5模型,拥有小红书优质作者写作经验。', '欢迎使用小红书写作模型!', '你是一名优秀的小红书人文、风光作者,你热爱旅游,每去往一个城市你都会用美妙的文字抒写着这座城市的大街小巷,描述着这座城市的美好。', 0x31, 0, '2024-05-07 15:30:30', '2024-05-07 15:35:54', 1, 1, b'1'); +INSERT INTO `ai_chat_role` (`id`, `user_id`, `model_id`, `name`, `avatar`, `category`, `sort`, `description`, `welcome_message`, `system_message`, `public_status`, `status`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (9, 1, 9, '小红书写作v1', 'http://baidu.com', 'writing', 0, '采用gpt3.5模型,拥有小红书优质作者写作经验。', '欢迎使用小红书写作模型!', '你是一名优秀的小红书人文、风光作者,你热爱旅游,每去往一个城市你都会用美妙的文字抒写着这座城市的大街小巷,描述着这座城市的美好。', 0x30, 0, '2024-05-07 15:36:40', '2024-05-07 15:36:40', 1, 1, b'0'); +COMMIT; + +-- ---------------------------- +-- Table structure for ai_image +-- ---------------------------- +DROP TABLE IF EXISTS `ai_image`; +CREATE TABLE `ai_image` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `user_id` bigint DEFAULT NULL, + `prompt` varchar(2000) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '提示词\n', + `modal` varchar(32) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '模型\n', + `size` varchar(32) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。\n', + `drawing_status` varchar(32) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '绘画状态:提交、排队、绘画中、绘画完成、绘画失败\n', + `drawing_image_url` varchar(512) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '绘画图片地址\n', + `drawing_error_message` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '错误信息', + `mj_message_id` varchar(32) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '用户操作的消息编号(MJ返回)\n', + `mj_operation_id` varchar(128) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '用户操作的操作编号(MJ返回)\n', + `mj_operation_name` varchar(32) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '用户操作的操作名字(MJ返回)\n', + `mj_operations` json DEFAULT NULL COMMENT 'mj图片生产成功保存的 components json 数组\n', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `creator` bigint DEFAULT NULL COMMENT '创建用户', + `updater` bigint DEFAULT NULL COMMENT '更新用户', + `deleted` bit(1) DEFAULT b'0' COMMENT '删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; + +-- ---------------------------- +-- Records of ai_image +-- ---------------------------- +BEGIN; +INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `modal`, `size`, `drawing_status`, `drawing_image_url`, `drawing_error_message`, `mj_message_id`, `mj_operation_id`, `mj_operation_name`, `mj_operations`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (22, 1, 'Cute cartoon style mobile game scene, a colorful camping car with an outdoor table and chairs next to it on the road in a spring forest, the simple structure of the camper van, soft lighting, C4D rendering, 3d model in the style of a cartoon, cute shape, a pastel color scheme, closeup view from the side angle, high resolution, bright colors, a happy atmosphere. --ar 1:2 --v 6.0', 'midjoureny', NULL, 'fail', NULL, 'You have reached the maximum allowed number of concurrent jobs. Don\'t worry, this job will start as soon as another one finishes!', NULL, NULL, NULL, NULL, '2024-05-08 17:26:01', '2024-05-08 17:26:04', 1, NULL, b'0'); +INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `modal`, `size`, `drawing_status`, `drawing_image_url`, `drawing_error_message`, `mj_message_id`, `mj_operation_id`, `mj_operation_name`, `mj_operations`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (23, 1, 'Cute cartoon style mobile game scene, a colorful camping car with an outdoor table and chairs next to it on the road in a spring forest, the simple structure of the camper van, soft lighting, C4D rendering, 3d model in the style of a cartoon, cute shape, a pastel color scheme, closeup view from the side angle, high resolution, bright colors, a happy atmosphere. --ar 1:2 --v 6.0', 'midjoureny', NULL, 'fail', NULL, 'Your job queue is full. Please wait for a job to finish first, then resubmit this one.', '1788144718477979648', NULL, NULL, NULL, '2024-05-08 17:51:38', '2024-05-08 17:51:39', 1, NULL, b'0'); +INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `modal`, `size`, `drawing_status`, `drawing_image_url`, `drawing_error_message`, `mj_message_id`, `mj_operation_id`, `mj_operation_name`, `mj_operations`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (24, 1, 'Cute cartoon style mobile game scene, a colorful camping car with an outdoor table and chairs next to it on the road in a spring forest, the simple structure of the camper van, soft lighting, C4D rendering, 3d model in the style of a cartoon, cute shape, a pastel color scheme, closeup view from the side angle, high resolution, bright colors, a happy atmosphere. --ar 1:2 --v 6.0', 'midjoureny', NULL, 'submit', NULL, NULL, '1788145293357699072', NULL, NULL, NULL, '2024-05-08 17:53:55', '2024-05-08 17:53:55', 1, 1, b'0'); COMMIT; SET FOREIGN_KEY_CHECKS = 1; From 84a3cd3a757998cf51bde89dc1d74f91ab2ec4dd Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 8 May 2024 18:12:12 +0800 Subject: [PATCH 248/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E5=A4=84=E7=90=86=20nonce=20id=20=E5=BF=85=E9=A1=BB=E6=98=AF?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=E9=95=BF=E6=95=B4=E5=9E=8Bid=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/service/impl/AiImageServiceImpl.java | 6 ++++-- .../ai/midjourney/api/MidjourneyInteractionsApi.java | 3 +-- .../ai/midjourney/MidjourneyInteractionsTests.java | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java index e0d797d18..19281d4df 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.ai.service.impl; +import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.exception.AiException; import cn.iocoder.yudao.framework.ai.image.ImageGeneration; @@ -123,11 +124,12 @@ public class AiImageServiceImpl implements AiImageService { @Transactional(rollbackFor = Exception.class) public void midjourney(AiImageMidjourneyReqVO req) { // 保存数据库 + String messageId = String.valueOf(IdUtil.getSnowflakeNextId()); AiImageDO aiImageDO = doSave(req.getPrompt(), null, "midjoureny", null, AiImageDrawingStatusEnum.SUBMIT, null, - null, null, null); + messageId, null, null); // 提交 midjourney 任务 - Boolean imagine = midjourneyInteractionsApi.imagine(aiImageDO.getId(), req.getPrompt()); + Boolean imagine = midjourneyInteractionsApi.imagine(messageId, req.getPrompt()); if (!imagine) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MIDJOURNEY_IMAGINE_FAIL); } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractionsApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractionsApi.java index 8edeb22da..7a578c832 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractionsApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractionsApi.java @@ -38,8 +38,7 @@ public class MidjourneyInteractionsApi extends MidjourneyInteractions { this.url = midjourneyConfig.getServerUrl().concat(midjourneyConfig.getApiInteractions()); } - public Boolean imagine(Long id, String prompt) { - String nonce = String.valueOf(id); + public Boolean imagine(String nonce, String prompt) { // 获取请求模板 String requestTemplate = midjourneyConfig.getRequestTemplates().get("imagine"); // 设置参数 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java index bfc5aaa85..fda7818f0 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java @@ -40,7 +40,7 @@ public class MidjourneyInteractionsTests { @Test public void mjImageTest() { MidjourneyInteractionsApi mjImagineInteractions = new MidjourneyInteractionsApi(midjourneyConfig); - mjImagineInteractions.imagine(IdUtil.getSnowflakeNextId(), "童话里应该是什么样子?"); + mjImagineInteractions.imagine(String.valueOf(IdUtil.getSnowflakeNextId()), "童话里应该是什么样子?"); } From 2734e54b0c0953123472655cfdfeb4ef70d49103 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 8 May 2024 18:12:30 +0800 Subject: [PATCH 249/684] =?UTF-8?q?=E3=80=90=E6=B5=8B=E8=AF=95=E3=80=91mj?= =?UTF-8?q?=E7=94=9F=E6=88=90=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao-module-ai-biz/src/main/resources/http/image.http | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http index dda3f04f9..3f360aee1 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http @@ -15,10 +15,10 @@ Authorization: {{token}} ### chat midjourney -POST {{baseUrl}}/ai/image/midjourney +POST {{baseUrl}}/admin-api/ai/image/midjourney Content-Type: application/json Authorization: {{token}} { - "prompt": "Mona Lisa, eating on a seat under a tree, wearing white clothes, smiling at the sky" + "prompt": "Cute cartoon style mobile game scene, a colorful camping car with an outdoor table and chairs next to it on the road in a spring forest, the simple structure of the camper van, soft lighting, C4D rendering, 3d model in the style of a cartoon, cute shape, a pastel color scheme, closeup view from the side angle, high resolution, bright colors, a happy atmosphere. --ar 1:2 --v 6.0" } \ No newline at end of file From 04cb9bad5b58ee0525bc35afc32c39bea3c7c2e6 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 9 May 2024 16:40:28 +0800 Subject: [PATCH 250/684] =?UTF-8?q?=E3=80=90=E4=BF=AE=E5=A4=8D=E3=80=91?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20imagine=20=E7=89=88=E6=9C=AC=E8=BF=87?= =?UTF-8?q?=E6=9C=9F=EF=BC=8C=E4=B8=8D=E8=83=BD=E6=8F=90=E4=BA=A4=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E9=97=AE=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/http-body/imagine.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/imagine.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/imagine.json index f4554cc50..4182d8bd1 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/imagine.json +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/imagine.json @@ -6,7 +6,7 @@ "session_id": "$session_id", "nonce": "$nonce", "data": { - "version": "1166847114203123795", + "version": "1237876415471554623", "id": "938956540159881230", "name": "imagine", "type": 1, From caca47b6d786008a0b94266b17c75eed8e7d1508 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 9 May 2024 23:03:10 +0800 Subject: [PATCH 251/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9AAPI=20=E5=AF=86=E9=92=A5=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/ErrorCodeConstants.java | 8 ++- .../iocoder/yudao/module/ai/package-info.java | 5 -- .../admin/model/AiApiKeyController.java | 72 +++++++++++++++++++ .../model/vo/apikey/AiApiKeyPageReqVO.java | 27 +++++++ .../admin/model/vo/apikey/AiApiKeyRespVO.java | 28 ++++++++ .../model/vo/apikey/AiApiKeySaveReqVO.java | 34 +++++++++ .../model/vo/model/AiChatModelListRespVO.java | 4 -- .../ai/dal/dataobject/model/AiApiKeyDO.java | 12 ++-- .../ai/dal/mysql/model/AiApiKeyMapper.java | 26 +++++++ .../ai/service/model/AiApiKeyService.java | 54 ++++++++++++++ .../ai/service/model/AiApiKeyServiceImpl.java | 70 ++++++++++++++++++ .../yudao/framework/ai/AiPlatformEnum.java | 4 +- 12 files changed, 322 insertions(+), 22 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/package-info.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiApiKeyController.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyPageReqVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyRespVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeySaveReqVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiApiKeyMapper.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index fde06746e..302c13a84 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -3,13 +3,14 @@ package cn.iocoder.yudao.module.ai; import cn.iocoder.yudao.framework.common.exception.ErrorCode; /** - * System 错误码枚举类 + * AI 错误码枚举类 * - * system 系统,使用 1-002-000-000 段 + * ai 系统,使用 1-040-000-000 段 */ public interface ErrorCodeConstants { - // ========== 模块 ai 错误码区间 [1-022-000-000 ~ 1-023-000-000) ========== + // ========== API 密钥 1-040-000-000 ========== + ErrorCode API_KEY_NOT_EXISTS = new ErrorCode(1_040_000_000, "AI API 密钥不存在"); // chat @@ -37,4 +38,5 @@ public interface ErrorCodeConstants { ErrorCode AI_MODAL_PLATFORM_PARAMS_INCORRECT = new ErrorCode(1_022_000_083, "AI 平台参数不正确! {} "); ErrorCode AI_MODAL_DISABLE_NOT_USED = new ErrorCode(1_022_000_084, "AI 模型禁用不能使用!"); + } diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/package-info.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/package-info.java deleted file mode 100644 index 6fa1f167a..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -/** - * author: fansili - * time: 2024/3/3 18:14 - */ -package cn.iocoder.yudao.module.ai; \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiApiKeyController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiApiKeyController.java new file mode 100644 index 000000000..7add01901 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiApiKeyController.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.ai.controller.admin.model; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveReqVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; +import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - AI API 密钥") +@RestController +@RequestMapping("/ai/api-key") +@Validated +public class AiApiKeyController { + + @Resource + private AiApiKeyService apiKeyService; + + @PostMapping("/create") + @Operation(summary = "创建AI API 密钥") + @PreAuthorize("@ss.hasPermission('ai:api-key:create')") + public CommonResult createApiKey(@Valid @RequestBody AiApiKeySaveReqVO createReqVO) { + return success(apiKeyService.createApiKey(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新AI API 密钥") + @PreAuthorize("@ss.hasPermission('ai:api-key:update')") + public CommonResult updateApiKey(@Valid @RequestBody AiApiKeySaveReqVO updateReqVO) { + apiKeyService.updateApiKey(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除AI API 密钥") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('ai:api-key:delete')") + public CommonResult deleteApiKey(@RequestParam("id") Long id) { + apiKeyService.deleteApiKey(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得AI API 密钥") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('ai:api-key:query')") + public CommonResult getApiKey(@RequestParam("id") Long id) { + AiApiKeyDO apiKey = apiKeyService.getApiKey(id); + return success(BeanUtils.toBean(apiKey, AiApiKeyRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得AI API 密钥分页") + @PreAuthorize("@ss.hasPermission('ai:api-key:query')") + public CommonResult> getApiKeyPage(@Valid AiApiKeyPageReqVO pageReqVO) { + PageResult pageResult = apiKeyService.getApiKeyPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, AiApiKeyRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyPageReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyPageReqVO.java new file mode 100644 index 000000000..021e0f80c --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyPageReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - AI API 密钥分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class AiApiKeyPageReqVO extends PageParam { + + @Schema(description = "名称", example = "文心一言") + private String name; + + @Schema(description = "平台", example = "OpenAI") + private String platform; + + @Schema(description = "状态", example = "1") + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyRespVO.java new file mode 100644 index 000000000..55d6d802b --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyRespVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@Schema(description = "管理后台 - AI API 密钥 Response VO") +@Data +public class AiApiKeyRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23538") + private Long id; + + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "文心一言") + private String name; + + @Schema(description = "密钥", requiredMode = Schema.RequiredMode.REQUIRED, example = "ABC") + private String apiKey; + + @Schema(description = "平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI") + private String platform; + + @Schema(description = "自定义 API 地址", example = "https://aip.baidubce.com") + private String url; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeySaveReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeySaveReqVO.java new file mode 100644 index 000000000..8fbc8fde7 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeySaveReqVO.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import jakarta.validation.constraints.*; + +@Schema(description = "管理后台 - AI API 密钥新增/修改 Request VO") +@Data +public class AiApiKeySaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23538") + private Long id; + + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "文心一言") + @NotEmpty(message = "名称不能为空") + private String name; + + @Schema(description = "密钥", requiredMode = Schema.RequiredMode.REQUIRED, example = "ABC") + @NotEmpty(message = "密钥不能为空") + private String apiKey; + + @Schema(description = "平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI") + @NotEmpty(message = "平台不能为空") + private String platform; + + @Schema(description = "自定义 API 地址", example = "https://aip.baidubce.com") + private String url; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "状态不能为空") + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListRespVO.java index 59a8900a6..916106a23 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListRespVO.java @@ -1,9 +1,5 @@ package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; -import cn.iocoder.yudao.framework.ai.AiPlatformEnum; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; -import com.baomidou.mybatisplus.annotation.TableId; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiApiKeyDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiApiKeyDO.java index 9512f4c5e..306c1e086 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiApiKeyDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiApiKeyDO.java @@ -31,18 +31,16 @@ public class AiApiKeyDO extends BaseDO { * 名称 */ private String name; + /** + * 密钥 + */ + private String apiKey; /** * 平台 * * 枚举 {@link AiPlatformEnum} */ private String platform; - /** - * 用途 - * - * TODO 芋艿:枚举;chat、image - */ - private Integer type; /** * API 地址 */ @@ -54,6 +52,4 @@ public class AiApiKeyDO extends BaseDO { */ private Integer status; - // TODO 芋艿:proxyUrl 代理地址 - } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiApiKeyMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiApiKeyMapper.java new file mode 100644 index 000000000..fef4965b8 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiApiKeyMapper.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.ai.dal.mysql.model; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageReqVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * AI API 密钥 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface AiApiKeyMapper extends BaseMapperX { + + default PageResult selectPage(AiApiKeyPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(AiApiKeyDO::getName, reqVO.getName()) + .eqIfPresent(AiApiKeyDO::getPlatform, reqVO.getPlatform()) + .eqIfPresent(AiApiKeyDO::getStatus, reqVO.getStatus()) + .orderByDesc(AiApiKeyDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java new file mode 100644 index 000000000..7390bc8e6 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.ai.service.model; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveReqVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; +import jakarta.validation.Valid; + +/** + * AI API 密钥 Service 接口 + * + * @author 芋道源码 + */ +public interface AiApiKeyService { + + /** + * 创建AI API 密钥 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createApiKey(@Valid AiApiKeySaveReqVO createReqVO); + + /** + * 更新AI API 密钥 + * + * @param updateReqVO 更新信息 + */ + void updateApiKey(@Valid AiApiKeySaveReqVO updateReqVO); + + /** + * 删除AI API 密钥 + * + * @param id 编号 + */ + void deleteApiKey(Long id); + + /** + * 获得AI API 密钥 + * + * @param id 编号 + * @return AI API 密钥 + */ + AiApiKeyDO getApiKey(Long id); + + /** + * 获得AI API 密钥分页 + * + * @param pageReqVO 分页查询 + * @return AI API 密钥分页 + */ + PageResult getApiKeyPage(AiApiKeyPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java new file mode 100644 index 000000000..9bafb17d5 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.ai.service.model; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveReqVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; +import cn.iocoder.yudao.module.ai.dal.mysql.model.AiApiKeyMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.API_KEY_NOT_EXISTS; + +/** + * AI API 密钥 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class AiApiKeyServiceImpl implements AiApiKeyService { + + @Resource + private AiApiKeyMapper apiKeyMapper; + + @Override + public Long createApiKey(AiApiKeySaveReqVO createReqVO) { + // 插入 + AiApiKeyDO apiKey = BeanUtils.toBean(createReqVO, AiApiKeyDO.class); + apiKeyMapper.insert(apiKey); + // 返回 + return apiKey.getId(); + } + + @Override + public void updateApiKey(AiApiKeySaveReqVO updateReqVO) { + // 校验存在 + validateApiKeyExists(updateReqVO.getId()); + // 更新 + AiApiKeyDO updateObj = BeanUtils.toBean(updateReqVO, AiApiKeyDO.class); + apiKeyMapper.updateById(updateObj); + } + + @Override + public void deleteApiKey(Long id) { + // 校验存在 + validateApiKeyExists(id); + // 删除 + apiKeyMapper.deleteById(id); + } + + private void validateApiKeyExists(Long id) { + if (apiKeyMapper.selectById(id) == null) { + throw exception(API_KEY_NOT_EXISTS); + } + } + + @Override + public AiApiKeyDO getApiKey(Long id) { + return apiKeyMapper.selectById(id); + } + + @Override + public PageResult getApiKeyPage(AiApiKeyPageReqVO pageReqVO) { + return apiKeyMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java index 752cb042d..427202391 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java @@ -6,6 +6,7 @@ import lombok.Getter; import java.util.List; +// TODO 芋艿:这块,看看要不要调整下; /** * ai 模型平台 * @@ -16,11 +17,10 @@ import java.util.List; @AllArgsConstructor public enum AiPlatformEnum { - YI_YAN("yiyan", "一言"), QIAN_WEN("qianwen", "千问"), XING_HUO("xinghuo", "星火"), - OPEN_AI("openai", "openAi"), + OPEN_AI("openai", "openAi"), // TODO 芋艿:OpenAI OPEN_AI_DALL("dall", "dall"), MIDJOURNEY("midjourney", "midjourney"), From 8e7fc1ff964325ac5583e268f2c7792a54eed5e5 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 10 May 2024 15:29:11 +0800 Subject: [PATCH 252/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E5=A2=9E=E5=8A=A0=20mjNonce=20?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=EF=BC=8C=E7=94=9F=E6=88=90=E5=A5=BD=E3=80=81?= =?UTF-8?q?=E6=88=96=E5=BC=82=E5=B8=B8=E7=9A=84=E5=9B=BE=E7=89=87=E4=BF=A1?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/dal/dataobject/image/AiImageDO.java | 4 +- .../module/ai/dal/mysql/AiImageMapper.java | 10 ++++ .../ai/service/impl/AiImageServiceImpl.java | 4 +- .../YuDaoMidjourneyMessageHandler.java | 12 ++--- .../src/main/resources/http/image.http | 2 +- .../imageGenerationProcess/test2.json | 54 +++++++++++++++++++ .../src/main/resources/application-local.yaml | 12 +++-- 7 files changed, 81 insertions(+), 17 deletions(-) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/test2.json diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java index ea83d2181..c04fea12f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java @@ -49,8 +49,8 @@ public class AiImageDO extends BaseDO { // ============ mj 需要字段 - @Schema(description = "用户操作的消息编号(MJ返回)") - private String mjMessageId; + @Schema(description = "用户操作的Nonce编号(MJ返回)") + private String mjNonceId; @Schema(description = "用户操作的操作编号(MJ返回)") private String mjOperationId; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiImageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiImageMapper.java index ef2b6a596..1ee5b436d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiImageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiImageMapper.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.ai.dal.mysql; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; @@ -17,4 +18,13 @@ import org.springframework.stereotype.Repository; public interface AiImageMapper extends BaseMapperX { + /** + * 更新 - 根据 messageId + * + * @param mjNonceId + * @param aiImageDO + */ + default void updateByMjNonce(Long mjNonceId, AiImageDO aiImageDO) { + this.update(aiImageDO, new LambdaQueryWrapperX().eq(AiImageDO::getMjNonceId, mjNonceId)); + } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java index 19281d4df..d306b4b2f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java @@ -145,7 +145,7 @@ public class AiImageServiceImpl implements AiImageService { // 校验 OperateId 是否存在 AiImageMidjourneyOperationsVO midjourneyOperationsVO = validateMidjourneyOperationsExists(midjourneyOperations, req.getOperateId()); // 校验 messageId - validateMessageId(aiImageDO.getMjMessageId(), req.getMessageId()); + validateMessageId(aiImageDO.getMjNonceId(), req.getMessageId()); // 获取 mjOperationName String mjOperationName = midjourneyOperationsVO.getLabel(); // 保存一个 image 任务记录 @@ -222,7 +222,7 @@ public class AiImageServiceImpl implements AiImageService { aiImageDO.setDrawingImageUrl(drawingImageUrl); aiImageDO.setDrawingErrorMessage(drawingErrorMessage); // - aiImageDO.setMjMessageId(mjMessageId); + aiImageDO.setMjNonceId(mjMessageId); aiImageDO.setMjOperationId(mjOperationId); aiImageDO.setMjOperationName(mjOperationName); aiImageMapper.insert(aiImageDO); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java index 43ca13b6a..24f70b782 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java @@ -62,12 +62,11 @@ public class YuDaoMidjourneyMessageHandler implements MidjourneyMessageHandler { private void errorHandler(MidjourneyMessage midjourneyMessage) { // image 编号 - Long aiImageId = Long.valueOf(midjourneyMessage.getNonce()); + Long nonceId = Long.valueOf(midjourneyMessage.getNonce()); // 获取 error message String errorMessage = getErrorMessage(midjourneyMessage); - aiImageMapper.updateById( + aiImageMapper.updateByMjNonce(nonceId, new AiImageDO() - .setId(aiImageId) .setDrawingErrorMessage(errorMessage) .setDrawingStatus(AiImageDrawingStatusEnum.FAIL.getStatus()) ); @@ -83,7 +82,7 @@ public class YuDaoMidjourneyMessageHandler implements MidjourneyMessageHandler { private void successHandler(MidjourneyMessage midjourneyMessage) { // 获取id - Long aiImageId = Long.valueOf(midjourneyMessage.getNonce()); + Long nonceId = Long.valueOf(midjourneyMessage.getNonce()); // 获取生成 url String imageUrl = null; if (CollUtil.isNotEmpty(midjourneyMessage.getAttachments())) { @@ -102,12 +101,11 @@ public class YuDaoMidjourneyMessageHandler implements MidjourneyMessageHandler { // 获取 midjourneyOperations List midjourneyOperations = getMidjourneyOperationsList(midjourneyMessage); // 更新数据库 - aiImageMapper.updateById( + aiImageMapper.updateByMjNonce(nonceId, new AiImageDO() - .setId(aiImageId) .setDrawingImageUrl(imageUrl) .setDrawingStatus(drawingStatusEnum == null ? null : drawingStatusEnum.getStatus()) - .setMjMessageId(midjourneyMessage.getId()) + .setMjNonceId(midjourneyMessage.getId()) .setMjOperations(JsonUtils.toJsonString(midjourneyOperations)) ); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http index 3f360aee1..bf1165773 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http @@ -20,5 +20,5 @@ Content-Type: application/json Authorization: {{token}} { - "prompt": "Cute cartoon style mobile game scene, a colorful camping car with an outdoor table and chairs next to it on the road in a spring forest, the simple structure of the camper van, soft lighting, C4D rendering, 3d model in the style of a cartoon, cute shape, a pastel color scheme, closeup view from the side angle, high resolution, bright colors, a happy atmosphere. --ar 1:2 --v 6.0" + "prompt": "Cute cartoon style mobile game scene, a colorful camping car with an outdoor table and chairs next to it on the road in a spring forest, the simple structure of the camper van, soft lighting, C4D rendering, 3d model in the style of a cartoon, cute shape, a pastel color scheme, closeup view from the side angle, high resolution, bright colors, a happy atmosphere." } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/test2.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/test2.json new file mode 100644 index 000000000..172152804 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/test2.json @@ -0,0 +1,54 @@ +{ + "type": 2, + "application_id": "936929561302675456", + "guild_id": "1237948819677904956", + "channel_id": "1237948819677904960", + "session_id": "4bdb0c32158f625bbd7f0a54bfbb54aa", + "data": { + "version": "1237876415471554623", + "id": "938956540159881230", + "name": "imagine", + "type": 1, + "options": [ + { + "type": 3, + "name": "prompt", + "value": "哈哈哈" + } + ], + "application_command": { + "id": "938956540159881230", + "type": 1, + "application_id": "936929561302675456", + "version": "1237876415471554623", + "name": "imagine", + "description": "Create images with Midjourney", + "options": [ + { + "type": 3, + "name": "prompt", + "description": "The prompt to imagine", + "required": true, + "description_localized": "The prompt to imagine", + "name_localized": "prompt" + } + ], + "dm_permission": true, + "contexts": [ + 0, + 1, + 2 + ], + "integration_types": [ + 0, + 1 + ], + "global_popularity_rank": 1, + "description_localized": "Create images with Midjourney", + "name_localized": "imagine" + }, + "attachments": [] + }, + "nonce": "1238062212925358080", + "analytics_location": "slash_ui" +} \ No newline at end of file diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 1c16251d7..959988d7d 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -52,7 +52,7 @@ spring: # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=ruoyi-vue-pro;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true;useUnicode=true;characterEncoding=utf-8 # SQLServer 连接的示例 # url: jdbc:dm://127.0.0.1:5236?schema=RUOYI_VUE_PRO # DM 连接的示例 username: root - password: 123456 + password: root # username: sa # SQL Server 连接的示例 # password: Yudao@2024 # SQL Server 连接的示例 # username: SYSDBA # DM 连接的示例 @@ -61,7 +61,7 @@ spring: lazy: true # 开启懒加载,保证启动速度 url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true username: root - password: 123456 + password: root # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 data: @@ -248,9 +248,9 @@ yudao: style: vivid midjourney: enable: true - token: OTc1MzcyNDg1OTcxMzEyNzAw.G2iiSo.OqW9vToC5dokiyb1QOWnCwRPsYpOjLyNcf9--M - guild-id: 1234355413420347402 - channel-id: 1234380679576424448 + token: MTE4MjE3MjY2MjkxNTY3ODIzOA.GEV1SG.c49F8lZoGCUHwsj8O0UdodmM6nyQHvuD2fXflw + guild-id: 1237948819677904956 + channel-id: 1237948819677904960 captcha: enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试; security: @@ -267,6 +267,8 @@ yudao: enable: false demo: false # 关闭演示模式 tencent-lbs-key: TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E # QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc + tenant: + enable: false justauth: enabled: true From c1e2ba9ed4dd069835844d2c71b69795809e985a Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 10 May 2024 17:26:10 +0800 Subject: [PATCH 253/684] =?UTF-8?q?=E3=80=90todo=E3=80=91mj=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E4=BF=A1=E6=81=AF=20=E5=A2=9E=E5=8A=A0=20todo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java | 1 + 1 file changed, 1 insertion(+) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java index 24f70b782..0260a1511 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java @@ -83,6 +83,7 @@ public class YuDaoMidjourneyMessageHandler implements MidjourneyMessageHandler { private void successHandler(MidjourneyMessage midjourneyMessage) { // 获取id Long nonceId = Long.valueOf(midjourneyMessage.getNonce()); + // TODO @芋艿 这个地方有问题,不能根据 nonce来更新,不返回这个信息(别人获取了 image-xxx-xx 后面一段hash,由于没有mj账号测试,暂不清楚。) // 获取生成 url String imageUrl = null; if (CollUtil.isNotEmpty(midjourneyMessage.getAttachments())) { From b9deba889c64e5e24fa068c8ab70e44beaaa8e7b Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 10 May 2024 22:48:49 +0800 Subject: [PATCH 254/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9AAPI=20=E6=A8=A1=E5=9E=8B=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/ErrorCodeConstants.java | 16 +-- .../admin/model/AiApiKeyController.java | 10 +- .../admin/model/AiChatModelController.java | 93 +++++++------ .../admin/model/AiChatRoleController.java | 23 ++-- .../vo/chatModel/AiChatModelPageReqVO.java | 22 +++ .../model/vo/chatModel/AiChatModelRespVO.java | 45 +++++++ .../vo/chatModel/AiChatModelSaveReqVO.java | 50 +++++++ .../model/vo/model/AiChatModalRespVO.java | 50 ------- .../vo/model/AiChatModalUpdateReqVO.java | 63 --------- .../model/vo/model/AiChatModelAddReqVO.java | 53 -------- .../model/vo/model/AiChatModelListReqVO.java | 22 --- .../model/vo/model/AiChatModelListRespVO.java | 50 ------- .../vo/model/AiChatModelUpdateReqVO.java | 57 -------- .../ai/convert/AiChatMessageConvert.java | 8 -- .../module/ai/convert/AiChatModelConvert.java | 57 -------- .../ai/dal/mysql/AiChatModelMapper.java | 15 ++- .../module/ai/service/AiChatModelService.java | 67 --------- .../module/ai/service/AiChatRoleService.java | 1 + .../service/impl/AiChatModalServiceImpl.java | 127 ------------------ .../service/impl/AiChatRoleServiceImpl.java | 10 +- .../ai/service/impl/AiChatServiceImpl.java | 26 ++-- .../ai/service/model/AiApiKeyService.java | 22 ++- .../ai/service/model/AiApiKeyServiceImpl.java | 18 ++- .../AiChatConversationServiceImpl.java | 8 +- .../ai/service/model/AiChatModelService.java | 63 +++++++++ .../service/model/AiChatModelServiceImpl.java | 92 +++++++++++++ .../yudao/framework/ai/AiPlatformEnum.java | 2 +- 27 files changed, 407 insertions(+), 663 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatModel/AiChatModelPageReqVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatModel/AiChatModelRespVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatModel/AiChatModelSaveReqVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalRespVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalUpdateReqVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelAddReqVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListReqVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListRespVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelUpdateReqVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModelConvert.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModelService.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/{impl => model}/AiChatConversationServiceImpl.java (93%) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelService.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index 302c13a84..a3c343e12 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -11,10 +11,15 @@ public interface ErrorCodeConstants { // ========== API 密钥 1-040-000-000 ========== ErrorCode API_KEY_NOT_EXISTS = new ErrorCode(1_040_000_000, "AI API 密钥不存在"); + ErrorCode API_KEY_DISABLE = new ErrorCode(1_040_000_001, "AI API 密钥已禁用!"); - // chat + // ========== API 聊天模型 1-040-001-000 ========== - ErrorCode AI_MODULE_NOT_SUPPORTED = new ErrorCode(1_022_000_000, "AI 模型暂不支持!"); + ErrorCode CHAT_MODAL_NOT_EXIST = new ErrorCode(1_040_001_000, "AI 模型不存在!"); + ErrorCode CHAT_MODAL_DISABLE = new ErrorCode(1_040_001_001, "AI 模型({})已禁用!"); + + // ErrorCode AI_MODAL_CONFIG_PARAMS_INCORRECT = new ErrorCode(1_022_000_081, "AI 模型 config 参数不正确! {} "); +// ErrorCode AI_MODAL_PLATFORM_PARAMS_INCORRECT = new ErrorCode(1_022_000_083, "AI 平台参数不正确! {} "); // conversation @@ -31,12 +36,5 @@ public interface ErrorCodeConstants { ErrorCode AI_CHAT_ROLE_NOT_EXIST = new ErrorCode(1_022_000_060, "AI 角色不存在!"); ErrorCode AI_CHAT_ROLE_NOT_PUBLIC = new ErrorCode(1_022_000_060, "AI 角色未公开!"); - // modal - - ErrorCode AI_MODAL_NOT_EXIST = new ErrorCode(1_022_000_080, "AI 模型不存在!"); - ErrorCode AI_MODAL_CONFIG_PARAMS_INCORRECT = new ErrorCode(1_022_000_081, "AI 模型 config 参数不正确! {} "); - ErrorCode AI_MODAL_PLATFORM_PARAMS_INCORRECT = new ErrorCode(1_022_000_083, "AI 平台参数不正确! {} "); - ErrorCode AI_MODAL_DISABLE_NOT_USED = new ErrorCode(1_022_000_084, "AI 模型禁用不能使用!"); - } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiApiKeyController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiApiKeyController.java index 7add01901..78b588647 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiApiKeyController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiApiKeyController.java @@ -29,14 +29,14 @@ public class AiApiKeyController { private AiApiKeyService apiKeyService; @PostMapping("/create") - @Operation(summary = "创建AI API 密钥") + @Operation(summary = "创建 API 密钥") @PreAuthorize("@ss.hasPermission('ai:api-key:create')") public CommonResult createApiKey(@Valid @RequestBody AiApiKeySaveReqVO createReqVO) { return success(apiKeyService.createApiKey(createReqVO)); } @PutMapping("/update") - @Operation(summary = "更新AI API 密钥") + @Operation(summary = "更新 API 密钥") @PreAuthorize("@ss.hasPermission('ai:api-key:update')") public CommonResult updateApiKey(@Valid @RequestBody AiApiKeySaveReqVO updateReqVO) { apiKeyService.updateApiKey(updateReqVO); @@ -44,7 +44,7 @@ public class AiApiKeyController { } @DeleteMapping("/delete") - @Operation(summary = "删除AI API 密钥") + @Operation(summary = "删除 API 密钥") @Parameter(name = "id", description = "编号", required = true) @PreAuthorize("@ss.hasPermission('ai:api-key:delete')") public CommonResult deleteApiKey(@RequestParam("id") Long id) { @@ -53,7 +53,7 @@ public class AiApiKeyController { } @GetMapping("/get") - @Operation(summary = "获得AI API 密钥") + @Operation(summary = "获得 API 密钥") @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('ai:api-key:query')") public CommonResult getApiKey(@RequestParam("id") Long id) { @@ -62,7 +62,7 @@ public class AiApiKeyController { } @GetMapping("/page") - @Operation(summary = "获得AI API 密钥分页") + @Operation(summary = "获得 API 密钥分页") @PreAuthorize("@ss.hasPermission('ai:api-key:query')") public CommonResult> getApiKeyPage(@Valid AiApiKeyPageReqVO pageReqVO) { PageResult pageResult = apiKeyService.getApiKeyPage(pageReqVO); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java index 010d143cc..7d73e222a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java @@ -2,60 +2,71 @@ package cn.iocoder.yudao.module.ai.controller.admin.model; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelAddReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelListReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelListRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelUpdateReqVO; -import cn.iocoder.yudao.module.ai.service.AiChatModelService; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelPageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelSaveReqVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; +import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -// TODO @fan:调整下接口;相关 vo 的命名等等;modal => model +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -/** - * ai 模型 - * - * @author fansili - * @time 2024/4/24 19:42 - * @since 1.0 - */ -@Tag(name = "A6-AI模型") +@Tag(name = "管理后台 - AI 聊天模型") @RestController -@RequestMapping("/ai/chat/model") -@Slf4j -@AllArgsConstructor +@RequestMapping("/ai/chat-model") +@Validated public class AiChatModelController { - private final AiChatModelService aiChatModelService; + @Resource + private AiChatModelService chatModelService; - @Operation(summary = "ai模型 - 模型列表") - @GetMapping("/list") - public PageResult list(@ModelAttribute AiChatModelListReqVO req) { - return aiChatModelService.list(req); + @PostMapping("/create") + @Operation(summary = "创建聊天模型") + @PreAuthorize("@ss.hasPermission('ai:chat-model:create')") + public CommonResult createChatModel(@Valid @RequestBody AiChatModelSaveReqVO createReqVO) { + return success(chatModelService.createChatModel(createReqVO)); } - @Operation(summary = "ai模型 - 添加") - @PutMapping("/add") - public CommonResult add(@RequestBody @Validated AiChatModelAddReqVO req) { - aiChatModelService.add(req); - return CommonResult.success(null); + @PutMapping("/update") + @Operation(summary = "更新聊天模型") + @PreAuthorize("@ss.hasPermission('ai:chat-model:update')") + public CommonResult updateChatModel(@Valid @RequestBody AiChatModelSaveReqVO updateReqVO) { + chatModelService.updateChatModel(updateReqVO); + return success(true); } - @Operation(summary = "ai模型 - 修改") - @PostMapping("/update") - public CommonResult update(@RequestBody @Validated AiChatModelUpdateReqVO req) { - aiChatModelService.update(req); - return CommonResult.success(null); - } - - @Operation(summary = "ai模型 - 删除") @DeleteMapping("/delete") - public CommonResult delete(@RequestParam("id") Long id) { - aiChatModelService.delete(id); - return CommonResult.success(null); + @Operation(summary = "删除聊天模型") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('ai:chat-model:delete')") + public CommonResult deleteChatModel(@RequestParam("id") Long id) { + chatModelService.deleteChatModel(id); + return success(true); } -} + + @GetMapping("/get") + @Operation(summary = "获得聊天模型") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('ai:chat-model:query')") + public CommonResult getChatModel(@RequestParam("id") Long id) { + AiChatModelDO chatModel = chatModelService.getChatModel(id); + return success(BeanUtils.toBean(chatModel, AiChatModelRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得聊天模型分页") + @PreAuthorize("@ss.hasPermission('ai:chat-model:query')") + public CommonResult> getChatModelPage(@Valid AiChatModelPageReqVO pageReqVO) { + PageResult pageResult = chatModelService.getChatModelPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, AiChatModelRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java index 1aab42600..1de4b3991 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java @@ -6,26 +6,20 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.*; import cn.iocoder.yudao.module.ai.service.AiChatRoleService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -// TODO @fan:调整下接口;相关 vo 的命名等等;modal => model -/** - * ai chat 角色 - * - * @fansili - * @since v1.0 - */ -@Tag(name = "A4-chat角色") +@Tag(name = "管理后台 - AI 聊天角色") @RestController -@RequestMapping("/ai/chat/role") -@Slf4j -@AllArgsConstructor +@RequestMapping("/ai/chat-role") +@Validated public class AiChatRoleController { - private final AiChatRoleService chatRoleService; + @Resource + private AiChatRoleService chatRoleService; @Operation(summary = "chat角色 - 角色列表") @GetMapping("/list") @@ -60,4 +54,9 @@ public class AiChatRoleController { chatRoleService.delete(id); return CommonResult.success(null); } + + // ========== 角色管理 ========== + + + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatModel/AiChatModelPageReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatModel/AiChatModelPageReqVO.java new file mode 100644 index 000000000..0971522eb --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatModel/AiChatModelPageReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel; + +import lombok.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +@Schema(description = "管理后台 - API 聊天模型分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class AiChatModelPageReqVO extends PageParam { + + @Schema(description = "模型名字", example = "张三") + private String name; + + @Schema(description = "模型标识", example = "gpt-3.5-turbo-0125") + private String model; + + @Schema(description = "模型平台", example = "OpenAI") + private String platform; + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatModel/AiChatModelRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatModel/AiChatModelRespVO.java new file mode 100644 index 000000000..681dabe68 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatModel/AiChatModelRespVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - AI 聊天模型 Response VO") +@Data +public class AiChatModelRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2630") + private Long id; + + @Schema(description = "API 秘钥编号", example = "22042") + private Long keyId; + + @Schema(description = "模型名字", example = "张三") + private String name; + + @Schema(description = "模型标识", example = "gpt-3.5-turbo-0125") + private String model; + + @Schema(description = "模型平台", example = "OpenAI") + private String platform; + + @Schema(description = "排序", example = "1") + private Integer sort; + + @Schema(description = "状态", example = "2") + private Integer status; + + @Schema(description = "温度参数", example = "1") + private Double temperature; + + @Schema(description = "单条回复的最大 Token 数量", example = "4096") + private Integer maxTokens; + + @Schema(description = "上下文的最大 Message 数量", example = "8192") + private Integer maxContexts; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatModel/AiChatModelSaveReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatModel/AiChatModelSaveReqVO.java new file mode 100644 index 000000000..4fad5a1fc --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatModel/AiChatModelSaveReqVO.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import jakarta.validation.constraints.*; + +@Schema(description = "管理后台 - API 聊天模型新增/修改 Request VO") +@Data +public class AiChatModelSaveReqVO { + + @Schema(description = "编号", example = "2630") + private Long id; + + @Schema(description = "API 秘钥编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22042") + @NotNull(message = "API 秘钥编号不能为空") + private Long keyId; + + @Schema(description = "模型名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + @NotEmpty(message = "模型名字不能为空") + private String name; + + @Schema(description = "模型标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "gpt-3.5-turbo-0125") + @NotEmpty(message = "模型标识不能为空") + private String model; + + @Schema(description = "模型平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI") + @NotEmpty(message = "模型平台不能为空") + private String platform; + + @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "排序不能为空") + private Integer sort; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @InEnum(CommonStatusEnum.class) + @NotNull(message = "状态不能为空") + private Integer status; + + @Schema(description = "温度参数", example = "1") + private Double temperature; + + @Schema(description = "单条回复的最大 Token 数量", example = "4096") + private Integer maxTokens; + + @Schema(description = "上下文的最大 Message 数量", example = "8192") + private Integer maxContexts; + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalRespVO.java deleted file mode 100644 index 28a439733..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalRespVO.java +++ /dev/null @@ -1,50 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.Size; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * modal list - * - * @author fansili - * @time 2024/4/24 19:56 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatModalRespVO { - - @Schema(description = "编号") - private Long id; - - @Schema(description = "API 秘钥编号") - private Long keyId; - - @Schema(description = "模型名字") - private String name; - - @Schema(description = "模型类型(qianwen、yiyan、xinghuo、openai)") - private String model; - - @Size(max = 32, message = "模型平台最大32个字符") - private String platform; - - @Schema(description = "排序") - private Integer sort; - - @Schema(description = "状态") - private Integer status; - - // ========== 会话配置 ========== - - @Schema(description = "温度参数") - private Integer temperature; - - @Schema(description = "单条回复的最大 Token 数量") - private Integer maxTokens; - - @Schema(description = "上下文的最大 Message 数量") - private Integer maxContexts; -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalUpdateReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalUpdateReqVO.java deleted file mode 100644 index 4e9fd898c..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModalUpdateReqVO.java +++ /dev/null @@ -1,63 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * ai chat modal - * - * @author fansili - * @time 2024/4/24 19:47 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatModalUpdateReqVO { - - @Schema(description = "编号") - @Size(max = 32, message = "编号最大32个字符") - @NotNull(message = "编号不能为空") - private Long id; - - @Schema(description = "API 秘钥编号") - @Size(max = 32, message = "API 秘钥编号最大32个字符") - @NotNull(message = "API 秘钥编号不能为空!") - private Long keyId; - - @Schema(description = "模型名字") - @Size(max = 60, message = "模型名字最大60个字符") - @NotNull(message = "模型名字不能为空!") - private String name; - - @Schema(description = "模型类型(qianwen、yiyan、xinghuo、openai)") - @Size(max = 32, message = "模型类型最大32个字符") - @NotNull(message = "model模型不能为空!") - private String model; - - @Size(max = 32, message = "模型平台最大32个字符") - @Schema(description = "模型平台 参考 AiPlatformEnum") - @NotNull(message = "平台不能为空!") - private String platform; - - @Schema(description = "排序") - @NotNull(message = "sort排序不能为空!") - private Integer sort; - - @Schema(description = "状态") - @NotNull(message = "状态不能为空!") - private Integer status; - - // ========== 会话配置 ========== - - @Schema(description = "温度参数") - private Integer temperature; - - @Schema(description = "单条回复的最大 Token 数量") - private Integer maxTokens; - - @Schema(description = "上下文的最大 Message 数量") - private Integer maxContexts; -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelAddReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelAddReqVO.java deleted file mode 100644 index 569760fab..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelAddReqVO.java +++ /dev/null @@ -1,53 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * ai chat modal - * - * @author fansili - * @time 2024/4/24 19:47 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatModelAddReqVO { - - @Schema(description = "API 秘钥编号") - @NotNull(message = "API 秘钥编号不能为空!") - private Long keyId; - - @Schema(description = "模型名字") - @Size(max = 60, message = "模型名字最大60个字符") - @NotNull(message = "模型名字不能为空!") - private String name; - - @Schema(description = "模型类型(qianwen、yiyan、xinghuo、openai)") - @Size(max = 32, message = "模型类型最大32个字符") - @NotNull(message = "model模型不能为空!") - private String model; - - @Size(max = 32, message = "模型平台最大32个字符") - @Schema(description = "模型平台 参考 AiPlatformEnum") - @NotNull(message = "平台不能为空!") - private String platform; - - @Schema(description = "排序") - @NotNull(message = "sort排序不能为空!") - private Integer sort; - - // ========== 会话配置 ========== - - @Schema(description = "温度参数") - private Integer temperature; - - @Schema(description = "单条回复的最大 Token 数量") - private Integer maxTokens; - - @Schema(description = "上下文的最大 Message 数量") - private Integer maxContexts; -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListReqVO.java deleted file mode 100644 index 7e3cfff13..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListReqVO.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * modal list - * - * @author fansili - * @time 2024/4/24 19:56 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatModelListReqVO extends PageParam { - - @Schema(description = "名字搜搜") - private String search; - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListRespVO.java deleted file mode 100644 index 916106a23..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelListRespVO.java +++ /dev/null @@ -1,50 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * modal list - * - * @author fansili - * @time 2024/4/24 19:56 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatModelListRespVO { - - @Schema(description = "编号") - private Long id; - - @Schema(description = "API 秘钥编号") - private Long keyId; - - @Schema(description = "模型名称") - private String name; - - @Schema(description = "模型标志") - private String model; - - @Schema(description = "平台") - private String platform; - - @Schema(description = "排序值") - private Integer sort; - - @Schema(description = "状态") - private Integer status; - - // ========== 会话配置 ========== - - @Schema(description = "温度参数") - private Double temperature; - - @Schema(description = "单条回复的最大 Token 数量") - private Integer maxTokens; - - @Schema(description = "上下文的最大 Message 数量") - private Integer maxContexts; - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelUpdateReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelUpdateReqVO.java deleted file mode 100644 index 577e998e9..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiChatModelUpdateReqVO.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * ai chat modal - * - * @author fansili - * @time 2024/4/24 19:47 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatModelUpdateReqVO { - - @Schema(description = "编号") - @NotNull(message = "编号不能为空") - private Long id; - - @Schema(description = "API 秘钥编号") - @NotNull(message = "API 秘钥编号不能为空!") - private Long keyId; - - @Schema(description = "模型名字") - @Size(max = 60, message = "模型名字最大60个字符") - @NotNull(message = "模型名字不能为空!") - private String name; - - @Schema(description = "模型类型(qianwen、yiyan、xinghuo、openai)") - @Size(max = 32, message = "模型类型最大32个字符") - @NotNull(message = "model模型不能为空!") - private String model; - - @Size(max = 32, message = "模型平台最大32个字符") - @Schema(description = "模型平台 参考 AiPlatformEnum") - @NotNull(message = "平台不能为空!") - private String platform; - - @Schema(description = "排序") - @NotNull(message = "sort排序不能为空!") - private Integer sort; - - // ========== 会话配置 ========== - - @Schema(description = "温度参数") - private Integer temperature; - - @Schema(description = "单条回复的最大 Token 数量") - private Integer maxTokens; - - @Schema(description = "上下文的最大 Message 数量") - private Integer maxContexts; -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java index d067a26f3..a5019b2cd 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java @@ -19,14 +19,6 @@ public interface AiChatMessageConvert { AiChatMessageConvert INSTANCE = Mappers.getMapper(AiChatMessageConvert.class); - /** - * 转换 ChatMessageListRes - * - * @param list - * @return - */ - List convert(List list); - /** * 转换 AiChatMessageRespVO * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModelConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModelConvert.java deleted file mode 100644 index d6d57b5ef..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatModelConvert.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.iocoder.yudao.module.ai.convert; - -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelAddReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelListRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModelUpdateReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * 聊天 modal - * - * @author fansili - * @time 2024/4/18 16:39 - * @since 1.0 - */ -@Mapper -public interface AiChatModelConvert { - - AiChatModelConvert INSTANCE = Mappers.getMapper(AiChatModelConvert.class); - - /** - * 转换 - AiChatModalListRes - * - * @param list - * @return - */ - List convertAiChatModalListRes(List list); - - /** - * 转换 - AiChatModalDO - * - * @param req - * @return - */ - AiChatModelDO convertAiChatModalDO(AiChatModelAddReqVO req); - - /** - * 转换 - AiChatModalDO - * - * @param req - * @return - */ - AiChatModelDO convertAiChatModalDO(AiChatModelUpdateReqVO req); - - /** - * 转换 - AiChatModalRes - * - * @param aiChatModalDO - * @return - */ - AiChatModalRespVO convertAiChatModalRes(AiChatModelDO aiChatModalDO); - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java index 46d66ff5f..c2d75a218 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java @@ -5,21 +5,19 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelPageReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import org.apache.ibatis.annotations.Mapper; -import org.springframework.stereotype.Repository; /** - * chat modal + * API 聊天模型 Mapper * * @author fansili - * @time 2024/4/24 19:41 - * @since 1.0 */ -@Repository @Mapper public interface AiChatModelMapper extends BaseMapperX { + // TODO 芋艿:要搞一下 /** * 查询 - 第一个modal * @@ -36,5 +34,12 @@ public interface AiChatModelMapper extends BaseMapperX { return pageResult.getList().get(0); } + default PageResult selectPage(AiChatModelPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(AiChatModelDO::getName, reqVO.getName()) + .eqIfPresent(AiChatModelDO::getModel, reqVO.getModel()) + .eqIfPresent(AiChatModelDO::getPlatform, reqVO.getPlatform()) + .orderByDesc(AiChatModelDO::getId)); + } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModelService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModelService.java deleted file mode 100644 index 07a902dd8..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModelService.java +++ /dev/null @@ -1,67 +0,0 @@ -package cn.iocoder.yudao.module.ai.service; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.*; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; - -/** - * ai modal - * - * @author fansili - * @time 2024/4/24 19:42 - * @since 1.0 - */ -public interface AiChatModelService { - - /** - * ai modal - 列表 - * - * @param req - * @return - */ - PageResult list(AiChatModelListReqVO req); - - /** - * ai modal - 添加 - * - * @param req - */ - void add(AiChatModelAddReqVO req); - - /** - * ai modal - 更新 - * - * @param req - */ - void update(AiChatModelUpdateReqVO req); - - /** - * ai modal - 删除 - * - * @param id - */ - void delete(Long id); - - /** - * 获取 - 获取 modal - * - * @param modalId - * @return - */ - AiChatModalRespVO getChatModalOfValidate(Long modalId); - - /** - * 校验 - 是否存在 - * - * @param id - * @return - */ - AiChatModelDO validateExists(Long id); - - /** - * 校验 - 校验是否可用 - * - * @param chatModal - */ - void validateAvailable(AiChatModalRespVO chatModal); -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java index 96d722100..c2f56a240 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java @@ -72,4 +72,5 @@ public interface AiChatRoleService { * @param aiChatRoleDO */ void validateIsPublic(AiChatRoleDO aiChatRoleDO); + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java deleted file mode 100644 index 0aec7a94c..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java +++ /dev/null @@ -1,127 +0,0 @@ -package cn.iocoder.yudao.module.ai.service.impl; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.extra.validation.ValidationUtil; -import cn.iocoder.yudao.framework.ai.AiPlatformEnum; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.ai.ErrorCodeConstants; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.*; -import cn.iocoder.yudao.module.ai.convert.AiChatModelConvert; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; -import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModelMapper; -import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalConfigVO; -import cn.iocoder.yudao.module.ai.service.AiChatModelService; -import jakarta.validation.ConstraintViolation; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Set; - -/** - * ai 模型 - * - * @author fansili - * @time 2024/4/24 19:42 - * @since 1.0 - */ -@AllArgsConstructor -@Service -@Slf4j -public class AiChatModalServiceImpl implements AiChatModelService { - - private final AiChatModelMapper aiChatModelMapper; - - @Override - public PageResult list(AiChatModelListReqVO req) { - LambdaQueryWrapperX queryWrapperX = new LambdaQueryWrapperX<>(); - // 查询的都是未禁用的模型 - queryWrapperX.eq(AiChatModelDO::getStatus, CommonStatusEnum.ENABLE.getStatus()); - // search - if (!StrUtil.isBlank(req.getSearch())) { - queryWrapperX.like(AiChatModelDO::getName, req.getSearch().trim()); - } - // 默认排序 - queryWrapperX.orderByAsc(AiChatModelDO::getSort); - // 查询 - PageResult aiChatModalDOPageResult = aiChatModelMapper.selectPage(req, queryWrapperX); - // 转换 res - List resList = AiChatModelConvert.INSTANCE.convertAiChatModalListRes(aiChatModalDOPageResult.getList()); - return new PageResult<>(resList, aiChatModalDOPageResult.getTotal()); - } - - @Override - public void add(AiChatModelAddReqVO req) { - // 校验 platform、type - validatePlatform(req.getPlatform()); - // 转换 do - AiChatModelDO insertChatModalDO = AiChatModelConvert.INSTANCE.convertAiChatModalDO(req); - // 设置默认属性 - insertChatModalDO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - // 保存数据库 - aiChatModelMapper.insert(insertChatModalDO); - } - - @Override - public void update(AiChatModelUpdateReqVO req) { - // 校验 platform - validatePlatform(req.getPlatform()); - // 校验模型是否存在 - validateExists(req.getId()); - // 转换 updateChatModalDO - AiChatModelDO updateChatModalDO = AiChatModelConvert.INSTANCE.convertAiChatModalDO(req); - updateChatModalDO.setId(req.getId()); - // 更新数据库 - aiChatModelMapper.updateById(updateChatModalDO); - } - - @Override - public void delete(Long id) { - // 检查 modal 是否存在 - validateExists(id); - // 删除 delete - aiChatModelMapper.deleteById(id); - } - - @Override - public AiChatModalRespVO getChatModalOfValidate(Long modalId) { - // 检查 modal 是否存在 - AiChatModelDO aiChatModalDO = validateExists(modalId); - return AiChatModelConvert.INSTANCE.convertAiChatModalRes(aiChatModalDO); - } - - @Override - public void validateAvailable(AiChatModalRespVO chatModal) { - // 对话模型是否可用 - if (!CommonStatusEnum.ENABLE.getStatus().equals(chatModal.getStatus())) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_DISABLE_NOT_USED); - } - } - - public AiChatModelDO validateExists(Long id) { - AiChatModelDO aiChatModalDO = aiChatModelMapper.selectById(id); - if (aiChatModalDO == null) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_NOT_EXIST); - } - return aiChatModalDO; - } - - private void validatePlatform(String platform) { - try { - AiPlatformEnum.valueOfPlatform(platform); - } catch (IllegalArgumentException e) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_PLATFORM_PARAMS_INCORRECT, e.getMessage()); - } - } - - private void validateModalConfig(AiChatModalConfigVO aiChatModalConfigVO) { - Set> validate = ValidationUtil.validate(aiChatModalConfigVO); - for (ConstraintViolation constraintViolation : validate) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_CONFIG_PARAMS_INCORRECT, constraintViolation.getMessage()); - } - } -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java index cc432fe41..426481495 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java @@ -12,7 +12,7 @@ import cn.iocoder.yudao.module.ai.convert.AiChatRoleConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatRoleMapper; import cn.iocoder.yudao.module.ai.enums.AiChatRoleCategoryEnum; -import cn.iocoder.yudao.module.ai.service.AiChatModelService; +import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; import cn.iocoder.yudao.module.ai.service.AiChatRoleService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -57,8 +57,8 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { public void add(AiChatRoleAddReqVO req) { // 转换enum,并校验enum AiChatRoleCategoryEnum.valueOfCategory(req.getCategory()); - // 校验模型是否存在 - aiChatModalService.validateExists(req.getModelId()); + // 校验模型是否存在 TODO +// aiChatModalService.validateExists(req.getModelId()); // 转换do AiChatRoleDO insertAiChatRoleDO = AiChatRoleConvert.INSTANCE.convertAiChatRoleDO(req); insertAiChatRoleDO.setUserId(SecurityFrameworkUtils.getLoginUserId()); @@ -73,8 +73,8 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { validateExists(req.getId()); // 转换enum,并校验enum AiChatRoleCategoryEnum.valueOfCategory(req.getCategory()); - // 校验模型是否存在 - aiChatModalService.validateExists(req.getModelId()); + // 校验模型是否存在 TODO +// aiChatModalService.validateExists(req.getModelId()); // 转换do AiChatRoleDO updateChatRole = AiChatRoleConvert.INSTANCE.convertAiChatRoleDO(req); updateChatRole.setId(req.getId()); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index 90649f417..be8f81d72 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -12,14 +12,14 @@ import cn.iocoder.yudao.module.ai.config.AiChatClientFactory; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRespVO; import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatMessageMapper; import cn.iocoder.yudao.module.ai.service.AiChatConversationService; -import cn.iocoder.yudao.module.ai.service.AiChatModelService; +import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; import cn.iocoder.yudao.module.ai.service.AiChatRoleService; import cn.iocoder.yudao.module.ai.service.AiChatService; import lombok.AllArgsConstructor; @@ -57,9 +57,7 @@ public class AiChatServiceImpl implements AiChatService { // 查询对话 AiChatConversationRespVO conversation = chatConversationService.getConversationOfValidate(req.getConversationId()); // 获取对话模型 - AiChatModalRespVO chatModal = aiChatModalService.getChatModalOfValidate(conversation.getModelId()); - // 对话模型是否可用 - aiChatModalService.validateAvailable(chatModal); + AiChatModelDO chatModel = aiChatModalService.validateChatModel(conversation.getModelId()); // 获取角色信息 AiChatRoleDO aiChatRoleDO = null; if (conversation.getRoleId() != null) { @@ -68,10 +66,10 @@ public class AiChatServiceImpl implements AiChatService { // 校验角色是否公开 aiChatRoleService.validateIsPublic(aiChatRoleDO); // 获取 client 类型 - AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(chatModal.getPlatform()); + AiPlatformEnum platformEnum = AiPlatformEnum.validatePlatform(chatModel.getPlatform()); // 保存 chat message insertChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(), - chatModal.getModel(), chatModal.getId(), req.getContent(), + chatModel.getModel(), chatModel.getId(), req.getContent(), null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); String content = null; int tokens = 0; @@ -93,7 +91,7 @@ public class AiChatServiceImpl implements AiChatService { } finally { // 保存 chat message insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), - chatModal.getModel(), chatModal.getId(), content, + chatModel.getModel(), chatModel.getId(), content, tokens, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); } return new AiChatMessageRespVO().setContent(content); @@ -128,9 +126,7 @@ public class AiChatServiceImpl implements AiChatService { // 查询对话 AiChatConversationRespVO conversation = chatConversationService.getConversationOfValidate(req.getConversationId()); // 获取对话模型 - AiChatModalRespVO chatModal = aiChatModalService.getChatModalOfValidate(conversation.getModelId()); - // 对话模型是否可用 - aiChatModalService.validateAvailable(chatModal); + AiChatModelDO chatModel = aiChatModalService.validateChatModel(conversation.getModelId()); // 获取角色信息 AiChatRoleDO aiChatRoleDO = null; if (conversation.getRoleId() != null) { @@ -145,10 +141,10 @@ public class AiChatServiceImpl implements AiChatService { // req.setTemperature(req.getTemperature()); // 保存 chat message insertChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(), - chatModal.getModel(), chatModal.getId(), req.getContent(), + chatModel.getModel(), chatModel.getId(), req.getContent(), null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); // 获取 client 类型 - AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(chatModal.getPlatform()); + AiPlatformEnum platformEnum = AiPlatformEnum.validatePlatform(chatModel.getPlatform()); StreamingChatClient streamingChatClient = aiChatClientFactory.getStreamingChatClient(platformEnum); Flux streamResponse = streamingChatClient.stream(prompt); // 转换 flex AiChatMessageRespVO @@ -167,7 +163,7 @@ public class AiChatServiceImpl implements AiChatService { log.info("发送完成!"); // 保存 chat message insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), - chatModal.getModel(), chatModal.getId(), contentBuffer.toString(), + chatModel.getModel(), chatModel.getId(), contentBuffer.toString(), tokens.get(), conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); } }).doOnError(new Consumer() { @@ -176,7 +172,7 @@ public class AiChatServiceImpl implements AiChatService { log.error("发送错误 {}!", throwable.getMessage()); // 保存 chat message insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), - chatModal.getModel(), chatModal.getId(), throwable.getMessage(), + chatModel.getModel(), chatModel.getId(), throwable.getMessage(), tokens.get(), conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); } }); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java index 7390bc8e6..4da3c3500 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java @@ -14,7 +14,7 @@ import jakarta.validation.Valid; public interface AiApiKeyService { /** - * 创建AI API 密钥 + * 创建 API 密钥 * * @param createReqVO 创建信息 * @return 编号 @@ -22,32 +22,40 @@ public interface AiApiKeyService { Long createApiKey(@Valid AiApiKeySaveReqVO createReqVO); /** - * 更新AI API 密钥 + * 更新 API 密钥 * * @param updateReqVO 更新信息 */ void updateApiKey(@Valid AiApiKeySaveReqVO updateReqVO); /** - * 删除AI API 密钥 + * 删除 API 密钥 * * @param id 编号 */ void deleteApiKey(Long id); /** - * 获得AI API 密钥 + * 获得 API 密钥 * * @param id 编号 - * @return AI API 密钥 + * @return API 密钥 */ AiApiKeyDO getApiKey(Long id); /** - * 获得AI API 密钥分页 + * 校验 API 密钥 + * + * @param id 比那好 + * @return API 密钥 + */ + AiApiKeyDO validateApiKey(Long id); + + /** + * 获得 API 密钥分页 * * @param pageReqVO 分页查询 - * @return AI API 密钥分页 + * @return API 密钥分页 */ PageResult getApiKeyPage(AiApiKeyPageReqVO pageReqVO); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java index 9bafb17d5..06e68748f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.ai.service.model; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageReqVO; @@ -11,7 +12,7 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.API_KEY_NOT_EXISTS; +import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.*; /** * AI API 密钥 Service 实现类 @@ -51,10 +52,12 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { apiKeyMapper.deleteById(id); } - private void validateApiKeyExists(Long id) { - if (apiKeyMapper.selectById(id) == null) { + private AiApiKeyDO validateApiKeyExists(Long id) { + AiApiKeyDO apiKey = apiKeyMapper.selectById(id); + if (apiKey == null) { throw exception(API_KEY_NOT_EXISTS); } + return apiKey; } @Override @@ -62,6 +65,15 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { return apiKeyMapper.selectById(id); } + @Override + public AiApiKeyDO validateApiKey(Long id) { + AiApiKeyDO apiKey = validateApiKeyExists(id); + if (CommonStatusEnum.isDisable(apiKey.getStatus())) { + throw exception(API_KEY_DISABLE); + } + return apiKey; + } + @Override public PageResult getApiKeyPage(AiApiKeyPageReqVO pageReqVO) { return apiKeyMapper.selectPage(pageReqVO); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatConversationServiceImpl.java similarity index 93% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatConversationServiceImpl.java index dc5205011..5d25f2a11 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatConversationServiceImpl.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.service.impl; +package cn.iocoder.yudao.module.ai.service.model; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; @@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRespVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleRespVO; import cn.iocoder.yudao.module.ai.convert.AiChatConversationConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; @@ -15,7 +14,6 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModelMapper; import cn.iocoder.yudao.module.ai.service.AiChatConversationService; -import cn.iocoder.yudao.module.ai.service.AiChatModelService; import cn.iocoder.yudao.module.ai.service.AiChatRoleService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -87,9 +85,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService // 校验对话是否存在 validateExists(updateReqVO.getId()); // 获取模型信息并验证 - AiChatModalRespVO chatModal = aiChatModalService.getChatModalOfValidate(updateReqVO.getModelId()); - // 校验modal是否可用 - aiChatModalService.validateAvailable(chatModal); + aiChatModalService.validateChatModel(updateReqVO.getModelId()); // 更新对话信息 AiChatConversationDO updateAiChatConversationDO = AiChatConversationConvert.INSTANCE.convertAiChatConversationDO(updateReqVO); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelService.java new file mode 100644 index 000000000..d05941989 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelService.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.module.ai.service.model; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelPageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelSaveReqVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; +import jakarta.validation.Valid; + +/** + * AI 聊天模型 Service 接口 + * + * @author fansili + * @since 2024/4/24 19:42 + */ +public interface AiChatModelService { + + /** + * 创建聊天模型 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createChatModel(@Valid AiChatModelSaveReqVO createReqVO); + + /** + * 更新聊天模型 + * + * @param updateReqVO 更新信息 + */ + void updateChatModel(@Valid AiChatModelSaveReqVO updateReqVO); + + /** + * 删除聊天模型 + * + * @param id 编号 + */ + void deleteChatModel(Long id); + + /** + * 获得聊天模型 + * + * @param id 编号 + * @return API 聊天模型 + */ + AiChatModelDO getChatModel(Long id); + + /** + * 获得聊天模型分页 + * + * @param pageReqVO 分页查询 + * @return API 聊天模型分页 + */ + PageResult getChatModelPage(AiChatModelPageReqVO pageReqVO); + + /** + * 校验聊天模型 + * + * @param id 编号 + * @return 聊天模型 + */ + AiChatModelDO validateChatModel(Long id); + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java new file mode 100644 index 000000000..0c0386ccc --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java @@ -0,0 +1,92 @@ +package cn.iocoder.yudao.module.ai.service.model; + +import cn.iocoder.yudao.framework.ai.AiPlatformEnum; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelPageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelSaveReqVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; +import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModelMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.*; + +/** + * AI 聊天模型 Service 实现类 + * + * @author fansili + */ +@Service +@Validated +public class AiChatModelServiceImpl implements AiChatModelService { + + @Resource + private AiApiKeyService apiKeyService; + + @Resource + private AiChatModelMapper chatModelMapper; + + @Override + public Long createChatModel(AiChatModelSaveReqVO createReqVO) { + // 1. 校验 + AiPlatformEnum.validatePlatform(createReqVO.getPlatform()); + apiKeyService.validateApiKey(createReqVO.getKeyId()); + + // 2. 插入 + AiChatModelDO chatModel = BeanUtils.toBean(createReqVO, AiChatModelDO.class); + chatModelMapper.insert(chatModel); + return chatModel.getId(); + } + + @Override + public void updateChatModel(AiChatModelSaveReqVO updateReqVO) { + // 1. 校验 + validateChatModelExists(updateReqVO.getId()); + AiPlatformEnum.validatePlatform(updateReqVO.getPlatform()); + apiKeyService.validateApiKey(updateReqVO.getKeyId()); + + // 2. 更新 + AiChatModelDO updateObj = BeanUtils.toBean(updateReqVO, AiChatModelDO.class); + chatModelMapper.updateById(updateObj); + } + + @Override + public void deleteChatModel(Long id) { + // 校验存在 + validateChatModelExists(id); + // 删除 + chatModelMapper.deleteById(id); + } + + private AiChatModelDO validateChatModelExists(Long id) { + AiChatModelDO model = chatModelMapper.selectById(id); + if (chatModelMapper.selectById(id) == null) { + throw exception(CHAT_MODAL_NOT_EXIST); + } + return model; + } + + @Override + public AiChatModelDO getChatModel(Long id) { + return chatModelMapper.selectById(id); + } + + @Override + public PageResult getChatModelPage(AiChatModelPageReqVO pageReqVO) { + return chatModelMapper.selectPage(pageReqVO); + } + + @Override + public AiChatModelDO validateChatModel(Long id) { + AiChatModelDO model = validateChatModelExists(id); + if (CommonStatusEnum.isDisable(model.getStatus())) { + throw exception(CHAT_MODAL_DISABLE); + } + return model; + } + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java index 427202391..c774d2515 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java @@ -41,7 +41,7 @@ public enum AiPlatformEnum { AiPlatformEnum.MIDJOURNEY ); - public static AiPlatformEnum valueOfPlatform(String platform) { + public static AiPlatformEnum validatePlatform(String platform) { for (AiPlatformEnum itemEnum : AiPlatformEnum.values()) { if (itemEnum.getPlatform().equals(platform)) { return itemEnum; From 99ab07de69258ee04dee4e84a888f56151d83476 Mon Sep 17 00:00:00 2001 From: scholar <1145227973@qq.com> Date: Sat, 11 May 2024 11:35:27 +0800 Subject: [PATCH 255/684] =?UTF-8?q?=E5=AE=8C=E6=88=90todo=20xml=E9=83=A8?= =?UTF-8?q?=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CrmStatisticsPerformanceServiceImpl.java | 88 ++++++------------- .../CrmStatisticsPerformanceMapper.xml | 48 +++++----- 2 files changed, 50 insertions(+), 86 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java index b8fa94c7a..07734e01d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java @@ -16,10 +16,12 @@ import org.springframework.validation.annotation.Validated; import jakarta.annotation.Resource; import java.math.BigDecimal; +import java.time.LocalDateTime; import java.util.*; import java.util.function.Function; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; /** * CRM 员工业绩分析 Service 实现类 @@ -55,85 +57,47 @@ public class CrmStatisticsPerformanceServiceImpl implements CrmStatisticsPerform } /** - * 获得员工业绩数据,并通过如下方法拿到对应的lastYearCount,lastMonthCount - * 比如说,构造2024 年的CrmStatisticsPerformanceRespVO,获得 2023-01 到 2024-12的月统计数据即可 - * 可以数据 group by 年-月,2023-01 到 2024-12的,然后聚合出 CrmStatisticsPerformanceRespVO + * 获得员工业绩数据 + * + * 1. 获得今年 + 去年的数据 + * 2. 遍历今年的月份,逐个拼接去年的月份数据 + * * @param performanceReqVO 参数 * @param performanceFunction 员工业绩统计方法 * @return 员工业绩数据 */ private List getPerformance(CrmStatisticsPerformanceReqVO performanceReqVO, - Function> performanceFunction) { + Function> performanceFunction) { // 1. 获得用户编号数组 - final List userIds = getUserIds(performanceReqVO); + List userIds = getUserIds(performanceReqVO); if (CollUtil.isEmpty(userIds)) { return Collections.emptyList(); } performanceReqVO.setUserIds(userIds); // 2. 获得业绩数据 + int year = Integer.parseInt(LocalDateTimeUtil.format(performanceReqVO.getTimes()[0],"yyyy"));//获取查询的年份 + LocalDateTime[] timesRange = performanceReqVO.getTimes();//以时间段形式去数据库查询,时间段为所查询年份和前一年,两年时间的数据,便于计算同比数据 + timesRange[0] = performanceReqVO.getTimes()[0].minusYears(1);//查询的起始时间往前推一年 + timesRange[1] = performanceReqVO.getTimes()[1];//查询的结束时间 + performanceReqVO.setTimes(timesRange); List performanceList = performanceFunction.apply(performanceReqVO); + Map performanceMap = convertMap(performanceList, CrmStatisticsPerformanceRespVO::getTime, + CrmStatisticsPerformanceRespVO::getCurrentMonthCount); - // 获取查询的年份 - String currentYear = LocalDateTimeUtil.format(performanceReqVO.getTimes()[0],"yyyy"); - Map currentYearMap = new TreeMap<>();//查询当年的map数据 - Map lastYearMap = new TreeMap<>();//前一年的map数据 - + // 3. 组装数据返回 + List result = new ArrayList<>(); for (int month = 1; month <= 12; month++) { - //根据数据库的月销售数据查询结果,构造查询当年的map数据 - String currentYearKey = String.format("%d%02d", Integer.parseInt(currentYear), month); - buildYearMapData(performanceList, currentYearMap, currentYearKey); - - //根据数据库的月销售数据查询结果,构造查询前一年的map数据 - String lastYearKey = String.format("%d%02d", Integer.parseInt(currentYear)-1, month); - buildYearMapData(performanceList, lastYearMap, lastYearKey); - } - //根据构造好的map数据,计算查询当年的环比和同比数据,并构造好返回的respVOList - List respVOList = new ArrayList<>(); - for (int key : currentYearMap.keySet()) { - BigDecimal lastYearCount = lastYearMap.get(key-100).getCurrentMonthCount(); - BigDecimal lastMonthCount; - if (key % 100 > 1) {//2-12月份的前一个月数据 - lastMonthCount = currentYearMap.get(key-1).getCurrentMonthCount(); - } else {//1月份的前一个月数据 - lastMonthCount = lastYearMap.get(key-89).getCurrentMonthCount(); - } - - currentYearMap.get(key).setLastYearCount(lastYearCount); - currentYearMap.get(key).setLastMonthCount(lastMonthCount); - - respVOList.add(currentYearMap.get(key)); - } - - return respVOList; - } - - /** - * 根据mapKey,添加当年和前一年的月销售记录到对应的map结构中 - * @param performanceList 数据库中查询到的月销售记录 - * @param YearDataMap 将查询到的月销售记录put到对应的map中,如果月销售记录为null,置为0 - * @param mapKey 对应的mapKey - */ - private void buildYearMapData(List performanceList, - Map YearDataMap, - String mapKey) - { - CrmStatisticsPerformanceRespVO currentYearData = performanceList.stream() - .filter(data -> data.getTime().equals(mapKey)) - .findFirst() - .orElse(null); - - if(currentYearData != null) { - YearDataMap.put(Integer.parseInt(mapKey), currentYearData); - } else { - CrmStatisticsPerformanceRespVO defaultVO = new CrmStatisticsPerformanceRespVO(); - defaultVO.setTime(mapKey); - defaultVO.setCurrentMonthCount(BigDecimal.ZERO); - defaultVO.setLastMonthCount(BigDecimal.ZERO); - defaultVO.setLastYearCount(BigDecimal.ZERO); - YearDataMap.put(Integer.parseInt(mapKey), defaultVO); + String currentMonth = String.format("%d%02d", year, month); + String lastMonth = month == 1 ? String.format("%d%02d", year - 1, 12) : String.format("%d%02d", year, month - 1); + String lastYear = String.format("%d%02d", year - 1, month); + result.add(new CrmStatisticsPerformanceRespVO().setTime(currentMonth) + .setCurrentMonthCount(performanceMap.getOrDefault(currentMonth, BigDecimal.ZERO)) + .setLastMonthCount(performanceMap.getOrDefault(lastMonth, BigDecimal.ZERO)) + .setLastYearCount(performanceMap.getOrDefault(lastYear, BigDecimal.ZERO))); } + return result; } /** diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsPerformanceMapper.xml b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsPerformanceMapper.xml index ee9ec4e44..f22b4fabe 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsPerformanceMapper.xml +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsPerformanceMapper.xml @@ -5,51 +5,51 @@ From 73ef9211f92a105290c92cc49114a620fe553b17 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 11 May 2024 17:55:36 +0800 Subject: [PATCH 256/684] =?UTF-8?q?feat=EF=BC=9A=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=B0=8F=E7=A8=8B=E5=BA=8F=E7=A0=81=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/social/AppSocialUserController.java | 18 ++++- .../app/social/vo/AppSocialWxQrcodeReqVO.java | 65 +++++++++++++++++++ .../system/api/social/SocialUserApi.java | 20 ++++-- .../api/social/dto/SocialWxQrcodeReqDTO.java | 64 ++++++++++++++++++ .../system/enums/ErrorCodeConstants.java | 6 +- .../system/api/social/SocialUserApiImpl.java | 6 ++ .../service/social/SocialClientService.java | 26 +++++--- .../social/SocialClientServiceImpl.java | 24 +++++-- .../service/social/SocialUserService.java | 9 +++ .../service/social/SocialUserServiceImpl.java | 6 ++ 10 files changed, 219 insertions(+), 25 deletions(-) create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java create mode 100644 yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialWxQrcodeReqDTO.java diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java index fcdd2132d..304bb1690 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java @@ -7,18 +7,21 @@ import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserBindReqVO; import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserRespVO; import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserUnbindReqVO; +import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialWxQrcodeReqVO; import cn.iocoder.yudao.module.system.api.social.SocialUserApi; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialWxQrcodeReqDTO; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Operation; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; +import java.util.Base64; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -60,4 +63,13 @@ public class AppSocialUserController { return success(BeanUtils.toBean(socialUser, AppSocialUserRespVO.class)); } + @PostMapping("/wxacode") + @Operation(summary = "获得微信小程序码") + @PreAuthenticated + public CommonResult getWxQrcode(@RequestBody @Valid AppSocialWxQrcodeReqVO reqVO) { + byte[] wxQrcode = socialUserApi.getWxQrcode(BeanUtils.toBean(reqVO, SocialWxQrcodeReqDTO.class).setUserId(getLoginUserId()) + .setUserType(UserTypeEnum.MEMBER.getValue()).setSocialType(reqVO.getType())); + return success(Base64.getEncoder().encodeToString(wxQrcode)); + } + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java new file mode 100644 index 000000000..fd352fb8e --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java @@ -0,0 +1,65 @@ +package cn.iocoder.yudao.module.member.controller.app.social.vo; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "用户 APP - 获得获取小程序码 Request VO") +@Data +public class AppSocialWxQrcodeReqVO { + + private static String SCENE = "1011"; // 默认场景值 1011 扫描二维码 + private static String ENV_VERSION = "develop"; // 小程序版本。正式版为 "release",体验版为 "trial",开发版为 "develop" + private static Integer WIDTH = 430; // 二维码宽度 + private static Boolean AUTO_COLOR = true; // 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 + private static Boolean CHECK_PATH = true; // 默认true 检查 page 是否存在 + private static Boolean IS_HYALINE = true; // 是否需要透明底色, is_hyaline 为true时,生成透明底色的小程序码 + + /** + * 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~, 其它字符请自行编码为合法字符 + * (因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式) + */ + @Schema(description = "场景值/页面参数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1001") + private String scene = SCENE; + /** + * 页面路径 + */ + @Schema(description = "页面路径", requiredMode = Schema.RequiredMode.REQUIRED, example = "pages/goods/index") + @NotEmpty(message = "页面路径不能为空") + private String path; + /** + * 要打开的小程序版本。默认是开发版。 + */ + @Schema(description = "小程序版本", requiredMode = Schema.RequiredMode.REQUIRED, example = "develop") + private String envVersion = ENV_VERSION; + /** + * 二维码宽度 + */ + @Schema(description = "二维码宽度", requiredMode = Schema.RequiredMode.REQUIRED, example = "430") + private Integer width = WIDTH; + /** + * 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 + */ + @Schema(description = "是/否自动配置线条颜色", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean isAutoColor = AUTO_COLOR; + /** + * 默认true 检查 page 是否存在,为 true 时 page 必须是已经发布的小程序存在的页面(否则报错); + * 为 false 时允许小程序未发布或者 page 不存在,但 page 有数量上限(60000个)请勿滥用 + */ + @Schema(description = "是/否检查 page 是否存在", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean isCheckPath = CHECK_PATH; + /** + * 是否需要透明底色, is_hyaline 为true时,生成透明底色的小程序码 + */ + @Schema(description = "是/否需要透明底色", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean isHyaline = IS_HYALINE; + + @Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @InEnum(SocialTypeEnum.class) + @NotNull(message = "社交平台的类型不能为空") + private Integer type; + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java index e24f8356d..3bde3eab9 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; - +import cn.iocoder.yudao.module.system.api.social.dto.SocialWxQrcodeReqDTO; import jakarta.validation.Valid; /** @@ -32,8 +32,8 @@ public interface SocialUserApi { /** * 获得社交用户,基于 userId * - * @param userType 用户类型 - * @param userId 用户编号 + * @param userType 用户类型 + * @param userId 用户编号 * @param socialType 社交平台的类型 * @return 社交用户 */ @@ -44,12 +44,20 @@ public interface SocialUserApi { * * 在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常 * - * @param userType 用户类型 + * @param userType 用户类型 * @param socialType 社交平台的类型 - * @param code 授权码 - * @param state state + * @param code 授权码 + * @param state state * @return 社交用户 */ SocialUserRespDTO getSocialUserByCode(Integer userType, Integer socialType, String code, String state); + /** + * 获得小程序二维码 + * + * @param reqVO 请求信息 + * @return 小程序二维码 + */ + byte[] getWxQrcode(@Valid SocialWxQrcodeReqDTO reqVO); + } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialWxQrcodeReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialWxQrcodeReqDTO.java new file mode 100644 index 000000000..00b7ea488 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialWxQrcodeReqDTO.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.system.api.social.dto; + +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class SocialWxQrcodeReqDTO { + + /** + * 用户编号 + */ + @NotNull(message = "用户编号不能为空") + private Long userId; + /** + * 用户类型 + */ + @InEnum(UserTypeEnum.class) + @NotNull(message = "用户类型不能为空") + private Integer userType; + + /** + * 社交平台的类型 + */ + @InEnum(SocialTypeEnum.class) + @NotNull(message = "社交平台的类型不能为空") + private Integer socialType; + + /** + * 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~, 其它字符请自行编码为合法字符 + * (因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式) + */ + private String scene; + /** + * 页面路径 + */ + @NotEmpty(message = "页面路径不能为空") + private String path; + /** + * 要打开的小程序版本。默认是开发版。 + */ + private String envVersion; + /** + * 二维码宽度 + */ + private Integer width; + /** + * 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 + */ + private Boolean isAutoColor; + /** + * 默认true 检查 page 是否存在,为 true 时 page 必须是已经发布的小程序存在的页面(否则报错); + * 为 false 时允许小程序未发布或者 page 不存在,但 page 有数量上限(60000个)请勿滥用 + */ + private Boolean isCheckPath; + /** + * 是否需要透明底色, is_hyaline 为true时,生成透明底色的小程序码 + */ + private Boolean isHyaline; + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java index 1b4c313c8..412ac413e 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java @@ -120,8 +120,10 @@ public interface ErrorCodeConstants { ErrorCode SOCIAL_USER_NOT_FOUND = new ErrorCode(1_002_018_001, "社交授权失败,找不到对应的用户"); ErrorCode SOCIAL_CLIENT_WEIXIN_MINI_APP_PHONE_CODE_ERROR = new ErrorCode(1_002_018_200, "获得手机号失败"); - ErrorCode SOCIAL_CLIENT_NOT_EXISTS = new ErrorCode(1_002_018_201, "社交客户端不存在"); - ErrorCode SOCIAL_CLIENT_UNIQUE = new ErrorCode(1_002_018_202, "社交客户端已存在配置"); + ErrorCode SOCIAL_CLIENT_WEIXIN_MINI_APP_QRCODE_ERROR = new ErrorCode(1_002_018_201, "获得小程序码失败"); + ErrorCode SOCIAL_CLIENT_NOT_EXISTS = new ErrorCode(1_002_018_202, "社交客户端不存在"); + ErrorCode SOCIAL_CLIENT_UNIQUE = new ErrorCode(1_002_018_203, "社交客户端已存在配置"); + // ========== OAuth2 客户端 1-002-020-000 ========= ErrorCode OAUTH2_CLIENT_NOT_EXISTS = new ErrorCode(1_002_020_000, "OAuth2 客户端不存在"); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java index eb8331618..c5e3e490a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.api.social; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialWxQrcodeReqDTO; import cn.iocoder.yudao.module.system.service.social.SocialUserService; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -42,4 +43,9 @@ public class SocialUserApiImpl implements SocialUserApi { return socialUserService.getSocialUserByCode(userType, socialType, code, state); } + @Override + public byte[] getWxQrcode(SocialWxQrcodeReqDTO reqVO) { + return socialUserService.getWxQrcode(reqVO); + } + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientService.java index f41e8d371..f7d8cd0e2 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientService.java @@ -2,14 +2,14 @@ package cn.iocoder.yudao.module.system.service.social; import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.api.social.dto.SocialWxQrcodeReqDTO; import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialClientDO; import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import com.xingyuv.jushauth.model.AuthUser; -import me.chanjar.weixin.common.bean.WxJsapiSignature; - import jakarta.validation.Valid; +import me.chanjar.weixin.common.bean.WxJsapiSignature; /** * 社交应用 Service 接口 @@ -21,8 +21,8 @@ public interface SocialClientService { /** * 获得社交平台的授权 URL * - * @param socialType 社交平台的类型 {@link SocialTypeEnum} - * @param userType 用户类型 + * @param socialType 社交平台的类型 {@link SocialTypeEnum} + * @param userType 用户类型 * @param redirectUri 重定向 URL * @return 社交平台的授权 URL */ @@ -32,9 +32,9 @@ public interface SocialClientService { * 请求社交平台,获得授权的用户 * * @param socialType 社交平台的类型 - * @param userType 用户类型 - * @param code 授权码 - * @param state 授权 state + * @param userType 用户类型 + * @param code 授权码 + * @param state 授权 state * @return 授权的用户 */ AuthUser getAuthUser(Integer socialType, Integer userType, String code, String state); @@ -45,7 +45,7 @@ public interface SocialClientService { * 创建微信公众号的 JS SDK 初始化所需的签名 * * @param userType 用户类型 - * @param url 访问的 URL 地址 + * @param url 访问的 URL 地址 * @return 签名 */ WxJsapiSignature createWxMpJsapiSignature(Integer userType, String url); @@ -55,12 +55,20 @@ public interface SocialClientService { /** * 获得微信小程序的手机信息 * - * @param userType 用户类型 + * @param userType 用户类型 * @param phoneCode 手机授权码 * @return 手机信息 */ WxMaPhoneNumberInfo getWxMaPhoneNumberInfo(Integer userType, String phoneCode); + /** + * 获得小程序二维码 + * + * @param reqVO 请求信息 + * @return 小程序二维码 + */ + byte[] getWxQrcode(SocialWxQrcodeReqDTO reqVO); + // =================== 客户端管理 =================== /** diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java index 84da0e5e1..978f6161c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java @@ -13,6 +13,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.cache.CacheUtils; import cn.iocoder.yudao.framework.common.util.http.HttpUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.system.api.social.dto.SocialWxQrcodeReqDTO; import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialClientDO; @@ -139,7 +140,7 @@ public class SocialClientServiceImpl implements SocialClientService { * 构建 AuthRequest 对象,支持多租户配置 * * @param socialType 社交类型 - * @param userType 用户类型 + * @param userType 用户类型 * @return AuthRequest 对象 */ @VisibleForTesting @@ -196,7 +197,7 @@ public class SocialClientServiceImpl implements SocialClientService { /** * 创建 clientId + clientSecret 对应的 WxMpService 对象 * - * @param clientId 微信公众号 appId + * @param clientId 微信公众号 appId * @param clientSecret 微信公众号 secret * @return WxMpService 对象 */ @@ -227,6 +228,19 @@ public class SocialClientServiceImpl implements SocialClientService { } } + @Override + public byte[] getWxQrcode(SocialWxQrcodeReqDTO reqVO) { + WxMaService service = getWxMaService(reqVO.getUserType()); + try { + return service.getQrcodeService().createWxaCodeUnlimitBytes(reqVO.getScene(), reqVO.getPath(), + reqVO.getIsCheckPath(), reqVO.getEnvVersion(), reqVO.getWidth(), reqVO.getIsAutoColor(), + null, reqVO.getIsHyaline()); + } catch (WxErrorException e) { + log.error("[getWxQrcode][reqVO({})) 获得小程序码失败]", reqVO, e); + throw exception(SOCIAL_CLIENT_WEIXIN_MINI_APP_QRCODE_ERROR); + } + } + /** * 获得 clientId + clientSecret 对应的 WxMpService 对象 * @@ -248,7 +262,7 @@ public class SocialClientServiceImpl implements SocialClientService { /** * 创建 clientId + clientSecret 对应的 WxMaService 对象 * - * @param clientId 微信小程序 appId + * @param clientId 微信小程序 appId * @param clientSecret 微信小程序 secret * @return WxMaService 对象 */ @@ -310,8 +324,8 @@ public class SocialClientServiceImpl implements SocialClientService { * * 原因是,不同端(userType)选择某个社交登录(socialType)时,需要通过 {@link #buildAuthRequest(Integer, Integer)} 构建对应的请求 * - * @param id 编号 - * @param userType 用户类型 + * @param id 编号 + * @param userType 用户类型 * @param socialType 社交类型 */ private void validateSocialClientUnique(Long id, Integer userType, Integer socialType) { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java index 739ff2d94..40ba45542 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialWxQrcodeReqDTO; import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; @@ -86,4 +87,12 @@ public interface SocialUserService { */ PageResult getSocialUserPage(SocialUserPageReqVO pageReqVO); + /** + * 获得小程序二维码 + * + * @param reqVO 请求信息 + * @return 小程序二维码 + */ + byte[] getWxQrcode(SocialWxQrcodeReqDTO reqVO); + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java index 7f1b271ad..5d236e938 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialWxQrcodeReqDTO; import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserBindDO; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; @@ -170,4 +171,9 @@ public class SocialUserServiceImpl implements SocialUserService { return socialUserMapper.selectPage(pageReqVO); } + @Override + public byte[] getWxQrcode(SocialWxQrcodeReqDTO reqVO) { + return socialClientService.getWxQrcode(reqVO); + } + } From 9fbaada1be2cc0f9045731a29e156465acd63d24 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 11 May 2024 19:46:49 +0800 Subject: [PATCH 257/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9AAPI=20=E6=A8=A1=E5=9E=8B=E7=AE=A1=E7=90=86=EF=BC=88?= =?UTF-8?q?=E5=AE=8C=E5=96=84=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/admin/model/AiApiKeyController.java | 12 ++++++++++++ .../admin/model/AiChatModelController.java | 12 ++++++++++++ .../module/ai/dal/mysql/AiChatModelMapper.java | 10 +++++++++- .../module/ai/service/model/AiApiKeyService.java | 9 +++++++++ .../ai/service/model/AiApiKeyServiceImpl.java | 7 +++++++ .../ai/service/model/AiChatModelService.java | 14 ++++++++++++-- .../ai/service/model/AiChatModelServiceImpl.java | 8 ++++++++ .../iocoder/yudao/framework/ai/AiPlatformEnum.java | 12 ++++++------ 8 files changed, 75 insertions(+), 9 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiApiKeyController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiApiKeyController.java index 78b588647..2bc190051 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiApiKeyController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiApiKeyController.java @@ -6,7 +6,9 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyRespVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelRespVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -17,7 +19,10 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.List; + import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @Tag(name = "管理后台 - AI API 密钥") @RestController @@ -69,4 +74,11 @@ public class AiApiKeyController { return success(BeanUtils.toBean(pageResult, AiApiKeyRespVO.class)); } + @GetMapping("/simple-list") + @Operation(summary = "获得 API 密钥分页列表") + public CommonResult> getApiKeySimpleList() { + List list = apiKeyService.getApiKeyList(); + return success(convertList(list, key -> new AiChatModelRespVO().setId(key.getId()).setName(key.getName()))); + } + } \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java index 7d73e222a..6d568140b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java @@ -17,7 +17,11 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.List; +import java.util.function.Function; + import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @Tag(name = "管理后台 - AI 聊天模型") @RestController @@ -69,4 +73,12 @@ public class AiChatModelController { return success(BeanUtils.toBean(pageResult, AiChatModelRespVO.class)); } + @GetMapping("/simple-list") + @Operation(summary = "获得聊天模型列表") + @Parameter(name = "status", description = "状态", required = true, example = "1") + public CommonResult> getChatModelSimpleList(@RequestParam("status") Integer status) { + List list = chatModelService.getChatModelList(status); + return success(convertList(list, model -> new AiChatModelRespVO().setId(model.getId()).setName(model.getName()))); + } + } \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java index c2d75a218..289730f93 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java @@ -9,6 +9,8 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatMode import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import org.apache.ibatis.annotations.Mapper; +import java.util.List; + /** * API 聊天模型 Mapper * @@ -39,7 +41,13 @@ public interface AiChatModelMapper extends BaseMapperX { .likeIfPresent(AiChatModelDO::getName, reqVO.getName()) .eqIfPresent(AiChatModelDO::getModel, reqVO.getModel()) .eqIfPresent(AiChatModelDO::getPlatform, reqVO.getPlatform()) - .orderByDesc(AiChatModelDO::getId)); + .orderByAsc(AiChatModelDO::getSort)); + } + + default List selectList(Integer status) { + return selectList(new LambdaQueryWrapperX() + .eq(AiChatModelDO::getStatus, status) + .orderByAsc(AiChatModelDO::getSort)); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java index 4da3c3500..331dd62e2 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java @@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveR import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; import jakarta.validation.Valid; +import java.util.List; + /** * AI API 密钥 Service 接口 * @@ -59,4 +61,11 @@ public interface AiApiKeyService { */ PageResult getApiKeyPage(AiApiKeyPageReqVO pageReqVO); + /** + * 获得 API 密钥列表 + * + * @return API 密钥列表 + */ + List getApiKeyList(); + } \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java index 06e68748f..f8a83ce57 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java @@ -11,6 +11,8 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import java.util.List; + import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.*; @@ -79,4 +81,9 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { return apiKeyMapper.selectPage(pageReqVO); } + @Override + public List getApiKeyList() { + return apiKeyMapper.selectList(); + } + } \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelService.java index d05941989..72d2233e5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelService.java @@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatMode import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import jakarta.validation.Valid; +import java.util.List; + /** * AI 聊天模型 Service 接口 * @@ -40,7 +42,7 @@ public interface AiChatModelService { * 获得聊天模型 * * @param id 编号 - * @return API 聊天模型 + * @return 聊天模型 */ AiChatModelDO getChatModel(Long id); @@ -48,7 +50,7 @@ public interface AiChatModelService { * 获得聊天模型分页 * * @param pageReqVO 分页查询 - * @return API 聊天模型分页 + * @return 聊天模型分页 */ PageResult getChatModelPage(AiChatModelPageReqVO pageReqVO); @@ -60,4 +62,12 @@ public interface AiChatModelService { */ AiChatModelDO validateChatModel(Long id); + /** + * 获得聊天模型列表 + * + * @param status 状态 + * @return 聊天模型列表 + */ + List getChatModelList(Integer status); + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java index 0c0386ccc..47c3cad57 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java @@ -12,6 +12,8 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import java.util.List; + import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.*; @@ -89,4 +91,10 @@ public class AiChatModelServiceImpl implements AiChatModelService { return model; } + @Override + public List getChatModelList(Integer status) { + chatModelMapper.selectList(status); + return null; + } + } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java index c774d2515..3882e1a99 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java @@ -20,7 +20,7 @@ public enum AiPlatformEnum { YI_YAN("yiyan", "一言"), QIAN_WEN("qianwen", "千问"), XING_HUO("xinghuo", "星火"), - OPEN_AI("openai", "openAi"), // TODO 芋艿:OpenAI + OPENAI("OpenAI", "OpenAI"), OPEN_AI_DALL("dall", "dall"), MIDJOURNEY("midjourney", "midjourney"), @@ -33,7 +33,7 @@ public enum AiPlatformEnum { AiPlatformEnum.YI_YAN, AiPlatformEnum.QIAN_WEN, AiPlatformEnum.XING_HUO, - AiPlatformEnum.OPEN_AI + AiPlatformEnum.OPENAI ); public static List IMAGE_PLATFORM_LIST = Lists.newArrayList( @@ -42,12 +42,12 @@ public enum AiPlatformEnum { ); public static AiPlatformEnum validatePlatform(String platform) { - for (AiPlatformEnum itemEnum : AiPlatformEnum.values()) { - if (itemEnum.getPlatform().equals(platform)) { - return itemEnum; + for (AiPlatformEnum platformEnum : AiPlatformEnum.values()) { + if (platformEnum.getPlatform().equals(platform)) { + return platformEnum; } } - throw new IllegalArgumentException("Invalid MessageType value: " + platform); + throw new IllegalArgumentException("非法平台: " + platform); } } From 0641f793a374b8056c97cc226156776858cc3608 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 11 May 2024 21:51:59 +0800 Subject: [PATCH 258/684] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91=E5=85=A8=E5=B1=80=EF=BC=9A=E5=BE=AE=E4=BF=A1?= =?UTF-8?q?=E5=B0=8F=E7=A8=8B=E5=BA=8F=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/social/AppSocialUserController.java | 3 +- .../app/social/vo/AppSocialWxQrcodeReqVO.java | 39 +++++++------------ .../api/social/dto/SocialWxQrcodeReqDTO.java | 28 +++++++++---- .../system/api/social/SocialUserApiImpl.java | 1 + 4 files changed, 39 insertions(+), 32 deletions(-) diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java index 304bb1690..f6a351a33 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java @@ -63,9 +63,10 @@ public class AppSocialUserController { return success(BeanUtils.toBean(socialUser, AppSocialUserRespVO.class)); } + // TODO @puhui999:是不是 url 叫 wxa-qrcode?然后相关的方法,都做下调整哈;因为是微信小程序的二维码 @PostMapping("/wxacode") @Operation(summary = "获得微信小程序码") - @PreAuthenticated + @PreAuthenticated // TODO @puhui999:可能不需要登录 public CommonResult getWxQrcode(@RequestBody @Valid AppSocialWxQrcodeReqVO reqVO) { byte[] wxQrcode = socialUserApi.getWxQrcode(BeanUtils.toBean(reqVO, SocialWxQrcodeReqDTO.class).setUserId(getLoginUserId()) .setUserType(UserTypeEnum.MEMBER.getValue()).setSocialType(reqVO.getType())); diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java index fd352fb8e..15d9e20a1 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java @@ -7,53 +7,44 @@ import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.Data; +// TODO @芋艿:需要精简下参数; @Schema(description = "用户 APP - 获得获取小程序码 Request VO") @Data public class AppSocialWxQrcodeReqVO { + // TODO @puhui999:这个后续不用前端传递,应该是后端搞的 private static String SCENE = "1011"; // 默认场景值 1011 扫描二维码 + // TODO @puhui999:这个默认是不是 release 哈? private static String ENV_VERSION = "develop"; // 小程序版本。正式版为 "release",体验版为 "trial",开发版为 "develop" + // TODO @puhui999:这个去掉;因为本身就是 430 啦; private static Integer WIDTH = 430; // 二维码宽度 + // TODO @puhui999:这个去掉;因为本身就是 true 啦; private static Boolean AUTO_COLOR = true; // 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 + // TODO @puhui999:这个去掉;因为本身就是 true 啦; private static Boolean CHECK_PATH = true; // 默认true 检查 page 是否存在 + // TODO @puhui999:这个去掉;因为本身就是 true 啦; private static Boolean IS_HYALINE = true; // 是否需要透明底色, is_hyaline 为true时,生成透明底色的小程序码 - /** - * 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~, 其它字符请自行编码为合法字符 - * (因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式) - */ - @Schema(description = "场景值/页面参数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1001") + @Schema(description = "场景值", requiredMode = Schema.RequiredMode.REQUIRED, example = "1001") private String scene = SCENE; - /** - * 页面路径 - */ + @Schema(description = "页面路径", requiredMode = Schema.RequiredMode.REQUIRED, example = "pages/goods/index") @NotEmpty(message = "页面路径不能为空") private String path; - /** - * 要打开的小程序版本。默认是开发版。 - */ + + // TODO @puhui999:这个应该不传递哈 @Schema(description = "小程序版本", requiredMode = Schema.RequiredMode.REQUIRED, example = "develop") private String envVersion = ENV_VERSION; - /** - * 二维码宽度 - */ + @Schema(description = "二维码宽度", requiredMode = Schema.RequiredMode.REQUIRED, example = "430") private Integer width = WIDTH; - /** - * 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 - */ + @Schema(description = "是/否自动配置线条颜色", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") private Boolean isAutoColor = AUTO_COLOR; - /** - * 默认true 检查 page 是否存在,为 true 时 page 必须是已经发布的小程序存在的页面(否则报错); - * 为 false 时允许小程序未发布或者 page 不存在,但 page 有数量上限(60000个)请勿滥用 - */ + @Schema(description = "是/否检查 page 是否存在", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") private Boolean isCheckPath = CHECK_PATH; - /** - * 是否需要透明底色, is_hyaline 为true时,生成透明底色的小程序码 - */ + @Schema(description = "是/否需要透明底色", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") private Boolean isHyaline = IS_HYALINE; diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialWxQrcodeReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialWxQrcodeReqDTO.java index 00b7ea488..d5e7f194f 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialWxQrcodeReqDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialWxQrcodeReqDTO.java @@ -7,9 +7,17 @@ import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.Data; +/** + * 获取小程序码 Request DTO + * + * @see 获取不限制的小程序码 + * + * @author HUIHUI + */ @Data public class SocialWxQrcodeReqDTO { + // TODO @puhui999:userId、userType 应该后续要搞成抽象参数;说白了,就是 path 的参数; socialType 应该去掉,因为就是微信的; /** * 用户编号 */ @@ -30,9 +38,9 @@ public class SocialWxQrcodeReqDTO { private Integer socialType; /** - * 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~, 其它字符请自行编码为合法字符 - * (因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式) + * 场景 */ + @NotEmpty(message = "场景不能为空") private String scene; /** * 页面路径 @@ -40,24 +48,30 @@ public class SocialWxQrcodeReqDTO { @NotEmpty(message = "页面路径不能为空") private String path; /** - * 要打开的小程序版本。默认是开发版。 + * 要打开的小程序版本 */ private String envVersion; /** * 二维码宽度 */ private Integer width; + + // TODO @puhui999:autoColor + /** - * 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 + * 是否需要透明底色 */ private Boolean isAutoColor; + + // TODO @puhui999: checkPath /** - * 默认true 检查 page 是否存在,为 true 时 page 必须是已经发布的小程序存在的页面(否则报错); - * 为 false 时允许小程序未发布或者 page 不存在,但 page 有数量上限(60000个)请勿滥用 + * 是否检查 page 是否存在 */ private Boolean isCheckPath; + + // TODO @puhui999: hyaline /** - * 是否需要透明底色, is_hyaline 为true时,生成透明底色的小程序码 + * 是否需要透明底色 */ private Boolean isHyaline; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java index c5e3e490a..ad56c9ee5 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java @@ -43,6 +43,7 @@ public class SocialUserApiImpl implements SocialUserApi { return socialUserService.getSocialUserByCode(userType, socialType, code, state); } + // TODO @puhui999:貌似搞到 SocialClientApiImpl 更合适,二维码和用户关系不大;这样 socialUserService 也不用绕一次了 @Override public byte[] getWxQrcode(SocialWxQrcodeReqDTO reqVO) { return socialUserService.getWxQrcode(reqVO); From e1a5302b251a603fd6440632cec176df815248a0 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 11 May 2024 22:05:41 +0800 Subject: [PATCH 259/684] =?UTF-8?q?=E3=80=90=E4=BF=AE=E5=A4=8D=E3=80=91?= =?UTF-8?q?=E5=95=86=E5=9F=8E=EF=BC=9A=E7=A7=92=E6=9D=80=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E6=AE=B5=E9=85=8D=E7=BD=AE=E7=9A=84=20URL=20`simple-list`=20?= =?UTF-8?q?=E4=B8=8D=E6=AD=A3=E7=A1=AE=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/admin/seckill/SeckillConfigController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java index 21b9a1400..093003bac 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java @@ -78,9 +78,9 @@ public class SeckillConfigController { return success(SeckillConfigConvert.INSTANCE.convertList(list)); } - @GetMapping("/list-all-simple") + @GetMapping("/simple-list") @Operation(summary = "获得所有开启状态的秒杀时段精简列表", description = "主要用于前端的下拉选项") - public CommonResult> getListAllSimple() { + public CommonResult> getSeckillConfigSimpleList() { List list = seckillConfigService.getSeckillConfigListByStatus( CommonStatusEnum.ENABLE.getStatus()); return success(SeckillConfigConvert.INSTANCE.convertList1(list)); From 4a0ad205ae13ba7ca104dc5b75723a4d6b1a37f9 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 11 May 2024 22:30:37 +0800 Subject: [PATCH 260/684] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91CRM=EF=BC=9A=E4=BC=98=E5=8C=96=E5=91=98?= =?UTF-8?q?=E5=B7=A5=E4=B8=9A=E7=BB=A9=E7=BB=9F=E8=AE=A1=E7=9A=84=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CrmStatisticsPerformanceReqVO.java | 1 - .../CrmStatisticsPerformanceServiceImpl.java | 17 +++++++---------- .../CrmStatisticsPerformanceMapper.xml | 6 +++--- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/performance/CrmStatisticsPerformanceReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/performance/CrmStatisticsPerformanceReqVO.java index de76acbb3..bfb5c840f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/performance/CrmStatisticsPerformanceReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/performance/CrmStatisticsPerformanceReqVO.java @@ -33,7 +33,6 @@ public class CrmStatisticsPerformanceReqVO { @Schema(description = "负责人用户 id 集合", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "2") private List userIds; - // TODO @scholar:应该传递的是 int year;年份 @Schema(description = "时间范围", requiredMode = Schema.RequiredMode.REQUIRED) @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @NotEmpty(message = "时间范围不能为空") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java index 07734e01d..1e7e3bbb2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.crm.service.statistics; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceReqVO; import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceRespVO; @@ -10,14 +9,16 @@ import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; - import java.math.BigDecimal; import java.time.LocalDateTime; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; import java.util.function.Function; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @@ -40,7 +41,6 @@ public class CrmStatisticsPerformanceServiceImpl implements CrmStatisticsPerform @Resource private DeptApi deptApi; - @Override public List getContractCountPerformance(CrmStatisticsPerformanceReqVO performanceReqVO) { return getPerformance(performanceReqVO, performanceMapper::selectContractCountPerformance); @@ -77,11 +77,8 @@ public class CrmStatisticsPerformanceServiceImpl implements CrmStatisticsPerform performanceReqVO.setUserIds(userIds); // 2. 获得业绩数据 - int year = Integer.parseInt(LocalDateTimeUtil.format(performanceReqVO.getTimes()[0],"yyyy"));//获取查询的年份 - LocalDateTime[] timesRange = performanceReqVO.getTimes();//以时间段形式去数据库查询,时间段为所查询年份和前一年,两年时间的数据,便于计算同比数据 - timesRange[0] = performanceReqVO.getTimes()[0].minusYears(1);//查询的起始时间往前推一年 - timesRange[1] = performanceReqVO.getTimes()[1];//查询的结束时间 - performanceReqVO.setTimes(timesRange); + int year = performanceReqVO.getTimes()[0].getYear(); // 获取查询的年份 + performanceReqVO.getTimes()[0] = performanceReqVO.getTimes()[0].minusYears(1); List performanceList = performanceFunction.apply(performanceReqVO); Map performanceMap = convertMap(performanceList, CrmStatisticsPerformanceRespVO::getTime, CrmStatisticsPerformanceRespVO::getCurrentMonthCount); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsPerformanceMapper.xml b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsPerformanceMapper.xml index f22b4fabe..81962cdae 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsPerformanceMapper.xml +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsPerformanceMapper.xml @@ -7,7 +7,7 @@ SELECT DATE_FORMAT(order_date, '%Y%m') AS time, COUNT(1) AS currentMonthCount - FROM crm_contract + FROM crm_contract WHERE deleted = 0 AND audit_status = ${@cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum@APPROVE.status} AND owner_user_id in @@ -24,7 +24,7 @@ SELECT DATE_FORMAT(order_date, '%Y%m') AS time, IFNULL(SUM(total_price), 0) AS currentMonthCount - FROM crm_contract + FROM crm_contract WHERE deleted = 0 AND audit_status = ${@cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum@APPROVE.status} AND owner_user_id in @@ -41,7 +41,7 @@ SELECT DATE_FORMAT(return_time, '%Y%m') AS time, IFNULL(SUM(price), 0) AS currentMonthCount - FROM crm_receivable + FROM crm_receivable WHERE deleted = 0 AND audit_status = ${@cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum@APPROVE.status} AND owner_user_id in From 79bd78998d25dda9ab7f308c7ca8e9ee67912eed Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 12 May 2024 14:20:24 +0800 Subject: [PATCH 261/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=A8=A1=E5=9E=8B=E5=A4=B4=E5=83=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/vo/message/AiChatMessageRespVO.java | 10 ++++++++++ .../module/ai/dal/mysql/AiChatModelMapper.java | 12 +++++++++++- .../module/ai/service/AiChatModelService.java | 12 ++++++++++++ .../service/impl/AiChatModalServiceImpl.java | 7 +++++++ .../ai/service/impl/AiChatServiceImpl.java | 18 +++++++++++++++++- 5 files changed, 57 insertions(+), 2 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java index d5f830d17..f117c67c6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java @@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.time.LocalDateTime; + @Schema(description = "管理后台 - AI 聊天消息 Response VO") @Data public class AiChatMessageRespVO { @@ -19,6 +21,9 @@ public class AiChatMessageRespVO { @Schema(description = "用户编号", example = "4096") private Long userId; // 仅当 user 发送时非空 + @Schema(description = "用户头像", example = "http://xxx") + private Long avatarUrl; // 仅当 user 发送时非空 + @Schema(description = "角色编号", example = "888") private Long roleId; // 仅当 assistant 回复时非空 @@ -28,10 +33,15 @@ public class AiChatMessageRespVO { @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "123") private Long modelId; + @Schema(description = "模型图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "123") + private String modelImage; + @Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,你好啊") private String content; @Schema(description = "消耗 Token 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "80") private Integer tokens; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-05-12 12:51") + private LocalDateTime createTime; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java index 46d66ff5f..418b25975 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java @@ -9,6 +9,10 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; +import java.util.Collection; +import java.util.List; +import java.util.Set; + /** * chat modal * @@ -36,5 +40,11 @@ public interface AiChatModelMapper extends BaseMapperX { return pageResult.getList().get(0); } - + /** + * 查询 - 根据 ids + * + * @param modalIds + * @return + */ + List selectByIds(Collection modalIds); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModelService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModelService.java index 07a902dd8..d133c729e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModelService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModelService.java @@ -4,6 +4,9 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.*; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; +import java.util.List; +import java.util.Set; + /** * ai modal * @@ -64,4 +67,13 @@ public interface AiChatModelService { * @param chatModal */ void validateAvailable(AiChatModalRespVO chatModal); + + /** + * 获取 - 根据 ids 批量获取 + * + * @param modalIds + * @return + */ + List getModalByIds(Set modalIds); + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java index 0aec7a94c..e25110e1f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java @@ -17,6 +17,7 @@ import cn.iocoder.yudao.module.ai.service.AiChatModelService; import jakarta.validation.ConstraintViolation; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScannerRegistrar; import org.springframework.stereotype.Service; import java.util.List; @@ -35,6 +36,7 @@ import java.util.Set; public class AiChatModalServiceImpl implements AiChatModelService { private final AiChatModelMapper aiChatModelMapper; + private final MapperScannerRegistrar mapperScannerRegistrar; @Override public PageResult list(AiChatModelListReqVO req) { @@ -102,6 +104,11 @@ public class AiChatModalServiceImpl implements AiChatModelService { } } + @Override + public List getModalByIds(Set modalIds) { + return aiChatModelMapper.selectByIds(modalIds); + } + public AiChatModelDO validateExists(Long id) { AiChatModelDO aiChatModalDO = aiChatModelMapper.selectById(id); if (aiChatModalDO == null) { diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index 90649f417..de33e65e4 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessage import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiChatModalRespVO; import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatMessageMapper; @@ -29,8 +30,11 @@ import org.springframework.transaction.annotation.Transactional; import reactor.core.publisher.Flux; import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; +import java.util.stream.Collectors; /** * 聊天 service @@ -188,8 +192,20 @@ public class AiChatServiceImpl implements AiChatService { chatConversationService.validateExists(conversationId); // 获取对话所有 message List aiChatMessageDOList = aiChatMessageMapper.selectByConversationId(conversationId); + // 获取模型信息 + Set modalIds = aiChatMessageDOList.stream().map(AiChatMessageDO::getModelId).collect(Collectors.toSet()); + List modalList = aiChatModalService.getModalByIds(modalIds); + Map modalIdMap = modalList.stream().collect(Collectors.toMap(AiChatModelDO::getId, o -> o)); // 转换 AiChatMessageRespVO - return AiChatMessageConvert.INSTANCE.convertAiChatMessageRespVOList(aiChatMessageDOList); + List aiChatMessageRespList = AiChatMessageConvert.INSTANCE.convertAiChatMessageRespVOList(aiChatMessageDOList); + // 设置用户头像 和 模型头像 todo @芋艿 这里需要转换 用户头像、模型头像 + return aiChatMessageRespList.stream().map(item -> { + if (modalIdMap.containsKey(item.getModelId())) { +// modalIdMap.get(item.getModelId()); +// item.setModelImage() + } + return item; + }).collect(Collectors.toList()); } @Override From 5a4162cdc13bc9cb8939133cb24f1a9a936d3435 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 12 May 2024 19:04:58 +0800 Subject: [PATCH 262/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E4=BC=98=E5=8C=96=20chat=20event=20stream=20=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E4=BA=A4=E4=BA=92=EF=BC=8C=E5=A2=9E=E5=8A=A0=20add=20message?= =?UTF-8?q?=20=E4=BC=98=E5=85=88=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/ErrorCodeConstants.java | 4 + .../admin/chat/AiChatMessageController.java | 11 +- .../vo/message/AiChatMessageAddReqVO.java | 20 +++ .../vo/message/AiChatMessageAddRespVO.java | 17 +++ .../message/AiChatMessageSendStreamReqVO.java | 16 +++ .../ai/convert/AiChatMessageConvert.java | 9 ++ .../ai/dal/mysql/AiChatModelMapper.java | 1 - .../module/ai/service/AiChatModelService.java | 78 ----------- .../module/ai/service/AiChatService.java | 13 +- .../service/impl/AiChatModalServiceImpl.java | 132 ------------------ .../ai/service/impl/AiChatServiceImpl.java | 121 ++++++++++------ .../ai/service/model/AiChatModelService.java | 10 ++ .../service/model/AiChatModelServiceImpl.java | 8 ++ 13 files changed, 181 insertions(+), 259 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageAddReqVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageAddRespVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendStreamReqVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModelService.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index a3c343e12..4e101cd7e 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -36,5 +36,9 @@ public interface ErrorCodeConstants { ErrorCode AI_CHAT_ROLE_NOT_EXIST = new ErrorCode(1_022_000_060, "AI 角色不存在!"); ErrorCode AI_CHAT_ROLE_NOT_PUBLIC = new ErrorCode(1_022_000_060, "AI 角色未公开!"); + // chat + + ErrorCode AI_CHAT_MESSAGE_NOT_EXIST = new ErrorCode(1_022_000_100, "AI 提问的 MessageId 不存在!"); + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java index 82392ed27..fb0d9f5ad 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java @@ -1,8 +1,7 @@ package cn.iocoder.yudao.module.ai.controller.admin.chat; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.*; import cn.iocoder.yudao.module.ai.service.AiChatService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -38,10 +37,16 @@ public class AiChatMessageController { // TODO @fan:要不要使用 Flux 来返回;可以使用 Flux @Operation(summary = "发送消息(流式)", description = "流式返回,响应较快") @PostMapping(value = "/send-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) - public Flux sendMessageStream(@Validated @RequestBody AiChatMessageSendReqVO sendReqVO) { + public Flux sendMessageStream(@Validated @RequestBody AiChatMessageSendStreamReqVO sendReqVO) { return chatService.chatStream(sendReqVO); } + @Operation(summary = "添加/提问", description = "先创建好 message 前端才好渲染") + @PostMapping(value = "/add") + public CommonResult add(@Validated @RequestBody AiChatMessageAddReqVO req) { + return success(chatService.add(req)); + } + @Operation(summary = "获得指定会话的消息列表") @GetMapping("/list-by-conversation-id") @Parameter(name = "conversationId", required = true, description = "会话编号", example = "1024") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageAddReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageAddReqVO.java new file mode 100644 index 000000000..994472d03 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageAddReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - AI 聊天消息发送 Request VO") +@Data +public class AiChatMessageAddReqVO { + + @Schema(description = "聊天对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "聊天对话编号不能为空") + private Long conversationId; + + @Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "帮我写个 Java 算法") + @NotEmpty(message = "聊天内容不能为空") + private String content; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageAddRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageAddRespVO.java new file mode 100644 index 000000000..70cfb5b40 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageAddRespVO.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - AI 聊天消息 Add Response VO") +@Data +public class AiChatMessageAddRespVO { + + @Schema(description = "用户信息") + private AiChatMessageRespVO userMessage; + + @Schema(description = "系统信息") + private AiChatMessageRespVO systemMessage; +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendStreamReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendStreamReqVO.java new file mode 100644 index 000000000..cfd67ccba --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendStreamReqVO.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - AI 聊天消息发送 Request VO") +@Data +public class AiChatMessageSendStreamReqVO { + + @Schema(description = "提问的 messageId", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "提问的 messageId 不能为空") + private Long id; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java index a5019b2cd..05f7b83b6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java @@ -26,4 +26,13 @@ public interface AiChatMessageConvert { * @return */ List convertAiChatMessageRespVOList(List aiChatMessageDOList); + + /** + * 转换 - aiChatMessageDO + * + * @param aiChatMessageDO + * @return + */ + AiChatMessageRespVO convertAiChatMessageRespVO(AiChatMessageDO aiChatMessageDO); + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java index 8d00cd66c..7eaef6602 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java @@ -11,7 +11,6 @@ import org.apache.ibatis.annotations.Mapper; import java.util.Collection; import java.util.List; -import java.util.Set; /** * API 聊天模型 Mapper diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModelService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModelService.java deleted file mode 100644 index aeb7bbccb..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatModelService.java +++ /dev/null @@ -1,78 +0,0 @@ -package cn.iocoder.yudao.module.ai.service; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.*; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; - -import java.util.List; -import java.util.Set; - -/** - * ai modal - * - * @author fansili - * @time 2024/4/24 19:42 - * @since 1.0 - */ -public interface AiChatModelService { - - /** - * ai modal - 列表 - * - * @param req - * @return - */ - PageResult list(AiChatModelListReqVO req); - - /** - * ai modal - 添加 - * - * @param req - */ - void add(AiChatModelAddReqVO req); - - /** - * ai modal - 更新 - * - * @param req - */ - void update(AiChatModelUpdateReqVO req); - - /** - * ai modal - 删除 - * - * @param id - */ - void delete(Long id); - - /** - * 获取 - 获取 modal - * - * @param modalId - * @return - */ - AiChatModalRespVO getChatModalOfValidate(Long modalId); - - /** - * 校验 - 是否存在 - * - * @param id - * @return - */ - AiChatModelDO validateExists(Long id); - - /** - * 校验 - 校验是否可用 - * - * @param chatModal - */ - void validateAvailable(AiChatModalRespVO chatModal); - - /** - * 获取 - 根据 ids 批量获取 - * - * @param modalIds - * @return - */ - List getModalByIds(Set modalIds); -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java index a5e97ce5f..7be2b8afc 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.ai.service; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.*; import reactor.core.publisher.Flux; import java.util.List; @@ -29,7 +28,15 @@ public interface AiChatService { * @param sendReqVO * @return */ - Flux chatStream(AiChatMessageSendReqVO sendReqVO); + Flux chatStream(AiChatMessageSendStreamReqVO sendReqVO); + + /** + * 添加 - message + * + * @param sendReqVO + * @return + */ + AiChatMessageRespVO add(AiChatMessageAddReqVO sendReqVO); /** * 获取 - 获取对话 message list diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java deleted file mode 100644 index 51a972fa7..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatModalServiceImpl.java +++ /dev/null @@ -1,132 +0,0 @@ -package cn.iocoder.yudao.module.ai.service.impl; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.extra.validation.ValidationUtil; -import cn.iocoder.yudao.framework.ai.AiPlatformEnum; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.ai.ErrorCodeConstants; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.*; -import cn.iocoder.yudao.module.ai.convert.AiChatModelConvert; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; -import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModelMapper; -import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalConfigVO; -import cn.iocoder.yudao.module.ai.service.AiChatModelService; -import jakarta.validation.ConstraintViolation; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Set; - -/** - * ai 模型 - * - * @author fansili - * @time 2024/4/24 19:42 - * @since 1.0 - */ -@AllArgsConstructor -@Service -@Slf4j -public class AiChatModalServiceImpl implements AiChatModelService { - - private final AiChatModelMapper aiChatModelMapper; - - @Override - public PageResult list(AiChatModelListReqVO req) { - LambdaQueryWrapperX queryWrapperX = new LambdaQueryWrapperX<>(); - // 查询的都是未禁用的模型 - queryWrapperX.eq(AiChatModelDO::getStatus, CommonStatusEnum.ENABLE.getStatus()); - // search - if (!StrUtil.isBlank(req.getSearch())) { - queryWrapperX.like(AiChatModelDO::getName, req.getSearch().trim()); - } - // 默认排序 - queryWrapperX.orderByAsc(AiChatModelDO::getSort); - // 查询 - PageResult aiChatModalDOPageResult = aiChatModelMapper.selectPage(req, queryWrapperX); - // 转换 res - List resList = AiChatModelConvert.INSTANCE.convertAiChatModalListRes(aiChatModalDOPageResult.getList()); - return new PageResult<>(resList, aiChatModalDOPageResult.getTotal()); - } - - @Override - public void add(AiChatModelAddReqVO req) { - // 校验 platform、type - validatePlatform(req.getPlatform()); - // 转换 do - AiChatModelDO insertChatModalDO = AiChatModelConvert.INSTANCE.convertAiChatModalDO(req); - // 设置默认属性 - insertChatModalDO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - // 保存数据库 - aiChatModelMapper.insert(insertChatModalDO); - } - - @Override - public void update(AiChatModelUpdateReqVO req) { - // 校验 platform - validatePlatform(req.getPlatform()); - // 校验模型是否存在 - validateExists(req.getId()); - // 转换 updateChatModalDO - AiChatModelDO updateChatModalDO = AiChatModelConvert.INSTANCE.convertAiChatModalDO(req); - updateChatModalDO.setId(req.getId()); - // 更新数据库 - aiChatModelMapper.updateById(updateChatModalDO); - } - - @Override - public void delete(Long id) { - // 检查 modal 是否存在 - validateExists(id); - // 删除 delete - aiChatModelMapper.deleteById(id); - } - - @Override - public AiChatModalRespVO getChatModalOfValidate(Long modalId) { - // 检查 modal 是否存在 - AiChatModelDO aiChatModalDO = validateExists(modalId); - return AiChatModelConvert.INSTANCE.convertAiChatModalRes(aiChatModalDO); - } - - @Override - public void validateAvailable(AiChatModalRespVO chatModal) { - // 对话模型是否可用 - if (!CommonStatusEnum.ENABLE.getStatus().equals(chatModal.getStatus())) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_DISABLE_NOT_USED); - } - } - - @Override - public List getModalByIds(Set modalIds) { - return aiChatModelMapper.selectByIds(modalIds); - } - - public AiChatModelDO validateExists(Long id) { - AiChatModelDO aiChatModalDO = aiChatModelMapper.selectById(id); - if (aiChatModalDO == null) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_NOT_EXIST); - } - return aiChatModalDO; - } - - private void validatePlatform(String platform) { - try { - AiPlatformEnum.valueOfPlatform(platform); - } catch (IllegalArgumentException e) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_PLATFORM_PARAMS_INCORRECT, e.getMessage()); - } - } - - private void validateModalConfig(AiChatModalConfigVO aiChatModalConfigVO) { - Set> validate = ValidationUtil.validate(aiChatModalConfigVO); - for (ConstraintViolation constraintViolation : validate) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_CONFIG_PARAMS_INCORRECT, constraintViolation.getMessage()); - } - } -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index c3842e409..a7dcd122d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -7,11 +7,15 @@ import cn.iocoder.yudao.framework.ai.chat.ChatResponse; import cn.iocoder.yudao.framework.ai.chat.StreamingChatClient; import cn.iocoder.yudao.framework.ai.chat.messages.MessageType; import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.config.AiChatClientFactory; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageAddReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendStreamReqVO; import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; @@ -19,11 +23,12 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatMessageMapper; import cn.iocoder.yudao.module.ai.service.AiChatConversationService; -import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; import cn.iocoder.yudao.module.ai.service.AiChatRoleService; import cn.iocoder.yudao.module.ai.service.AiChatService; +import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.http.HttpMessageConverters; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import reactor.core.publisher.Flux; @@ -53,6 +58,7 @@ public class AiChatServiceImpl implements AiChatService { private final AiChatConversationService chatConversationService; private final AiChatModelService aiChatModalService; private final AiChatRoleService aiChatRoleService; + private final HttpMessageConverters messageConverters; @Transactional(rollbackFor = Exception.class) public AiChatMessageRespVO chat(AiChatMessageSendReqVO req) { @@ -124,7 +130,75 @@ public class AiChatServiceImpl implements AiChatService { return insertChatMessageDO; } - public Flux chatStream(AiChatMessageSendReqVO req) { + public Flux chatStream(AiChatMessageSendStreamReqVO req) { + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + // 查询提问的 message + AiChatMessageDO aiChatMessageDO = aiChatMessageMapper.selectById(req.getId()); + if (aiChatMessageDO == null) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CHAT_MESSAGE_NOT_EXIST); + } + // 查询对话 + AiChatConversationRespVO conversation = chatConversationService.getConversationOfValidate(aiChatMessageDO.getConversationId()); + // 获取对话模型 + AiChatModelDO chatModel = aiChatModalService.validateChatModel(conversation.getModelId()); + // 获取角色信息 + AiChatRoleDO aiChatRoleDO = null; + if (conversation.getRoleId() != null) { + aiChatRoleDO = aiChatRoleService.validateExists(conversation.getRoleId()); + } + // 校验角色是否公开 + aiChatRoleService.validateIsPublic(aiChatRoleDO); + // 创建 chat 需要的 Prompt + Prompt prompt = new Prompt(aiChatMessageDO.getContent()); + // 提前创建一个 system message + AiChatMessageDO systemMessage = insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), + chatModel.getModel(), chatModel.getId(), "", + 0, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); +// req.setTopK(req.getTopK()); +// req.setTopP(req.getTopP()); +// req.setTemperature(req.getTemperature()); + // 获取 client 类型 + AiPlatformEnum platformEnum = AiPlatformEnum.validatePlatform(chatModel.getPlatform()); + StreamingChatClient streamingChatClient = aiChatClientFactory.getStreamingChatClient(platformEnum); + Flux streamResponse = streamingChatClient.stream(prompt); + // 转换 flex AiChatMessageRespVO + StringBuffer contentBuffer = new StringBuffer(); + AtomicInteger tokens = new AtomicInteger(0); + return streamResponse.map(res -> { + AiChatMessageRespVO aiChatMessageRespVO = + AiChatMessageConvert.INSTANCE.convertAiChatMessageRespVO(systemMessage); + aiChatMessageRespVO.setContent(res.getResult().getOutput().getContent()); + contentBuffer.append(res.getResult().getOutput().getContent()); + tokens.incrementAndGet(); + return aiChatMessageRespVO; + } + ).doOnComplete(new Runnable() { + @Override + public void run() { + log.info("发送完成!"); + // 保存 chat message + aiChatMessageMapper.updateById(new AiChatMessageDO() + .setId(systemMessage.getId()) + .setContent(contentBuffer.toString()) + .setTokens(tokens.get()) + ); + } + }).doOnError(new Consumer() { + @Override + public void accept(Throwable throwable) { + log.error("发送错误 {}!", throwable.getMessage()); + // 更新错误信息 + aiChatMessageMapper.updateById(new AiChatMessageDO() + .setId(systemMessage.getId()) + .setContent(throwable.getMessage()) + .setTokens(tokens.get()) + ); + } + }); + } + + @Override + public AiChatMessageRespVO add(AiChatMessageAddReqVO req) { Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 查询对话 AiChatConversationRespVO conversation = chatConversationService.getConversationOfValidate(req.getConversationId()); @@ -137,48 +211,10 @@ public class AiChatServiceImpl implements AiChatService { } // 校验角色是否公开 aiChatRoleService.validateIsPublic(aiChatRoleDO); - // 创建 chat 需要的 Prompt - Prompt prompt = new Prompt(req.getContent()); -// req.setTopK(req.getTopK()); -// req.setTopP(req.getTopP()); -// req.setTemperature(req.getTemperature()); - // 保存 chat message - insertChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(), + AiChatMessageDO userMessage = insertChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(), chatModel.getModel(), chatModel.getId(), req.getContent(), null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); - // 获取 client 类型 - AiPlatformEnum platformEnum = AiPlatformEnum.validatePlatform(chatModel.getPlatform()); - StreamingChatClient streamingChatClient = aiChatClientFactory.getStreamingChatClient(platformEnum); - Flux streamResponse = streamingChatClient.stream(prompt); - // 转换 flex AiChatMessageRespVO - StringBuffer contentBuffer = new StringBuffer(); - AtomicInteger tokens = new AtomicInteger(0); - return streamResponse.map(res -> { - AiChatMessageRespVO aiChatMessageRespVO = new AiChatMessageRespVO(); - aiChatMessageRespVO.setContent(res.getResult().getOutput().getContent()); - contentBuffer.append(res.getResult().getOutput().getContent()); - tokens.incrementAndGet(); - return aiChatMessageRespVO; - } - ).doOnComplete(new Runnable() { - @Override - public void run() { - log.info("发送完成!"); - // 保存 chat message - insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), - chatModel.getModel(), chatModel.getId(), contentBuffer.toString(), - tokens.get(), conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); - } - }).doOnError(new Consumer() { - @Override - public void accept(Throwable throwable) { - log.error("发送错误 {}!", throwable.getMessage()); - // 保存 chat message - insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), - chatModel.getModel(), chatModel.getId(), throwable.getMessage(), - tokens.get(), conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); - } - }); + return AiChatMessageConvert.INSTANCE.convertAiChatMessageRespVO(userMessage); } @Override @@ -207,4 +243,5 @@ public class AiChatServiceImpl implements AiChatService { public Boolean deleteMessage(Long id) { return aiChatMessageMapper.deleteById(id) > 0; } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelService.java index d05941989..de203661e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelService.java @@ -6,6 +6,9 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatMode import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import jakarta.validation.Valid; +import java.util.List; +import java.util.Set; + /** * AI 聊天模型 Service 接口 * @@ -60,4 +63,11 @@ public interface AiChatModelService { */ AiChatModelDO validateChatModel(Long id); + /** + * 获取 - 根据多个 ids 获取 + * + * @param modalIds + * @return + */ + List getModalByIds(Set modalIds); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java index 0c0386ccc..5e87fd180 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java @@ -12,6 +12,9 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import java.util.List; +import java.util.Set; + import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.*; @@ -89,4 +92,9 @@ public class AiChatModelServiceImpl implements AiChatModelService { return model; } + @Override + public List getModalByIds(Set modalIds) { + return chatModelMapper.selectByIds(modalIds); + } + } \ No newline at end of file From 56caa3d598d6d639f5fcfabfe78e6fcd72ba16be Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 12 May 2024 19:43:41 +0800 Subject: [PATCH 263/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E8=B0=83=E6=95=B4=20ai=20starter=20=E7=9A=84=E5=8C=85?= =?UTF-8?q?=E5=B0=81=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/config/AiChatClientFactory.java | 12 +++--- .../module/ai/convert/AiImageConvert.java | 2 +- .../dal/dataobject/chat/AiChatMessageDO.java | 2 +- .../ai/dal/dataobject/model/AiApiKeyDO.java | 2 +- .../dal/dataobject/model/AiChatModelDO.java | 2 +- .../module/ai/dal/vo/AiChatModalConfigVO.java | 9 +++-- .../ai/dal/vo/AiChatModalDallConfigVO.java | 2 +- .../ai/service/impl/AiChatServiceImpl.java | 12 +++--- .../ai/service/impl/AiImageServiceImpl.java | 24 ++++++------ .../YuDaoMidjourneyMessageHandler.java | 6 +-- .../service/model/AiChatModelServiceImpl.java | 3 +- .../yudao-spring-boot-starter-ai/pom.xml | 2 + .../ai/config/YudaoAiAutoConfiguration.java | 38 +++++++++---------- .../ai/config/YudaoAiImageProperties.java | 9 ++--- .../ai/config/YudaoAiProperties.java | 10 ++--- .../ai/{ => core/enums}/AiPlatformEnum.java | 2 +- .../ai/{ => core}/exception/AiException.java | 3 +- .../yudao/framework/ai/core/package-info.java | 4 ++ .../yudao/framework/ai/package-info.java | 15 -------- .../springframework}/ai/chat/ChatClient.java | 8 ++-- .../ai/chat/ChatException.java | 2 +- .../ai/chat/ChatResponse.java | 7 ++-- .../springframework}/ai/chat/Generation.java | 8 ++-- .../ai/chat/StreamingChatClient.java | 6 +-- .../ai/chat/messages/AbstractMessage.java | 2 +- .../ai/chat/messages/AssistantMessage.java | 2 +- .../ai/chat/messages/ChatMessage.java | 2 +- .../ai/chat/messages/FunctionMessage.java | 2 +- .../ai/chat/messages/MediaData.java | 2 +- .../ai/chat/messages/Message.java | 2 +- .../ai/chat/messages/MessageType.java | 2 +- .../ai/chat/messages/SystemMessage.java | 2 +- .../ai/chat/messages/UserMessage.java | 2 +- .../chat/metadata/ChatGenerationMetadata.java | 4 +- .../chat/metadata/ChatResponseMetadata.java | 4 +- .../ai/chat/metadata/EmptyRateLimit.java | 2 +- .../ai/chat/metadata/EmptyUsage.java | 2 +- .../ai/chat/metadata/PromptMetadata.java | 2 +- .../ai/chat/metadata/RateLimit.java | 2 +- .../ai/chat/metadata/Usage.java | 2 +- .../ai/chat/package-info.java | 2 +- .../chat/prompt/AssistantPromptTemplate.java | 6 +-- .../ai/chat/prompt/ChatOptions.java | 4 +- .../ai/chat/prompt/ChatOptionsBuilder.java | 2 +- .../ai/chat/prompt/ChatPromptTemplate.java | 4 +- .../chat/prompt/FunctionPromptTemplate.java | 2 +- .../ai/chat/prompt/Prompt.java | 11 +++--- .../ai/chat/prompt/PromptTemplate.java | 8 ++-- .../ai/chat/prompt/PromptTemplateActions.java | 2 +- .../prompt/PromptTemplateChatActions.java | 4 +- .../prompt/PromptTemplateMessageActions.java | 4 +- .../prompt/PromptTemplateStringActions.java | 2 +- .../ai/chat/prompt/SystemPromptTemplate.java | 6 +-- .../ai/chat/prompt/TemplateFormat.java | 2 +- .../springframework}/ai/image/Image.java | 2 +- .../ai/image/ImageClient.java | 4 +- .../ai/image/ImageGeneration.java | 4 +- .../ai/image/ImageGenerationMetadata.java | 4 +- .../ai/image/ImageMessage.java | 2 +- .../ai/image/ImageOptions.java | 4 +- .../ai/image/ImageOptionsBuilder.java | 2 +- .../ai/image/ImagePrompt.java | 4 +- .../ai/image/ImageResponse.java | 4 +- .../ai/image/ImageResponseMetadata.java | 4 +- .../ai/model/ModelClient.java | 2 +- .../ai/model/ModelOptions.java | 2 +- .../ai/model/ModelOptionsUtils.java | 2 +- .../ai/model/ModelRequest.java | 2 +- .../ai/model/ModelResponse.java | 2 +- .../ai/model/ModelResult.java | 2 +- .../ai/model/ResponseMetadata.java | 2 +- .../ai/model/ResultMetadata.java | 2 +- .../ai/model/StreamingModelClient.java | 2 +- .../function/AbstractFunctionCallSupport.java | 2 +- .../function/AbstractFunctionCallback.java | 2 +- .../ai/model/function/FunctionCallback.java | 2 +- .../function/FunctionCallbackContext.java | 2 +- .../function/FunctionCallbackWrapper.java | 4 +- .../function/FunctionCallingOptions.java | 2 +- .../FunctionCallingOptionsBuilder.java | 4 +- .../ai/model/function/TypeResolverHelper.java | 2 +- .../ai/model/package-info.java | 2 +- .../models}/midjourney/MidjourneyConfig.java | 2 +- .../models}/midjourney/MidjourneyMessage.java | 4 +- .../api/MidjourneyInteractions.java | 6 +-- .../api/MidjourneyInteractionsApi.java | 14 +++---- .../midjourney/api/req/AttachmentsReq.java | 2 +- .../midjourney/api/req/DescribeReq.java | 2 +- .../models}/midjourney/api/req/ReRollReq.java | 2 +- .../api/res/UploadAttachmentsRes.java | 2 +- .../constants/MidjourneyConstants.java | 2 +- .../MidjourneyGennerateStatusEnum.java | 2 +- .../constants/MidjourneyInteractionsEnum.java | 2 +- .../constants/MidjourneyMessageTypeEnum.java | 2 +- .../constants/MidjourneyNotifyCode.java | 2 +- .../midjourney/util/MidjourneyUtil.java | 4 +- .../midjourney/webSocket/FailureCallback.java | 2 +- .../webSocket/MidjourneyMessageHandler.java | 4 +- .../webSocket/MidjourneyWebSocketStarter.java | 10 ++--- .../midjourney/webSocket/SuccessCallback.java | 2 +- .../webSocket/WebSocketStarter.java | 2 +- .../midjourney/webSocket/WssNotify.java | 2 +- .../handler/MidjourneyWebSocketHandler.java | 10 ++--- .../listener/MidjourneyMessageListener.java | 16 ++++---- .../ai/models/openai}/OpenAiImageApi.java | 6 +-- .../ai/models/openai}/OpenAiImageClient.java | 14 +++---- .../ai/models/openai}/OpenAiImageOptions.java | 8 ++-- .../openai}/api/OpenAiImageRequest.java | 2 +- .../openai}/api/OpenAiImageResponse.java | 2 +- .../openai}/enums/OpenAiImageModelEnum.java | 2 +- .../openai}/enums/OpenAiImageStyleEnum.java | 2 +- .../ai/models/tongyi}/QianWenChatClient.java | 11 +++--- .../ai/models/tongyi}/QianWenChatModal.java | 2 +- .../ai/models/tongyi}/QianWenOptions.java | 4 +- .../ai/models/tongyi}/api/QianWenApi.java | 8 ++-- .../tongyi}/api/QianWenChatCompletion.java | 2 +- .../api/QianWenChatCompletionMessage.java | 2 +- .../api/QianWenChatCompletionRequest.java | 2 +- .../ai/models/tongyi}/package-info.java | 2 +- .../ai/models/xinghuo}/XingHuoChatClient.java | 13 ++++--- .../ai/models/xinghuo}/XingHuoChatModel.java | 2 +- .../ai/models/xinghuo}/XingHuoOptions.java | 4 +- .../ai/models/xinghuo}/api/XingHuoApi.java | 6 +-- .../xinghuo}/api/XingHuoChatCompletion.java | 2 +- .../api/XingHuoChatCompletionMessage.java | 2 +- .../api/XingHuoChatCompletionRequest.java | 2 +- .../ai/models/yiyan}/YiYanChatClient.java | 19 +++++----- .../ai/models/yiyan}/YiYanChatModel.java | 2 +- .../ai/models/yiyan}/YiYanOptions.java | 6 +-- .../ai/models/yiyan}/api/YiYanApi.java | 9 ++--- .../ai/models/yiyan}/api/YiYanAuthRes.java | 2 +- .../yiyan}/api/YiYanChatCompletion.java | 2 +- .../api/YiYanChatCompletionMessage.java | 2 +- .../api/YiYanChatCompletionRequest.java | 2 +- .../yiyan}/exception/YiYanApiException.java | 2 +- .../org/springframework/ai/package-info.java | 15 ++++++++ ...AbstractConversionServiceOutputParser.java | 2 +- .../AbstractMessageConverterOutputParser.java | 2 +- .../ai/parser/BeanOutputParser.java | 2 +- .../ai/parser/FormatProvider.java | 2 +- .../ai/parser/ListOutputParser.java | 2 +- .../ai/parser/MapOutputParser.java | 2 +- .../ai/parser/OutputParser.java | 2 +- .../springframework}/ai/parser/Parser.java | 2 +- .../springframework}/ai/parser/README.md | 0 .../ai/chat/QianWenChatClientTests.java | 19 +++++----- .../ai/chat/XingHuoChatClientMainTests.java | 4 +- .../ai/chat/XingHuoChatClientTests.java | 17 +++++---- .../framework/ai/chat/XingHuoOkHttpTests.java | 6 +-- .../framework/ai/chat/YiYanChatTests.java | 17 +++++---- .../MidjourneyInteractionsTests.java | 11 +++--- .../ai/midjourney/MidjourneyUtilTests.java | 2 +- .../midjourney/MidjourneyWebSocketTests.java | 7 ++-- .../openAiImage/OpenAiImageClientTests.java | 10 ++--- 154 files changed, 366 insertions(+), 359 deletions(-) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/{ => core/enums}/AiPlatformEnum.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/{ => core}/exception/AiException.java (68%) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/package-info.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/ChatClient.java (81%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/ChatException.java (82%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/ChatResponse.java (94%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/Generation.java (90%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/StreamingChatClient.java (83%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/messages/AbstractMessage.java (98%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/messages/AssistantMessage.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/messages/ChatMessage.java (95%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/messages/FunctionMessage.java (95%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/messages/MediaData.java (95%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/messages/Message.java (93%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/messages/MessageType.java (97%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/messages/SystemMessage.java (97%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/messages/UserMessage.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/metadata/ChatGenerationMetadata.java (95%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/metadata/ChatResponseMetadata.java (92%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/metadata/EmptyRateLimit.java (95%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/metadata/EmptyUsage.java (94%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/metadata/PromptMetadata.java (98%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/metadata/RateLimit.java (98%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/metadata/Usage.java (97%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/package-info.java (94%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/prompt/AssistantPromptTemplate.java (88%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/prompt/ChatOptions.java (90%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/prompt/ChatOptionsBuilder.java (97%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/prompt/ChatPromptTemplate.java (95%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/prompt/FunctionPromptTemplate.java (93%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/prompt/Prompt.java (87%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/prompt/PromptTemplate.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/prompt/PromptTemplateActions.java (94%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/prompt/PromptTemplateChatActions.java (66%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/prompt/PromptTemplateMessageActions.java (73%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/prompt/PromptTemplateStringActions.java (77%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/prompt/SystemPromptTemplate.java (88%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/chat/prompt/TemplateFormat.java (95%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/image/Image.java (97%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/image/ImageClient.java (89%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/image/ImageGeneration.java (93%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/image/ImageGenerationMetadata.java (86%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/image/ImageMessage.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/image/ImageOptions.java (90%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/image/ImageOptionsBuilder.java (98%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/image/ImagePrompt.java (95%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/image/ImageResponse.java (95%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/image/ImageResponseMetadata.java (88%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/model/ModelClient.java (97%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/model/ModelOptions.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/model/ModelOptionsUtils.java (99%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/model/ModelRequest.java (97%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/model/ModelResponse.java (97%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/model/ModelResult.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/model/ResponseMetadata.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/model/ResultMetadata.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/model/StreamingModelClient.java (97%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/model/function/AbstractFunctionCallSupport.java (99%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/model/function/AbstractFunctionCallback.java (98%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/model/function/FunctionCallback.java (97%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/model/function/FunctionCallbackContext.java (98%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/model/function/FunctionCallbackWrapper.java (97%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/model/function/FunctionCallingOptions.java (97%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/model/function/FunctionCallingOptionsBuilder.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/model/function/TypeResolverHelper.java (98%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/model/package-info.java (93%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/MidjourneyConfig.java (97%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/MidjourneyMessage.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/api/MidjourneyInteractions.java (94%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/api/MidjourneyInteractionsApi.java (93%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/api/req/AttachmentsReq.java (85%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/api/req/DescribeReq.java (85%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/api/req/ReRollReq.java (87%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/api/res/UploadAttachmentsRes.java (91%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/constants/MidjourneyConstants.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/constants/MidjourneyGennerateStatusEnum.java (91%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/constants/MidjourneyInteractionsEnum.java (89%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/constants/MidjourneyMessageTypeEnum.java (85%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/constants/MidjourneyNotifyCode.java (73%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/util/MidjourneyUtil.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/webSocket/FailureCallback.java (57%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/webSocket/MidjourneyMessageHandler.java (61%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/webSocket/MidjourneyWebSocketStarter.java (95%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/webSocket/SuccessCallback.java (66%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/webSocket/WebSocketStarter.java (60%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/webSocket/WssNotify.java (72%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/webSocket/handler/MidjourneyWebSocketHandler.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai => org/springframework/ai/models}/midjourney/webSocket/listener/MidjourneyMessageListener.java (90%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/imageopenai => org/springframework/ai/models/openai}/OpenAiImageApi.java (94%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/imageopenai => org/springframework/ai/models/openai}/OpenAiImageClient.java (90%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/imageopenai => org/springframework/ai/models/openai}/OpenAiImageOptions.java (91%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/imageopenai => org/springframework/ai/models/openai}/api/OpenAiImageRequest.java (97%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/imageopenai => org/springframework/ai/models/openai}/api/OpenAiImageResponse.java (92%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/imageopenai => org/springframework/ai/models/openai}/enums/OpenAiImageModelEnum.java (92%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/imageopenai => org/springframework/ai/models/openai}/enums/OpenAiImageStyleEnum.java (94%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatqianwen => org/springframework/ai/models/tongyi}/QianWenChatClient.java (95%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatqianwen => org/springframework/ai/models/tongyi}/QianWenChatModal.java (97%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatqianwen => org/springframework/ai/models/tongyi}/QianWenOptions.java (97%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatqianwen => org/springframework/ai/models/tongyi}/api/QianWenApi.java (89%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatqianwen => org/springframework/ai/models/tongyi}/api/QianWenChatCompletion.java (62%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatqianwen => org/springframework/ai/models/tongyi}/api/QianWenChatCompletionMessage.java (64%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatqianwen => org/springframework/ai/models/tongyi}/api/QianWenChatCompletionRequest.java (84%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatqianwen => org/springframework/ai/models/tongyi}/package-info.java (86%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatxinghuo => org/springframework/ai/models/xinghuo}/XingHuoChatClient.java (93%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatxinghuo => org/springframework/ai/models/xinghuo}/XingHuoChatModel.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatxinghuo => org/springframework/ai/models/xinghuo}/XingHuoOptions.java (93%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatxinghuo => org/springframework/ai/models/xinghuo}/api/XingHuoApi.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatxinghuo => org/springframework/ai/models/xinghuo}/api/XingHuoChatCompletion.java (94%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatxinghuo => org/springframework/ai/models/xinghuo}/api/XingHuoChatCompletionMessage.java (64%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatxinghuo => org/springframework/ai/models/xinghuo}/api/XingHuoChatCompletionRequest.java (97%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatyiyan => org/springframework/ai/models/yiyan}/YiYanChatClient.java (91%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatyiyan => org/springframework/ai/models/yiyan}/YiYanChatModel.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatyiyan => org/springframework/ai/models/yiyan}/YiYanOptions.java (95%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatyiyan => org/springframework/ai/models/yiyan}/api/YiYanApi.java (89%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatyiyan => org/springframework/ai/models/yiyan}/api/YiYanAuthRes.java (94%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatyiyan => org/springframework/ai/models/yiyan}/api/YiYanChatCompletion.java (97%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatyiyan => org/springframework/ai/models/yiyan}/api/YiYanChatCompletionMessage.java (64%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatyiyan => org/springframework/ai/models/yiyan}/api/YiYanChatCompletionRequest.java (99%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework/ai/chatyiyan => org/springframework/ai/models/yiyan}/exception/YiYanApiException.java (81%) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/package-info.java rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/parser/AbstractConversionServiceOutputParser.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/parser/AbstractMessageConverterOutputParser.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/parser/BeanOutputParser.java (99%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/parser/FormatProvider.java (95%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/parser/ListOutputParser.java (97%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/parser/MapOutputParser.java (97%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/parser/OutputParser.java (95%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/parser/Parser.java (93%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{cn/iocoder/yudao/framework => org/springframework}/ai/parser/README.md (100%) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java index 6ee948994..e15eff590 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.ai.config; -import cn.iocoder.yudao.framework.ai.AiPlatformEnum; -import cn.iocoder.yudao.framework.ai.chat.ChatClient; -import cn.iocoder.yudao.framework.ai.chat.StreamingChatClient; -import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient; -import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatClient; -import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatClient; +import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; +import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.StreamingChatClient; +import org.springframework.ai.models.tongyi.QianWenChatClient; +import org.springframework.ai.models.xinghuo.XingHuoChatClient; +import org.springframework.ai.models.yiyan.YiYanChatClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java index 27bf11136..b0f8abc39 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.ai.convert; -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyMessage; +import org.springframework.ai.models.midjourney.MidjourneyMessage; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingRespVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageListRespVO; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java index 7e57f7ea0..831b7622d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.chat; -import cn.iocoder.yudao.framework.ai.chat.messages.MessageType; +import org.springframework.ai.chat.messages.MessageType; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiApiKeyDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiApiKeyDO.java index 306c1e086..e251d55c8 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiApiKeyDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiApiKeyDO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.model; -import cn.iocoder.yudao.framework.ai.AiPlatformEnum; +import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.KeySequence; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModelDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModelDO.java index 8c86127c3..723428009 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModelDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModelDO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.model; -import cn.iocoder.yudao.framework.ai.AiPlatformEnum; +import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.KeySequence; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalConfigVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalConfigVO.java index 1b6e957d0..ed5ecf217 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalConfigVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalConfigVO.java @@ -1,7 +1,10 @@ package cn.iocoder.yudao.module.ai.dal.vo; +import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import lombok.Data; import lombok.experimental.Accessors; +import org.springframework.ai.models.xinghuo.XingHuoChatModel; +import org.springframework.ai.models.yiyan.YiYanChatModel; /** * modal config @@ -16,13 +19,13 @@ public class AiChatModalConfigVO { /** * 模型平台 (冗余,方便类型转换) - * 参考:{@link cn.iocoder.yudao.framework.ai.AiPlatformEnum} + * 参考:{@link AiPlatformEnum} */ private String platform; /** * 模型类型(冗余,方便类型转换) - * {@link cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel} - * {@link cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel} + * {@link YiYanChatModel} + * {@link XingHuoChatModel} */ private String type; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalDallConfigVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalDallConfigVO.java index c7dce40e6..d77b4ec87 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalDallConfigVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalDallConfigVO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.ai.dal.vo; -import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageStyleEnum; +import org.springframework.ai.models.openai.enums.OpenAiImageStyleEnum; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index a7dcd122d..36316dc97 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -1,12 +1,12 @@ package cn.iocoder.yudao.module.ai.service.impl; import cn.hutool.core.exceptions.ExceptionUtil; -import cn.iocoder.yudao.framework.ai.AiPlatformEnum; -import cn.iocoder.yudao.framework.ai.chat.ChatClient; -import cn.iocoder.yudao.framework.ai.chat.ChatResponse; -import cn.iocoder.yudao.framework.ai.chat.StreamingChatClient; -import cn.iocoder.yudao.framework.ai.chat.messages.MessageType; -import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; +import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; +import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.StreamingChatClient; +import org.springframework.ai.chat.messages.MessageType; +import org.springframework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java index d306b4b2f..4727127c9 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java @@ -2,18 +2,18 @@ package cn.iocoder.yudao.module.ai.service.impl; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.ai.exception.AiException; -import cn.iocoder.yudao.framework.ai.image.ImageGeneration; -import cn.iocoder.yudao.framework.ai.image.ImagePrompt; -import cn.iocoder.yudao.framework.ai.image.ImageResponse; -import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageClient; -import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageOptions; -import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageModelEnum; -import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageStyleEnum; -import cn.iocoder.yudao.framework.ai.midjourney.api.MidjourneyInteractionsApi; -import cn.iocoder.yudao.framework.ai.midjourney.api.req.ReRollReq; -import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyWebSocketStarter; -import cn.iocoder.yudao.framework.ai.midjourney.webSocket.WssNotify; +import cn.iocoder.yudao.framework.ai.core.exception.AiException; +import org.springframework.ai.image.ImageGeneration; +import org.springframework.ai.image.ImagePrompt; +import org.springframework.ai.image.ImageResponse; +import org.springframework.ai.models.openai.OpenAiImageClient; +import org.springframework.ai.models.openai.OpenAiImageOptions; +import org.springframework.ai.models.openai.enums.OpenAiImageModelEnum; +import org.springframework.ai.models.openai.enums.OpenAiImageStyleEnum; +import org.springframework.ai.models.midjourney.api.MidjourneyInteractionsApi; +import org.springframework.ai.models.midjourney.api.req.ReRollReq; +import org.springframework.ai.models.midjourney.webSocket.MidjourneyWebSocketStarter; +import org.springframework.ai.models.midjourney.webSocket.WssNotify; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java index 0260a1511..d1ccc080e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java @@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.ai.service.midjourneyHandler; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyMessage; -import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyGennerateStatusEnum; -import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyMessageHandler; +import org.springframework.ai.models.midjourney.MidjourneyMessage; +import org.springframework.ai.models.midjourney.constants.MidjourneyGennerateStatusEnum; +import org.springframework.ai.models.midjourney.webSocket.MidjourneyMessageHandler; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyOperationsVO; import cn.iocoder.yudao.module.ai.convert.AiImageConvert; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java index ed6e16cee..c185ffea5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.ai.service.model; -import cn.iocoder.yudao.framework.ai.AiPlatformEnum; +import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -14,7 +14,6 @@ import org.springframework.validation.annotation.Validated; import java.util.List; -import java.util.List; import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml index 3a52489a5..2195b4bcc 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml @@ -10,6 +10,7 @@ yudao-spring-boot-starter-ai + 21 @@ -17,6 +18,7 @@ UTF-8 + org.springframework spring-core diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index 6eedb5997..88581f88a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -1,25 +1,25 @@ package cn.iocoder.yudao.framework.ai.config; import cn.hutool.core.io.IoUtil; -import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient; -import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatModal; -import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenOptions; -import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenApi; -import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatClient; -import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoOptions; -import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoApi; -import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatClient; -import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanOptions; -import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanApi; -import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageApi; -import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageClient; -import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageOptions; -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyMessage; -import cn.iocoder.yudao.framework.ai.midjourney.api.MidjourneyInteractionsApi; -import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyMessageHandler; -import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyWebSocketStarter; -import cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener.MidjourneyMessageListener; +import org.springframework.ai.models.tongyi.QianWenChatClient; +import org.springframework.ai.models.tongyi.QianWenChatModal; +import org.springframework.ai.models.tongyi.QianWenOptions; +import org.springframework.ai.models.tongyi.api.QianWenApi; +import org.springframework.ai.models.xinghuo.XingHuoChatClient; +import org.springframework.ai.models.xinghuo.XingHuoOptions; +import org.springframework.ai.models.xinghuo.api.XingHuoApi; +import org.springframework.ai.models.yiyan.YiYanChatClient; +import org.springframework.ai.models.yiyan.YiYanOptions; +import org.springframework.ai.models.yiyan.api.YiYanApi; +import org.springframework.ai.models.openai.OpenAiImageApi; +import org.springframework.ai.models.openai.OpenAiImageClient; +import org.springframework.ai.models.openai.OpenAiImageOptions; +import org.springframework.ai.models.midjourney.MidjourneyConfig; +import org.springframework.ai.models.midjourney.MidjourneyMessage; +import org.springframework.ai.models.midjourney.api.MidjourneyInteractionsApi; +import org.springframework.ai.models.midjourney.webSocket.MidjourneyMessageHandler; +import org.springframework.ai.models.midjourney.webSocket.MidjourneyWebSocketStarter; +import org.springframework.ai.models.midjourney.webSocket.listener.MidjourneyMessageListener; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; import org.springframework.boot.autoconfigure.AutoConfiguration; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiImageProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiImageProperties.java index 11246df68..1f17a1203 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiImageProperties.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiImageProperties.java @@ -1,12 +1,11 @@ package cn.iocoder.yudao.framework.ai.config; -import cn.iocoder.yudao.framework.ai.AiPlatformEnum; -import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel; -import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoOptions; -import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel; +import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; +import org.springframework.ai.models.xinghuo.XingHuoChatModel; +import org.springframework.ai.models.xinghuo.XingHuoOptions; +import org.springframework.ai.models.yiyan.YiYanChatModel; import lombok.Data; import lombok.experimental.Accessors; -import org.springframework.boot.context.properties.ConfigurationProperties; import java.util.LinkedHashMap; import java.util.Map; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java index 57ef69ef6..a23b9109c 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.framework.ai.config; -import cn.iocoder.yudao.framework.ai.AiPlatformEnum; -import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel; -import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel; -import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageModelEnum; -import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageStyleEnum; +import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; +import org.springframework.ai.models.xinghuo.XingHuoChatModel; +import org.springframework.ai.models.yiyan.YiYanChatModel; +import org.springframework.ai.models.openai.enums.OpenAiImageModelEnum; +import org.springframework.ai.models.openai.enums.OpenAiImageStyleEnum; import lombok.Data; import lombok.experimental.Accessors; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java index 3882e1a99..590797d17 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai; +package cn.iocoder.yudao.framework.ai.core.enums; import com.google.common.collect.Lists; import lombok.AllArgsConstructor; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/exception/AiException.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/exception/AiException.java similarity index 68% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/exception/AiException.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/exception/AiException.java index d98b7afc2..bad13c691 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/exception/AiException.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/exception/AiException.java @@ -1,5 +1,6 @@ -package cn.iocoder.yudao.framework.ai.exception; +package cn.iocoder.yudao.framework.ai.core.exception; +// TODO @fan:这个有办法干掉么? /** * ai 异常 * diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/package-info.java new file mode 100644 index 000000000..b728517d0 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/package-info.java @@ -0,0 +1,4 @@ +/** + * 芋道 AI Starter,整体参考 spring-ai 拓展 + */ +package cn.iocoder.yudao.framework.ai.core; \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java deleted file mode 100644 index ffd2ac933..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java +++ /dev/null @@ -1,15 +0,0 @@ -/** - * author: fansili - * time: 2024/3/12 20:29 - * - * TODO @fansili:包的想法,需要重点看看 - * - * 1. org.springframework.ai:包括 chat、image、model、parser、util 部分 - * - * 2. yudao.framework.models - * \qianwen 通义千问 - * \yiyan 文心一言 - * \xinghuo 星火 - * \midjourney - */ -package cn.iocoder.yudao.framework.ai; \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/ChatClient.java similarity index 81% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatClient.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/ChatClient.java index 6fd8e8981..bd6aa3e56 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/ChatClient.java @@ -14,12 +14,12 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat; +package org.springframework.ai.chat; -import cn.iocoder.yudao.framework.ai.chat.messages.UserMessage; -import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; -import cn.iocoder.yudao.framework.ai.model.ModelClient; +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.model.ModelClient; @FunctionalInterface public interface ChatClient extends ModelClient { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatException.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/ChatException.java similarity index 82% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatException.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/ChatException.java index 2b9660154..bc9222699 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatException.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/ChatException.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.chat; +package org.springframework.ai.chat; /** * 聊天异常 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatResponse.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/ChatResponse.java similarity index 94% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatResponse.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/ChatResponse.java index a6de72d7a..641212b97 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/ChatResponse.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/ChatResponse.java @@ -13,13 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat; +package org.springframework.ai.chat; -import cn.iocoder.yudao.framework.ai.chat.metadata.ChatResponseMetadata; -import cn.iocoder.yudao.framework.ai.model.ModelResponse; +import org.springframework.ai.chat.metadata.ChatResponseMetadata; +import org.springframework.ai.model.ModelResponse; import org.springframework.util.CollectionUtils; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/Generation.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/Generation.java similarity index 90% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/Generation.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/Generation.java index 1835d16d2..ca1784835 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/Generation.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/Generation.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat; +package org.springframework.ai.chat; -import cn.iocoder.yudao.framework.ai.chat.messages.AssistantMessage; -import cn.iocoder.yudao.framework.ai.chat.metadata.ChatGenerationMetadata; -import cn.iocoder.yudao.framework.ai.model.ModelResult; +import org.springframework.ai.chat.messages.AssistantMessage; +import org.springframework.ai.chat.metadata.ChatGenerationMetadata; +import org.springframework.ai.model.ModelResult; import org.springframework.lang.Nullable; import java.util.Map; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/StreamingChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/StreamingChatClient.java similarity index 83% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/StreamingChatClient.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/StreamingChatClient.java index fdd604f4d..079989db4 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/StreamingChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/StreamingChatClient.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat; +package org.springframework.ai.chat; -import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; -import cn.iocoder.yudao.framework.ai.model.StreamingModelClient; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.model.StreamingModelClient; import reactor.core.publisher.Flux; @FunctionalInterface diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/AbstractMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/AbstractMessage.java similarity index 98% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/AbstractMessage.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/AbstractMessage.java index 8c8e60d5a..7cc936072 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/AbstractMessage.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/AbstractMessage.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.messages; +package org.springframework.ai.chat.messages; import org.springframework.core.io.Resource; import org.springframework.util.Assert; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/AssistantMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/AssistantMessage.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/AssistantMessage.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/AssistantMessage.java index 6a18eeba8..28710db1c 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/AssistantMessage.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/AssistantMessage.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.messages; +package org.springframework.ai.chat.messages; import java.util.Map; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/ChatMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/ChatMessage.java similarity index 95% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/ChatMessage.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/ChatMessage.java index 16470135b..194aa54af 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/ChatMessage.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/ChatMessage.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.messages; +package org.springframework.ai.chat.messages; import java.util.Map; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/FunctionMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/FunctionMessage.java similarity index 95% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/FunctionMessage.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/FunctionMessage.java index d8b6fccbd..1faba6a79 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/FunctionMessage.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/FunctionMessage.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.messages; +package org.springframework.ai.chat.messages; import java.util.Map; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/MediaData.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/MediaData.java similarity index 95% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/MediaData.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/MediaData.java index fed60221f..9acd9b151 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/MediaData.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/MediaData.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.messages; +package org.springframework.ai.chat.messages; import org.springframework.util.Assert; import org.springframework.util.MimeType; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/Message.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/Message.java similarity index 93% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/Message.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/Message.java index 89c7b4fb4..10c893ad7 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/Message.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/Message.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.messages; +package org.springframework.ai.chat.messages; import java.util.List; import java.util.Map; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/MessageType.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/MessageType.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/MessageType.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/MessageType.java index 2c803a060..a227c4530 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/MessageType.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/MessageType.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.messages; +package org.springframework.ai.chat.messages; public enum MessageType { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/SystemMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/SystemMessage.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/SystemMessage.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/SystemMessage.java index c474f24bd..f8c67f2b4 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/SystemMessage.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/SystemMessage.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.messages; +package org.springframework.ai.chat.messages; import org.springframework.core.io.Resource; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/UserMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/UserMessage.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/UserMessage.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/UserMessage.java index 2b8f547f7..ca7f360c2 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/messages/UserMessage.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/UserMessage.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.messages; +package org.springframework.ai.chat.messages; import org.springframework.core.io.Resource; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/ChatGenerationMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/ChatGenerationMetadata.java similarity index 95% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/ChatGenerationMetadata.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/ChatGenerationMetadata.java index a90dda5bf..d9f5fc56e 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/ChatGenerationMetadata.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/ChatGenerationMetadata.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.metadata; +package org.springframework.ai.chat.metadata; -import cn.iocoder.yudao.framework.ai.model.ResultMetadata; +import org.springframework.ai.model.ResultMetadata; import org.springframework.lang.Nullable; /** diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/ChatResponseMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/ChatResponseMetadata.java similarity index 92% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/ChatResponseMetadata.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/ChatResponseMetadata.java index ebcb4ab06..38eb1fd59 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/ChatResponseMetadata.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/ChatResponseMetadata.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.metadata; +package org.springframework.ai.chat.metadata; -import cn.iocoder.yudao.framework.ai.model.ResponseMetadata; +import org.springframework.ai.model.ResponseMetadata; /** * Abstract Data Type (ADT) modeling common AI provider metadata returned in an AI diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/EmptyRateLimit.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/EmptyRateLimit.java similarity index 95% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/EmptyRateLimit.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/EmptyRateLimit.java index 62aeeb531..480a94d3e 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/EmptyRateLimit.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/EmptyRateLimit.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.metadata; +package org.springframework.ai.chat.metadata; import java.time.Duration; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/EmptyUsage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/EmptyUsage.java similarity index 94% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/EmptyUsage.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/EmptyUsage.java index 11f0255c1..027e30279 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/EmptyUsage.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/EmptyUsage.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.metadata; +package org.springframework.ai.chat.metadata; /** * A EmpytUsage implementation that returns zero for all property getters diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/PromptMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/PromptMetadata.java similarity index 98% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/PromptMetadata.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/PromptMetadata.java index 94bad3aa5..becb12ded 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/PromptMetadata.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/PromptMetadata.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.metadata; +package org.springframework.ai.chat.metadata; import org.springframework.util.Assert; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/RateLimit.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/RateLimit.java similarity index 98% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/RateLimit.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/RateLimit.java index 6842783ba..22dd64b18 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/RateLimit.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/RateLimit.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.metadata; +package org.springframework.ai.chat.metadata; import java.time.Duration; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/Usage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/Usage.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/Usage.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/Usage.java index cecbc828e..de4fb9ac6 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/metadata/Usage.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/Usage.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.metadata; +package org.springframework.ai.chat.metadata; /** * 抽象数据类型(ADT)封装关于人工智能提供商API使用的元数据根据AI请求。 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/package-info.java similarity index 94% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/package-info.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/package-info.java index 17c341f00..98d92eb71 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/package-info.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/package-info.java @@ -11,4 +11,4 @@ * This bounded context is designed to encapsulate all aspects of chat-based AI * functionalities, maintaining a clear boundary from other contexts within the AI domain. */ -package cn.iocoder.yudao.framework.ai.chat; \ No newline at end of file +package org.springframework.ai.chat; \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/AssistantPromptTemplate.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/AssistantPromptTemplate.java similarity index 88% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/AssistantPromptTemplate.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/AssistantPromptTemplate.java index cfe91527e..ae6373cf1 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/AssistantPromptTemplate.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/AssistantPromptTemplate.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.prompt; +package org.springframework.ai.chat.prompt; -import cn.iocoder.yudao.framework.ai.chat.messages.AssistantMessage; -import cn.iocoder.yudao.framework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.AssistantMessage; +import org.springframework.ai.chat.messages.Message; import org.springframework.core.io.Resource; import java.util.Map; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/ChatOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/ChatOptions.java similarity index 90% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/ChatOptions.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/ChatOptions.java index 979ca6b20..5c45a37ba 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/ChatOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/ChatOptions.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.prompt; +package org.springframework.ai.chat.prompt; -import cn.iocoder.yudao.framework.ai.model.ModelOptions; +import org.springframework.ai.model.ModelOptions; /** * 聊天选项代表了常见的选项,可在不同的聊天模式中移植。 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/ChatOptionsBuilder.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/ChatOptionsBuilder.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/ChatOptionsBuilder.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/ChatOptionsBuilder.java index c3e236ea0..f702f6350 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/ChatOptionsBuilder.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/ChatOptionsBuilder.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.prompt; +package org.springframework.ai.chat.prompt; public class ChatOptionsBuilder { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/ChatPromptTemplate.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/ChatPromptTemplate.java similarity index 95% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/ChatPromptTemplate.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/ChatPromptTemplate.java index a06c981c7..15f9ca5d4 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/ChatPromptTemplate.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/ChatPromptTemplate.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.prompt; +package org.springframework.ai.chat.prompt; -import cn.iocoder.yudao.framework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.Message; import java.util.ArrayList; import java.util.List; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/FunctionPromptTemplate.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/FunctionPromptTemplate.java similarity index 93% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/FunctionPromptTemplate.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/FunctionPromptTemplate.java index e94545c23..4c7ce981f 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/FunctionPromptTemplate.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/FunctionPromptTemplate.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.prompt; +package org.springframework.ai.chat.prompt; public class FunctionPromptTemplate extends PromptTemplate { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/Prompt.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/Prompt.java similarity index 87% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/Prompt.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/Prompt.java index 95b5cd8aa..a598b3c35 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/Prompt.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/Prompt.java @@ -14,13 +14,12 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.prompt; +package org.springframework.ai.chat.prompt; -import cn.iocoder.yudao.framework.ai.chat.ChatResponse; -import cn.iocoder.yudao.framework.ai.chat.messages.Message; -import cn.iocoder.yudao.framework.ai.chat.messages.UserMessage; -import cn.iocoder.yudao.framework.ai.model.ModelOptions; -import cn.iocoder.yudao.framework.ai.model.ModelRequest; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.model.ModelOptions; +import org.springframework.ai.model.ModelRequest; import java.util.Collections; import java.util.List; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplate.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplate.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplate.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplate.java index 7c0c0f7f3..f1e910da0 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplate.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplate.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.prompt; +package org.springframework.ai.chat.prompt; -import cn.iocoder.yudao.framework.ai.chat.messages.Message; -import cn.iocoder.yudao.framework.ai.chat.messages.UserMessage; -import cn.iocoder.yudao.framework.ai.parser.OutputParser; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.parser.OutputParser; import org.antlr.runtime.Token; import org.antlr.runtime.TokenStream; import org.springframework.core.io.Resource; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateActions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateActions.java similarity index 94% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateActions.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateActions.java index bdee00acb..8097e3f35 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateActions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateActions.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.prompt; +package org.springframework.ai.chat.prompt; import java.util.Map; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateChatActions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateChatActions.java similarity index 66% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateChatActions.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateChatActions.java index 922d57c8d..24d9f908c 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateChatActions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateChatActions.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.framework.ai.chat.prompt; +package org.springframework.ai.chat.prompt; -import cn.iocoder.yudao.framework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.Message; import java.util.List; import java.util.Map; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateMessageActions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateMessageActions.java similarity index 73% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateMessageActions.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateMessageActions.java index 8de851a89..17ff49286 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateMessageActions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateMessageActions.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.framework.ai.chat.prompt; +package org.springframework.ai.chat.prompt; -import cn.iocoder.yudao.framework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.Message; import java.util.Map; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateStringActions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateStringActions.java similarity index 77% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateStringActions.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateStringActions.java index 58015b47d..0cd9df3b2 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/PromptTemplateStringActions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateStringActions.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.chat.prompt; +package org.springframework.ai.chat.prompt; import java.util.Map; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/SystemPromptTemplate.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/SystemPromptTemplate.java similarity index 88% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/SystemPromptTemplate.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/SystemPromptTemplate.java index cafade4bb..539287d07 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/SystemPromptTemplate.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/SystemPromptTemplate.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.prompt; +package org.springframework.ai.chat.prompt; -import cn.iocoder.yudao.framework.ai.chat.messages.Message; -import cn.iocoder.yudao.framework.ai.chat.messages.SystemMessage; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.SystemMessage; import org.springframework.core.io.Resource; import java.util.Map; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/TemplateFormat.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/TemplateFormat.java similarity index 95% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/TemplateFormat.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/TemplateFormat.java index c22a78db3..1001ee266 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chat/prompt/TemplateFormat.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/TemplateFormat.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.chat.prompt; +package org.springframework.ai.chat.prompt; public enum TemplateFormat { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/Image.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/Image.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/Image.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/Image.java index d6fc44da0..3c6ae1ea1 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/Image.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/Image.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.image; +package org.springframework.ai.image; import java.util.Objects; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageClient.java similarity index 89% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageClient.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageClient.java index 98fc44ff6..1993fbe92 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageClient.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.image; +package org.springframework.ai.image; -import cn.iocoder.yudao.framework.ai.model.ModelClient; +import org.springframework.ai.model.ModelClient; public interface ImageClient extends ModelClient { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageGeneration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageGeneration.java similarity index 93% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageGeneration.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageGeneration.java index 5ec655de8..924f5872a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageGeneration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageGeneration.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.image; +package org.springframework.ai.image; -import cn.iocoder.yudao.framework.ai.model.ModelResult; +import org.springframework.ai.model.ModelResult; public class ImageGeneration implements ModelResult { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageGenerationMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageGenerationMetadata.java similarity index 86% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageGenerationMetadata.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageGenerationMetadata.java index 1d620d2c7..e140aa814 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageGenerationMetadata.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageGenerationMetadata.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.image; +package org.springframework.ai.image; -import cn.iocoder.yudao.framework.ai.model.ResultMetadata; +import org.springframework.ai.model.ResultMetadata; public interface ImageGenerationMetadata extends ResultMetadata { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageMessage.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageMessage.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageMessage.java index 6a01c6c21..51d378b8c 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageMessage.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageMessage.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.image; +package org.springframework.ai.image; import java.util.Objects; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageOptions.java similarity index 90% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageOptions.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageOptions.java index d9cfd0e86..428376364 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageOptions.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.image; +package org.springframework.ai.image; -import cn.iocoder.yudao.framework.ai.model.ModelOptions; +import org.springframework.ai.model.ModelOptions; /** * ImageOptions represent the common options, portable across different image generation diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageOptionsBuilder.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageOptionsBuilder.java similarity index 98% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageOptionsBuilder.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageOptionsBuilder.java index d1bc47473..49dc3497d 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageOptionsBuilder.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageOptionsBuilder.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.image; +package org.springframework.ai.image; public class ImageOptionsBuilder { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImagePrompt.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImagePrompt.java similarity index 95% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImagePrompt.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImagePrompt.java index 75ec51948..4f9dcdc59 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImagePrompt.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImagePrompt.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.image; +package org.springframework.ai.image; -import cn.iocoder.yudao.framework.ai.model.ModelRequest; +import org.springframework.ai.model.ModelRequest; import java.util.Collections; import java.util.List; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageResponse.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageResponse.java similarity index 95% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageResponse.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageResponse.java index ca91be5c0..d3e314526 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageResponse.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageResponse.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.image; +package org.springframework.ai.image; -import cn.iocoder.yudao.framework.ai.model.ModelResponse; +import org.springframework.ai.model.ModelResponse; import java.util.List; import java.util.Objects; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageResponseMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageResponseMetadata.java similarity index 88% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageResponseMetadata.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageResponseMetadata.java index c4332c6c3..78fa5e7de 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/image/ImageResponseMetadata.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageResponseMetadata.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.image; +package org.springframework.ai.image; -import cn.iocoder.yudao.framework.ai.model.ResponseMetadata; +import org.springframework.ai.model.ResponseMetadata; public interface ImageResponseMetadata extends ResponseMetadata { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelClient.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelClient.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelClient.java index 705a7a976..03bec4c70 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelClient.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.model; +package org.springframework.ai.model; /** * The ModelClient interface provides a generic API for invoking AI models. It is designed diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelOptions.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelOptions.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelOptions.java index 6a5a738fe..96b301b79 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelOptions.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.model; +package org.springframework.ai.model; /** * Interface representing the customizable options for AI model interactions. This marker diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelOptionsUtils.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelOptionsUtils.java similarity index 99% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelOptionsUtils.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelOptionsUtils.java index 0d6f74007..9360399b6 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelOptionsUtils.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelOptionsUtils.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.model; +package org.springframework.ai.model; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonProcessingException; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelRequest.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelRequest.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelRequest.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelRequest.java index 915aba26e..b3c4969d4 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelRequest.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelRequest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.model; +package org.springframework.ai.model; /** * 表示对AI模型的请求的接口。此接口封装了 与人工智能模型交互所需的必要信息,包括指令或 输入(通用类型T)和附加模型选项。它提供了一种标准化的方式 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelResponse.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelResponse.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelResponse.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelResponse.java index 0bc0cc593..b3f40ffe7 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelResponse.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelResponse.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.model; +package org.springframework.ai.model; import java.util.List; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelResult.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelResult.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelResult.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelResult.java index 616be1817..5a5613a72 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ModelResult.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelResult.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.model; +package org.springframework.ai.model; /** * This interface provides methods to access the main output of the AI model and the diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ResponseMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ResponseMetadata.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ResponseMetadata.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ResponseMetadata.java index 2a85cdf7a..15e685d02 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ResponseMetadata.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ResponseMetadata.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.model; +package org.springframework.ai.model; /** * 表示与AI模型的响应相关联的元数据的接口。此接口 旨在提供有关人工智能生成反应的附加信息 模型,包括处理细节和模型特定数据。它是一种价值 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ResultMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ResultMetadata.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ResultMetadata.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ResultMetadata.java index 528b76459..78d5f7f6a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/ResultMetadata.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ResultMetadata.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.model; +package org.springframework.ai.model; /** * Interface representing metadata associated with the results of an AI model. This diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/StreamingModelClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/StreamingModelClient.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/StreamingModelClient.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/StreamingModelClient.java index abbe8598c..da1db1504 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/StreamingModelClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/StreamingModelClient.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.model; +package org.springframework.ai.model; import reactor.core.publisher.Flux; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/AbstractFunctionCallSupport.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/AbstractFunctionCallSupport.java similarity index 99% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/AbstractFunctionCallSupport.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/AbstractFunctionCallSupport.java index 33409f72d..67a34b1b1 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/AbstractFunctionCallSupport.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/AbstractFunctionCallSupport.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.model.function; +package org.springframework.ai.model.function; import org.springframework.util.CollectionUtils; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/AbstractFunctionCallback.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/AbstractFunctionCallback.java similarity index 98% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/AbstractFunctionCallback.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/AbstractFunctionCallback.java index 044c1813c..801ea3c10 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/AbstractFunctionCallback.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/AbstractFunctionCallback.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.model.function; +package org.springframework.ai.model.function; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallback.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallback.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallback.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallback.java index a14a59b8f..91fc3ba8a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallback.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallback.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.model.function; +package org.springframework.ai.model.function; /** * diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackContext.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallbackContext.java similarity index 98% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackContext.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallbackContext.java index ca24e2673..5524182bc 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackContext.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallbackContext.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.model.function; +package org.springframework.ai.model.function; import com.fasterxml.jackson.annotation.JsonClassDescription; import org.springframework.beans.BeansException; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackWrapper.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallbackWrapper.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackWrapper.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallbackWrapper.java index d82412125..23c981b0e 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallbackWrapper.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallbackWrapper.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.framework.ai.model.function; +package org.springframework.ai.model.function; -import cn.iocoder.yudao.framework.ai.model.ModelOptionsUtils; +import org.springframework.ai.model.ModelOptionsUtils; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.util.Assert; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallingOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallingOptions.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallingOptions.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallingOptions.java index fdb42d6a4..c66a4f5b1 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallingOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallingOptions.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.model.function; +package org.springframework.ai.model.function; import java.util.List; import java.util.Set; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallingOptionsBuilder.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallingOptionsBuilder.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallingOptionsBuilder.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallingOptionsBuilder.java index 4fc258b4a..44044400d 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/FunctionCallingOptionsBuilder.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallingOptionsBuilder.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.model.function; +package org.springframework.ai.model.function; -import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; +import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.util.Assert; import java.util.ArrayList; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/TypeResolverHelper.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/TypeResolverHelper.java similarity index 98% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/TypeResolverHelper.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/TypeResolverHelper.java index e1c8c4932..604ce0adc 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/function/TypeResolverHelper.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/TypeResolverHelper.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.model.function; +package org.springframework.ai.model.function; import net.jodah.typetools.TypeResolver; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/package-info.java similarity index 93% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/package-info.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/package-info.java index d2cf8e37b..12eaa53b4 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/model/package-info.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/package-info.java @@ -8,4 +8,4 @@ * ensuring a broad applicability across diverse AI scenarios. * */ -package cn.iocoder.yudao.framework.ai.model; \ No newline at end of file +package org.springframework.ai.model; \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyConfig.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/MidjourneyConfig.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyConfig.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/MidjourneyConfig.java index 8f749baf4..ea35c7768 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyConfig.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/MidjourneyConfig.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney; +package org.springframework.ai.models.midjourney; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/MidjourneyMessage.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyMessage.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/MidjourneyMessage.java index 3ee83be1e..30ce8ceac 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyMessage.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/MidjourneyMessage.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.framework.ai.midjourney; +package org.springframework.ai.models.midjourney; -import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyGennerateStatusEnum; +import org.springframework.ai.models.midjourney.constants.MidjourneyGennerateStatusEnum; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/MidjourneyInteractions.java similarity index 94% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractions.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/MidjourneyInteractions.java index 76549239a..6e64b2cb1 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/MidjourneyInteractions.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.framework.ai.midjourney.api; +package org.springframework.ai.models.midjourney.api; import cn.hutool.core.util.IdUtil; -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; -import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyConstants; +import org.springframework.ai.models.midjourney.MidjourneyConfig; +import org.springframework.ai.models.midjourney.constants.MidjourneyConstants; import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpHeaders; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractionsApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/MidjourneyInteractionsApi.java similarity index 93% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractionsApi.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/MidjourneyInteractionsApi.java index 7a578c832..3771113d0 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/MidjourneyInteractionsApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/MidjourneyInteractionsApi.java @@ -1,12 +1,12 @@ -package cn.iocoder.yudao.framework.ai.midjourney.api; +package org.springframework.ai.models.midjourney.api; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; -import cn.iocoder.yudao.framework.ai.midjourney.api.req.AttachmentsReq; -import cn.iocoder.yudao.framework.ai.midjourney.api.req.DescribeReq; -import cn.iocoder.yudao.framework.ai.midjourney.api.req.ReRollReq; -import cn.iocoder.yudao.framework.ai.midjourney.api.res.UploadAttachmentsRes; -import cn.iocoder.yudao.framework.ai.midjourney.util.MidjourneyUtil; +import org.springframework.ai.models.midjourney.MidjourneyConfig; +import org.springframework.ai.models.midjourney.api.req.AttachmentsReq; +import org.springframework.ai.models.midjourney.api.req.DescribeReq; +import org.springframework.ai.models.midjourney.api.req.ReRollReq; +import org.springframework.ai.models.midjourney.api.res.UploadAttachmentsRes; +import org.springframework.ai.models.midjourney.util.MidjourneyUtil; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.google.common.collect.Lists; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/req/AttachmentsReq.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/req/AttachmentsReq.java similarity index 85% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/req/AttachmentsReq.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/req/AttachmentsReq.java index ed18a4834..97de61bc6 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/req/AttachmentsReq.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/req/AttachmentsReq.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.api.req; +package org.springframework.ai.models.midjourney.api.req; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/req/DescribeReq.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/req/DescribeReq.java similarity index 85% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/req/DescribeReq.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/req/DescribeReq.java index 49a4ab31a..62e13c895 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/req/DescribeReq.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/req/DescribeReq.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.api.req; +package org.springframework.ai.models.midjourney.api.req; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/req/ReRollReq.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/req/ReRollReq.java similarity index 87% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/req/ReRollReq.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/req/ReRollReq.java index 0d8368987..990b60e5b 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/req/ReRollReq.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/req/ReRollReq.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.api.req; +package org.springframework.ai.models.midjourney.api.req; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/res/UploadAttachmentsRes.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/res/UploadAttachmentsRes.java similarity index 91% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/res/UploadAttachmentsRes.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/res/UploadAttachmentsRes.java index cba21c974..6d8c0e908 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/api/res/UploadAttachmentsRes.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/res/UploadAttachmentsRes.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.api.res; +package org.springframework.ai.models.midjourney.api.res; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyConstants.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/constants/MidjourneyConstants.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyConstants.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/constants/MidjourneyConstants.java index 29387a27b..b80ae6e98 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyConstants.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/constants/MidjourneyConstants.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.constants; +package org.springframework.ai.models.midjourney.constants; public final class MidjourneyConstants { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyGennerateStatusEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/constants/MidjourneyGennerateStatusEnum.java similarity index 91% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyGennerateStatusEnum.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/constants/MidjourneyGennerateStatusEnum.java index ef7147beb..1d2d36b0c 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyGennerateStatusEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/constants/MidjourneyGennerateStatusEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.constants; +package org.springframework.ai.models.midjourney.constants; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyInteractionsEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/constants/MidjourneyInteractionsEnum.java similarity index 89% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyInteractionsEnum.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/constants/MidjourneyInteractionsEnum.java index 08832e78b..1f5bbc448 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyInteractionsEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/constants/MidjourneyInteractionsEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.constants; +package org.springframework.ai.models.midjourney.constants; import lombok.Getter; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyMessageTypeEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/constants/MidjourneyMessageTypeEnum.java similarity index 85% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyMessageTypeEnum.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/constants/MidjourneyMessageTypeEnum.java index 9c8eb9ed5..b13a4efe8 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyMessageTypeEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/constants/MidjourneyMessageTypeEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.constants; +package org.springframework.ai.models.midjourney.constants; public enum MidjourneyMessageTypeEnum { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyNotifyCode.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/constants/MidjourneyNotifyCode.java similarity index 73% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyNotifyCode.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/constants/MidjourneyNotifyCode.java index 1dccb8a41..b2cc65a3d 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MidjourneyNotifyCode.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/constants/MidjourneyNotifyCode.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.constants; +package org.springframework.ai.models.midjourney.constants; import lombok.experimental.UtilityClass; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MidjourneyUtil.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/util/MidjourneyUtil.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MidjourneyUtil.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/util/MidjourneyUtil.java index 7e4c94e2b..50376b3f0 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MidjourneyUtil.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/util/MidjourneyUtil.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.framework.ai.midjourney.util; +package org.springframework.ai.models.midjourney.util; import cn.hutool.core.text.CharSequenceUtil; -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyMessage; +import org.springframework.ai.models.midjourney.MidjourneyMessage; import java.util.Map; import java.util.regex.Matcher; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/FailureCallback.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/FailureCallback.java similarity index 57% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/FailureCallback.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/FailureCallback.java index 29bdb062c..9e03c076a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/FailureCallback.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/FailureCallback.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.webSocket; +package org.springframework.ai.models.midjourney.webSocket; public interface FailureCallback { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MidjourneyMessageHandler.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/MidjourneyMessageHandler.java similarity index 61% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MidjourneyMessageHandler.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/MidjourneyMessageHandler.java index d5522fc82..efb794899 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MidjourneyMessageHandler.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/MidjourneyMessageHandler.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.framework.ai.midjourney.webSocket; +package org.springframework.ai.models.midjourney.webSocket; -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyMessage; +import org.springframework.ai.models.midjourney.MidjourneyMessage; /** * message handler diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MidjourneyWebSocketStarter.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/MidjourneyWebSocketStarter.java similarity index 95% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MidjourneyWebSocketStarter.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/MidjourneyWebSocketStarter.java index ddf7f3f7b..d4c81f369 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MidjourneyWebSocketStarter.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/MidjourneyWebSocketStarter.java @@ -1,12 +1,12 @@ -package cn.iocoder.yudao.framework.ai.midjourney.webSocket; +package org.springframework.ai.models.midjourney.webSocket; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.thread.ThreadUtil; -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; -import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyNotifyCode; -import cn.iocoder.yudao.framework.ai.midjourney.webSocket.handler.MidjourneyWebSocketHandler; -import cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener.MidjourneyMessageListener; +import org.springframework.ai.models.midjourney.MidjourneyConfig; +import org.springframework.ai.models.midjourney.constants.MidjourneyNotifyCode; +import org.springframework.ai.models.midjourney.webSocket.handler.MidjourneyWebSocketHandler; +import org.springframework.ai.models.midjourney.webSocket.listener.MidjourneyMessageListener; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.apache.tomcat.websocket.Constants; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/SuccessCallback.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/SuccessCallback.java similarity index 66% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/SuccessCallback.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/SuccessCallback.java index 729498fbc..3b0426da0 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/SuccessCallback.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/SuccessCallback.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.webSocket; +package org.springframework.ai.models.midjourney.webSocket; public interface SuccessCallback { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/WebSocketStarter.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/WebSocketStarter.java similarity index 60% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/WebSocketStarter.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/WebSocketStarter.java index 5a438aacc..0b48eaab3 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/WebSocketStarter.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/WebSocketStarter.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.webSocket; +package org.springframework.ai.models.midjourney.webSocket; public interface WebSocketStarter { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/WssNotify.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/WssNotify.java similarity index 72% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/WssNotify.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/WssNotify.java index 33c8a29e8..8b85c39cc 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/WssNotify.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/WssNotify.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.midjourney.webSocket; +package org.springframework.ai.models.midjourney.webSocket; /** * 通知信息 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/handler/MidjourneyWebSocketHandler.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/handler/MidjourneyWebSocketHandler.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/handler/MidjourneyWebSocketHandler.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/handler/MidjourneyWebSocketHandler.java index b6fbf5c21..8f985c425 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/handler/MidjourneyWebSocketHandler.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/handler/MidjourneyWebSocketHandler.java @@ -1,14 +1,14 @@ -package cn.iocoder.yudao.framework.ai.midjourney.webSocket.handler; +package org.springframework.ai.models.midjourney.webSocket.handler; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.RandomUtil; import cn.hutool.http.useragent.UserAgent; import cn.hutool.http.useragent.UserAgentUtil; -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; -import cn.iocoder.yudao.framework.ai.midjourney.webSocket.FailureCallback; -import cn.iocoder.yudao.framework.ai.midjourney.webSocket.SuccessCallback; -import cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener.MidjourneyMessageListener; +import org.springframework.ai.models.midjourney.MidjourneyConfig; +import org.springframework.ai.models.midjourney.webSocket.FailureCallback; +import org.springframework.ai.models.midjourney.webSocket.SuccessCallback; +import org.springframework.ai.models.midjourney.webSocket.listener.MidjourneyMessageListener; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.utils.data.DataArray; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/listener/MidjourneyMessageListener.java similarity index 90% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/listener/MidjourneyMessageListener.java index 0d196faf9..c99309e5a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MidjourneyMessageListener.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/webSocket/listener/MidjourneyMessageListener.java @@ -1,16 +1,16 @@ -package cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener; +package org.springframework.ai.models.midjourney.webSocket.listener; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig; -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyMessage; -import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyConstants; -import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyGennerateStatusEnum; -import cn.iocoder.yudao.framework.ai.midjourney.constants.MidjourneyMessageTypeEnum; -import cn.iocoder.yudao.framework.ai.midjourney.util.MidjourneyUtil; -import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyMessageHandler; +import org.springframework.ai.models.midjourney.MidjourneyConfig; +import org.springframework.ai.models.midjourney.MidjourneyMessage; +import org.springframework.ai.models.midjourney.constants.MidjourneyConstants; +import org.springframework.ai.models.midjourney.constants.MidjourneyGennerateStatusEnum; +import org.springframework.ai.models.midjourney.constants.MidjourneyMessageTypeEnum; +import org.springframework.ai.models.midjourney.util.MidjourneyUtil; +import org.springframework.ai.models.midjourney.webSocket.MidjourneyMessageHandler; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.utils.data.DataObject; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/OpenAiImageApi.java similarity index 94% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageApi.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/OpenAiImageApi.java index efc15a3ba..6cde315e7 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/OpenAiImageApi.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.framework.ai.imageopenai; +package org.springframework.ai.models.openai; import cn.hutool.json.JSONUtil; -import cn.iocoder.yudao.framework.ai.imageopenai.api.OpenAiImageRequest; -import cn.iocoder.yudao.framework.ai.imageopenai.api.OpenAiImageResponse; +import org.springframework.ai.models.openai.api.OpenAiImageRequest; +import org.springframework.ai.models.openai.api.OpenAiImageResponse; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import io.netty.channel.ChannelOption; import lombok.extern.slf4j.Slf4j; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/OpenAiImageClient.java similarity index 90% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageClient.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/OpenAiImageClient.java index 4dd536f99..558a0e6e8 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/OpenAiImageClient.java @@ -1,17 +1,17 @@ -package cn.iocoder.yudao.framework.ai.imageopenai; +package org.springframework.ai.models.openai; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.codec.Base64; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; -import cn.iocoder.yudao.framework.ai.chat.ChatException; -import cn.iocoder.yudao.framework.ai.chatyiyan.exception.YiYanApiException; -import cn.iocoder.yudao.framework.ai.exception.AiException; -import cn.iocoder.yudao.framework.ai.image.*; -import cn.iocoder.yudao.framework.ai.imageopenai.api.OpenAiImageRequest; -import cn.iocoder.yudao.framework.ai.imageopenai.api.OpenAiImageResponse; +import org.springframework.ai.chat.ChatException; +import org.springframework.ai.models.yiyan.exception.YiYanApiException; +import cn.iocoder.yudao.framework.ai.core.exception.AiException; +import org.springframework.ai.models.openai.api.OpenAiImageRequest; +import org.springframework.ai.models.openai.api.OpenAiImageResponse; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; +import org.springframework.ai.image.*; import org.springframework.retry.RetryCallback; import org.springframework.retry.RetryContext; import org.springframework.retry.RetryListener; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/OpenAiImageOptions.java similarity index 91% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/OpenAiImageOptions.java index c2fa74890..c6c903031 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/OpenAiImageOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/OpenAiImageOptions.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.framework.ai.imageopenai; +package org.springframework.ai.models.openai; -import cn.iocoder.yudao.framework.ai.image.ImageOptions; -import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageModelEnum; -import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageStyleEnum; +import org.springframework.ai.image.ImageOptions; +import org.springframework.ai.models.openai.enums.OpenAiImageModelEnum; +import org.springframework.ai.models.openai.enums.OpenAiImageStyleEnum; import lombok.Data; import lombok.Getter; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageRequest.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/api/OpenAiImageRequest.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageRequest.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/api/OpenAiImageRequest.java index 44ee174a2..0c01e1ea0 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageRequest.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/api/OpenAiImageRequest.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.imageopenai.api; +package org.springframework.ai.models.openai.api; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageResponse.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/api/OpenAiImageResponse.java similarity index 92% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageResponse.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/api/OpenAiImageResponse.java index 02698963e..beab4cdee 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/api/OpenAiImageResponse.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/api/OpenAiImageResponse.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.imageopenai.api; +package org.springframework.ai.models.openai.api; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/enums/OpenAiImageModelEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/enums/OpenAiImageModelEnum.java similarity index 92% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/enums/OpenAiImageModelEnum.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/enums/OpenAiImageModelEnum.java index 08cd2ae95..635c62bba 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/enums/OpenAiImageModelEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/enums/OpenAiImageModelEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.imageopenai.enums; +package org.springframework.ai.models.openai.enums; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/enums/OpenAiImageStyleEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/enums/OpenAiImageStyleEnum.java similarity index 94% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/enums/OpenAiImageStyleEnum.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/enums/OpenAiImageStyleEnum.java index 63feb85d3..d7999cd72 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/imageopenai/enums/OpenAiImageStyleEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/enums/OpenAiImageStyleEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.imageopenai.enums; +package org.springframework.ai.models.openai.enums; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java similarity index 95% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java index e18ebe036..7707d6879 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java @@ -1,10 +1,11 @@ -package cn.iocoder.yudao.framework.ai.chatqianwen; +package org.springframework.ai.models.tongyi; import cn.iocoder.yudao.framework.ai.chat.*; -import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; -import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; -import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenApi; -import cn.iocoder.yudao.framework.ai.chatyiyan.exception.YiYanApiException; +import org.springframework.ai.chat.*; +import org.springframework.ai.chat.prompt.ChatOptions; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.models.tongyi.api.QianWenApi; +import org.springframework.ai.models.yiyan.exception.YiYanApiException; import com.alibaba.dashscope.aigc.generation.GenerationResult; import com.alibaba.dashscope.aigc.generation.models.QwenParam; import com.alibaba.dashscope.common.Message; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatModal.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatModal.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatModal.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatModal.java index 7fd9411bf..9474a8df5 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatModal.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatModal.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.chatqianwen; +package org.springframework.ai.models.tongyi; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenOptions.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenOptions.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenOptions.java index 4cec86466..9a677607d 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenOptions.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.framework.ai.chatqianwen; +package org.springframework.ai.models.tongyi; -import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; +import org.springframework.ai.chat.prompt.ChatOptions; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenApi.java similarity index 89% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenApi.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenApi.java index c5d2bb680..2e905114f 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenApi.java @@ -1,12 +1,10 @@ -package cn.iocoder.yudao.framework.ai.chatqianwen.api; +package org.springframework.ai.models.tongyi.api; -import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatModal; -import cn.iocoder.yudao.framework.ai.exception.AiException; +import org.springframework.ai.models.tongyi.QianWenChatModal; +import cn.iocoder.yudao.framework.ai.core.exception.AiException; import com.alibaba.dashscope.aigc.generation.Generation; import com.alibaba.dashscope.aigc.generation.GenerationResult; import com.alibaba.dashscope.aigc.generation.models.QwenParam; -import com.alibaba.dashscope.common.Message; -import com.alibaba.dashscope.common.Role; import com.alibaba.dashscope.exception.InputRequiredException; import com.alibaba.dashscope.exception.NoApiKeyException; import io.reactivex.Flowable; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletion.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletion.java similarity index 62% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletion.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletion.java index 474a7d826..1c3c6109b 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletion.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletion.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.chatqianwen.api; +package org.springframework.ai.models.tongyi.api; /** diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletionMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionMessage.java similarity index 64% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletionMessage.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionMessage.java index 07680cbf4..4e5d02323 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletionMessage.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionMessage.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.chatqianwen.api; +package org.springframework.ai.models.tongyi.api; /** * author: fansili diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletionRequest.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionRequest.java similarity index 84% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletionRequest.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionRequest.java index 5017ea4ea..04b69848f 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/api/QianWenChatCompletionRequest.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionRequest.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.chatqianwen.api; +package org.springframework.ai.models.tongyi.api; import com.alibaba.dashscope.aigc.generation.models.QwenParam; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/package-info.java similarity index 86% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/package-info.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/package-info.java index c22dbe067..8d7793b34 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/package-info.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/package-info.java @@ -8,4 +8,4 @@ * author: fansili * time: 2024/3/13 21:05 */ -package cn.iocoder.yudao.framework.ai.chatqianwen; \ No newline at end of file +package org.springframework.ai.models.tongyi; \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoChatClient.java similarity index 93% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoChatClient.java index 90ae6dfee..9025d82fa 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoChatClient.java @@ -1,13 +1,14 @@ -package cn.iocoder.yudao.framework.ai.chatxinghuo; +package org.springframework.ai.models.xinghuo; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.exceptions.ExceptionUtil; import cn.iocoder.yudao.framework.ai.chat.*; -import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; -import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; -import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoApi; -import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletion; -import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletionRequest; +import org.springframework.ai.chat.*; +import org.springframework.ai.chat.prompt.ChatOptions; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.models.xinghuo.api.XingHuoApi; +import org.springframework.ai.models.xinghuo.api.XingHuoChatCompletion; +import org.springframework.ai.models.xinghuo.api.XingHuoChatCompletionRequest; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.retry.RetryCallback; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatModel.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoChatModel.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatModel.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoChatModel.java index 5be9f40a9..859e41c03 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoChatModel.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoChatModel.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.chatxinghuo; +package org.springframework.ai.models.xinghuo; import lombok.Getter; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoOptions.java similarity index 93% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoOptions.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoOptions.java index 7d5603282..8efa7527b 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/XingHuoOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoOptions.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.framework.ai.chatxinghuo; +package org.springframework.ai.models.xinghuo; -import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; +import org.springframework.ai.chat.prompt.ChatOptions; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoApi.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoApi.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoApi.java index e2a85779e..027e8a2d2 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoApi.java @@ -1,10 +1,8 @@ -package cn.iocoder.yudao.framework.ai.chatxinghuo.api; +package org.springframework.ai.models.xinghuo.api; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONUtil; -import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel; -import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletion; -import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletionRequest; +import org.springframework.ai.models.xinghuo.XingHuoChatModel; import lombok.Data; import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletion.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoChatCompletion.java similarity index 94% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletion.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoChatCompletion.java index a0f965327..e419d522e 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletion.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoChatCompletion.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.chatxinghuo.api; +package org.springframework.ai.models.xinghuo.api; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletionMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoChatCompletionMessage.java similarity index 64% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletionMessage.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoChatCompletionMessage.java index faa3c8c73..f0e0f8d1e 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletionMessage.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoChatCompletionMessage.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.chatxinghuo.api; +package org.springframework.ai.models.xinghuo.api; /** * author: fansili diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletionRequest.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoChatCompletionRequest.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletionRequest.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoChatCompletionRequest.java index a90697bfc..3f2b211ff 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatxinghuo/api/XingHuoChatCompletionRequest.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoChatCompletionRequest.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.chatxinghuo.api; +package org.springframework.ai.models.xinghuo.api; import lombok.Data; import lombok.Getter; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatClient.java similarity index 91% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatClient.java index d95e9fb99..fecc6acc0 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatClient.java @@ -1,15 +1,16 @@ -package cn.iocoder.yudao.framework.ai.chatyiyan; +package org.springframework.ai.models.yiyan; import cn.hutool.core.bean.BeanUtil; import cn.iocoder.yudao.framework.ai.chat.*; -import cn.iocoder.yudao.framework.ai.chat.messages.Message; -import cn.iocoder.yudao.framework.ai.chat.messages.MessageType; -import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; -import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; -import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanApi; -import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletion; -import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletionRequest; -import cn.iocoder.yudao.framework.ai.chatyiyan.exception.YiYanApiException; +import org.springframework.ai.chat.*; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.MessageType; +import org.springframework.ai.chat.prompt.ChatOptions; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.models.yiyan.api.YiYanApi; +import org.springframework.ai.models.yiyan.api.YiYanChatCompletion; +import org.springframework.ai.models.yiyan.api.YiYanChatCompletionRequest; +import org.springframework.ai.models.yiyan.exception.YiYanApiException; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; import org.springframework.http.ResponseEntity; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatModel.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatModel.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatModel.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatModel.java index 4c8b3aa85..abed185e6 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanChatModel.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatModel.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.chatyiyan; +package org.springframework.ai.models.yiyan; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanOptions.java similarity index 95% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanOptions.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanOptions.java index 84f0ced4c..aac8e4949 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/YiYanOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanOptions.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.framework.ai.chatyiyan; +package org.springframework.ai.models.yiyan; -import cn.iocoder.yudao.framework.ai.chat.prompt.ChatOptions; -import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletionRequest; +import org.springframework.ai.chat.prompt.ChatOptions; +import org.springframework.ai.models.yiyan.api.YiYanChatCompletionRequest; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanApi.java similarity index 89% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanApi.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanApi.java index ad1059b1a..a8f4aa322 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanApi.java @@ -1,10 +1,7 @@ -package cn.iocoder.yudao.framework.ai.chatyiyan.api; +package org.springframework.ai.models.yiyan.api; -import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel; -import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanAuthRes; -import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletion; -import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletionRequest; -import cn.iocoder.yudao.framework.ai.chatyiyan.exception.YiYanApiException; +import org.springframework.ai.models.yiyan.YiYanChatModel; +import org.springframework.ai.models.yiyan.exception.YiYanApiException; import lombok.Data; import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanAuthRes.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanAuthRes.java similarity index 94% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanAuthRes.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanAuthRes.java index e828858c2..f9f1f27db 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanAuthRes.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanAuthRes.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.chatyiyan.api; +package org.springframework.ai.models.yiyan.api; import lombok.Data; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletion.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanChatCompletion.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletion.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanChatCompletion.java index b995da82a..8e02db659 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletion.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanChatCompletion.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.chatyiyan.api; +package org.springframework.ai.models.yiyan.api; import lombok.Data; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletionMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanChatCompletionMessage.java similarity index 64% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletionMessage.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanChatCompletionMessage.java index ce6259c76..278b1a7d6 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletionMessage.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanChatCompletionMessage.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.chatyiyan.api; +package org.springframework.ai.models.yiyan.api; /** * author: fansili diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletionRequest.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanChatCompletionRequest.java similarity index 99% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletionRequest.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanChatCompletionRequest.java index de6c19ee1..22e918835 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/api/YiYanChatCompletionRequest.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanChatCompletionRequest.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.chatyiyan.api; +package org.springframework.ai.models.yiyan.api; import lombok.Data; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/exception/YiYanApiException.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/exception/YiYanApiException.java similarity index 81% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/exception/YiYanApiException.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/exception/YiYanApiException.java index dbb8ed93a..94850f56a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatyiyan/exception/YiYanApiException.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/exception/YiYanApiException.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.ai.chatyiyan.exception; +package org.springframework.ai.models.yiyan.exception; /** * 一言 api 调用异常 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/package-info.java new file mode 100644 index 000000000..b38419f6f --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/package-info.java @@ -0,0 +1,15 @@ +/** + * 从 https://github.com/spring-projects/spring-ai 拷贝。 + * + * 最大目的:适配 JDK8 兼容性 + * + * 包路径: + * 1. chat、parser、model、parser 包:https://github.com/spring-projects/spring-ai/tree/main/spring-ai-core 拷贝 + * 2. models 包:对标 https://github.com/spring-projects/spring-ai/tree/main/models 拷贝 + * 2.1 tongyi 包:【阿里】通义千问,对标 spring-cloud-alibaba 提供的 ai 包 + * 2.2 yiyan 包:【百度】文心一言,自己实现 + * 2.3 xinghuo 包:【讯飞】星火,自己实现 + * 2.4 openai 包:【OpenAI】ChatGPT,拷贝 spring-ai 提供的 models/openai 包 + * 2.5 midjourney 包:Midjourney,参考 https://github.com/novicezk/midjourney-proxy 实现 + */ +package org.springframework.ai; \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/AbstractConversionServiceOutputParser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/AbstractConversionServiceOutputParser.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/AbstractConversionServiceOutputParser.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/AbstractConversionServiceOutputParser.java index cee9fff42..a06827f39 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/AbstractConversionServiceOutputParser.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/AbstractConversionServiceOutputParser.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.parser; +package org.springframework.ai.parser; import org.springframework.core.convert.support.DefaultConversionService; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/AbstractMessageConverterOutputParser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/AbstractMessageConverterOutputParser.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/AbstractMessageConverterOutputParser.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/AbstractMessageConverterOutputParser.java index abe5005ab..01dbadaf1 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/AbstractMessageConverterOutputParser.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/AbstractMessageConverterOutputParser.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.parser; +package org.springframework.ai.parser; import org.springframework.messaging.converter.MessageConverter; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/BeanOutputParser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/BeanOutputParser.java similarity index 99% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/BeanOutputParser.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/BeanOutputParser.java index 109e75fc4..fa09c26af 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/BeanOutputParser.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/BeanOutputParser.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.parser; +package org.springframework.ai.parser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.util.DefaultIndenter; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/FormatProvider.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/FormatProvider.java similarity index 95% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/FormatProvider.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/FormatProvider.java index 53d001729..8d0cb76b0 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/FormatProvider.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/FormatProvider.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.parser; +package org.springframework.ai.parser; /** * Implementations of this interface provides instructions for how the output of a diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/ListOutputParser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/ListOutputParser.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/ListOutputParser.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/ListOutputParser.java index 37fd49b89..d11225797 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/ListOutputParser.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/ListOutputParser.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.parser; +package org.springframework.ai.parser; import org.springframework.core.convert.support.DefaultConversionService; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/MapOutputParser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/MapOutputParser.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/MapOutputParser.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/MapOutputParser.java index bd57b3b44..90f017f79 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/MapOutputParser.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/MapOutputParser.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.parser; +package org.springframework.ai.parser; import org.springframework.messaging.Message; import org.springframework.messaging.converter.MappingJackson2MessageConverter; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/OutputParser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/OutputParser.java similarity index 95% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/OutputParser.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/OutputParser.java index 1543532b3..cbc7e6e5a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/OutputParser.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/OutputParser.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.parser; +package org.springframework.ai.parser; /** * Converts the (raw) LLM output into a structured responses of type. The diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/Parser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/Parser.java similarity index 93% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/Parser.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/Parser.java index 6016ee51c..559473f08 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/Parser.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/Parser.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.framework.ai.parser; +package org.springframework.ai.parser; @FunctionalInterface public interface Parser { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/README.md b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/README.md similarity index 100% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/parser/README.md rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/README.md diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java index 16ddfa45d..0882f72a0 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java @@ -1,12 +1,13 @@ package cn.iocoder.yudao.framework.ai.chat; -import cn.iocoder.yudao.framework.ai.chat.messages.SystemMessage; -import cn.iocoder.yudao.framework.ai.chat.messages.UserMessage; -import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; -import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient; -import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatModal; -import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenOptions; -import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenApi; +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.messages.SystemMessage; +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.models.tongyi.QianWenChatClient; +import org.springframework.ai.models.tongyi.QianWenChatModal; +import org.springframework.ai.models.tongyi.QianWenOptions; +import org.springframework.ai.models.tongyi.api.QianWenApi; import com.alibaba.dashscope.aigc.generation.GenerationResult; import com.alibaba.dashscope.aigc.generation.models.QwenParam; import com.alibaba.dashscope.common.Message; @@ -46,7 +47,7 @@ public class QianWenChatClientTests { @Test public void callTest() { - List messages = new ArrayList<>(); + List messages = new ArrayList<>(); messages.add(new SystemMessage("你是一个优质的小红书文艺作者,抒写着各城市的美好文化和风景。")); messages.add(new UserMessage("长沙怎么样?")); @@ -56,7 +57,7 @@ public class QianWenChatClientTests { @Test public void streamTest() { - List messages = new ArrayList<>(); + List messages = new ArrayList<>(); messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。")); messages.add(new UserMessage("长沙怎么样?")); diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientMainTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientMainTests.java index 674e4dc6d..77cf9effc 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientMainTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientMainTests.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.framework.ai.chat; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONUtil; -import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletion; -import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletionRequest; +import org.springframework.ai.models.xinghuo.api.XingHuoChatCompletion; +import org.springframework.ai.models.xinghuo.api.XingHuoChatCompletionRequest; import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient; import org.springframework.web.reactive.socket.client.WebSocketClient; import reactor.core.publisher.Flux; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java index ee32b6717..44793907e 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java @@ -1,13 +1,14 @@ package cn.iocoder.yudao.framework.ai.chat; -import cn.iocoder.yudao.framework.ai.chat.messages.Message; -import cn.iocoder.yudao.framework.ai.chat.messages.SystemMessage; -import cn.iocoder.yudao.framework.ai.chat.messages.UserMessage; -import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; -import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatClient; -import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel; -import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoOptions; -import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoApi; +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.SystemMessage; +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.models.xinghuo.XingHuoChatClient; +import org.springframework.ai.models.xinghuo.XingHuoChatModel; +import org.springframework.ai.models.xinghuo.XingHuoOptions; +import org.springframework.ai.models.xinghuo.api.XingHuoApi; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoOkHttpTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoOkHttpTests.java index 3f2903201..f45f96412 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoOkHttpTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoOkHttpTests.java @@ -2,9 +2,9 @@ package cn.iocoder.yudao.framework.ai.chat; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONUtil; -import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatClient; -import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletion; -import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoChatCompletionRequest; +import org.springframework.ai.models.xinghuo.XingHuoChatClient; +import org.springframework.ai.models.xinghuo.api.XingHuoChatCompletion; +import org.springframework.ai.models.xinghuo.api.XingHuoChatCompletionRequest; import okhttp3.*; import org.jetbrains.annotations.NotNull; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java index df98541fc..f54ae39c8 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java @@ -1,13 +1,14 @@ package cn.iocoder.yudao.framework.ai.chat; -import cn.iocoder.yudao.framework.ai.chat.messages.Message; -import cn.iocoder.yudao.framework.ai.chat.messages.SystemMessage; -import cn.iocoder.yudao.framework.ai.chat.messages.UserMessage; -import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; -import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatClient; -import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel; -import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanOptions; -import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanApi; +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.SystemMessage; +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.models.yiyan.YiYanChatClient; +import org.springframework.ai.models.yiyan.YiYanChatModel; +import org.springframework.ai.models.yiyan.YiYanOptions; +import org.springframework.ai.models.yiyan.api.YiYanApi; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java index fda7818f0..d93ac0b25 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsTests.java @@ -2,11 +2,12 @@ package cn.iocoder.yudao.framework.ai.midjourney; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.IdUtil; -import cn.iocoder.yudao.framework.ai.midjourney.api.MidjourneyInteractionsApi; -import cn.iocoder.yudao.framework.ai.midjourney.api.req.AttachmentsReq; -import cn.iocoder.yudao.framework.ai.midjourney.api.req.DescribeReq; -import cn.iocoder.yudao.framework.ai.midjourney.api.req.ReRollReq; -import cn.iocoder.yudao.framework.ai.midjourney.api.res.UploadAttachmentsRes; +import org.springframework.ai.models.midjourney.MidjourneyConfig; +import org.springframework.ai.models.midjourney.api.MidjourneyInteractionsApi; +import org.springframework.ai.models.midjourney.api.req.AttachmentsReq; +import org.springframework.ai.models.midjourney.api.req.DescribeReq; +import org.springframework.ai.models.midjourney.api.req.ReRollReq; +import org.springframework.ai.models.midjourney.api.res.UploadAttachmentsRes; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import org.junit.Before; import org.junit.Test; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyUtilTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyUtilTests.java index 39d64931f..b5604b86d 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyUtilTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyUtilTests.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.framework.ai.midjourney; -import cn.iocoder.yudao.framework.ai.midjourney.util.MidjourneyUtil; +import org.springframework.ai.models.midjourney.util.MidjourneyUtil; import org.junit.Test; /** diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyWebSocketTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyWebSocketTests.java index cf90b17d8..ff0395653 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyWebSocketTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyWebSocketTests.java @@ -1,9 +1,10 @@ package cn.iocoder.yudao.framework.ai.midjourney; import cn.hutool.core.io.FileUtil; -import cn.iocoder.yudao.framework.ai.midjourney.webSocket.WssNotify; -import cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener.MidjourneyMessageListener; -import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyWebSocketStarter; +import org.springframework.ai.models.midjourney.MidjourneyConfig; +import org.springframework.ai.models.midjourney.webSocket.WssNotify; +import org.springframework.ai.models.midjourney.webSocket.listener.MidjourneyMessageListener; +import org.springframework.ai.models.midjourney.webSocket.MidjourneyWebSocketStarter; import org.junit.Before; import org.junit.Test; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java index b85ec8841..ba439c683 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.framework.ai.openAiImage; -import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageApi; -import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageClient; -import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageOptions; -import cn.iocoder.yudao.framework.ai.image.ImagePrompt; -import cn.iocoder.yudao.framework.ai.image.ImageResponse; +import org.springframework.ai.models.openai.OpenAiImageApi; +import org.springframework.ai.models.openai.OpenAiImageClient; +import org.springframework.ai.models.openai.OpenAiImageOptions; +import org.springframework.ai.image.ImagePrompt; +import org.springframework.ai.image.ImageResponse; import org.junit.Before; import org.junit.Test; From 37952c6a102368c9b3e53828b66bf86deb8d7a1b Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 12 May 2024 19:53:45 +0800 Subject: [PATCH 264/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E8=B0=83=E6=95=B4=20ai=20starter=20=E7=9A=84=E5=8C=85?= =?UTF-8?q?=E5=B0=81=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/springframework/ai/models/tongyi/QianWenChatClient.java | 1 - .../org/springframework/ai/models/xinghuo/XingHuoChatClient.java | 1 - .../org/springframework/ai/models/yiyan/YiYanChatClient.java | 1 - 3 files changed, 3 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java index 7707d6879..c1d0d41bf 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java @@ -1,6 +1,5 @@ package org.springframework.ai.models.tongyi; -import cn.iocoder.yudao.framework.ai.chat.*; import org.springframework.ai.chat.*; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.prompt.Prompt; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoChatClient.java index 9025d82fa..740d74910 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoChatClient.java @@ -2,7 +2,6 @@ package org.springframework.ai.models.xinghuo; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.exceptions.ExceptionUtil; -import cn.iocoder.yudao.framework.ai.chat.*; import org.springframework.ai.chat.*; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.prompt.Prompt; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatClient.java index fecc6acc0..819976629 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatClient.java @@ -1,7 +1,6 @@ package org.springframework.ai.models.yiyan; import cn.hutool.core.bean.BeanUtil; -import cn.iocoder.yudao.framework.ai.chat.*; import org.springframework.ai.chat.*; import org.springframework.ai.chat.messages.Message; import org.springframework.ai.chat.messages.MessageType; From 6bc1f8d0f949cd3f09d7b4d39f55633eb85f02f7 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 13 May 2024 13:12:33 +0800 Subject: [PATCH 265/684] =?UTF-8?q?=E3=80=90=E4=BF=AE=E5=A4=8D=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E4=B8=B4=E6=97=B6=E8=A7=A3=E5=86=B3=20send-stream=20?= =?UTF-8?q?=E8=A2=AB=E6=9D=83=E9=99=90=E6=8B=A6=E6=88=AA=20Access=20Denied?= =?UTF-8?q?=20=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/admin/chat/AiChatMessageController.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java index fb0d9f5ad..7a6c1bc12 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java @@ -7,6 +7,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; +import jakarta.annotation.security.PermitAll; import lombok.extern.slf4j.Slf4j; import org.springframework.http.MediaType; import org.springframework.validation.annotation.Validated; @@ -37,6 +38,7 @@ public class AiChatMessageController { // TODO @fan:要不要使用 Flux 来返回;可以使用 Flux @Operation(summary = "发送消息(流式)", description = "流式返回,响应较快") @PostMapping(value = "/send-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) + @PermitAll // 解决 SSE 最终响应的时候,会被 Access Denied 拦截的问题 public Flux sendMessageStream(@Validated @RequestBody AiChatMessageSendStreamReqVO sendReqVO) { return chatService.chatStream(sendReqVO); } From 1676f671d8170144ec64acfe9ef451913ed0dd47 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 13 May 2024 20:46:37 +0800 Subject: [PATCH 266/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E8=81=8A=E5=A4=A9=E8=A7=92=E8=89=B2=E7=AE=A1=E7=90=86?= =?UTF-8?q?=EF=BC=8850%=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/ErrorCodeConstants.java | 12 +- .../admin/model/AiChatRoleController.java | 94 ++++++++----- .../model/vo/role/AiChatRoleAddReqVO.java | 52 ------- .../model/vo/role/AiChatRoleListReqVO.java | 20 --- .../model/vo/role/AiChatRoleListRespVO.java | 52 ------- .../model/vo/role/AiChatRolePageReqVO.java | 27 ++++ .../admin/model/vo/role/AiChatRoleRespVO.java | 54 +++++--- .../model/vo/role/AiChatRoleSaveReqVO.java | 57 ++++++++ .../AiChatRoleUpdatePublicStatusReqVO.java | 27 ---- .../model/vo/role/AiChatRoleUpdateReqVO.java | 62 --------- .../module/ai/convert/AiChatRoleConvert.java | 56 -------- .../ai/dal/dataobject/model/AiChatRoleDO.java | 7 +- .../module/ai/dal/mysql/AiChatRoleMapper.java | 18 ++- .../module/ai/service/AiChatRoleService.java | 76 ----------- .../AiChatConversationServiceImpl.java | 12 +- .../service/impl/AiChatRoleServiceImpl.java | 129 ------------------ .../ai/service/impl/AiChatServiceImpl.java | 28 +--- .../ai/service/model/AiChatRoleService.java | 61 +++++++++ .../service/model/AiChatRoleServiceImpl.java | 85 ++++++++++++ 19 files changed, 355 insertions(+), 574 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleAddReqVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListReqVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListRespVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRolePageReqVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleSaveReqVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdatePublicStatusReqVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdateReqVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/{model => impl}/AiChatConversationServiceImpl.java (93%) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index 4e101cd7e..b65314f52 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -18,8 +18,9 @@ public interface ErrorCodeConstants { ErrorCode CHAT_MODAL_NOT_EXIST = new ErrorCode(1_040_001_000, "AI 模型不存在!"); ErrorCode CHAT_MODAL_DISABLE = new ErrorCode(1_040_001_001, "AI 模型({})已禁用!"); - // ErrorCode AI_MODAL_CONFIG_PARAMS_INCORRECT = new ErrorCode(1_022_000_081, "AI 模型 config 参数不正确! {} "); -// ErrorCode AI_MODAL_PLATFORM_PARAMS_INCORRECT = new ErrorCode(1_022_000_083, "AI 平台参数不正确! {} "); + // ========== API 聊天模型 1-040-002-000 ========== + ErrorCode CHAT_ROLE_NOT_EXISTS = new ErrorCode(1_040_002_000, "AI 聊天角色不存在"); + ErrorCode CHAT_ROLE_DISABLE = new ErrorCode(1_040_001_001, "AI 聊天角色({})已禁用!"); // conversation @@ -31,14 +32,7 @@ public interface ErrorCodeConstants { ErrorCode AI_MIDJOURNEY_OPERATION_NOT_EXISTS = new ErrorCode(1_022_000_040, "midjourney 操作不存在!"); ErrorCode AI_MIDJOURNEY_MESSAGE_ID_INCORRECT = new ErrorCode(1_022_000_040, "midjourney message id 不正确!"); - // role - - ErrorCode AI_CHAT_ROLE_NOT_EXIST = new ErrorCode(1_022_000_060, "AI 角色不存在!"); - ErrorCode AI_CHAT_ROLE_NOT_PUBLIC = new ErrorCode(1_022_000_060, "AI 角色未公开!"); - // chat - ErrorCode AI_CHAT_MESSAGE_NOT_EXIST = new ErrorCode(1_022_000_100, "AI 提问的 MessageId 不存在!"); - } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java index 1de4b3991..5757d8316 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java @@ -1,17 +1,30 @@ package cn.iocoder.yudao.module.ai.controller.admin.model; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.*; -import cn.iocoder.yudao.module.ai.service.AiChatRoleService; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRolePageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleSaveReqVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; +import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + @Tag(name = "管理后台 - AI 聊天角色") @RestController @RequestMapping("/ai/chat-role") @@ -21,42 +34,55 @@ public class AiChatRoleController { @Resource private AiChatRoleService chatRoleService; - @Operation(summary = "chat角色 - 角色列表") - @GetMapping("/list") - public PageResult list(@Validated @ModelAttribute AiChatRoleListReqVO req) { - return chatRoleService.list(req); - } + // TODO 芋艿:我的分页 - @Operation(summary = "chat角色 - 添加") - @PutMapping("/add") - public CommonResult add(@Validated @RequestBody AiChatRoleAddReqVO req) { - chatRoleService.add(req); - return CommonResult.success(null); - } + // TODO 芋艿:我的新增 - @Operation(summary = "chat角色 - 修改") - @PostMapping("/update") - public CommonResult update(@Validated @RequestBody AiChatRoleUpdateReqVO req) { - chatRoleService.update(req); - return CommonResult.success(null); - } + // TODO 芋艿:我的修改 - @Operation(summary = "chat角色 - 修改可见性") - @PostMapping("/update-public-status") - public CommonResult updatePublicStatus(@Validated @RequestBody AiChatRoleUpdatePublicStatusReqVO req) { - chatRoleService.updatePublicStatus(req); - return CommonResult.success(null); - } - - @Operation(summary = "chat角色 - 删除") - @DeleteMapping("/delete") - public CommonResult delete(@RequestParam("id") Long id) { - chatRoleService.delete(id); - return CommonResult.success(null); - } + // TODO 芋艿:我的删除 // ========== 角色管理 ========== + @PostMapping("/create") + @Operation(summary = "创建聊天角色") + @PreAuthorize("@ss.hasPermission('ai:chat-role:create')") + public CommonResult createChatRole(@Valid @RequestBody AiChatRoleSaveReqVO createReqVO) { + return success(chatRoleService.createChatRole(createReqVO)); + } + @PutMapping("/update") + @Operation(summary = "更新聊天角色") + @PreAuthorize("@ss.hasPermission('ai:chat-role:update')") + public CommonResult updateChatRole(@Valid @RequestBody AiChatRoleSaveReqVO updateReqVO) { + chatRoleService.updateChatRole(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除聊天角色") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('ai:chat-role:delete')") + public CommonResult deleteChatRole(@RequestParam("id") Long id) { + chatRoleService.deleteChatRole(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得聊天角色") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('ai:chat-role:query')") + public CommonResult getChatRole(@RequestParam("id") Long id) { + AiChatRoleDO chatRole = chatRoleService.getChatRole(id); + return success(BeanUtils.toBean(chatRole, AiChatRoleRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得聊天角色分页") + @PreAuthorize("@ss.hasPermission('ai:chat-role:query')") + public CommonResult> getChatRolePage(@Valid AiChatRolePageReqVO pageReqVO) { + PageResult pageResult = chatRoleService.getChatRolePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, AiChatRoleRespVO.class)); + } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleAddReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleAddReqVO.java deleted file mode 100644 index f069caf97..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleAddReqVO.java +++ /dev/null @@ -1,52 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * chat 角色列表 - * - * @fansili - * @since v1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatRoleAddReqVO { - - @NotNull - @Schema(description = "角色名,角色的显示名称") - private String name; - - @Schema(description = "头像") - private String avatar; - - @NotNull - @Schema(description = "分类,角色所属的类别,如娱乐、创作等") - private String category; - - @NotNull - @Schema(description = "角色描述") - private String description; - - @Schema(description = "角色欢迎语") - private String welcomeMessage; - - @NotNull - @Schema(description = "角色设定(消息)") - private String systemMessage; - - @NotNull - @Schema(description = "模型编号") - private Long modelId; - - @NotNull - @Schema(description = "开启状态 0、open 1、close") - private Boolean publicStatus; - - @NotNull - @Schema(description = "排序") - private Integer sort; - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListReqVO.java deleted file mode 100644 index 247154a4c..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * chat 角色列表 - * - * @fansili - * @since v1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatRoleListReqVO extends PageParam { - - @Schema(description = "查询") - private String search; -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListRespVO.java deleted file mode 100644 index 3eee736be..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleListRespVO.java +++ /dev/null @@ -1,52 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * chat 角色列表 - * - * @fansili - * @since v1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatRoleListRespVO { - - @Schema(description = "编号", example = "1") - private Long id; - - @Schema(description = "角色名称", example = "小红书写作") - private String name; - - @Schema(description = "角色头像", example = "http://...") - private String avatar; - - @Schema(description = "角色分类", example = "writing") - private String category; - - @Schema(description = "角色描述", example = "角色描述") - private String description; - - @Schema(description = "角色欢迎语", example = "欢迎...") - private String welcomeMessage; - - @Schema(description = "角色设定(消息)", example = "你是拥有丰富的小红书写作经验作者xxxx") - private String systemMessage; - - @Schema(description = "用户编号", example = "1") - private Long userId; - - @Schema(description = "模型编号", example = "1") - private Long modelId; - - @Schema(description = "是否公开 true - 公开;false - 私有", example = "true") - private Boolean publicStatus; - - @Schema(description = "排序值 asc", example = "1") - private Integer sort; - - @Schema(description = "状态 0、开启 1、关闭", example = "1") - private Integer status; -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRolePageReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRolePageReqVO.java new file mode 100644 index 000000000..d1eb417d6 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRolePageReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - AI 聊天角色分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class AiChatRolePageReqVO extends PageParam { + + @Schema(description = "角色名称", example = "李四") + private String name; + + @Schema(description = "角色类别", example = "创作") + private String category; + + @Schema(description = "是否公开", example = "1") + private Boolean publicStatus; + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleRespVO.java index a28dd4f4c..60dbf07df 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleRespVO.java @@ -2,36 +2,50 @@ package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.experimental.Accessors; -/** - * chat 角色 - * - * @fansili - * @since v1.0 - */ +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - AI 聊天角色 Response VO") @Data -@Accessors(chain = true) public class AiChatRoleRespVO { - @Schema(description = "id") + @Schema(description = "角色编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32746") private Long id; - @Schema(description = "用户id") + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "9442") private Long userId; - @Schema(description = "角色名字") + @Schema(description = "模型编号", example = "17640") + private Long modelId; + + @Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") private String name; - @Schema(description = "角色介绍,详细描述角色的功能或用途") - private String introduce; + @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + private String avatar; - @Schema(description = "分类,角色所属的类别,如娱乐、创作等") - private String classify; + @Schema(description = "角色类别", requiredMode = Schema.RequiredMode.REQUIRED, example = "创作") + private String category; - @Schema(description = "状态 open、close") - private String enable; + @Schema(description = "角色排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer sort; - @Schema(description = "角色的使用次数统计") - private Integer useCount; -} + @Schema(description = "角色描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对") + private String description; + + @Schema(description = "角色欢迎语", requiredMode = Schema.RequiredMode.REQUIRED) + private String welcomeMessage; + + @Schema(description = "角色上下文", requiredMode = Schema.RequiredMode.REQUIRED) + private String systemMessage; + + @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Boolean publicStatus; + + @Schema(description = "状态", example = "1") + private Integer status; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleSaveReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleSaveReqVO.java new file mode 100644 index 000000000..97f92f3d1 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleSaveReqVO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import jakarta.validation.constraints.*; + +@Schema(description = "管理后台 - AI 聊天角色新增/修改 Request VO") +@Data +public class AiChatRoleSaveReqVO { + + @Schema(description = "角色编号", example = "32746") + private Long id; + + @Schema(description = "模型编号", example = "17640") + private Long modelId; + + @Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + @NotEmpty(message = "角色名称不能为空") + private String name; + + @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @NotEmpty(message = "角色头像不能为空") + private String avatar; + + @Schema(description = "角色类别", requiredMode = Schema.RequiredMode.REQUIRED, example = "创作") + @NotEmpty(message = "角色类别不能为空") + private String category; + + @Schema(description = "角色排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "角色排序不能为空") + private Integer sort; + + @Schema(description = "角色描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对") + @NotEmpty(message = "角色描述不能为空") + private String description; + + @Schema(description = "角色欢迎语", requiredMode = Schema.RequiredMode.REQUIRED, example = "Talk is cheap, i will show code") + @NotEmpty(message = "角色欢迎语不能为空") + private String welcomeMessage; + + @Schema(description = "角色上下文", requiredMode = Schema.RequiredMode.REQUIRED, example = "现在开始你扮演一位程序员,你是一名优秀的程序员,具有很强的逻辑思维能力,总能高效的解决问题") + @NotEmpty(message = "角色上下文不能为空") + private String systemMessage; + + @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "是否公开不能为空") + private Boolean publicStatus; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "状态不能为空") + @InEnum(CommonStatusEnum.class) + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdatePublicStatusReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdatePublicStatusReqVO.java deleted file mode 100644 index c61b6d964..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdatePublicStatusReqVO.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * chat 角色 - 修改可见性 - * - * @fansili - * @since v1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatRoleUpdatePublicStatusReqVO extends PageParam { - - - @NotNull(message = "角色编号不能为空") - @Schema(description = "角色编号") - private Long id; - - @NotNull(message = "开启状态不能为空") - @Schema(description = "开启状态 open、close") - private Boolean publicStatus; -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdateReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdateReqVO.java deleted file mode 100644 index d578b2f74..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleUpdateReqVO.java +++ /dev/null @@ -1,62 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * chat 角色 - 更新 - * - * @fansili - * @since v1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatRoleUpdateReqVO extends PageParam { - - - @NotNull(message = "角色编号不能为空") - @Schema(description = "角色编号") - private Long id; - - @NotNull - @Schema(description = "角色名,角色的显示名称") - private String name; - - @Schema(description = "头像") - private String avatar; - - @NotNull - @Schema(description = "分类,角色所属的类别,如娱乐、创作等") - private String category; - - @NotNull - @Schema(description = "角色描述") - private String description; - - @Schema(description = "角色欢迎语") - private String welcomeMessage; - - @NotNull - @Schema(description = "角色设定(消息)") - private String systemMessage; - - @NotNull - @Schema(description = "模型编号") - private Long modelId; - - @NotNull - @Schema(description = "开启状态 open、close") - private Boolean publicStatus; - - @NotNull - @Schema(description = "排序") - private Integer sort; - - @NotNull - @Schema(description = "状态") - private Integer status; - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java deleted file mode 100644 index 269b4a6ee..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatRoleConvert.java +++ /dev/null @@ -1,56 +0,0 @@ -package cn.iocoder.yudao.module.ai.convert; - -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleAddReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleUpdateReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleListRespVO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * 聊天 对话 convert - * - * @author fansili - * @time 2024/4/18 16:39 - * @since 1.0 - */ -@Mapper -public interface AiChatRoleConvert { - - AiChatRoleConvert INSTANCE = Mappers.getMapper(AiChatRoleConvert.class); - - /** - * 转换 - ChatRoleListRes - * - * @param roleList - * @return - */ - List convertChatRoleListRes(List roleList); - - /** - * 转换 - AiChatRoleDO - * - * @param req - * @return - */ - AiChatRoleDO convertAiChatRoleDO(AiChatRoleAddReqVO req); - - /** - * 转换 - AiChatRoleDO - * - * @param req - * @return - */ - AiChatRoleDO convertAiChatRoleDO(AiChatRoleUpdateReqVO req); - - /** - * 转换 - AiChatRoleRes - * - * @param aiChatRoleDO - * @return - */ - AiChatRoleRespVO convertAiChatRoleRes(AiChatRoleDO aiChatRoleDO); -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java index 51cf67c86..1b33199d4 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java @@ -46,7 +46,7 @@ public class AiChatRoleDO extends BaseDO { */ private String welcomeMessage; /** - * 角色设定(消息) + * 角色上下文 */ private String systemMessage; @@ -65,9 +65,10 @@ public class AiChatRoleDO extends BaseDO { private Long modelId; /** - * 是否公开 true - 公开;false - 私有 + * 是否公开 * - * true - 公开;false - 私有 + * 1. true - 公开;由管理员在【角色管理】所创建 + * 2. false - 私有;由个人在【我的角色】所创建 */ private Boolean publicStatus; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java index 1ab7117b7..2aea83c44 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java @@ -1,17 +1,27 @@ package cn.iocoder.yudao.module.ai.dal.mysql; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRolePageReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; /** - * role mapper + * AI 聊天角色 Mapper * - * @fansili - * @since v1.0 + * @author fansili */ -@Repository @Mapper public interface AiChatRoleMapper extends BaseMapperX { + + default PageResult selectPage(AiChatRolePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(AiChatRoleDO::getName, reqVO.getName()) + .eqIfPresent(AiChatRoleDO::getCategory, reqVO.getCategory()) + .eqIfPresent(AiChatRoleDO::getPublicStatus, reqVO.getPublicStatus()) + .orderByDesc(AiChatRoleDO::getId)); + } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java deleted file mode 100644 index c2f56a240..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatRoleService.java +++ /dev/null @@ -1,76 +0,0 @@ -package cn.iocoder.yudao.module.ai.service; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.*; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; - -/** - * chat 角色 - * - * @fansili - * @since v1.0 - */ -public interface AiChatRoleService { - - /** - * 获取聊天角色列表 - * - * @param req - * @return - */ - PageResult list(AiChatRoleListReqVO req); - - /** - * chat角色 - 添加 - * - * @param req - * @return - */ - void add(AiChatRoleAddReqVO req); - - /** - * chat角色 - 修改 - * - * @param req - */ - void update(AiChatRoleUpdateReqVO req); - - - /** - * chat角色 - 修改可见性 - * - * @param req - */ - void updatePublicStatus(AiChatRoleUpdatePublicStatusReqVO req); - - /** - * chat角色 - 删除 - * - * @param chatRoleId - */ - void delete(Long chatRoleId); - - /** - * 获取角色 - * - * @param roleId - * @return - */ - AiChatRoleRespVO getChatRole(Long roleId); - - /** - * 校验 - 角色是否存在 - * - * @param id - * @return - */ - AiChatRoleDO validateExists(Long id); - - /** - * 校验 - 角色是否公开 - * - * @param aiChatRoleDO - */ - void validateIsPublic(AiChatRoleDO aiChatRoleDO); - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java similarity index 93% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatConversationServiceImpl.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java index 5d25f2a11..336f34858 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.service.model; +package cn.iocoder.yudao.module.ai.service.impl; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; @@ -7,14 +7,15 @@ import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleRespVO; import cn.iocoder.yudao.module.ai.convert.AiChatConversationConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModelMapper; import cn.iocoder.yudao.module.ai.service.AiChatConversationService; -import cn.iocoder.yudao.module.ai.service.AiChatRoleService; +import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; +import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; @@ -45,10 +46,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService // 默认使用 sort 排序第一个模型 AiChatModelDO aiChatModalDO = aiChatModalMapper.selectFirstModal(); // 查询角色 - AiChatRoleRespVO chatRoleRes = null; - if (req.getRoleId() != null) { - chatRoleRes = aiChatRoleService.getChatRole(req.getRoleId()); - } + AiChatRoleDO chatRoleRes = req.getRoleId() != null ? aiChatRoleService.getChatRole(req.getRoleId()) : null; Long chatRoleId = chatRoleRes != null ? chatRoleRes.getId() : null; // 创建新的 Conversation AiChatConversationDO insertConversation = saveConversation(AiCommonConstants.CONVERSATION_DEFAULT_TITLE, diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java deleted file mode 100644 index 426481495..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatRoleServiceImpl.java +++ /dev/null @@ -1,129 +0,0 @@ -package cn.iocoder.yudao.module.ai.service.impl; - -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; -import cn.iocoder.yudao.module.ai.ErrorCodeConstants; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.*; -import cn.iocoder.yudao.module.ai.convert.AiChatRoleConvert; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.dal.mysql.AiChatRoleMapper; -import cn.iocoder.yudao.module.ai.enums.AiChatRoleCategoryEnum; -import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; -import cn.iocoder.yudao.module.ai.service.AiChatRoleService; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.util.List; - -/** - * chat 角色 - * - * @fansili - * @since v1.0 - */ -@Service -@AllArgsConstructor -@Slf4j -public class AiChatRoleServiceImpl implements AiChatRoleService { - - private final AiChatRoleMapper aiChatRoleMapper; - private final AiChatModelService aiChatModalService; - - @Override - public PageResult list(AiChatRoleListReqVO req) { - // 查询条件 - LambdaQueryWrapperX queryWrapperX = new LambdaQueryWrapperX<>(); - // search 查询 - if (!StrUtil.isBlank(req.getSearch())) { - queryWrapperX.eq(AiChatRoleDO::getName, req.getSearch()); - } - // 默认排序id desc - queryWrapperX.orderByDesc(AiChatRoleDO::getId); - // - PageResult aiChatRoleDOPageResult = aiChatRoleMapper.selectPage(req, queryWrapperX); - Long total = aiChatRoleDOPageResult.getTotal(); - List roleList = aiChatRoleDOPageResult.getList(); - // 换货res - List chatRoleListResList = AiChatRoleConvert.INSTANCE.convertChatRoleListRes(roleList); - return new PageResult<>(chatRoleListResList, total); - } - - @Override - public void add(AiChatRoleAddReqVO req) { - // 转换enum,并校验enum - AiChatRoleCategoryEnum.valueOfCategory(req.getCategory()); - // 校验模型是否存在 TODO -// aiChatModalService.validateExists(req.getModelId()); - // 转换do - AiChatRoleDO insertAiChatRoleDO = AiChatRoleConvert.INSTANCE.convertAiChatRoleDO(req); - insertAiChatRoleDO.setUserId(SecurityFrameworkUtils.getLoginUserId()); - insertAiChatRoleDO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - // 保存 - aiChatRoleMapper.insert(insertAiChatRoleDO); - } - - @Override - public void update(AiChatRoleUpdateReqVO req) { - // 检查角色是否存在 - validateExists(req.getId()); - // 转换enum,并校验enum - AiChatRoleCategoryEnum.valueOfCategory(req.getCategory()); - // 校验模型是否存在 TODO -// aiChatModalService.validateExists(req.getModelId()); - // 转换do - AiChatRoleDO updateChatRole = AiChatRoleConvert.INSTANCE.convertAiChatRoleDO(req); - updateChatRole.setId(req.getId()); - aiChatRoleMapper.updateById(updateChatRole); - } - - - @Override - public void updatePublicStatus(AiChatRoleUpdatePublicStatusReqVO req) { - // 检查角色是否存在 - validateExists(req.getId()); - // 更新 - aiChatRoleMapper.updateById( - new AiChatRoleDO() - .setId(req.getId()) - .setPublicStatus(req.getPublicStatus()) - ); - } - - @Override - public void delete(Long chatRoleId) { - // 检查角色是否存在 - validateExists(chatRoleId); - // 删除 - aiChatRoleMapper.deleteById(chatRoleId); - } - - @Override - public AiChatRoleRespVO getChatRole(Long roleId) { - // 检查角色是否存在 - AiChatRoleDO aiChatRoleDO = validateExists(roleId); - return AiChatRoleConvert.INSTANCE.convertAiChatRoleRes(aiChatRoleDO); - } - - public AiChatRoleDO validateExists(Long id) { - AiChatRoleDO aiChatRoleDO = aiChatRoleMapper.selectById(id); - if (aiChatRoleDO == null) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CHAT_ROLE_NOT_EXIST); - } - return aiChatRoleDO; - } - - public void validateIsPublic(AiChatRoleDO aiChatRoleDO) { - if (aiChatRoleDO == null) { - return; - } - if (!aiChatRoleDO.getPublicStatus()) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CHAT_ROLE_NOT_PUBLIC); - } - } -} - diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index 36316dc97..87d652eef 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -23,12 +23,11 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatMessageMapper; import cn.iocoder.yudao.module.ai.service.AiChatConversationService; -import cn.iocoder.yudao.module.ai.service.AiChatRoleService; +import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; import cn.iocoder.yudao.module.ai.service.AiChatService; import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.autoconfigure.http.HttpMessageConverters; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import reactor.core.publisher.Flux; @@ -53,12 +52,12 @@ import java.util.stream.Collectors; public class AiChatServiceImpl implements AiChatService { private final AiChatClientFactory aiChatClientFactory; + private final AiChatMessageMapper aiChatMessageMapper; private final AiChatConversationMapper aiChatConversationMapper; private final AiChatConversationService chatConversationService; private final AiChatModelService aiChatModalService; - private final AiChatRoleService aiChatRoleService; - private final HttpMessageConverters messageConverters; + private final AiChatRoleService chatRoleService; @Transactional(rollbackFor = Exception.class) public AiChatMessageRespVO chat(AiChatMessageSendReqVO req) { @@ -68,12 +67,7 @@ public class AiChatServiceImpl implements AiChatService { // 获取对话模型 AiChatModelDO chatModel = aiChatModalService.validateChatModel(conversation.getModelId()); // 获取角色信息 - AiChatRoleDO aiChatRoleDO = null; - if (conversation.getRoleId() != null) { - aiChatRoleDO = aiChatRoleService.validateExists(conversation.getRoleId()); - } - // 校验角色是否公开 - aiChatRoleService.validateIsPublic(aiChatRoleDO); + AiChatRoleDO chatRoleDO = conversation.getRoleId() != null ? chatRoleService.validateChatRole(conversation.getRoleId()) : null; // 获取 client 类型 AiPlatformEnum platformEnum = AiPlatformEnum.validatePlatform(chatModel.getPlatform()); // 保存 chat message @@ -142,12 +136,7 @@ public class AiChatServiceImpl implements AiChatService { // 获取对话模型 AiChatModelDO chatModel = aiChatModalService.validateChatModel(conversation.getModelId()); // 获取角色信息 - AiChatRoleDO aiChatRoleDO = null; - if (conversation.getRoleId() != null) { - aiChatRoleDO = aiChatRoleService.validateExists(conversation.getRoleId()); - } - // 校验角色是否公开 - aiChatRoleService.validateIsPublic(aiChatRoleDO); + AiChatRoleDO chatRoleDO = conversation.getRoleId() != null ? chatRoleService.validateChatRole(conversation.getRoleId()) : null; // 创建 chat 需要的 Prompt Prompt prompt = new Prompt(aiChatMessageDO.getContent()); // 提前创建一个 system message @@ -204,13 +193,6 @@ public class AiChatServiceImpl implements AiChatService { AiChatConversationRespVO conversation = chatConversationService.getConversationOfValidate(req.getConversationId()); // 获取对话模型 AiChatModelDO chatModel = aiChatModalService.validateChatModel(conversation.getModelId()); - // 获取角色信息 - AiChatRoleDO aiChatRoleDO = null; - if (conversation.getRoleId() != null) { - aiChatRoleDO = aiChatRoleService.validateExists(conversation.getRoleId()); - } - // 校验角色是否公开 - aiChatRoleService.validateIsPublic(aiChatRoleDO); AiChatMessageDO userMessage = insertChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(), chatModel.getModel(), chatModel.getId(), req.getContent(), null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java new file mode 100644 index 000000000..a4d554adb --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.ai.service.model; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRolePageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleSaveReqVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; +import jakarta.validation.Valid; + +/** + * AI 聊天角色 Service 接口 + * + * @author fansili + */ +public interface AiChatRoleService { + + /** + * 创建聊天角色 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createChatRole(@Valid AiChatRoleSaveReqVO createReqVO); + + /** + * 更新聊天角色 + * + * @param updateReqVO 更新信息 + */ + void updateChatRole(@Valid AiChatRoleSaveReqVO updateReqVO); + + /** + * 删除聊天角色 + * + * @param id 编号 + */ + void deleteChatRole(Long id); + + /** + * 获得聊天角色 + * + * @param id 编号 + * @return AI 聊天角色 + */ + AiChatRoleDO getChatRole(Long id); + + /** + * 校验角色是否存在 + * + * @param id 角色编号 + */ + AiChatRoleDO validateChatRole(Long id); + + /** + * 获得AI 聊天角色分页 + * + * @param pageReqVO 分页查询 + * @return AI 聊天角色分页 + */ + PageResult getChatRolePage(AiChatRolePageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java new file mode 100644 index 000000000..93e79240f --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.ai.service.model; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRolePageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleSaveReqVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; +import cn.iocoder.yudao.module.ai.dal.mysql.AiChatRoleMapper; +import jakarta.annotation.Resource; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_ROLE_DISABLE; +import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_ROLE_NOT_EXISTS; + +/** + * AI 聊天角色 Service 实现类 + * + * @author fansili + */ +@Service +@AllArgsConstructor +@Slf4j +public class AiChatRoleServiceImpl implements AiChatRoleService { + + @Resource + private AiChatRoleMapper chatRoleMapper; + + @Override + public Long createChatRole(AiChatRoleSaveReqVO createReqVO) { + AiChatRoleDO chatRole = BeanUtils.toBean(createReqVO, AiChatRoleDO.class); + chatRoleMapper.insert(chatRole); + return chatRole.getId(); + } + + @Override + public void updateChatRole(AiChatRoleSaveReqVO updateReqVO) { + // 校验存在 + validateChatRoleExists(updateReqVO.getId()); + // 更新 + AiChatRoleDO updateObj = BeanUtils.toBean(updateReqVO, AiChatRoleDO.class); + chatRoleMapper.updateById(updateObj); + } + + @Override + public void deleteChatRole(Long id) { + // 校验存在 + validateChatRoleExists(id); + // 删除 + chatRoleMapper.deleteById(id); + } + + private AiChatRoleDO validateChatRoleExists(Long id) { + AiChatRoleDO chatRole = chatRoleMapper.selectById(id); + if (chatRole == null) { + throw exception(CHAT_ROLE_NOT_EXISTS); + } + return chatRole; + } + + @Override + public AiChatRoleDO getChatRole(Long id) { + return chatRoleMapper.selectById(id); + } + + @Override + public AiChatRoleDO validateChatRole(Long id) { + AiChatRoleDO chatRole = validateChatRoleExists(id); + if (CommonStatusEnum.isDisable(chatRole.getStatus())) { + throw exception(CHAT_ROLE_DISABLE, chatRole.getName()); + } + return chatRole; + } + + @Override + public PageResult getChatRolePage(AiChatRolePageReqVO pageReqVO) { + return chatRoleMapper.selectPage(pageReqVO); + } + +} + From 31453e19d4a33296cae0395d5545391bb56b8ee2 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 13 May 2024 21:47:58 +0800 Subject: [PATCH 267/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E8=81=8A=E5=A4=A9=E8=A7=92=E8=89=B2=E7=AE=A1=E7=90=86?= =?UTF-8?q?=EF=BC=8880%=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/model/AiChatModelController.java | 3 ++- .../admin/model/AiChatRoleController.java | 12 +++--------- .../vo/{role => chatRole}/AiChatRolePageReqVO.java | 7 +------ .../vo/{role => chatRole}/AiChatRoleRespVO.java | 13 +++++++++++-- .../vo/{role => chatRole}/AiChatRoleSaveReqVO.java | 5 +++-- .../yudao/module/ai/dal/mysql/AiChatRoleMapper.java | 5 ++--- .../ai/service/model/AiChatModelServiceImpl.java | 3 +-- .../module/ai/service/model/AiChatRoleService.java | 4 ++-- .../ai/service/model/AiChatRoleServiceImpl.java | 5 ++--- 9 files changed, 27 insertions(+), 30 deletions(-) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/{role => chatRole}/AiChatRolePageReqVO.java (67%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/{role => chatRole}/AiChatRoleRespVO.java (74%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/{role => chatRole}/AiChatRoleSaveReqVO.java (93%) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java index 6d568140b..1b50be79d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java @@ -78,7 +78,8 @@ public class AiChatModelController { @Parameter(name = "status", description = "状态", required = true, example = "1") public CommonResult> getChatModelSimpleList(@RequestParam("status") Integer status) { List list = chatModelService.getChatModelList(status); - return success(convertList(list, model -> new AiChatModelRespVO().setId(model.getId()).setName(model.getName()))); + return success(convertList(list, model -> new AiChatModelRespVO().setId(model.getId()) + .setName(model.getName()).setModel(model.getModel()))); } } \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java index 5757d8316..a3eace769 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java @@ -1,28 +1,22 @@ package cn.iocoder.yudao.module.ai.controller.admin.model; -import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRolePageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleSaveReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRolePageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.io.IOException; -import java.util.List; - import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @Tag(name = "管理后台 - AI 聊天角色") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRolePageReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRolePageReqVO.java similarity index 67% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRolePageReqVO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRolePageReqVO.java index d1eb417d6..237c83463 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRolePageReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRolePageReqVO.java @@ -1,13 +1,8 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role; +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole; import lombok.*; -import java.util.*; import io.swagger.v3.oas.annotations.media.Schema; import cn.iocoder.yudao.framework.common.pojo.PageParam; -import org.springframework.format.annotation.DateTimeFormat; -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @Schema(description = "管理后台 - AI 聊天角色分页 Request VO") @Data diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java similarity index 74% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleRespVO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java index 60dbf07df..3adef6b25 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java @@ -1,5 +1,9 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role; +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; +import com.fhs.core.trans.anno.Trans; +import com.fhs.core.trans.constant.TransType; +import com.fhs.core.trans.vo.VO; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -7,7 +11,7 @@ import java.time.LocalDateTime; @Schema(description = "管理后台 - AI 聊天角色 Response VO") @Data -public class AiChatRoleRespVO { +public class AiChatRoleRespVO implements VO { @Schema(description = "角色编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32746") private Long id; @@ -16,7 +20,12 @@ public class AiChatRoleRespVO { private Long userId; @Schema(description = "模型编号", example = "17640") + @Trans(type = TransType.SIMPLE, target = AiChatModelDO.class, fields = {"name", "model"}, refs = {"modelName", "model"}) private Long modelId; + @Schema(description = "模型名字", example = "张三") + private String modelName; + @Schema(description = "模型标识", example = "gpt-3.5-turbo-0125") + private String model; @Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") private String name; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleSaveReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveReqVO.java similarity index 93% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleSaveReqVO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveReqVO.java index 97f92f3d1..1dc62947b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/role/AiChatRoleSaveReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveReqVO.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role; +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.validation.InEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; -import java.util.*; import jakarta.validation.constraints.*; +import org.hibernate.validator.constraints.URL; @Schema(description = "管理后台 - AI 聊天角色新增/修改 Request VO") @Data @@ -23,6 +23,7 @@ public class AiChatRoleSaveReqVO { @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") @NotEmpty(message = "角色头像不能为空") + @URL(message = "角色头像必须是 URL 格式") private String avatar; @Schema(description = "角色类别", requiredMode = Schema.RequiredMode.REQUIRED, example = "创作") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java index 2aea83c44..ac592d38a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java @@ -3,10 +3,9 @@ package cn.iocoder.yudao.module.ai.dal.mysql; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRolePageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRolePageReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import org.apache.ibatis.annotations.Mapper; -import org.springframework.stereotype.Repository; /** * AI 聊天角色 Mapper @@ -21,7 +20,7 @@ public interface AiChatRoleMapper extends BaseMapperX { .likeIfPresent(AiChatRoleDO::getName, reqVO.getName()) .eqIfPresent(AiChatRoleDO::getCategory, reqVO.getCategory()) .eqIfPresent(AiChatRoleDO::getPublicStatus, reqVO.getPublicStatus()) - .orderByDesc(AiChatRoleDO::getId)); + .orderByAsc(AiChatRoleDO::getSort)); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java index c185ffea5..919fb5804 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java @@ -95,8 +95,7 @@ public class AiChatModelServiceImpl implements AiChatModelService { @Override public List getChatModelList(Integer status) { - chatModelMapper.selectList(status); - return null; + return chatModelMapper.selectList(status); } @Override diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java index a4d554adb..283311a67 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.ai.service.model; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRolePageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleSaveReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRolePageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import jakarta.validation.Valid; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java index 93e79240f..fcca7b225 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java @@ -1,11 +1,10 @@ package cn.iocoder.yudao.module.ai.service.model; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRolePageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleSaveReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRolePageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatRoleMapper; import jakarta.annotation.Resource; From 7344ec8aea5c6fc4dd30a0cc47cb1b773d3330b4 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 13 May 2024 22:55:01 +0800 Subject: [PATCH 268/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E8=81=8A=E5=A4=A9=E8=A7=92=E8=89=B2=E7=AE=A1=E7=90=86?= =?UTF-8?q?=EF=BC=88100%=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/model/AiChatRoleController.java | 50 +++++++++++++++++-- .../vo/chatRole/AiChatRoleSaveMyReqVO.java | 36 +++++++++++++ .../module/ai/dal/mysql/AiChatRoleMapper.java | 21 ++++++++ .../ai/service/model/AiChatRoleService.java | 50 +++++++++++++++++-- .../service/model/AiChatRoleServiceImpl.java | 50 ++++++++++++++++++- .../src/main/resources/application-local.yaml | 2 +- 6 files changed, 199 insertions(+), 10 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java index a3eace769..02f698b94 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java @@ -1,10 +1,12 @@ package cn.iocoder.yudao.module.ai.controller.admin.model; +import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRolePageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveMyReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; @@ -17,7 +19,10 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.List; + import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @Tag(name = "管理后台 - AI 聊天角色") @RestController @@ -28,13 +33,50 @@ public class AiChatRoleController { @Resource private AiChatRoleService chatRoleService; - // TODO 芋艿:我的分页 + @GetMapping("/my-page") + @Operation(summary = "获得【我的】聊天角色分页") + public CommonResult> getChatRoleMyPage(@Valid AiChatRolePageReqVO pageReqVO) { + PageResult pageResult = chatRoleService.getChatRoleMyPage(pageReqVO, getLoginUserId()); + return success(BeanUtils.toBean(pageResult, AiChatRoleRespVO.class)); + } - // TODO 芋艿:我的新增 + @GetMapping("/get-my") + @Operation(summary = "获得【我的】聊天角色") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + public CommonResult getChatRoleMy(@RequestParam("id") Long id) { + AiChatRoleDO chatRole = chatRoleService.getChatRole(id); + if (ObjUtil.notEqual(chatRole.getUserId(), getLoginUserId())) { + return success(null); + } + return success(BeanUtils.toBean(chatRole, AiChatRoleRespVO.class)); + } - // TODO 芋艿:我的修改 + @PostMapping("/create-my") + @Operation(summary = "创建【我的】聊天角色") + public CommonResult createChatRoleMy(@Valid @RequestBody AiChatRoleSaveMyReqVO createReqVO) { + return success(chatRoleService.createChatRoleMy(createReqVO, getLoginUserId())); + } - // TODO 芋艿:我的删除 + @PutMapping("/update-my") + @Operation(summary = "更新【我的】聊天角色") + public CommonResult updateChatRoleMy(@Valid @RequestBody AiChatRoleSaveMyReqVO updateReqVO) { + chatRoleService.updateChatRoleMy(updateReqVO, getLoginUserId()); + return success(true); + } + + @DeleteMapping("/delete-my") + @Operation(summary = "删除【我的】聊天角色") + @Parameter(name = "id", description = "编号", required = true) + public CommonResult deleteChatRoleMy(@RequestParam("id") Long id) { + chatRoleService.deleteChatRoleMy(id, getLoginUserId()); + return success(true); + } + + @GetMapping("/category-list") + @Operation(summary = "获得聊天角色的分类列表") + public CommonResult> getChatRoleCategoryList() { + return success(chatRoleService.getChatRoleCategoryList()); + } // ========== 角色管理 ========== diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java new file mode 100644 index 000000000..3c5641f08 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; +import org.hibernate.validator.constraints.URL; + +@Schema(description = "管理后台 - AI 聊天角色新增/修改【我的】 Request VO") +@Data +public class AiChatRoleSaveMyReqVO { + + @Schema(description = "角色编号", example = "32746") + private Long id; + + @Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + @NotEmpty(message = "角色名称不能为空") + private String name; + + @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @NotEmpty(message = "角色头像不能为空") + @URL(message = "角色头像必须是 URL 格式") + private String avatar; + + @Schema(description = "角色描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对") + @NotEmpty(message = "角色描述不能为空") + private String description; + + @Schema(description = "角色欢迎语", requiredMode = Schema.RequiredMode.REQUIRED, example = "Talk is cheap, i will show code") + @NotEmpty(message = "角色欢迎语不能为空") + private String welcomeMessage; + + @Schema(description = "角色上下文", requiredMode = Schema.RequiredMode.REQUIRED, example = "现在开始你扮演一位程序员,你是一名优秀的程序员,具有很强的逻辑思维能力,总能高效的解决问题") + @NotEmpty(message = "角色上下文不能为空") + private String systemMessage; + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java index ac592d38a..d89204005 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.ai.dal.mysql; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; @@ -7,6 +8,8 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleP import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import org.apache.ibatis.annotations.Mapper; +import java.util.List; + /** * AI 聊天角色 Mapper * @@ -23,4 +26,22 @@ public interface AiChatRoleMapper extends BaseMapperX { .orderByAsc(AiChatRoleDO::getSort)); } + default PageResult selectPageByMy(AiChatRolePageReqVO reqVO, Long userId) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(AiChatRoleDO::getName, reqVO.getName()) + .eqIfPresent(AiChatRoleDO::getCategory, reqVO.getCategory()) + // 情况一:公开 + .eq(Boolean.TRUE.equals(reqVO.getPublicStatus()), AiChatRoleDO::getPublicStatus, reqVO.getPublicStatus()) + // 情况二:私有 + .eq(Boolean.FALSE.equals(reqVO.getPublicStatus()), AiChatRoleDO::getUserId, userId) + .eq(Boolean.FALSE.equals(reqVO.getPublicStatus()), AiChatRoleDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) + .orderByAsc(AiChatRoleDO::getSort)); + } + + default List selectListGroupByCategory(Integer status) { + return selectList(new LambdaQueryWrapperX() + .eq(AiChatRoleDO::getStatus, status) + .apply("GROUP BY category")); + } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java index 283311a67..8b22d638c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java @@ -2,10 +2,13 @@ package cn.iocoder.yudao.module.ai.service.model; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRolePageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveMyReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import jakarta.validation.Valid; +import java.util.List; + /** * AI 聊天角色 Service 接口 * @@ -21,6 +24,15 @@ public interface AiChatRoleService { */ Long createChatRole(@Valid AiChatRoleSaveReqVO createReqVO); + /** + * 创建【我的】聊天角色 + * + * @param createReqVO 创建信息 + * @param userId 用户编号 + * @return 编号 + */ + Long createChatRoleMy(AiChatRoleSaveMyReqVO createReqVO, Long userId); + /** * 更新聊天角色 * @@ -28,6 +40,14 @@ public interface AiChatRoleService { */ void updateChatRole(@Valid AiChatRoleSaveReqVO updateReqVO); + /** + * 创建【我的】聊天角色 + * + * @param updateReqVO 更新信息 + * @param userId 用户编号 + */ + void updateChatRoleMy(AiChatRoleSaveMyReqVO updateReqVO, Long userId); + /** * 删除聊天角色 * @@ -35,6 +55,14 @@ public interface AiChatRoleService { */ void deleteChatRole(Long id); + /** + * 删除【我的】聊天角色 + * + * @param id 编号 + * @param userId 用户编号 + */ + void deleteChatRoleMy(Long id, Long userId); + /** * 获得聊天角色 * @@ -44,18 +72,34 @@ public interface AiChatRoleService { AiChatRoleDO getChatRole(Long id); /** - * 校验角色是否存在 + * 校验聊天角色是否合法 * * @param id 角色编号 */ AiChatRoleDO validateChatRole(Long id); /** - * 获得AI 聊天角色分页 + * 获得聊天角色分页 * * @param pageReqVO 分页查询 - * @return AI 聊天角色分页 + * @return 聊天角色分页 */ PageResult getChatRolePage(AiChatRolePageReqVO pageReqVO); + /** + * 获得【我的】聊天角色分页 + * + * @param pageReqVO 分页查询 + * @param userId 用户编号 + * @return 聊天角色分页 + */ + PageResult getChatRoleMyPage(AiChatRolePageReqVO pageReqVO, Long userId); + + /** + * 获得聊天角色的分类列表 + * + * @return 分类列表 + */ + List getChatRoleCategoryList(); + } \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java index fcca7b225..507e4ce74 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java @@ -1,18 +1,22 @@ package cn.iocoder.yudao.module.ai.service.model; +import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRolePageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveMyReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatRoleMapper; import jakarta.annotation.Resource; -import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.util.List; + import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_ROLE_DISABLE; import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_ROLE_NOT_EXISTS; @@ -22,7 +26,6 @@ import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_ROLE_NOT_EXISTS * @author fansili */ @Service -@AllArgsConstructor @Slf4j public class AiChatRoleServiceImpl implements AiChatRoleService { @@ -36,6 +39,14 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { return chatRole.getId(); } + @Override + public Long createChatRoleMy(AiChatRoleSaveMyReqVO createReqVO, Long userId) { + AiChatRoleDO chatRole = BeanUtils.toBean(createReqVO, AiChatRoleDO.class).setUserId(userId) + .setStatus(CommonStatusEnum.ENABLE.getStatus()).setPublicStatus(false); + chatRoleMapper.insert(chatRole); + return chatRole.getId(); + } + @Override public void updateChatRole(AiChatRoleSaveReqVO updateReqVO) { // 校验存在 @@ -45,6 +56,19 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { chatRoleMapper.updateById(updateObj); } + @Override + public void updateChatRoleMy(AiChatRoleSaveMyReqVO updateReqVO, Long userId) { + // 校验存在 + AiChatRoleDO chatRole = validateChatRoleExists(updateReqVO.getId()); + if (ObjectUtil.notEqual(chatRole.getUserId(), userId)) { + throw exception(CHAT_ROLE_NOT_EXISTS); + } + + // 更新 + AiChatRoleDO updateObj = BeanUtils.toBean(updateReqVO, AiChatRoleDO.class); + chatRoleMapper.updateById(updateObj); + } + @Override public void deleteChatRole(Long id) { // 校验存在 @@ -53,6 +77,17 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { chatRoleMapper.deleteById(id); } + @Override + public void deleteChatRoleMy(Long id, Long userId) { + // 校验存在 + AiChatRoleDO chatRole = validateChatRoleExists(id); + if (ObjectUtil.notEqual(chatRole.getUserId(), userId)) { + throw exception(CHAT_ROLE_NOT_EXISTS); + } + // 删除 + chatRoleMapper.deleteById(id); + } + private AiChatRoleDO validateChatRoleExists(Long id) { AiChatRoleDO chatRole = chatRoleMapper.selectById(id); if (chatRole == null) { @@ -80,5 +115,16 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { return chatRoleMapper.selectPage(pageReqVO); } + @Override + public PageResult getChatRoleMyPage(AiChatRolePageReqVO pageReqVO, Long userId) { + return chatRoleMapper.selectPageByMy(pageReqVO, userId); + } + + @Override + public List getChatRoleCategoryList() { + List list = chatRoleMapper.selectListGroupByCategory(CommonStatusEnum.ENABLE.getStatus()); + return convertList(list, AiChatRoleDO::getName); + } + } diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 959988d7d..41ef6ef1a 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -52,7 +52,7 @@ spring: # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=ruoyi-vue-pro;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true;useUnicode=true;characterEncoding=utf-8 # SQLServer 连接的示例 # url: jdbc:dm://127.0.0.1:5236?schema=RUOYI_VUE_PRO # DM 连接的示例 username: root - password: root + password: 123456 # username: sa # SQL Server 连接的示例 # password: Yudao@2024 # SQL Server 连接的示例 # username: SYSDBA # DM 连接的示例 From 64142965f36f6b4470e4637b320e99f08239e1a3 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 14 May 2024 13:24:55 +0800 Subject: [PATCH 269/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E8=81=8A=E5=A4=A9=E5=AF=B9=E8=AF=9D=E7=9A=84=E6=96=B0?= =?UTF-8?q?=E5=BB=BA=EF=BC=8850%=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/ErrorCodeConstants.java | 17 +-- .../chat/AiChatConversationController.java | 55 ++++---- .../AiChatConversationCreateMyReqVO.java | 13 ++ .../AiChatConversationCreateReqVO.java | 17 --- .../AiChatConversationListReqVO.java | 13 -- ...a => AiChatConversationUpdateMyReqVO.java} | 4 +- .../ai/convert/AiChatConversationConvert.java | 8 +- .../dataobject/chat/AiChatConversationDO.java | 2 + .../dal/dataobject/model/AiChatModelDO.java | 2 + .../ai/dal/mysql/AiChatModelMapper.java | 23 ++-- .../module/ai/dal/mysql/AiChatRoleMapper.java | 10 ++ .../{ => chat}/AiChatConversationService.java | 30 ++--- .../chat/AiChatConversationServiceImpl.java | 112 ++++++++++++++++ .../impl/AiChatConversationServiceImpl.java | 121 ------------------ .../ai/service/impl/AiChatServiceImpl.java | 2 +- .../ai/service/model/AiChatModelService.java | 10 +- .../service/model/AiChatModelServiceImpl.java | 13 +- .../ai/service/model/AiChatRoleService.java | 10 ++ .../service/model/AiChatRoleServiceImpl.java | 13 +- 19 files changed, 242 insertions(+), 233 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateMyReqVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateReqVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationListReqVO.java rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/{AiChatConversationUpdateReqVO.java => AiChatConversationUpdateMyReqVO.java} (88%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/{ => chat}/AiChatConversationService.java (60%) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index b65314f52..8948fcba4 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -14,17 +14,21 @@ public interface ErrorCodeConstants { ErrorCode API_KEY_DISABLE = new ErrorCode(1_040_000_001, "AI API 密钥已禁用!"); // ========== API 聊天模型 1-040-001-000 ========== - - ErrorCode CHAT_MODAL_NOT_EXIST = new ErrorCode(1_040_001_000, "AI 模型不存在!"); - ErrorCode CHAT_MODAL_DISABLE = new ErrorCode(1_040_001_001, "AI 模型({})已禁用!"); + ErrorCode CHAT_MODEL_NOT_EXISTS = new ErrorCode(1_040_001_000, "AI 模型不存在!"); + ErrorCode CHAT_MODEL_DISABLE = new ErrorCode(1_040_001_001, "AI 模型({})已禁用!"); + ErrorCode CHAT_MODEL_DEFAULT_NOT_EXISTS = new ErrorCode(1_040_001_002, "操作失败,找不到默认聊天模型"); // ========== API 聊天模型 1-040-002-000 ========== ErrorCode CHAT_ROLE_NOT_EXISTS = new ErrorCode(1_040_002_000, "AI 聊天角色不存在"); ErrorCode CHAT_ROLE_DISABLE = new ErrorCode(1_040_001_001, "AI 聊天角色({})已禁用!"); + ErrorCode CHAT_ROLE_DEFAULT_NOT_EXISTS = new ErrorCode(1_040_001_002, "操作失败,找不到默认聊天角色"); - // conversation + // ========== API 聊天会话 1-040-003-000 ========== - ErrorCode AI_CONVERSATION_NOT_EXISTS = new ErrorCode(1_022_000_002, "AI 对话不存在!");; + ErrorCode CHAT_CONVERSATION_NOT_EXISTS = new ErrorCode(1_040_003_000, "AI 对话不存在!");; + + // chat + ErrorCode AI_CHAT_MESSAGE_NOT_EXIST = new ErrorCode(1_022_000_100, "AI 提问的 MessageId 不存在!"); // midjourney @@ -32,7 +36,4 @@ public interface ErrorCodeConstants { ErrorCode AI_MIDJOURNEY_OPERATION_NOT_EXISTS = new ErrorCode(1_022_000_040, "midjourney 操作不存在!"); ErrorCode AI_MIDJOURNEY_MESSAGE_ID_INCORRECT = new ErrorCode(1_022_000_040, "midjourney message id 不正确!"); - // chat - ErrorCode AI_CHAT_MESSAGE_NOT_EXIST = new ErrorCode(1_022_000_100, "AI 提问的 MessageId 不存在!"); - } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java index 7bd3c5a14..3e56cb999 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java @@ -1,53 +1,50 @@ package cn.iocoder.yudao.module.ai.controller.admin.chat; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateMyReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateReqVO; -import cn.iocoder.yudao.module.ai.service.AiChatConversationService; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateMyReqVO; +import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; import jakarta.validation.Valid; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -@Slf4j -@Tag(name = "管理后台 - 聊天会话") +@Tag(name = "管理后台 - AI 聊天会话") @RestController @RequestMapping("/ai/chat/conversation") -@AllArgsConstructor +@Validated public class AiChatConversationController { - private final AiChatConversationService aiChatConversationService; + @Resource + private AiChatConversationService chatConversationService; - // TODO done @fan:实现一下 - @PostMapping("/create") - @Operation(summary = "创建聊天会话") - @PreAuthorize("@ss.hasPermission('ai:chat-conversation:create')") - public CommonResult createConversation(@RequestBody @Valid AiChatConversationCreateReqVO createReqVO) { - return success(aiChatConversationService.createConversation(createReqVO)); + @PostMapping("/create-my") + @Operation(summary = "创建【我的】聊天会话") + public CommonResult createChatConversationMy(@RequestBody @Valid AiChatConversationCreateMyReqVO createReqVO) { + return success(chatConversationService.createChatConversationMy(createReqVO, getLoginUserId())); + } + + @PutMapping("/update-my") + @Operation(summary = "更新【我的】聊天会话") + public CommonResult updateChatConversationMy(@RequestBody @Valid AiChatConversationUpdateMyReqVO updateReqVO) { + chatConversationService.updateChatConversationMy(updateReqVO, getLoginUserId()); + return success(true); } // TODO done @fan:实现一下 - @PutMapping("/update") - @Operation(summary = "更新聊天会话") - @PreAuthorize("@ss.hasPermission('ai:chat-conversation:create')") - public CommonResult updateConversation(@RequestBody @Valid AiChatConversationUpdateReqVO updateReqVO) { - return success(aiChatConversationService.updateConversation(updateReqVO)); - } - - // TODO done @fan:实现一下 - @GetMapping("/list") + @GetMapping("/my-list") @Operation(summary = "获得聊天会话列表") public CommonResult> getConversationList() { - return success(aiChatConversationService.listConversation()); + return success(chatConversationService.listConversation()); } // TODO @fan:实现一下 @@ -55,7 +52,7 @@ public class AiChatConversationController { @Operation(summary = "获得聊天会话") @Parameter(name = "id", required = true, description = "会话编号", example = "1024") public CommonResult getConversation(@RequestParam("id") Long id) { - return success(aiChatConversationService.getConversationOfValidate(id)); + return success(chatConversationService.getConversationOfValidate(id)); } // TODO @fan:实现一下 @@ -63,7 +60,9 @@ public class AiChatConversationController { @Operation(summary = "删除聊天会话") @Parameter(name = "id", required = true, description = "会话编号", example = "1024") public CommonResult deleteConversation(@RequestParam("id") Long id) { - return success(aiChatConversationService.deleteConversation(id)); + return success(chatConversationService.deleteConversation(id)); } + // ========== 会话管理 ========== + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateMyReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateMyReqVO.java new file mode 100644 index 000000000..d64ea7f61 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateMyReqVO.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - AI 聊天会话创建【我的】 Request VO") +@Data +public class AiChatConversationCreateMyReqVO { + + @Schema(description = "聊天角色编号", example = "666") + private Long roleId; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateReqVO.java deleted file mode 100644 index b1e119659..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateReqVO.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import lombok.experimental.Accessors; - -@Schema(description = "管理后台 - AI 聊天会话创建 Request VO") -@Data -public class AiChatConversationCreateReqVO { - - @Schema(description = "角色编号", example = "666") - private Long roleId; - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationListReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationListReqVO.java deleted file mode 100644 index 571cf0e38..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationListReqVO.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - AI 聊天会话 Response VO") -@Data -public class AiChatConversationListReqVO { - - @Schema(description = "会话标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是一个标题") - private String title; - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateMyReqVO.java similarity index 88% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateReqVO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateMyReqVO.java index e8bdabb19..4eb5a06c3 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateMyReqVO.java @@ -4,9 +4,9 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; -@Schema(description = "管理后台 - AI 聊天会话更新 Request VO") +@Schema(description = "管理后台 - AI 聊天会话更新【我的】 Request VO") @Data -public class AiChatConversationUpdateReqVO { +public class AiChatConversationUpdateMyReqVO { @Schema(description = "会话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @NotNull(message = "会话编号不能为空") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java index 50c4b64d6..7e1350617 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.ai.convert; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateMyReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import org.mapstruct.Mapper; @@ -36,10 +36,4 @@ public interface AiChatConversationConvert { */ AiChatConversationRespVO covnertChatConversationRes(AiChatConversationDO aiChatConversationDO); - /** - * 转换 - AiChatConversationDO - * - * @param updateReqVO - */ - AiChatConversationDO convertAiChatConversationDO(AiChatConversationUpdateReqVO updateReqVO); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java index a4651323c..c8613b5e1 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java @@ -26,6 +26,8 @@ import lombok.*; @AllArgsConstructor public class AiChatConversationDO extends BaseDO { + public static final String TITLE_DEFAULT = "新对话"; + /** * ID 编号,自增 */ diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModelDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModelDO.java index 723428009..c943f7ea6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModelDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModelDO.java @@ -11,6 +11,8 @@ import lombok.*; /** * AI 聊天模型 DO * + * 默认聊天模型:{@link #status} 为开启,并且 {@link #sort} 排序第一 + * * @author fansili * @since 2024/4/24 19:39 */ diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java index d254f9a81..3c959e961 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java @@ -5,8 +5,10 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelPageReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.apache.ibatis.annotations.Mapper; import java.util.List; @@ -22,23 +24,14 @@ import java.util.List; @Mapper public interface AiChatModelMapper extends BaseMapperX { - // TODO 芋艿:要搞一下 - /** - * 查询 - 第一个modal - * - * @return - */ - default AiChatModelDO selectFirstModal() { - PageResult pageResult = selectPage(new PageParam().setPageNo(1).setPageSize(1), - new LambdaQueryWrapperX() - .orderByAsc(AiChatModelDO::getSort) - ); - if (CollUtil.isEmpty(pageResult.getList())) { - return null; - } - return pageResult.getList().get(0); + default AiChatModelDO selectFirstByStatus(Integer status) { + return selectOne(new QueryWrapperX() + .eq("status", status) + .limitN(1) + .orderByAsc("sort")); } + // TODO 芋艿:不需要哈 /** * 查询 - 根据 ids * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java index d89204005..c0eeb549e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java @@ -4,7 +4,9 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRolePageReqVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import org.apache.ibatis.annotations.Mapper; @@ -18,6 +20,14 @@ import java.util.List; @Mapper public interface AiChatRoleMapper extends BaseMapperX { + default AiChatRoleDO selectFirstByPublicStatusAndStatus(Boolean publicStatus, Integer status) { + return selectOne(new QueryWrapperX() + .eq("status", status) + .eq("public_status", publicStatus) + .limitN(1) + .orderByAsc("sort")); + } + default PageResult selectPage(AiChatRolePageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() .likeIfPresent(AiChatRoleDO::getName, reqVO.getName()) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java similarity index 60% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java index 1abf2476f..ed8fa101c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatConversationService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java @@ -1,37 +1,35 @@ -package cn.iocoder.yudao.module.ai.service; +package cn.iocoder.yudao.module.ai.service.chat; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationListReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateMyReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateMyReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; -import org.jetbrains.annotations.NotNull; import java.util.List; /** - * chat 对话 + * AI 聊天对话 Service 接口 * - * @fansili - * @since v1.0 + * @author fansili */ public interface AiChatConversationService { /** - * 对话 - 创建对话 + * 创建【我的】聊天会话 * - * @param req - * @return + * @param createReqVO 创建信息 + * @param userId 用户编号 + * @return 聊天会话 */ - Long createConversation(AiChatConversationCreateReqVO req); + Long createChatConversationMy(AiChatConversationCreateMyReqVO createReqVO, Long userId); /** - * 对话 - 更新对话 + * 更新【我的】聊天会话 * - * @param updateReqVO - * @return + * @param updateReqVO 更新信息 + * @param userId 用户编号 */ - Boolean updateConversation(AiChatConversationUpdateReqVO updateReqVO); + void updateChatConversationMy(AiChatConversationUpdateMyReqVO updateReqVO, Long userId); /** * 获取 - 对话列表 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java new file mode 100644 index 000000000..b04f2b789 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java @@ -0,0 +1,112 @@ +package cn.iocoder.yudao.module.ai.service.chat; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateMyReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateMyReqVO; +import cn.iocoder.yudao.module.ai.convert.AiChatConversationConvert; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; +import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; +import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; +import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.*; +import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_CONVERSATION_NOT_EXISTS; + +/** + * AI 聊天对话 Service 实现类 + * + * @author fansili + */ +@Service +@Validated +@Slf4j +public class AiChatConversationServiceImpl implements AiChatConversationService { + + @Resource + private AiChatConversationMapper chatConversationMapper; + + @Resource + private AiChatModelService chatModalService; + @Resource + private AiChatRoleService chatRoleService; + + @Override + public Long createChatConversationMy(AiChatConversationCreateMyReqVO createReqVO, Long userId) { + // 1.1 获得 AiChatRoleDO 聊天角色 + AiChatRoleDO role = createReqVO.getRoleId() != null ? chatRoleService.validateChatRole(createReqVO.getRoleId()) + : chatRoleService.getRequiredDefaultChatRole(); + Assert.notNull(role, "必须找到聊天角色"); + // 1.2 获得 AiChatModelDO 聊天模型 + AiChatModelDO model = role.getModelId() != null ? chatModalService.validateChatModel(role.getId()) + : chatModalService.getRequiredDefaultChatModel(); + Assert.notNull(role, "必须找到默认模型"); + + // 2. 创建 AiChatConversationDO 聊天对话 + AiChatConversationDO conversation = new AiChatConversationDO() + .setUserId(userId).setTitle(AiChatConversationDO.TITLE_DEFAULT).setPinned(false) + .setRoleId(role.getId()).setModelId(model.getId()).setModel(model.getModel()) + .setTemperature(model.getTemperature()).setMaxTokens(model.getMaxTokens()).setMaxContexts(model.getMaxContexts()); + chatConversationMapper.insert(conversation); + return conversation.getId(); + } + + @Override + public void updateChatConversationMy(AiChatConversationUpdateMyReqVO updateReqVO, Long userId) { + // 1.1 校验对话是否存在 + AiChatConversationDO conversation = validateExists(updateReqVO.getId()); + if (ObjUtil.notEqual(conversation.getUserId(), userId)) { + throw exception(CHAT_CONVERSATION_NOT_EXISTS); + } + // 1.2 校验模型是否存在 + AiChatModelDO model = null; + if (updateReqVO.getModelId() != null) { + model = chatModalService.validateChatModel(updateReqVO.getModelId()); + } + // 1.3 校验温度参数、Token 数量、消息数量 TODO + + // 更新对话信息 + chatConversationMapper.updateById(BeanUtils.toBean(updateReqVO, AiChatConversationDO.class)); + } + + @Override + public List listConversation() { + // 获取用户id + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + // 查询前100对话 + List top100Conversation + = chatConversationMapper.selectTop100Conversation(loginUserId, null); + return AiChatConversationConvert.INSTANCE.covnertChatConversationResList(top100Conversation); + } + + @Override + public AiChatConversationRespVO getConversationOfValidate(Long id) { + AiChatConversationDO aiChatConversationDO = validateExists(id); + return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(aiChatConversationDO); + } + + @Override + public Boolean deleteConversation(Long id) { + return chatConversationMapper.deleteById(id) > 0; + } + + public AiChatConversationDO validateExists(Long id) { + AiChatConversationDO conversation = chatConversationMapper.selectById(id); + if (conversation == null) { + throw exception(CHAT_CONVERSATION_NOT_EXISTS); + } + return conversation; + } + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java deleted file mode 100644 index 336f34858..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatConversationServiceImpl.java +++ /dev/null @@ -1,121 +0,0 @@ -package cn.iocoder.yudao.module.ai.service.impl; - -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; -import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; -import cn.iocoder.yudao.module.ai.AiCommonConstants; -import cn.iocoder.yudao.module.ai.ErrorCodeConstants; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateReqVO; -import cn.iocoder.yudao.module.ai.convert.AiChatConversationConvert; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; -import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModelMapper; -import cn.iocoder.yudao.module.ai.service.AiChatConversationService; -import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; -import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.jetbrains.annotations.NotNull; -import org.springframework.stereotype.Service; - -import java.util.List; - -/** - * chat 对话 - * - * @fansili - * @since v1.0 - */ -@Service -@Slf4j -@AllArgsConstructor -public class AiChatConversationServiceImpl implements AiChatConversationService { - - private final AiChatModelMapper aiChatModalMapper; - private final AiChatModelService aiChatModalService; - private final AiChatRoleService aiChatRoleService; - private final AiChatConversationMapper aiChatConversationMapper; - - @Override - public Long createConversation(AiChatConversationCreateReqVO req) { - // 获取用户id - Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); - // 默认使用 sort 排序第一个模型 - AiChatModelDO aiChatModalDO = aiChatModalMapper.selectFirstModal(); - // 查询角色 - AiChatRoleDO chatRoleRes = req.getRoleId() != null ? aiChatRoleService.getChatRole(req.getRoleId()) : null; - Long chatRoleId = chatRoleRes != null ? chatRoleRes.getId() : null; - // 创建新的 Conversation - AiChatConversationDO insertConversation = saveConversation(AiCommonConstants.CONVERSATION_DEFAULT_TITLE, - loginUserId, chatRoleId, aiChatModalDO.getId(), aiChatModalDO.getModel() - ); - // 返回对话id - return insertConversation.getId(); - } - - private @NotNull AiChatConversationDO saveConversation(String title, - Long userId, - Long roleId, - Long modalId, - String model) { - AiChatConversationDO insertConversation = new AiChatConversationDO(); - insertConversation.setId(null); - insertConversation.setUserId(userId); - insertConversation.setTitle(title); - insertConversation.setPinned(false); - - insertConversation.setRoleId(roleId); - insertConversation.setModelId(modalId); - insertConversation.setModel(model); - - insertConversation.setTemperature(null); - insertConversation.setMaxTokens(null); - insertConversation.setMaxContexts(null); - aiChatConversationMapper.insert(insertConversation); - return insertConversation; - } - - @Override - public Boolean updateConversation(AiChatConversationUpdateReqVO updateReqVO) { - // 校验对话是否存在 - validateExists(updateReqVO.getId()); - // 获取模型信息并验证 - aiChatModalService.validateChatModel(updateReqVO.getModelId()); - // 更新对话信息 - AiChatConversationDO updateAiChatConversationDO - = AiChatConversationConvert.INSTANCE.convertAiChatConversationDO(updateReqVO); - return aiChatConversationMapper.updateById(updateAiChatConversationDO) > 0; - } - - @Override - public List listConversation() { - // 获取用户id - Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); - // 查询前100对话 - List top100Conversation - = aiChatConversationMapper.selectTop100Conversation(loginUserId, null); - return AiChatConversationConvert.INSTANCE.covnertChatConversationResList(top100Conversation); - } - - @Override - public AiChatConversationRespVO getConversationOfValidate(Long id) { - AiChatConversationDO aiChatConversationDO = validateExists(id); - return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(aiChatConversationDO); - } - - @Override - public Boolean deleteConversation(Long id) { - return aiChatConversationMapper.deleteById(id) > 0; - } - - public @NotNull AiChatConversationDO validateExists(Long id) { - AiChatConversationDO aiChatConversationDO = aiChatConversationMapper.selectById(id); - if (aiChatConversationDO == null) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CONVERSATION_NOT_EXISTS); - } - return aiChatConversationDO; - } -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index 87d652eef..d74880dfc 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -22,7 +22,7 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatMessageMapper; -import cn.iocoder.yudao.module.ai.service.AiChatConversationService; +import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService; import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; import cn.iocoder.yudao.module.ai.service.AiChatService; import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelService.java index b589ba679..08f0110fe 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelService.java @@ -8,7 +8,6 @@ import jakarta.validation.Valid; import java.util.List; -import java.util.List; import java.util.Set; /** @@ -49,6 +48,15 @@ public interface AiChatModelService { */ AiChatModelDO getChatModel(Long id); + /** + * 获得默认的聊天模型 + * + * 如果获取不到,则抛出 {@link cn.iocoder.yudao.framework.common.exception.ServiceException} 业务异常 + * + * @return 聊天模型 + */ + AiChatModelDO getRequiredDefaultChatModel(); + /** * 获得聊天模型分页 * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java index 919fb5804..59298f9fe 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java @@ -69,7 +69,7 @@ public class AiChatModelServiceImpl implements AiChatModelService { private AiChatModelDO validateChatModelExists(Long id) { AiChatModelDO model = chatModelMapper.selectById(id); if (chatModelMapper.selectById(id) == null) { - throw exception(CHAT_MODAL_NOT_EXIST); + throw exception(CHAT_MODEL_NOT_EXISTS); } return model; } @@ -79,6 +79,15 @@ public class AiChatModelServiceImpl implements AiChatModelService { return chatModelMapper.selectById(id); } + @Override + public AiChatModelDO getRequiredDefaultChatModel() { + AiChatModelDO model = chatModelMapper.selectFirstByStatus(CommonStatusEnum.ENABLE.getStatus()); + if (model == null) { + throw exception(CHAT_MODEL_DEFAULT_NOT_EXISTS); + } + return model; + } + @Override public PageResult getChatModelPage(AiChatModelPageReqVO pageReqVO) { return chatModelMapper.selectPage(pageReqVO); @@ -88,7 +97,7 @@ public class AiChatModelServiceImpl implements AiChatModelService { public AiChatModelDO validateChatModel(Long id) { AiChatModelDO model = validateChatModelExists(id); if (CommonStatusEnum.isDisable(model.getStatus())) { - throw exception(CHAT_MODAL_DISABLE); + throw exception(CHAT_MODEL_DISABLE); } return model; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java index 8b22d638c..7206fd104 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRolePageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveMyReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveReqVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import jakarta.validation.Valid; @@ -78,6 +79,15 @@ public interface AiChatRoleService { */ AiChatRoleDO validateChatRole(Long id); + /** + * 获得默认的聊天角色 + * + * 如果获取不到,则抛出 {@link cn.iocoder.yudao.framework.common.exception.ServiceException} 业务异常 + * + * @return 聊天角色 + */ + AiChatRoleDO getRequiredDefaultChatRole(); + /** * 获得聊天角色分页 * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java index 507e4ce74..e039c4113 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java @@ -17,8 +17,7 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; -import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_ROLE_DISABLE; -import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_ROLE_NOT_EXISTS; +import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.*; /** * AI 聊天角色 Service 实现类 @@ -110,6 +109,16 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { return chatRole; } + @Override + public AiChatRoleDO getRequiredDefaultChatRole() { + AiChatRoleDO chatRole = chatRoleMapper.selectFirstByPublicStatusAndStatus( + true, CommonStatusEnum.ENABLE.getStatus()); + if (chatRole == null) { + throw exception(CHAT_ROLE_DEFAULT_NOT_EXISTS); + } + return chatRole; + } + @Override public PageResult getChatRolePage(AiChatRolePageReqVO pageReqVO) { return chatRoleMapper.selectPage(pageReqVO); From 85b47e49258985acf58e6a6e56b5311975839746 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 14 May 2024 17:40:54 +0800 Subject: [PATCH 270/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A8=A1=E5=9E=8B=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-server/src/main/resources/application-local.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 41ef6ef1a..2f5e70b27 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -61,7 +61,7 @@ spring: lazy: true # 开启懒加载,保证启动速度 url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true username: root - password: root + password: 123456 # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 data: @@ -229,7 +229,7 @@ yudao: appId: 13c8cca6 appKey: cb6415c19d6162cda07b47316fcb0416 secretKey: Y2JiYTIxZjA3MDMxMjNjZjQzYzVmNzdh - chatModel: XING_HUO_3_5 + model: XING_HUO_3_5 yiyan: enable: true aiPlatform: YI_YAN @@ -240,7 +240,7 @@ yudao: appKey: x0cuLZ7XsaTCU08vuJWO87Lg secretKey: R9mYF9dl9KASgi5RUq0FQt3wRisSnOcK refreshTokenSecondTime: 86400 - chatModel: ERNIE4_3_5_8K + model: ERNIE4_3_5_8K openAiImage: enable: true api-key: ${OPEN_AI_KEY} From 4c05bd340ef2ec1b42ebfac427fc05df71f32634 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Tue, 14 May 2024 23:28:44 +0800 Subject: [PATCH 271/684] =?UTF-8?q?fix:=20=E8=8E=B7=E5=BE=97=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E5=B0=8F=E7=A8=8B=E5=BA=8F=E7=A0=81(base64=20image)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/social/AppSocialUserController.java | 15 ++++++++------- .../app/social/vo/AppSocialWxQrcodeReqVO.java | 9 +++++++-- .../module/system/api/social/SocialClientApi.java | 10 ++++++++++ .../module/system/api/social/SocialUserApi.java | 8 -------- .../system/api/social/SocialClientApiImpl.java | 6 ++++++ .../system/api/social/SocialUserApiImpl.java | 6 ------ .../service/social/SocialClientService.java | 2 +- .../service/social/SocialClientServiceImpl.java | 2 +- .../system/service/social/SocialUserService.java | 8 -------- .../service/social/SocialUserServiceImpl.java | 5 ----- 10 files changed, 33 insertions(+), 38 deletions(-) diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java index f6a351a33..a07e6324f 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserBind import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserRespVO; import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserUnbindReqVO; import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialWxQrcodeReqVO; +import cn.iocoder.yudao.module.system.api.social.SocialClientApi; import cn.iocoder.yudao.module.system.api.social.SocialUserApi; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; @@ -34,6 +35,8 @@ public class AppSocialUserController { @Resource private SocialUserApi socialUserApi; + @Resource + private SocialClientApi socialClientApi; @PostMapping("/bind") @Operation(summary = "社交绑定,使用 code 授权码") @@ -63,14 +66,12 @@ public class AppSocialUserController { return success(BeanUtils.toBean(socialUser, AppSocialUserRespVO.class)); } - // TODO @puhui999:是不是 url 叫 wxa-qrcode?然后相关的方法,都做下调整哈;因为是微信小程序的二维码 - @PostMapping("/wxacode") - @Operation(summary = "获得微信小程序码") - @PreAuthenticated // TODO @puhui999:可能不需要登录 + @PostMapping("/wxa-qrcode") + @Operation(summary = "获得微信小程序码(base64 image)") public CommonResult getWxQrcode(@RequestBody @Valid AppSocialWxQrcodeReqVO reqVO) { - byte[] wxQrcode = socialUserApi.getWxQrcode(BeanUtils.toBean(reqVO, SocialWxQrcodeReqDTO.class).setUserId(getLoginUserId()) - .setUserType(UserTypeEnum.MEMBER.getValue()).setSocialType(reqVO.getType())); - return success(Base64.getEncoder().encodeToString(wxQrcode)); + byte[] wxQrcode = socialClientApi.getWxaQrcode(BeanUtils.toBean(reqVO, SocialWxQrcodeReqDTO.class) + .setUserId(getLoginUserId()).setUserType(UserTypeEnum.MEMBER.getValue()).setSocialType(reqVO.getType())); + return success("data:image/png;base64," + Base64.getEncoder().encodeToString(wxQrcode)); } } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java index 15d9e20a1..6465b2384 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java @@ -12,8 +12,9 @@ import lombok.Data; @Data public class AppSocialWxQrcodeReqVO { - // TODO @puhui999:这个后续不用前端传递,应该是后端搞的 - private static String SCENE = "1011"; // 默认场景值 1011 扫描二维码 + // TODO @puhui999:这个后续不用前端传递,应该是后端搞的。 + // 页面路径不能携带参数(参数请放在scene字段里) + private static String SCENE = ""; // 默认场景值 1011 扫描二维码 // TODO @puhui999:这个默认是不是 release 哈? private static String ENV_VERSION = "develop"; // 小程序版本。正式版为 "release",体验版为 "trial",开发版为 "develop" // TODO @puhui999:这个去掉;因为本身就是 430 啦; @@ -28,6 +29,10 @@ public class AppSocialWxQrcodeReqVO { @Schema(description = "场景值", requiredMode = Schema.RequiredMode.REQUIRED, example = "1001") private String scene = SCENE; + /** + * 默认是主页,页面 page,例如 pages/index/index,根路径前不要填加 /,不能携带参数(参数请放在scene字段里), + * 如果不填写这个字段,默认跳主页面。scancode_time为系统保留参数,不允许配置 + */ @Schema(description = "页面路径", requiredMode = Schema.RequiredMode.REQUIRED, example = "pages/goods/index") @NotEmpty(message = "页面路径不能为空") private String path; diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApi.java index 7fdb35a32..cdc609b3f 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApi.java @@ -2,7 +2,9 @@ package cn.iocoder.yudao.module.system.api.social; import cn.iocoder.yudao.module.system.api.social.dto.SocialWxJsapiSignatureRespDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialWxPhoneNumberInfoRespDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialWxQrcodeReqDTO; import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; +import jakarta.validation.Valid; /** * 社交应用的 API 接口 @@ -39,4 +41,12 @@ public interface SocialClientApi { */ SocialWxPhoneNumberInfoRespDTO getWxMaPhoneNumberInfo(Integer userType, String phoneCode); + /** + * 获得小程序二维码 + * + * @param reqVO 请求信息 + * @return 小程序二维码 + */ + byte[] getWxaQrcode(@Valid SocialWxQrcodeReqDTO reqVO); + } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java index 3bde3eab9..6102c4eca 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java @@ -52,12 +52,4 @@ public interface SocialUserApi { */ SocialUserRespDTO getSocialUserByCode(Integer userType, Integer socialType, String code, String state); - /** - * 获得小程序二维码 - * - * @param reqVO 请求信息 - * @return 小程序二维码 - */ - byte[] getWxQrcode(@Valid SocialWxQrcodeReqDTO reqVO); - } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApiImpl.java index 2e82ad492..2a7b69cfe 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApiImpl.java @@ -4,6 +4,7 @@ import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.social.dto.SocialWxJsapiSignatureRespDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialWxPhoneNumberInfoRespDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialWxQrcodeReqDTO; import cn.iocoder.yudao.module.system.service.social.SocialClientService; import me.chanjar.weixin.common.bean.WxJsapiSignature; import org.springframework.stereotype.Service; @@ -40,4 +41,9 @@ public class SocialClientApiImpl implements SocialClientApi { return BeanUtils.toBean(info, SocialWxPhoneNumberInfoRespDTO.class); } + @Override + public byte[] getWxaQrcode(SocialWxQrcodeReqDTO reqVO) { + return socialClientService.getWxaQrcode(reqVO); + } + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java index ad56c9ee5..a8c30a0f8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java @@ -43,10 +43,4 @@ public class SocialUserApiImpl implements SocialUserApi { return socialUserService.getSocialUserByCode(userType, socialType, code, state); } - // TODO @puhui999:貌似搞到 SocialClientApiImpl 更合适,二维码和用户关系不大;这样 socialUserService 也不用绕一次了 - @Override - public byte[] getWxQrcode(SocialWxQrcodeReqDTO reqVO) { - return socialUserService.getWxQrcode(reqVO); - } - } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientService.java index f7d8cd0e2..7757d35d1 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientService.java @@ -67,7 +67,7 @@ public interface SocialClientService { * @param reqVO 请求信息 * @return 小程序二维码 */ - byte[] getWxQrcode(SocialWxQrcodeReqDTO reqVO); + byte[] getWxaQrcode(SocialWxQrcodeReqDTO reqVO); // =================== 客户端管理 =================== diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java index 978f6161c..aeff40cce 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java @@ -229,7 +229,7 @@ public class SocialClientServiceImpl implements SocialClientService { } @Override - public byte[] getWxQrcode(SocialWxQrcodeReqDTO reqVO) { + public byte[] getWxaQrcode(SocialWxQrcodeReqDTO reqVO) { WxMaService service = getWxMaService(reqVO.getUserType()); try { return service.getQrcodeService().createWxaCodeUnlimitBytes(reqVO.getScene(), reqVO.getPath(), diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java index 40ba45542..73d57687e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java @@ -87,12 +87,4 @@ public interface SocialUserService { */ PageResult getSocialUserPage(SocialUserPageReqVO pageReqVO); - /** - * 获得小程序二维码 - * - * @param reqVO 请求信息 - * @return 小程序二维码 - */ - byte[] getWxQrcode(SocialWxQrcodeReqDTO reqVO); - } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java index 5d236e938..dedab0db3 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java @@ -171,9 +171,4 @@ public class SocialUserServiceImpl implements SocialUserService { return socialUserMapper.selectPage(pageReqVO); } - @Override - public byte[] getWxQrcode(SocialWxQrcodeReqDTO reqVO) { - return socialClientService.getWxQrcode(reqVO); - } - } From 52b972907a2d47e689d91cb16ac35f8528953ef3 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Tue, 14 May 2024 23:29:47 +0800 Subject: [PATCH 272/684] =?UTF-8?q?member:=20=E5=A2=9E=E5=8A=A0=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E7=BC=96=E5=8F=B7=E8=BF=94=E5=9B=9E=EF=BC=8C=E5=88=86?= =?UTF-8?q?=E4=BA=AB=E6=B5=B7=E6=8A=A5=E6=9C=89=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/app/user/vo/AppMemberUserInfoRespVO.java | 3 +++ .../module/member/convert/user/MemberUserConvert.java | 9 +++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java index fa05e16d0..72e4fa3fa 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java @@ -11,6 +11,9 @@ import lombok.NoArgsConstructor; @AllArgsConstructor public class AppMemberUserInfoRespVO { + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") private String nickname; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/MemberUserConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/MemberUserConvert.java index aae9a7601..eaa5ab50e 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/MemberUserConvert.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/MemberUserConvert.java @@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO; import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; import org.mapstruct.Mapper; import org.mapstruct.Mapping; +import org.mapstruct.Mappings; import org.mapstruct.factory.Mappers; import java.util.List; @@ -27,8 +28,12 @@ public interface MemberUserConvert { AppMemberUserInfoRespVO convert(MemberUserDO bean); - @Mapping(source = "level", target = "level") - @Mapping(source = "bean.experience", target = "experience") + + @Mappings({ + @Mapping(source = "level", target = "level"), + @Mapping(source = "bean.id", target = "id"), + @Mapping(source = "bean.experience", target = "experience") + }) AppMemberUserInfoRespVO convert(MemberUserDO bean, MemberLevelDO level); MemberUserRespDTO convert2(MemberUserDO bean); From 69fa98792ce116458095ea79cb134682d33120c2 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 14 May 2024 23:46:29 +0800 Subject: [PATCH 273/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E8=81=8A=E5=A4=A9=E5=AF=B9=E8=AF=9D=E7=9A=84=E6=96=B0?= =?UTF-8?q?=E5=BB=BA=EF=BC=8880%=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/ErrorCodeConstants.java | 3 +- .../chat/AiChatConversationController.java | 10 +-- .../AiChatConversationRespVO.java | 24 ++++++- .../dal/mysql/AiChatConversationMapper.java | 65 ------------------- .../ai/dal/mysql/AiChatMessageMapper.java | 2 + .../mysql/chat/AiChatConversationMapper.java | 22 +++++++ .../chat/AiChatConversationService.java | 9 +-- .../chat/AiChatConversationServiceImpl.java | 28 ++++---- .../ai/service/impl/AiChatServiceImpl.java | 4 +- 9 files changed, 78 insertions(+), 89 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatConversationMapper.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index 8948fcba4..a70c58ba2 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -25,7 +25,8 @@ public interface ErrorCodeConstants { // ========== API 聊天会话 1-040-003-000 ========== - ErrorCode CHAT_CONVERSATION_NOT_EXISTS = new ErrorCode(1_040_003_000, "AI 对话不存在!");; + ErrorCode CHAT_CONVERSATION_NOT_EXISTS = new ErrorCode(1_040_003_000, "AI 对话不存在!"); + ErrorCode CHAT_CONVERSATION_MODEL_ERROR = new ErrorCode(1_040_003_001, "操作失败,该聊天模型的配置不完整"); // chat ErrorCode AI_CHAT_MESSAGE_NOT_EXIST = new ErrorCode(1_022_000_100, "AI 提问的 MessageId 不存在!"); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java index 3e56cb999..dcfe8d386 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java @@ -1,9 +1,11 @@ package cn.iocoder.yudao.module.ai.controller.admin.chat; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateMyReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateMyReqVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -40,11 +42,11 @@ public class AiChatConversationController { return success(true); } - // TODO done @fan:实现一下 @GetMapping("/my-list") - @Operation(summary = "获得聊天会话列表") - public CommonResult> getConversationList() { - return success(chatConversationService.listConversation()); + @Operation(summary = "获得【我的】聊天会话列表") + public CommonResult> getChatConversationMyList() { + List list = chatConversationService.getChatConversationListByUserId(getLoginUserId()); + return success(BeanUtils.toBean(list, AiChatConversationRespVO.class)); } // TODO @fan:实现一下 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java index 70ff21fc5..42c244e19 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java @@ -1,5 +1,11 @@ package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation; +import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelRespVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; +import com.fhs.core.trans.anno.Trans; +import com.fhs.core.trans.constant.TransType; +import com.fhs.core.trans.vo.VO; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -7,7 +13,7 @@ import lombok.experimental.Accessors; @Schema(description = "管理后台 - AI 聊天会话 Response VO") @Data -public class AiChatConversationRespVO { +public class AiChatConversationRespVO implements VO { @Schema(description = "会话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Long id; @@ -22,9 +28,12 @@ public class AiChatConversationRespVO { private Boolean pinned; @Schema(description = "角色编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1") + @Trans(type = TransType.SIMPLE, target = AiChatRoleDO.class, fields = "avatar", ref = "roleAvatar") private Long roleId; @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @Trans(type = TransType.SIMPLE, target = AiChatModelDO.class, fields = {"maxTokens", "maxContexts"}, + refs = {"modelMaxTokens", "modelMaxContexts"}) private Long modelId; @Schema(description = "模型标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "ERNIE-Bot-turbo-0922") @@ -39,4 +48,17 @@ public class AiChatConversationRespVO { @Schema(description = "上下文的最大 Message 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") private Integer maxContexts; + // ========== 关联 role 信息 ========== + + @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + private String roleAvatar; + + // ========== 关联 model 信息 ========== + + @Schema(description = "模型的单条回复的最大 Token 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096") + private Integer modelMaxTokens; + + @Schema(description = "模型的上下文的最大 Message 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Integer modelMaxContexts; + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatConversationMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatConversationMapper.java deleted file mode 100644 index 0333be30d..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatConversationMapper.java +++ /dev/null @@ -1,65 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Update; -import org.springframework.stereotype.Repository; - -import java.util.List; - -/** - * message mapper - * - * @fansili - * @since v1.0 - */ -@Repository -@Mapper -public interface AiChatConversationMapper extends BaseMapperX { - - /** - * 更新 - chat count - * - * @param id - */ - @Update("update ai_chat_conversation set chat_count = chat_count + 1 where id = #{id}") - void updateIncrChatCount(@Param("id") Long id); - - /** - * 查询 - 最新的对话 - * - * @param loginUserId - */ - default AiChatConversationDO selectLatestConversation(Long loginUserId) { - PageResult pageResult = selectPage(new PageParam().setPageNo(1).setPageSize(1), - new LambdaQueryWrapper() - .eq(AiChatConversationDO::getUserId, loginUserId) - .orderByDesc(AiChatConversationDO::getId)); - if (CollUtil.isEmpty(pageResult.getList())) { - return null; - } - return pageResult.getList().get(0); - } - - /** - * 查询 - 前100 - * - * @param search - */ - default List selectTop100Conversation(Long loginUserId, String search) { - LambdaQueryWrapper queryWrapper - = new LambdaQueryWrapper().eq(AiChatConversationDO::getUserId, loginUserId); - if (!StrUtil.isBlank(search)) { - queryWrapper.like(AiChatConversationDO::getTitle, search); - } - queryWrapper.orderByDesc(AiChatConversationDO::getId); - return selectPage(new PageParam().setPageNo(1).setPageSize(100), queryWrapper).getList(); - } -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java index 5f6083fdb..fef19af12 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.dal.mysql; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; @@ -30,4 +31,5 @@ public interface AiChatMessageMapper extends BaseMapperX { .orderByAsc(AiChatMessageDO::getId) ); } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java new file mode 100644 index 000000000..5d41fb080 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.ai.dal.mysql.chat; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * AI 聊天对话 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface AiChatConversationMapper extends BaseMapperX { + + default List selectListByUserId(Long userId) { + return selectList(AiChatConversationDO::getUserId, userId); + } + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java index ed8fa101c..626f7996b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java @@ -19,7 +19,7 @@ public interface AiChatConversationService { * * @param createReqVO 创建信息 * @param userId 用户编号 - * @return 聊天会话 + * @return 编号 */ Long createChatConversationMy(AiChatConversationCreateMyReqVO createReqVO, Long userId); @@ -32,11 +32,12 @@ public interface AiChatConversationService { void updateChatConversationMy(AiChatConversationUpdateMyReqVO updateReqVO, Long userId); /** - * 获取 - 对话列表 + * 获得【我的】聊天会话列表 * - * @return + * @param userId 用户编号 + * @return 聊天会话列表 */ - List listConversation(); + List getChatConversationListByUserId(Long userId); /** * 获取 - 对话 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java index b04f2b789..22465467e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.service.chat; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateMyReqVO; @@ -11,7 +12,7 @@ import cn.iocoder.yudao.module.ai.convert.AiChatConversationConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; +import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; import jakarta.annotation.Resource; @@ -22,6 +23,7 @@ import org.springframework.validation.annotation.Validated; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.*; +import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_CONVERSATION_MODEL_ERROR; import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_CONVERSATION_NOT_EXISTS; /** @@ -49,9 +51,10 @@ public class AiChatConversationServiceImpl implements AiChatConversationService : chatRoleService.getRequiredDefaultChatRole(); Assert.notNull(role, "必须找到聊天角色"); // 1.2 获得 AiChatModelDO 聊天模型 - AiChatModelDO model = role.getModelId() != null ? chatModalService.validateChatModel(role.getId()) + AiChatModelDO model = role.getModelId() != null ? chatModalService.validateChatModel(role.getModelId()) : chatModalService.getRequiredDefaultChatModel(); - Assert.notNull(role, "必须找到默认模型"); + Assert.notNull(model, "必须找到默认模型"); + validateChatModel(model); // 2. 创建 AiChatConversationDO 聊天对话 AiChatConversationDO conversation = new AiChatConversationDO() @@ -70,9 +73,10 @@ public class AiChatConversationServiceImpl implements AiChatConversationService throw exception(CHAT_CONVERSATION_NOT_EXISTS); } // 1.2 校验模型是否存在 - AiChatModelDO model = null; + AiChatModelDO model; if (updateReqVO.getModelId() != null) { model = chatModalService.validateChatModel(updateReqVO.getModelId()); + Assert.notNull(model, "必须找到默认模型"); } // 1.3 校验温度参数、Token 数量、消息数量 TODO @@ -81,13 +85,15 @@ public class AiChatConversationServiceImpl implements AiChatConversationService } @Override - public List listConversation() { - // 获取用户id - Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); - // 查询前100对话 - List top100Conversation - = chatConversationMapper.selectTop100Conversation(loginUserId, null); - return AiChatConversationConvert.INSTANCE.covnertChatConversationResList(top100Conversation); + public List getChatConversationListByUserId(Long userId) { + return chatConversationMapper.selectListByUserId(userId); + } + + private void validateChatModel(AiChatModelDO model) { + if (ObjectUtil.isAllNotEmpty(model.getTemperature(), model.getMaxTokens(), model.getMaxContexts())) { + return; + } + throw exception(CHAT_CONVERSATION_MODEL_ERROR); } @Override diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index d74880dfc..a73531ddd 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -20,7 +20,7 @@ import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper; +import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatMessageMapper; import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService; import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; @@ -119,8 +119,6 @@ public class AiChatServiceImpl implements AiChatService { .setMaxContexts(maxContexts); // 增加 chat message 记录 aiChatMessageMapper.insert(insertChatMessageDO); - // chat count 先+1 - aiChatConversationMapper.updateIncrChatCount(conversationId); return insertChatMessageDO; } From 78bb2d1dc8ae0bff30c18f14a99133e53d642c0d Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 15 May 2024 08:59:18 +0800 Subject: [PATCH 274/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E8=81=8A=E5=A4=A9=E5=AF=B9=E8=AF=9D=E7=9A=84=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E6=A0=87=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/ErrorCodeConstants.java | 18 +++++++------ .../dataobject/chat/AiChatConversationDO.java | 7 +++++ .../chat/AiChatConversationServiceImpl.java | 26 +++++++++++++------ 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index a70c58ba2..4542c0787 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -10,26 +10,28 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; public interface ErrorCodeConstants { // ========== API 密钥 1-040-000-000 ========== - ErrorCode API_KEY_NOT_EXISTS = new ErrorCode(1_040_000_000, "AI API 密钥不存在"); - ErrorCode API_KEY_DISABLE = new ErrorCode(1_040_000_001, "AI API 密钥已禁用!"); + ErrorCode API_KEY_NOT_EXISTS = new ErrorCode(1_040_000_000, "API 密钥不存在"); + ErrorCode API_KEY_DISABLE = new ErrorCode(1_040_000_001, "API 密钥已禁用!"); // ========== API 聊天模型 1-040-001-000 ========== - ErrorCode CHAT_MODEL_NOT_EXISTS = new ErrorCode(1_040_001_000, "AI 模型不存在!"); - ErrorCode CHAT_MODEL_DISABLE = new ErrorCode(1_040_001_001, "AI 模型({})已禁用!"); + ErrorCode CHAT_MODEL_NOT_EXISTS = new ErrorCode(1_040_001_000, "模型不存在!"); + ErrorCode CHAT_MODEL_DISABLE = new ErrorCode(1_040_001_001, "模型({})已禁用!"); ErrorCode CHAT_MODEL_DEFAULT_NOT_EXISTS = new ErrorCode(1_040_001_002, "操作失败,找不到默认聊天模型"); // ========== API 聊天模型 1-040-002-000 ========== - ErrorCode CHAT_ROLE_NOT_EXISTS = new ErrorCode(1_040_002_000, "AI 聊天角色不存在"); - ErrorCode CHAT_ROLE_DISABLE = new ErrorCode(1_040_001_001, "AI 聊天角色({})已禁用!"); + ErrorCode CHAT_ROLE_NOT_EXISTS = new ErrorCode(1_040_002_000, "聊天角色不存在"); + ErrorCode CHAT_ROLE_DISABLE = new ErrorCode(1_040_001_001, "聊天角色({})已禁用!"); ErrorCode CHAT_ROLE_DEFAULT_NOT_EXISTS = new ErrorCode(1_040_001_002, "操作失败,找不到默认聊天角色"); // ========== API 聊天会话 1-040-003-000 ========== - ErrorCode CHAT_CONVERSATION_NOT_EXISTS = new ErrorCode(1_040_003_000, "AI 对话不存在!"); + ErrorCode CHAT_CONVERSATION_NOT_EXISTS = new ErrorCode(1_040_003_000, "对话不存在!"); ErrorCode CHAT_CONVERSATION_MODEL_ERROR = new ErrorCode(1_040_003_001, "操作失败,该聊天模型的配置不完整"); + ErrorCode CHAT_CONVERSATION_UPDATE_MAX_TOKENS_ERROR = new ErrorCode(1_040_003_002, "更新对话失败,最大 Token 超过上限"); + ErrorCode CHAT_CONVERSATION_UPDATE_MAX_CONTEXTS_ERROR = new ErrorCode(1_040_003_002, "更新对话失败,最大 Context 超过上限"); // chat - ErrorCode AI_CHAT_MESSAGE_NOT_EXIST = new ErrorCode(1_022_000_100, "AI 提问的 MessageId 不存在!"); + ErrorCode AI_CHAT_MESSAGE_NOT_EXIST = new ErrorCode(1_022_000_100, "提问的 MessageId 不存在!"); // midjourney diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java index c8613b5e1..547387055 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java @@ -9,6 +9,9 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import java.time.LocalDateTime; +import java.util.Date; + /** * AI Chat 会话 DO * @@ -51,6 +54,10 @@ public class AiChatConversationDO extends BaseDO { * 是否置顶 */ private Boolean pinned; + /** + * 置顶时间 + */ + private LocalDateTime pinnedTime; /** * 角色编号 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java index 22465467e..41cbf329c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java @@ -20,11 +20,11 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import java.time.LocalDateTime; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.*; -import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_CONVERSATION_MODEL_ERROR; -import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_CONVERSATION_NOT_EXISTS; +import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.*; /** * AI 聊天对话 Service 实现类 @@ -72,16 +72,26 @@ public class AiChatConversationServiceImpl implements AiChatConversationService if (ObjUtil.notEqual(conversation.getUserId(), userId)) { throw exception(CHAT_CONVERSATION_NOT_EXISTS); } - // 1.2 校验模型是否存在 - AiChatModelDO model; - if (updateReqVO.getModelId() != null) { - model = chatModalService.validateChatModel(updateReqVO.getModelId()); + // 1.2 校验模型是否存在(修改模型的情况) + if (!ObjectUtil.isAllEmpty(updateReqVO.getModelId(), updateReqVO.getMaxTokens(), updateReqVO.getMaxContexts())) { + AiChatModelDO model = chatModalService.validateChatModel(updateReqVO.getModelId()); Assert.notNull(model, "必须找到默认模型"); + validateChatModel(model); + // 校验 Token 数量、上下文数量 + if (updateReqVO.getMaxTokens() != null && updateReqVO.getMaxTokens() > model.getMaxTokens()) { + throw exception(CHAT_CONVERSATION_UPDATE_MAX_TOKENS_ERROR); + } + if (updateReqVO.getMaxContexts() != null && updateReqVO.getMaxContexts() > model.getMaxContexts()) { + throw exception(CHAT_CONVERSATION_UPDATE_MAX_CONTEXTS_ERROR); + } } - // 1.3 校验温度参数、Token 数量、消息数量 TODO // 更新对话信息 - chatConversationMapper.updateById(BeanUtils.toBean(updateReqVO, AiChatConversationDO.class)); + AiChatConversationDO updateObj = BeanUtils.toBean(updateReqVO, AiChatConversationDO.class); + if (Boolean.TRUE.equals(updateReqVO.getPinned())) { + updateObj.setPinnedTime(LocalDateTime.now()); + } + chatConversationMapper.updateById(updateObj); } @Override From 5632c515271943200f4b189204947632bf77ccc9 Mon Sep 17 00:00:00 2001 From: DevDengChao <2325690622@qq.com> Date: Wed, 15 May 2024 13:44:18 +0800 Subject: [PATCH 275/684] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=20DeliveryExpressDO=20=E6=97=B6=E6=8F=90=E7=A4=BA=20i?= =?UTF-8?q?d=20=E8=BF=87=E5=A4=A7=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../trade/dal/dataobject/delivery/DeliveryExpressDO.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/delivery/DeliveryExpressDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/delivery/DeliveryExpressDO.java index 265066d83..c6b7fbf33 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/delivery/DeliveryExpressDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/delivery/DeliveryExpressDO.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.trade.dal.dataobject.delivery; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -20,7 +21,7 @@ public class DeliveryExpressDO extends BaseDO { /** * 编号,自增 */ - @TableId + @TableId(type = IdType.AUTO) private Long id; /** From c68f32cefeecd3afef706f9db677c38ba7c704d6 Mon Sep 17 00:00:00 2001 From: DevDengChao <2325690622@qq.com> Date: Wed, 15 May 2024 13:44:39 +0800 Subject: [PATCH 276/684] =?UTF-8?q?chore:=20=E5=A4=87=E6=B3=A8=E5=9B=A2?= =?UTF-8?q?=E9=95=BF=E7=BF=BB=E8=AF=91=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/trade/dal/dataobject/order/TradeOrderDO.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java index b127004aa..ba7e689f8 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java @@ -322,7 +322,7 @@ public class TradeOrderDO extends BaseDO { * * 关联 CombinationRecordDO 的 headId 字段 */ - private Long combinationHeadId; + private Long combinationHeadId; // FIXME 2024/5/15: "团长" 应该译作 leader / starter 而不是 head /** * 拼团记录编号 * From 9c111acfbe8a1e81542e345d2bef59327bc9cc1c Mon Sep 17 00:00:00 2001 From: DevDengChao <2325690622@qq.com> Date: Wed, 15 May 2024 13:44:57 +0800 Subject: [PATCH 277/684] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20TradeOrderU?= =?UTF-8?q?pdateServiceTest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../order/TradeOrderUpdateServiceTest.java | 50 +++- .../src/test/resources/sql/create_tables.sql | 275 ++++++++++-------- 2 files changed, 203 insertions(+), 122 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceTest.java index 3f05f5559..2f78dbe08 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceTest.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceTest.java @@ -1,33 +1,49 @@ package cn.iocoder.yudao.module.trade.service.order; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.member.api.address.MemberAddressApi; import cn.iocoder.yudao.module.member.api.user.MemberUserApi; import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; +import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi; import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; +import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressCreateReqVO; import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; +import cn.iocoder.yudao.module.trade.dal.redis.no.TradeNoRedisDAO; +import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderRefundStatusEnum; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderConfig; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; +import cn.iocoder.yudao.module.trade.service.cart.CartServiceImpl; +import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; +import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressServiceImpl; +import cn.iocoder.yudao.module.trade.service.message.TradeMessageServiceImpl; +import cn.iocoder.yudao.module.trade.service.order.handler.TradeOrderHandler; +import cn.iocoder.yudao.module.trade.service.price.TradePriceServiceImpl; +import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculator; +import jakarta.annotation.Resource; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; -import jakarta.annotation.Resource; import java.time.Duration; +import java.util.UUID; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; @@ -37,8 +53,10 @@ import static org.mockito.Mockito.when; * @author LeeYan9 * @since 2022-09-07 */ -@Disabled // TODO 芋艿:后续 fix 补充的单测 -@Import({TradeOrderUpdateServiceImpl.class, TradeOrderConfig.class}) +@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") +@Import({TradeOrderUpdateServiceImpl.class, TradeOrderConfig.class, CartServiceImpl.class, TradePriceServiceImpl.class, + DeliveryExpressServiceImpl.class, TradeMessageServiceImpl.class +}) public class TradeOrderUpdateServiceTest extends BaseDbUnitTest { @Resource @@ -55,7 +73,9 @@ public class TradeOrderUpdateServiceTest extends BaseDbUnitTest { private ProductSpuApi productSpuApi; @MockBean private ProductSkuApi productSkuApi; -// @MockBean + @MockBean + private ProductCommentApi productCommentApi; + // @MockBean // private PriceApi priceApi; @MockBean private PayOrderApi payOrderApi; @@ -66,11 +86,22 @@ public class TradeOrderUpdateServiceTest extends BaseDbUnitTest { @MockBean private TradeOrderProperties tradeOrderProperties; + @MockBean + private TradeNoRedisDAO tradeNoRedisDAO; + @MockBean + private TradeOrderHandler tradeOrderHandler; + @MockBean + private TradePriceCalculator tradePriceCalculator; + @MockBean + private NotifyMessageSendApi notifyMessageSendApi; + @Autowired + private DeliveryExpressService deliveryExpressService; @BeforeEach public void setUp() { when(tradeOrderProperties.getAppId()).thenReturn(888L); when(tradeOrderProperties.getPayExpireTime()).thenReturn(Duration.ofDays(1)); + when(tradeNoRedisDAO.generate(anyString())).thenReturn(UUID.randomUUID().toString()); } // @Test @@ -259,11 +290,18 @@ public class TradeOrderUpdateServiceTest extends BaseDbUnitTest { TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> { o.setId(1L).setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus()); o.setLogisticsId(null).setLogisticsNo(null).setDeliveryTime(null); + o.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()); + o.setDeliveryType(DeliveryTypeEnum.EXPRESS.getType()); }); tradeOrderMapper.insert(order); + + DeliveryExpressCreateReqVO expressCreateReqVO = new DeliveryExpressCreateReqVO(); + expressCreateReqVO.setCode("code").setName("Name").setLogo("logo").setSort(0).setStatus(CommonStatusEnum.ENABLE.getStatus()); + Long deliveryExpressId = deliveryExpressService.createDeliveryExpress(expressCreateReqVO); // 准备参数 TradeOrderDeliveryReqVO deliveryReqVO = new TradeOrderDeliveryReqVO().setId(1L) - .setLogisticsId(10L).setLogisticsNo("100"); + .setLogisticsId(deliveryExpressId).setLogisticsNo("100"); + // mock 方法(支付单) // 调用 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql index d263fdfb9..f619c01de 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql @@ -1,128 +1,155 @@ -CREATE TABLE IF NOT EXISTS "trade_order" ( - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "no" varchar NOT NULL, - "type" int NOT NULL, - "terminal" int NOT NULL, - "user_id" bigint NOT NULL, - "user_ip" varchar NOT NULL, - "user_remark" varchar, - "status" int NOT NULL, - "product_count" int NOT NULL, - "cancel_type" int, - "remark" varchar, - "pay_status" bit NOT NULL, - "pay_time" datetime, - "finish_time" datetime, - "cancel_time" datetime, - "original_price" int NOT NULL, - "order_price" int NOT NULL, - "discount_price" int NOT NULL, - "delivery_price" int NOT NULL, - "adjust_price" int NOT NULL, - "pay_price" int NOT NULL, - "pay_order_id" bigint, - "pay_channel_code" varchar, - "delivery_template_id" bigint, - "logistics_id" bigint, - "logistics_no" varchar, - "delivery_time" datetime, - "receive_time" datetime, - "receiver_name" varchar NOT NULL, - "receiver_mobile" varchar NOT NULL, - "receiver_area_id" int NOT NULL, - "receiver_post_code" int, - "receiver_detail_address" varchar NOT NULL, - "after_sale_status" int NOT NULL, - "refund_price" int NOT NULL, - "coupon_id" bigint NOT NULL, - "coupon_price" int NOT NULL, - "point_price" int NOT NULL, - "creator" varchar DEFAULT '', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar DEFAULT '', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - PRIMARY KEY ("id") +CREATE TABLE IF NOT EXISTS "trade_order" +( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "no" varchar NOT NULL, + "type" int NOT NULL, + "terminal" int NOT NULL, + "user_id" bigint NOT NULL, + "user_ip" varchar NOT NULL, + "user_remark" varchar, + "status" int NOT NULL, + "product_count" int NOT NULL, + "cancel_type" int, + "remark" varchar, + "comment_status" boolean, + "brokerage_user_id" bigint, + "pay_status" bit NOT NULL, + "pay_time" datetime, + "finish_time" datetime, + "cancel_time" datetime, + "total_price" int NULL, + "order_price" int NULL, + "discount_price" int NOT NULL, + "delivery_price" int NOT NULL, + "adjust_price" int NOT NULL, + "pay_price" int NOT NULL, + "delivery_type" int NOT NULL, + "pay_order_id" bigint, + "pay_channel_code" varchar, + "delivery_template_id" bigint, + "logistics_id" bigint, + "logistics_no" varchar, + "delivery_time" datetime, + "receive_time" datetime, + "receiver_name" varchar NOT NULL, + "receiver_mobile" varchar NOT NULL, + "receiver_area_id" int NOT NULL, + "receiver_post_code" int, + "receiver_detail_address" varchar NOT NULL, + "pick_up_store_id" long NULL, + "pick_up_verify_code" varchar NULL, + "refund_status" int NULL, + "refund_price" int NULL, + "after_sale_status" int NULL, + "coupon_id" bigint NOT NULL, + "coupon_price" int NOT NULL, + "use_point" int NULL, + "point_price" int NOT NULL, + "give_point" int NULL, + "refund_point" int NULL, + "vip_price" int NULL, + "seckill_activity_id" long NULL, + "bargain_activity_id" long NULL, + "bargain_record_id" long NULL, + "combination_activity_id" long NULL, + "combination_head_id" long NULL, + "combination_record_id" long NULL, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") ) COMMENT '交易订单表'; -CREATE TABLE IF NOT EXISTS "trade_order_item" ( - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "user_id" bigint NOT NULL, - "order_id" bigint NOT NULL, - "spu_id" bigint NOT NULL, - "spu_name" varchar NOT NULL, - "sku_id" bigint NOT NULL, - "properties" varchar, - "pic_url" varchar, - "count" int NOT NULL, - "original_price" int NOT NULL, - "original_unit_price" int NOT NULL, - "discount_price" int NOT NULL, - "pay_price" int NOT NULL, - "order_part_price" int NOT NULL, - "order_divide_price" int NOT NULL, - "after_sale_status" int NOT NULL, - "creator" varchar DEFAULT '', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar DEFAULT '', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - PRIMARY KEY ("id") +CREATE TABLE IF NOT EXISTS "trade_order_item" +( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "user_id" bigint NOT NULL, + "order_id" bigint NOT NULL, + "cart_id" int NULL, + "spu_id" bigint NOT NULL, + "spu_name" varchar NOT NULL, + "sku_id" bigint NOT NULL, + "properties" varchar, + "pic_url" varchar, + "count" int NOT NULL, + "comment_status" boolean NULL, + "price" int NOT NULL, + "discount_price" int NOT NULL, + "delivery_price" int NULL, + "adjust_price" int NULL, + "pay_price" int NOT NULL, + "coupon_price" int NULL, + "point_price" int NULL, + "use_point" int NULL, + "give_point" int NULL, + "vip_price" int NULL, + "after_sale_id" long NULL, + "after_sale_status" int NOT NULL, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") ) COMMENT '交易订单明细表'; -CREATE TABLE IF NOT EXISTS "trade_after_sale" ( - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "no" varchar NOT NULL, - "status" int NOT NULL, - "type" int NOT NULL, - "way" int NOT NULL, - "user_id" bigint NOT NULL, - "apply_reason" varchar NOT NULL, +CREATE TABLE IF NOT EXISTS "trade_after_sale" +( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "no" varchar NOT NULL, + "status" int NOT NULL, + "type" int NOT NULL, + "way" int NOT NULL, + "user_id" bigint NOT NULL, + "apply_reason" varchar NOT NULL, "apply_description" varchar, "apply_pic_urls" varchar, - "order_id" bigint NOT NULL, - "order_no" varchar NOT NULL, - "order_item_id" bigint NOT NULL, - "spu_id" bigint NOT NULL, - "spu_name" varchar NOT NULL, - "sku_id" bigint NOT NULL, - "properties" varchar, - "pic_url" varchar, - "count" int NOT NULL, - "audit_time" varchar, - "audit_user_id" bigint, - "audit_reason" varchar, - "refund_price" int NOT NULL, - "pay_refund_id" bigint, - "refund_time" varchar, - "logistics_id" bigint, - "logistics_no" varchar, - "delivery_time" varchar, - "receive_time" varchar, + "order_id" bigint NOT NULL, + "order_no" varchar NOT NULL, + "order_item_id" bigint NOT NULL, + "spu_id" bigint NOT NULL, + "spu_name" varchar NOT NULL, + "sku_id" bigint NOT NULL, + "properties" varchar, + "pic_url" varchar, + "count" int NOT NULL, + "audit_time" varchar, + "audit_user_id" bigint, + "audit_reason" varchar, + "refund_price" int NOT NULL, + "pay_refund_id" bigint, + "refund_time" varchar, + "logistics_id" bigint, + "logistics_no" varchar, + "delivery_time" varchar, + "receive_time" varchar, "receive_reason" varchar, - "creator" varchar DEFAULT '', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar DEFAULT '', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, PRIMARY KEY ("id") ) COMMENT '交易售后表'; -CREATE TABLE IF NOT EXISTS "trade_after_sale_log" ( - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "user_id" bigint NOT NULL, - "user_type" int NOT NULL, - "after_sale_id" bigint NOT NULL, - "order_id" bigint NOT NULL, - "order_item_id" bigint NOT NULL, +CREATE TABLE IF NOT EXISTS "trade_after_sale_log" +( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "user_id" bigint NOT NULL, + "user_type" int NOT NULL, + "after_sale_id" bigint NOT NULL, + "order_id" bigint NOT NULL, + "order_item_id" bigint NOT NULL, "before_status" int, - "after_status" int NOT NULL, - "content" varchar NOT NULL, - "creator" varchar DEFAULT '', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar DEFAULT '', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, + "after_status" int NOT NULL, + "content" varchar NOT NULL, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, PRIMARY KEY ("id") ) COMMENT '交易售后日志'; @@ -161,7 +188,7 @@ CREATE TABLE IF NOT EXISTS "trade_brokerage_record" "updater" varchar DEFAULT '', "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, "deleted" bit NOT NULL DEFAULT FALSE, - "tenant_id" bigint not null default '0', + "tenant_id" bigint not null default '0', PRIMARY KEY ("id") ) COMMENT '佣金记录'; CREATE TABLE IF NOT EXISTS "trade_brokerage_withdraw" @@ -186,6 +213,22 @@ CREATE TABLE IF NOT EXISTS "trade_brokerage_withdraw" "updater" varchar DEFAULT '', "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, "deleted" bit NOT NULL DEFAULT FALSE, - "tenant_id" bigint not null default '0', + "tenant_id" bigint not null default '0', + PRIMARY KEY ("id") +) COMMENT '佣金提现'; + +CREATE TABLE IF NOT EXISTS "trade_delivery_express" +( + "id" int NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "code" varchar NULL, + "name" varchar, + "logo" varchar NULL, + "sort" int NOT NULL, + "status" int NOT NULL, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, PRIMARY KEY ("id") ) COMMENT '佣金提现'; \ No newline at end of file From 314a015a2ef2dccc69607cbe8b1367653b227d0d Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 15 May 2024 18:16:50 +0800 Subject: [PATCH 278/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E8=A7=92=E8=89=B2=E5=88=86=E7=B1=BB=E5=88=97=E8=A1=A8=20group?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java | 3 ++- .../yudao/module/ai/service/model/AiChatRoleServiceImpl.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java index c0eeb549e..c2a9631dc 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java @@ -50,8 +50,9 @@ public interface AiChatRoleMapper extends BaseMapperX { default List selectListGroupByCategory(Integer status) { return selectList(new LambdaQueryWrapperX() + .select(AiChatRoleDO::getCategory) .eq(AiChatRoleDO::getStatus, status) - .apply("GROUP BY category")); + .groupBy(AiChatRoleDO::getCategory)); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java index e039c4113..196f1a6ac 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java @@ -132,7 +132,7 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { @Override public List getChatRoleCategoryList() { List list = chatRoleMapper.selectListGroupByCategory(CommonStatusEnum.ENABLE.getStatus()); - return convertList(list, AiChatRoleDO::getName); + return convertList(list, AiChatRoleDO::getCategory); } } From d0c7b2333a4103c6ac71fc50a3e4d4918f01fc38 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 15 May 2024 19:44:39 +0800 Subject: [PATCH 279/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E8=81=8A=E5=A4=A9=E5=AF=B9=E8=AF=9D=E7=9A=84=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/AiChatConversationController.java | 22 ++++---- .../AiChatConversationRespVO.java | 13 ++--- .../AiChatConversationUpdateMyReqVO.java | 3 ++ .../model/vo/chatRole/AiChatRoleRespVO.java | 5 +- .../vo/chatRole/AiChatRoleSaveMyReqVO.java | 8 +-- .../vo/chatRole/AiChatRoleSaveReqVO.java | 8 +-- .../ai/convert/AiChatConversationConvert.java | 39 -------------- .../dataobject/chat/AiChatConversationDO.java | 4 ++ .../ai/dal/dataobject/model/AiChatRoleDO.java | 6 +-- .../chat/AiChatConversationService.java | 17 ++++--- .../chat/AiChatConversationServiceImpl.java | 51 +++++++++---------- .../ai/service/impl/AiChatServiceImpl.java | 8 +-- .../src/main/resources/http/chat-role.http | 2 - 13 files changed, 67 insertions(+), 119 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java index dcfe8d386..6838fcf5b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.ai.controller.admin.chat; +import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateMyReqVO; @@ -49,20 +50,23 @@ public class AiChatConversationController { return success(BeanUtils.toBean(list, AiChatConversationRespVO.class)); } - // TODO @fan:实现一下 - @GetMapping("/get") - @Operation(summary = "获得聊天会话") + @GetMapping("/get-my") + @Operation(summary = "获得【我的】聊天会话") @Parameter(name = "id", required = true, description = "会话编号", example = "1024") - public CommonResult getConversation(@RequestParam("id") Long id) { - return success(chatConversationService.getConversationOfValidate(id)); + public CommonResult getChatConversationMy(@RequestParam("id") Long id) { + AiChatConversationDO conversation = chatConversationService.getChatConversation(id); + if (conversation != null && ObjUtil.notEqual(conversation.getUserId(), getLoginUserId())) { + conversation = null; + } + return success(BeanUtils.toBean(conversation, AiChatConversationRespVO.class)); } - // TODO @fan:实现一下 - @DeleteMapping("/delete") + @DeleteMapping("/delete-my") @Operation(summary = "删除聊天会话") @Parameter(name = "id", required = true, description = "会话编号", example = "1024") - public CommonResult deleteConversation(@RequestParam("id") Long id) { - return success(chatConversationService.deleteConversation(id)); + public CommonResult deleteChatConversationMy(@RequestParam("id") Long id) { + chatConversationService.deleteChatConversationMy(id, getLoginUserId()); + return success(true); } // ========== 会话管理 ========== diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java index 42c244e19..60e45eabd 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java @@ -32,13 +32,14 @@ public class AiChatConversationRespVO implements VO { private Long roleId; @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @Trans(type = TransType.SIMPLE, target = AiChatModelDO.class, fields = {"maxTokens", "maxContexts"}, - refs = {"modelMaxTokens", "modelMaxContexts"}) private Long modelId; @Schema(description = "模型标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "ERNIE-Bot-turbo-0922") private String model; + @Schema(description = "角色设定", example = "一个快乐的程序员") + private String systemMessage; + @Schema(description = "温度参数", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.8") private Double temperature; @@ -53,12 +54,4 @@ public class AiChatConversationRespVO implements VO { @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") private String roleAvatar; - // ========== 关联 model 信息 ========== - - @Schema(description = "模型的单条回复的最大 Token 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096") - private Integer modelMaxTokens; - - @Schema(description = "模型的上下文的最大 Message 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Integer modelMaxContexts; - } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateMyReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateMyReqVO.java index 4eb5a06c3..36e95d298 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateMyReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateMyReqVO.java @@ -21,6 +21,9 @@ public class AiChatConversationUpdateMyReqVO { @Schema(description = "模型编号", example = "1") private Long modelId; + @Schema(description = "角色设定", example = "一个快乐的程序员") + private String systemMessage; + @Schema(description = "温度参数", example = "0.8") private Double temperature; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java index 3adef6b25..eb34da274 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java @@ -42,10 +42,7 @@ public class AiChatRoleRespVO implements VO { @Schema(description = "角色描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对") private String description; - @Schema(description = "角色欢迎语", requiredMode = Schema.RequiredMode.REQUIRED) - private String welcomeMessage; - - @Schema(description = "角色上下文", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "角色设定", requiredMode = Schema.RequiredMode.REQUIRED) private String systemMessage; @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java index 3c5641f08..4673901d3 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java @@ -25,12 +25,8 @@ public class AiChatRoleSaveMyReqVO { @NotEmpty(message = "角色描述不能为空") private String description; - @Schema(description = "角色欢迎语", requiredMode = Schema.RequiredMode.REQUIRED, example = "Talk is cheap, i will show code") - @NotEmpty(message = "角色欢迎语不能为空") - private String welcomeMessage; - - @Schema(description = "角色上下文", requiredMode = Schema.RequiredMode.REQUIRED, example = "现在开始你扮演一位程序员,你是一名优秀的程序员,具有很强的逻辑思维能力,总能高效的解决问题") - @NotEmpty(message = "角色上下文不能为空") + @Schema(description = "角色设定", requiredMode = Schema.RequiredMode.REQUIRED, example = "现在开始你扮演一位程序员,你是一名优秀的程序员,具有很强的逻辑思维能力,总能高效的解决问题") + @NotEmpty(message = "角色设定不能为空") private String systemMessage; } \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveReqVO.java index 1dc62947b..bdda027ef 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveReqVO.java @@ -38,12 +38,8 @@ public class AiChatRoleSaveReqVO { @NotEmpty(message = "角色描述不能为空") private String description; - @Schema(description = "角色欢迎语", requiredMode = Schema.RequiredMode.REQUIRED, example = "Talk is cheap, i will show code") - @NotEmpty(message = "角色欢迎语不能为空") - private String welcomeMessage; - - @Schema(description = "角色上下文", requiredMode = Schema.RequiredMode.REQUIRED, example = "现在开始你扮演一位程序员,你是一名优秀的程序员,具有很强的逻辑思维能力,总能高效的解决问题") - @NotEmpty(message = "角色上下文不能为空") + @Schema(description = "角色设定", requiredMode = Schema.RequiredMode.REQUIRED, example = "现在开始你扮演一位程序员,你是一名优秀的程序员,具有很强的逻辑思维能力,总能高效的解决问题") + @NotEmpty(message = "角色设定不能为空") private String systemMessage; @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java deleted file mode 100644 index 7e1350617..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatConversationConvert.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.iocoder.yudao.module.ai.convert; - -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateMyReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * 聊天 对话 convert - * - * @author fansili - * @time 2024/4/18 16:39 - * @since 1.0 - */ -@Mapper -public interface AiChatConversationConvert { - - AiChatConversationConvert INSTANCE = Mappers.getMapper(AiChatConversationConvert.class); - - /** - * 转换 - 多个 ChatConversationRes - * - * @param top100Conversation - * @return - */ - List covnertChatConversationResList(List top100Conversation); - - /** - * 转换 - 单个 ChatConversationRes - * - * @param aiChatConversationDO - * @return - */ - AiChatConversationRespVO covnertChatConversationRes(AiChatConversationDO aiChatConversationDO); - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java index 547387055..b92e66143 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java @@ -81,6 +81,10 @@ public class AiChatConversationDO extends BaseDO { // ========== 会话配置 ========== + /** + * 角色设定 + */ + private String systemMessage; /** * 温度参数 * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java index 1b33199d4..28f6cda43 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java @@ -42,11 +42,7 @@ public class AiChatRoleDO extends BaseDO { */ private String description; /** - * 角色欢迎语 - */ - private String welcomeMessage; - /** - * 角色上下文 + * 角色设定 */ private String systemMessage; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java index 626f7996b..a17b173e5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.ai.service.chat; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateMyReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateMyReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; @@ -40,19 +39,20 @@ public interface AiChatConversationService { List getChatConversationListByUserId(Long userId); /** - * 获取 - 对话 + * 获得聊天会话 * - * @param id - * @return + * @param id 编号 + * @return 聊天会话 */ - AiChatConversationRespVO getConversationOfValidate(Long id); + AiChatConversationDO getChatConversation(Long id); /** - * 删除 - 根据id + * 删除【我的】聊天会话 * - * @param id + * @param id 编号 + * @param userId 用户编号 */ - Boolean deleteConversation(Long id); + void deleteChatConversationMy(Long id, Long userId); /** * 校验 - 是否存在 @@ -61,4 +61,5 @@ public interface AiChatConversationService { * @return */ AiChatConversationDO validateExists(Long id); + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java index 41cbf329c..f209a700f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java @@ -4,11 +4,9 @@ import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateMyReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateMyReqVO; -import cn.iocoder.yudao.module.ai.convert.AiChatConversationConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; @@ -59,7 +57,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService // 2. 创建 AiChatConversationDO 聊天对话 AiChatConversationDO conversation = new AiChatConversationDO() .setUserId(userId).setTitle(AiChatConversationDO.TITLE_DEFAULT).setPinned(false) - .setRoleId(role.getId()).setModelId(model.getId()).setModel(model.getModel()) + .setRoleId(role.getId()).setModelId(model.getId()).setModel(model.getModel()).setSystemMessage(role.getSystemMessage()) .setTemperature(model.getTemperature()).setMaxTokens(model.getMaxTokens()).setMaxContexts(model.getMaxContexts()); chatConversationMapper.insert(conversation); return conversation.getId(); @@ -73,24 +71,19 @@ public class AiChatConversationServiceImpl implements AiChatConversationService throw exception(CHAT_CONVERSATION_NOT_EXISTS); } // 1.2 校验模型是否存在(修改模型的情况) - if (!ObjectUtil.isAllEmpty(updateReqVO.getModelId(), updateReqVO.getMaxTokens(), updateReqVO.getMaxContexts())) { - AiChatModelDO model = chatModalService.validateChatModel(updateReqVO.getModelId()); - Assert.notNull(model, "必须找到默认模型"); - validateChatModel(model); - // 校验 Token 数量、上下文数量 - if (updateReqVO.getMaxTokens() != null && updateReqVO.getMaxTokens() > model.getMaxTokens()) { - throw exception(CHAT_CONVERSATION_UPDATE_MAX_TOKENS_ERROR); - } - if (updateReqVO.getMaxContexts() != null && updateReqVO.getMaxContexts() > model.getMaxContexts()) { - throw exception(CHAT_CONVERSATION_UPDATE_MAX_CONTEXTS_ERROR); - } + AiChatModelDO model = null; + if (updateReqVO.getModelId() != null) { + model = chatModalService.validateChatModel(updateReqVO.getModelId()); } - // 更新对话信息 + // 2. 更新对话信息 AiChatConversationDO updateObj = BeanUtils.toBean(updateReqVO, AiChatConversationDO.class); if (Boolean.TRUE.equals(updateReqVO.getPinned())) { updateObj.setPinnedTime(LocalDateTime.now()); } + if (model != null) { + updateObj.setModel(model.getModel()); + } chatConversationMapper.updateById(updateObj); } @@ -99,6 +92,23 @@ public class AiChatConversationServiceImpl implements AiChatConversationService return chatConversationMapper.selectListByUserId(userId); } + @Override + public AiChatConversationDO getChatConversation(Long id) { + return chatConversationMapper.selectById(id); + } + + @Override + public void deleteChatConversationMy(Long id, Long userId) { + // 1. 校验对话是否存在 + AiChatConversationDO conversation = validateExists(id); + if (ObjUtil.notEqual(conversation.getUserId(), userId)) { + throw exception(CHAT_CONVERSATION_NOT_EXISTS); + } + + // 2. 执行删除 + chatConversationMapper.deleteById(id); + } + private void validateChatModel(AiChatModelDO model) { if (ObjectUtil.isAllNotEmpty(model.getTemperature(), model.getMaxTokens(), model.getMaxContexts())) { return; @@ -106,17 +116,6 @@ public class AiChatConversationServiceImpl implements AiChatConversationService throw exception(CHAT_CONVERSATION_MODEL_ERROR); } - @Override - public AiChatConversationRespVO getConversationOfValidate(Long id) { - AiChatConversationDO aiChatConversationDO = validateExists(id); - return AiChatConversationConvert.INSTANCE.covnertChatConversationRes(aiChatConversationDO); - } - - @Override - public Boolean deleteConversation(Long id) { - return chatConversationMapper.deleteById(id) > 0; - } - public AiChatConversationDO validateExists(Long id) { AiChatConversationDO conversation = chatConversationMapper.selectById(id); if (conversation == null) { diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index a73531ddd..4642c648d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.service.impl; import cn.hutool.core.exceptions.ExceptionUtil; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import org.springframework.ai.chat.ChatClient; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.StreamingChatClient; @@ -54,7 +55,6 @@ public class AiChatServiceImpl implements AiChatService { private final AiChatClientFactory aiChatClientFactory; private final AiChatMessageMapper aiChatMessageMapper; - private final AiChatConversationMapper aiChatConversationMapper; private final AiChatConversationService chatConversationService; private final AiChatModelService aiChatModalService; private final AiChatRoleService chatRoleService; @@ -63,7 +63,7 @@ public class AiChatServiceImpl implements AiChatService { public AiChatMessageRespVO chat(AiChatMessageSendReqVO req) { Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 查询对话 - AiChatConversationRespVO conversation = chatConversationService.getConversationOfValidate(req.getConversationId()); + AiChatConversationDO conversation = chatConversationService.validateExists(req.getConversationId()); // 获取对话模型 AiChatModelDO chatModel = aiChatModalService.validateChatModel(conversation.getModelId()); // 获取角色信息 @@ -130,7 +130,7 @@ public class AiChatServiceImpl implements AiChatService { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CHAT_MESSAGE_NOT_EXIST); } // 查询对话 - AiChatConversationRespVO conversation = chatConversationService.getConversationOfValidate(aiChatMessageDO.getConversationId()); + AiChatConversationDO conversation = chatConversationService.validateExists(aiChatMessageDO.getConversationId()); // 获取对话模型 AiChatModelDO chatModel = aiChatModalService.validateChatModel(conversation.getModelId()); // 获取角色信息 @@ -188,7 +188,7 @@ public class AiChatServiceImpl implements AiChatService { public AiChatMessageRespVO add(AiChatMessageAddReqVO req) { Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 查询对话 - AiChatConversationRespVO conversation = chatConversationService.getConversationOfValidate(req.getConversationId()); + AiChatConversationDO conversation = chatConversationService.validateExists(req.getConversationId()); // 获取对话模型 AiChatModelDO chatModel = aiChatModalService.validateChatModel(conversation.getModelId()); AiChatMessageDO userMessage = insertChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(), diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http index 87502e313..d31e00f81 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-role.http @@ -14,7 +14,6 @@ Authorization: {{token}} "avatar": "http://baidu.com", "category": "writing", "description": "采用gpt3.5模型,拥有小红书优质作者写作经验。", - "welcomeMessage": "欢迎使用小红书写作模型!", "systemMessage": "你是一名优秀的小红书人文、风光作者,你热爱旅游,每去往一个城市你都会用美妙的文字抒写着这座城市的大街小巷,描述着这座城市的美好。", "publicStatus": 0, "sort": 0 @@ -33,7 +32,6 @@ Authorization: {{token}} "avatar": "http://baidu.com", "category": "writing", "description": "采用gpt3.5模型,拥有小红书优质作者写作经验。", - "welcomeMessage": "欢迎使用小红书写作模型!", "systemMessage": "你是一名优秀的小红书人文、风光作者,你热爱旅游,每去往一个城市你都会用美妙的文字抒写着这座城市的大街小巷,描述着这座城市的美好。", "publicStatus": 0, "sort": 0, From 20657ccaf36b1b261447d1d5d77435df743e7760 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 15 May 2024 21:20:18 +0800 Subject: [PATCH 280/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E8=81=8A=E5=A4=A9=E5=AF=B9=E8=AF=9D=E7=9A=84=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/admin/chat/AiChatMessageController.java | 5 +---- .../admin/chat/vo/conversation/AiChatConversationRespVO.java | 4 ++++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java index 7a6c1bc12..a89381ff4 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java @@ -18,24 +18,21 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -// TODO @芋艿:权限标识; @Tag(name = "管理后台 - 聊天消息") @RestController @RequestMapping("/ai/chat/message") @Slf4j public class AiChatMessageController { + @Resource private AiChatService chatService; @Operation(summary = "发送消息(段式)", description = "一次性返回,响应较慢") @PostMapping("/send") public CommonResult sendMessage(@Validated @RequestBody AiChatMessageSendReqVO sendReqVO) { - // TODO done @fan:使用 static import;这样就 success 就行了; return success(chatService.chat(sendReqVO)); } - // TODO @芋艿:调用这个方法异常,Unable to handle the Spring Security Exception because the response is already committed.;可以再试试 - // TODO @fan:要不要使用 Flux 来返回;可以使用 Flux @Operation(summary = "发送消息(流式)", description = "流式返回,响应较快") @PostMapping(value = "/send-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) @PermitAll // 解决 SSE 最终响应的时候,会被 Access Denied 拦截的问题 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java index 60e45eabd..214cf21d9 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java @@ -32,11 +32,15 @@ public class AiChatConversationRespVO implements VO { private Long roleId; @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @Trans(type = TransType.SIMPLE, target = AiChatModelDO.class, fields = "name", ref = "modelName") private Long modelId; @Schema(description = "模型标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "ERNIE-Bot-turbo-0922") private String model; + @Schema(description = "模型名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + private String modelName; + @Schema(description = "角色设定", example = "一个快乐的程序员") private String systemMessage; From b31e919d5235362a66e5a9bf7716b7a0990ad124 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 15 May 2024 23:06:18 +0800 Subject: [PATCH 281/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E6=B5=81=E5=BC=8F=E5=8F=91=E9=80=81=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E7=9A=84=E5=BE=AE=E8=B0=83=EF=BC=8C=E7=BB=9F=E4=B8=80=E6=88=90?= =?UTF-8?q?=E5=8D=95=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/chat/AiChatMessageController.http} | 6 +- .../admin/chat/AiChatMessageController.java | 11 +- .../chat/vo/message/AiChatMessageRespVO.java | 1 + .../vo/message/AiChatMessageSendRespVO.java | 36 +++++ .../message/AiChatMessageSendStreamReqVO.java | 16 -- .../ai/convert/AiChatMessageConvert.java | 8 - .../module/ai/service/AiChatService.java | 25 ++- .../ai/service/impl/AiChatServiceImpl.java | 152 ++++++++---------- .../ai/models/yiyan/YiYanChatClient.java | 5 +- 9 files changed, 124 insertions(+), 136 deletions(-) rename yudao-module-ai/yudao-module-ai-biz/src/main/{resources/http/chat-message.http => java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.http} (82%) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendStreamReqVO.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-message.http b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.http similarity index 82% rename from yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-message.http rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.http index b357ab66e..2d417a55f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat-message.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.http @@ -10,13 +10,13 @@ Authorization: {{token}} } -### chat call -POST {{baseUrl}}/admin-api/ai/chat/message/send-stream +### 发送消息(流式) +POST {{baseUrl}}/ai/chat/message/send-stream Content-Type: application/json Authorization: {{token}} { - "conversationId": "1781604279872581649", + "conversationId": "1781604279872581651", "content": "苹果是什么颜色?" } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java index a89381ff4..47f35f4ea 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java @@ -17,6 +17,7 @@ import reactor.core.publisher.Flux; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @Tag(name = "管理后台 - 聊天消息") @RestController @@ -36,14 +37,8 @@ public class AiChatMessageController { @Operation(summary = "发送消息(流式)", description = "流式返回,响应较快") @PostMapping(value = "/send-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) @PermitAll // 解决 SSE 最终响应的时候,会被 Access Denied 拦截的问题 - public Flux sendMessageStream(@Validated @RequestBody AiChatMessageSendStreamReqVO sendReqVO) { - return chatService.chatStream(sendReqVO); - } - - @Operation(summary = "添加/提问", description = "先创建好 message 前端才好渲染") - @PostMapping(value = "/add") - public CommonResult add(@Validated @RequestBody AiChatMessageAddReqVO req) { - return success(chatService.add(req)); + public Flux sendChatMessageStream(@Validated @RequestBody AiChatMessageSendReqVO sendReqVO) { + return chatService.sendChatMessageStream(sendReqVO, getLoginUserId()); } @Operation(summary = "获得指定会话的消息列表") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java index f117c67c6..c4863c735 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java @@ -44,4 +44,5 @@ public class AiChatMessageRespVO { @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-05-12 12:51") private LocalDateTime createTime; + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java new file mode 100644 index 000000000..9ea7900cb --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - AI 聊天消息发送 Response VO") +@Data +public class AiChatMessageSendRespVO { + + @Schema(description = "发送消息", requiredMode = Schema.RequiredMode.REQUIRED) + private Message send; + + @Schema(description = "接收消息", requiredMode = Schema.RequiredMode.REQUIRED) + private Message receive; + + @Schema(description = "消息") + @Data + public static class Message { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "role") + private String type; // 参见 MessageType 枚举类 + + @Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,你好啊") + private String content; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-05-12 12:51") + private LocalDateTime createTime; + + } + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendStreamReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendStreamReqVO.java deleted file mode 100644 index cfd67ccba..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendStreamReqVO.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 聊天消息发送 Request VO") -@Data -public class AiChatMessageSendStreamReqVO { - - @Schema(description = "提问的 messageId", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "提问的 messageId 不能为空") - private Long id; - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java index 05f7b83b6..eda556358 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java @@ -27,12 +27,4 @@ public interface AiChatMessageConvert { */ List convertAiChatMessageRespVOList(List aiChatMessageDOList); - /** - * 转换 - aiChatMessageDO - * - * @param aiChatMessageDO - * @return - */ - AiChatMessageRespVO convertAiChatMessageRespVO(AiChatMessageDO aiChatMessageDO); - } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java index 7be2b8afc..57d848eea 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java @@ -22,22 +22,6 @@ public interface AiChatService { */ AiChatMessageRespVO chat(AiChatMessageSendReqVO sendReqVO); - /** - * chat stream - * - * @param sendReqVO - * @return - */ - Flux chatStream(AiChatMessageSendStreamReqVO sendReqVO); - - /** - * 添加 - message - * - * @param sendReqVO - * @return - */ - AiChatMessageRespVO add(AiChatMessageAddReqVO sendReqVO); - /** * 获取 - 获取对话 message list * @@ -54,4 +38,13 @@ public interface AiChatService { */ Boolean deleteMessage(Long id); + /** + * 发送消息 + * + * @param sendReqVO + * @param userId + * @return + */ + Flux sendChatMessageStream(AiChatMessageSendReqVO sendReqVO, Long userId); + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index 4642c648d..1ab160bfc 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -1,27 +1,24 @@ package cn.iocoder.yudao.module.ai.service.impl; import cn.hutool.core.exceptions.ExceptionUtil; +import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import org.springframework.ai.chat.ChatClient; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.StreamingChatClient; import org.springframework.ai.chat.messages.MessageType; +import org.springframework.ai.chat.prompt.ChatOptionsBuilder; import org.springframework.ai.chat.prompt.Prompt; -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; -import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.config.AiChatClientFactory; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageAddReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendStreamReqVO; import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatConversationMapper; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatMessageMapper; import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService; import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; @@ -33,13 +30,16 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import reactor.core.publisher.Flux; +import java.time.LocalDateTime; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; import java.util.stream.Collectors; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_CONVERSATION_NOT_EXISTS; + /** * 聊天 service * @@ -52,11 +52,11 @@ import java.util.stream.Collectors; @AllArgsConstructor public class AiChatServiceImpl implements AiChatService { - private final AiChatClientFactory aiChatClientFactory; + private final AiChatClientFactory chatClientFactory; private final AiChatMessageMapper aiChatMessageMapper; private final AiChatConversationService chatConversationService; - private final AiChatModelService aiChatModalService; + private final AiChatModelService chatModalService; private final AiChatRoleService chatRoleService; @Transactional(rollbackFor = Exception.class) @@ -65,7 +65,7 @@ public class AiChatServiceImpl implements AiChatService { // 查询对话 AiChatConversationDO conversation = chatConversationService.validateExists(req.getConversationId()); // 获取对话模型 - AiChatModelDO chatModel = aiChatModalService.validateChatModel(conversation.getModelId()); + AiChatModelDO chatModel = chatModalService.validateChatModel(conversation.getModelId()); // 获取角色信息 AiChatRoleDO chatRoleDO = conversation.getRoleId() != null ? chatRoleService.validateChatRole(conversation.getRoleId()) : null; // 获取 client 类型 @@ -84,7 +84,7 @@ public class AiChatServiceImpl implements AiChatService { // req.setTopP(req.getTopP()); // req.setTemperature(req.getTemperature()); // 发送 call 调用 - ChatClient chatClient = aiChatClientFactory.getChatClient(platformEnum); + ChatClient chatClient = chatClientFactory.getChatClient(platformEnum); ChatResponse call = chatClient.call(prompt); content = call.getResult().getOutput().getContent(); tokens = call.getResults().size(); @@ -113,88 +113,72 @@ public class AiChatServiceImpl implements AiChatService { .setModelId(modelId) .setContent(content) .setTokens(tokens) - .setTemperature(temperature) .setMaxTokens(maxTokens) .setMaxContexts(maxContexts); + insertChatMessageDO.setCreateTime(LocalDateTime.now()); // 增加 chat message 记录 aiChatMessageMapper.insert(insertChatMessageDO); return insertChatMessageDO; } - public Flux chatStream(AiChatMessageSendStreamReqVO req) { - Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); - // 查询提问的 message - AiChatMessageDO aiChatMessageDO = aiChatMessageMapper.selectById(req.getId()); - if (aiChatMessageDO == null) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CHAT_MESSAGE_NOT_EXIST); - } - // 查询对话 - AiChatConversationDO conversation = chatConversationService.validateExists(aiChatMessageDO.getConversationId()); - // 获取对话模型 - AiChatModelDO chatModel = aiChatModalService.validateChatModel(conversation.getModelId()); - // 获取角色信息 - AiChatRoleDO chatRoleDO = conversation.getRoleId() != null ? chatRoleService.validateChatRole(conversation.getRoleId()) : null; - // 创建 chat 需要的 Prompt - Prompt prompt = new Prompt(aiChatMessageDO.getContent()); - // 提前创建一个 system message - AiChatMessageDO systemMessage = insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), - chatModel.getModel(), chatModel.getId(), "", - 0, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); -// req.setTopK(req.getTopK()); -// req.setTopP(req.getTopP()); -// req.setTemperature(req.getTemperature()); - // 获取 client 类型 - AiPlatformEnum platformEnum = AiPlatformEnum.validatePlatform(chatModel.getPlatform()); - StreamingChatClient streamingChatClient = aiChatClientFactory.getStreamingChatClient(platformEnum); - Flux streamResponse = streamingChatClient.stream(prompt); - // 转换 flex AiChatMessageRespVO - StringBuffer contentBuffer = new StringBuffer(); - AtomicInteger tokens = new AtomicInteger(0); - return streamResponse.map(res -> { - AiChatMessageRespVO aiChatMessageRespVO = - AiChatMessageConvert.INSTANCE.convertAiChatMessageRespVO(systemMessage); - aiChatMessageRespVO.setContent(res.getResult().getOutput().getContent()); - contentBuffer.append(res.getResult().getOutput().getContent()); - tokens.incrementAndGet(); - return aiChatMessageRespVO; - } - ).doOnComplete(new Runnable() { - @Override - public void run() { - log.info("发送完成!"); - // 保存 chat message - aiChatMessageMapper.updateById(new AiChatMessageDO() - .setId(systemMessage.getId()) - .setContent(contentBuffer.toString()) - .setTokens(tokens.get()) - ); - } - }).doOnError(new Consumer() { - @Override - public void accept(Throwable throwable) { - log.error("发送错误 {}!", throwable.getMessage()); - // 更新错误信息 - aiChatMessageMapper.updateById(new AiChatMessageDO() - .setId(systemMessage.getId()) - .setContent(throwable.getMessage()) - .setTokens(tokens.get()) - ); - } - }); - } - @Override - public AiChatMessageRespVO add(AiChatMessageAddReqVO req) { - Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); - // 查询对话 - AiChatConversationDO conversation = chatConversationService.validateExists(req.getConversationId()); - // 获取对话模型 - AiChatModelDO chatModel = aiChatModalService.validateChatModel(conversation.getModelId()); - AiChatMessageDO userMessage = insertChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(), - chatModel.getModel(), chatModel.getId(), req.getContent(), + public Flux sendChatMessageStream(AiChatMessageSendReqVO sendReqVO, Long userId) { + // 1.1 校验对话存在 + AiChatConversationDO conversation = chatConversationService.validateExists(sendReqVO.getConversationId()); + if (ObjUtil.notEqual(conversation.getUserId(), userId)) { + throw exception(CHAT_CONVERSATION_NOT_EXISTS); + } + // 1.2 校验模型 + AiChatModelDO model = chatModalService.validateChatModel(conversation.getModelId()); + AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); + StreamingChatClient chatClient = chatClientFactory.getStreamingChatClient(platform); + + // 2. 插入 user 发送消息 TODO tokens 计算 + AiChatMessageDO userMessage = insertChatMessage(conversation.getId(), MessageType.USER, userId, conversation.getRoleId(), + conversation.getModel(), conversation.getId(), sendReqVO.getContent(), null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); - return AiChatMessageConvert.INSTANCE.convertAiChatMessageRespVO(userMessage); + + // 3.1 插入 system 接收消息 + AiChatMessageDO systemMessage = insertChatMessage(conversation.getId(), MessageType.SYSTEM, userId, conversation.getRoleId(), + conversation.getModel(), conversation.getId(), conversation.getSystemMessage(), + 0, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); + // 3.2 创建 chat 需要的 Prompt + // TODO 消息上下文 + Prompt prompt = new Prompt(sendReqVO.getContent()); +// ChatOptionsBuilder.builder().withTemperature(conversation.getTemperature().floatValue()).build() + Flux streamResponse = chatClient.stream(prompt); + // 3.3 转换 flex AiChatMessageRespVO + StringBuffer contentBuffer = new StringBuffer(); + AtomicInteger tokens = new AtomicInteger(0); // TODO token 计算不对; + return streamResponse.map(res -> { + contentBuffer.append(res.getResult().getOutput().getContent()); + tokens.incrementAndGet(); + + AiChatMessageSendRespVO.Message send = new AiChatMessageSendRespVO.Message().setId(userMessage.getId()) + .setType(MessageType.USER.getValue()).setCreateTime(userMessage.getCreateTime()) + .setContent(sendReqVO.getContent()); + AiChatMessageSendRespVO.Message receive = new AiChatMessageSendRespVO.Message().setId(systemMessage.getId()) + .setType(MessageType.SYSTEM.getValue()).setCreateTime(systemMessage.getCreateTime()) + .setContent(res.getResult().getOutput().getContent()); + return new AiChatMessageSendRespVO().setSend(send).setReceive(receive); + }).doOnComplete(() -> { + log.info("发送完成!"); + // 保存 chat message + aiChatMessageMapper.updateById(new AiChatMessageDO() + .setId(systemMessage.getId()) + .setContent(contentBuffer.toString()) + .setTokens(tokens.get()) + ); + }).doOnError(throwable -> { + log.error("发送错误 {}!", throwable.getMessage()); + // 更新错误信息 TODO 貌似不应该更新异常 + aiChatMessageMapper.updateById(new AiChatMessageDO() + .setId(systemMessage.getId()) + .setContent(throwable.getMessage()) + .setTokens(tokens.get()) + ); + }); } @Override @@ -205,7 +189,7 @@ public class AiChatServiceImpl implements AiChatService { List aiChatMessageDOList = aiChatMessageMapper.selectByConversationId(conversationId); // 获取模型信息 Set modalIds = aiChatMessageDOList.stream().map(AiChatMessageDO::getModelId).collect(Collectors.toSet()); - List modalList = aiChatModalService.getModalByIds(modalIds); + List modalList = chatModalService.getModalByIds(modalIds); Map modalIdMap = modalList.stream().collect(Collectors.toMap(AiChatModelDO::getId, o -> o)); // 转换 AiChatMessageRespVO List aiChatMessageRespList = AiChatMessageConvert.INSTANCE.convertAiChatMessageRespVOList(aiChatMessageDOList); diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatClient.java index 819976629..5d1dd4f76 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatClient.java @@ -94,7 +94,10 @@ public class YiYanChatClient implements ChatClient, StreamingChatClient { String a = ";"; } }); - return response.map(res -> new ChatResponse(List.of(new Generation(res.getResult())))); + return response.map(res -> { + // TODO @fan:这里缺少了 usage 的封装 + return new ChatResponse(List.of(new Generation(res.getResult()))); + }); } private YiYanChatCompletionRequest createRequest(Prompt prompt, boolean stream) { From e6fefa06b7463582bd8f981c24364e2ef3fccf67 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 15 May 2024 23:13:54 +0800 Subject: [PATCH 282/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91AI?= =?UTF-8?q?=20=E8=A7=92=E8=89=B2=E5=88=86=E7=B1=BB=E5=A4=84=E7=90=86?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E8=A7=92=E8=89=B2=EF=BC=8C=E4=B8=BA=E7=A9=BA?= =?UTF-8?q?=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/service/model/AiChatRoleServiceImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java index 196f1a6ac..4372003d0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java @@ -14,6 +14,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @@ -132,7 +134,7 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { @Override public List getChatRoleCategoryList() { List list = chatRoleMapper.selectListGroupByCategory(CommonStatusEnum.ENABLE.getStatus()); - return convertList(list, AiChatRoleDO::getCategory); + return convertList(list.stream().filter(Objects::nonNull).collect(Collectors.toList()), AiChatRoleDO::getCategory); } } From e7a3f47d0268737c6713928957285e09542d0c20 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 16 May 2024 11:28:53 +0800 Subject: [PATCH 283/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91AI?= =?UTF-8?q?=20=E5=AF=B9=E8=AF=9D=E5=A2=9E=E5=8A=A0=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/vo/conversation/AiChatConversationRespVO.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java index 214cf21d9..78cd71365 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java @@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelRespVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; import com.fhs.core.trans.anno.Trans; import com.fhs.core.trans.constant.TransType; import com.fhs.core.trans.vo.VO; @@ -11,6 +13,9 @@ import jakarta.validation.constraints.NotNull; import lombok.Data; import lombok.experimental.Accessors; +import java.time.LocalDateTime; +import java.time.LocalTime; + @Schema(description = "管理后台 - AI 聊天会话 Response VO") @Data public class AiChatConversationRespVO implements VO { @@ -53,6 +58,9 @@ public class AiChatConversationRespVO implements VO { @Schema(description = "上下文的最大 Message 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") private Integer maxContexts; + @Schema(description = "最后更新时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-05-16") + private LocalDateTime updateTime; + // ========== 关联 role 信息 ========== @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") From fe63bda4c7afc96dabe9da560777b31089b7c984 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 16 May 2024 12:10:03 +0800 Subject: [PATCH 284/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91?= =?UTF-8?q?=E6=B8=85=E7=A9=BA=20Chat=20=E5=AF=B9=E8=AF=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/chat/AiChatConversationController.java | 7 +++++++ .../service/chat/AiChatConversationService.java | 6 ++++++ .../chat/AiChatConversationServiceImpl.java | 16 +++++++++++++--- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java index 6838fcf5b..9d0cd74c8 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java @@ -69,6 +69,13 @@ public class AiChatConversationController { return success(true); } + @DeleteMapping("/delete-my-all-except-pinned") + @Operation(summary = "删除所有对话(置顶除外)") + @Parameter(name = "id", required = true, description = "会话编号", example = "1024") + public CommonResult deleteMyAllExceptPinned() { + chatConversationService.deleteMyAllExceptPinned(getLoginUserId()); + return success(true); + } // ========== 会话管理 ========== } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java index a17b173e5..f93572e66 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java @@ -62,4 +62,10 @@ public interface AiChatConversationService { */ AiChatConversationDO validateExists(Long id); + /** + * 删除 - 所有对话,置顶除外 + * + * @param loginUserId + */ + void deleteMyAllExceptPinned(Long loginUserId); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java index f209a700f..85dd57afd 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java @@ -4,8 +4,8 @@ import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateMyReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateMyReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; @@ -21,8 +21,9 @@ import org.springframework.validation.annotation.Validated; import java.time.LocalDateTime; import java.util.List; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.*; -import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_CONVERSATION_MODEL_ERROR; +import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_CONVERSATION_NOT_EXISTS; /** * AI 聊天对话 Service 实现类 @@ -124,4 +125,13 @@ public class AiChatConversationServiceImpl implements AiChatConversationService return conversation; } + @Override + public void deleteMyAllExceptPinned(Long loginUserId) { + chatConversationMapper.delete( + new LambdaQueryWrapperX() + .eq(AiChatConversationDO::getUserId, loginUserId) + .eq(AiChatConversationDO::getPinned, false) + ); + } + } From 380ec112217a442b31172a527fb7f0c2ead7d428 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Thu, 16 May 2024 16:57:43 +0800 Subject: [PATCH 285/684] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=BE=AE=E4=BF=A1?= =?UTF-8?q?=E5=B0=8F=E7=A8=8B=E5=BA=8F=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/social/AppSocialUserController.java | 2 +- .../app/social/vo/AppSocialWxQrcodeReqVO.java | 37 ++++++------------ .../api/social/dto/SocialWxQrcodeReqDTO.java | 39 ++----------------- .../social/SocialClientServiceImpl.java | 7 ++-- 4 files changed, 20 insertions(+), 65 deletions(-) diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java index a07e6324f..6e3973525 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java @@ -70,7 +70,7 @@ public class AppSocialUserController { @Operation(summary = "获得微信小程序码(base64 image)") public CommonResult getWxQrcode(@RequestBody @Valid AppSocialWxQrcodeReqVO reqVO) { byte[] wxQrcode = socialClientApi.getWxaQrcode(BeanUtils.toBean(reqVO, SocialWxQrcodeReqDTO.class) - .setUserId(getLoginUserId()).setUserType(UserTypeEnum.MEMBER.getValue()).setSocialType(reqVO.getType())); + .setEnvVersion(AppSocialWxQrcodeReqVO.ENV_VERSION)); return success("data:image/png;base64," + Base64.getEncoder().encodeToString(wxQrcode)); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java index 6465b2384..10321519c 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java @@ -1,31 +1,25 @@ package cn.iocoder.yudao.module.member.controller.app.social.vo; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; import lombok.Data; -// TODO @芋艿:需要精简下参数; + @Schema(description = "用户 APP - 获得获取小程序码 Request VO") @Data public class AppSocialWxQrcodeReqVO { - // TODO @puhui999:这个后续不用前端传递,应该是后端搞的。 - // 页面路径不能携带参数(参数请放在scene字段里) - private static String SCENE = ""; // 默认场景值 1011 扫描二维码 - // TODO @puhui999:这个默认是不是 release 哈? - private static String ENV_VERSION = "develop"; // 小程序版本。正式版为 "release",体验版为 "trial",开发版为 "develop" - // TODO @puhui999:这个去掉;因为本身就是 430 啦; + // TODO @puhui999: 没有默认值 getQrcodeService().createWxaCodeUnlimitBytes() 转类型会报错 🤣 + public static String ENV_VERSION = "release"; // 小程序版本。正式版为 "release",体验版为 "trial",开发版为 "develop" + private static String SCENE = ""; // 页面路径不能携带参数(参数请放在scene字段里) private static Integer WIDTH = 430; // 二维码宽度 - // TODO @puhui999:这个去掉;因为本身就是 true 啦; private static Boolean AUTO_COLOR = true; // 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 - // TODO @puhui999:这个去掉;因为本身就是 true 啦; private static Boolean CHECK_PATH = true; // 默认true 检查 page 是否存在 - // TODO @puhui999:这个去掉;因为本身就是 true 啦; - private static Boolean IS_HYALINE = true; // 是否需要透明底色, is_hyaline 为true时,生成透明底色的小程序码 + private static Boolean HYALINE = true; // 是否需要透明底色, is_hyaline 为true时,生成透明底色的小程序码 + /** + * 页面路径不能携带参数(参数请放在scene字段里) + */ @Schema(description = "场景值", requiredMode = Schema.RequiredMode.REQUIRED, example = "1001") private String scene = SCENE; @@ -37,25 +31,16 @@ public class AppSocialWxQrcodeReqVO { @NotEmpty(message = "页面路径不能为空") private String path; - // TODO @puhui999:这个应该不传递哈 - @Schema(description = "小程序版本", requiredMode = Schema.RequiredMode.REQUIRED, example = "develop") - private String envVersion = ENV_VERSION; - @Schema(description = "二维码宽度", requiredMode = Schema.RequiredMode.REQUIRED, example = "430") private Integer width = WIDTH; @Schema(description = "是/否自动配置线条颜色", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - private Boolean isAutoColor = AUTO_COLOR; + private Boolean autoColor = AUTO_COLOR; @Schema(description = "是/否检查 page 是否存在", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - private Boolean isCheckPath = CHECK_PATH; + private Boolean checkPath = CHECK_PATH; @Schema(description = "是/否需要透明底色", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - private Boolean isHyaline = IS_HYALINE; - - @Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - @InEnum(SocialTypeEnum.class) - @NotNull(message = "社交平台的类型不能为空") - private Integer type; + private Boolean hyaline = HYALINE; } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialWxQrcodeReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialWxQrcodeReqDTO.java index d5e7f194f..efda43e81 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialWxQrcodeReqDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialWxQrcodeReqDTO.java @@ -1,42 +1,17 @@ package cn.iocoder.yudao.module.system.api.social.dto; -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; import lombok.Data; /** * 获取小程序码 Request DTO * - * @see 获取不限制的小程序码 - * * @author HUIHUI + * @see 获取不限制的小程序码 */ @Data public class SocialWxQrcodeReqDTO { - // TODO @puhui999:userId、userType 应该后续要搞成抽象参数;说白了,就是 path 的参数; socialType 应该去掉,因为就是微信的; - /** - * 用户编号 - */ - @NotNull(message = "用户编号不能为空") - private Long userId; - /** - * 用户类型 - */ - @InEnum(UserTypeEnum.class) - @NotNull(message = "用户类型不能为空") - private Integer userType; - - /** - * 社交平台的类型 - */ - @InEnum(SocialTypeEnum.class) - @NotNull(message = "社交平台的类型不能为空") - private Integer socialType; - /** * 场景 */ @@ -56,23 +31,17 @@ public class SocialWxQrcodeReqDTO { */ private Integer width; - // TODO @puhui999:autoColor - /** * 是否需要透明底色 */ - private Boolean isAutoColor; - - // TODO @puhui999: checkPath + private Boolean autoColor; /** * 是否检查 page 是否存在 */ - private Boolean isCheckPath; - - // TODO @puhui999: hyaline + private Boolean checkPath; /** * 是否需要透明底色 */ - private Boolean isHyaline; + private Boolean hyaline; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java index aeff40cce..41b27b171 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java @@ -9,6 +9,7 @@ import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ReflectUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.cache.CacheUtils; import cn.iocoder.yudao.framework.common.util.http.HttpUtils; @@ -230,11 +231,11 @@ public class SocialClientServiceImpl implements SocialClientService { @Override public byte[] getWxaQrcode(SocialWxQrcodeReqDTO reqVO) { - WxMaService service = getWxMaService(reqVO.getUserType()); + WxMaService service = getWxMaService(UserTypeEnum.MEMBER.getValue()); try { return service.getQrcodeService().createWxaCodeUnlimitBytes(reqVO.getScene(), reqVO.getPath(), - reqVO.getIsCheckPath(), reqVO.getEnvVersion(), reqVO.getWidth(), reqVO.getIsAutoColor(), - null, reqVO.getIsHyaline()); + reqVO.getCheckPath(), reqVO.getEnvVersion(), reqVO.getWidth(), reqVO.getAutoColor(), + null, reqVO.getHyaline()); } catch (WxErrorException e) { log.error("[getWxQrcode][reqVO({})) 获得小程序码失败]", reqVO, e); throw exception(SOCIAL_CLIENT_WEIXIN_MINI_APP_QRCODE_ERROR); From 7fca38ce1e270d8831b5ba426a2e82df6b009474 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 16 May 2024 22:42:39 +0800 Subject: [PATCH 286/684] =?UTF-8?q?=E3=80=90=E9=87=8D=E6=9E=84=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E6=9B=BF=E6=8D=A2=20spring-ai=20=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vo/message/AiChatMessageSendRespVO.java | 2 +- .../ai/dal/vo/AiChatModalDallConfigVO.java | 2 +- .../ai/service/impl/AiImageServiceImpl.java | 12 +- .../YuDaoMidjourneyMessageHandler.java | 2 +- .../yudao-spring-boot-starter-ai/pom.xml | 131 +----- .../ai/config/YudaoAiAutoConfiguration.java | 26 +- .../ai/config/YudaoAiProperties.java | 6 +- .../ai/core}/enums/OpenAiImageModelEnum.java | 3 +- .../ai/core}/enums/OpenAiImageStyleEnum.java | 3 +- .../ai/core/exception}/ChatException.java | 2 +- .../yudao/framework}/ai/package-info.java | 2 +- .../springframework/ai/chat/ChatClient.java | 36 -- .../springframework/ai/chat/ChatResponse.java | 118 ------ .../springframework/ai/chat/Generation.java | 86 ---- .../ai/chat/StreamingChatClient.java | 29 -- .../ai/chat/messages/AbstractMessage.java | 151 ------- .../ai/chat/messages/AssistantMessage.java | 47 --- .../ai/chat/messages/ChatMessage.java | 39 -- .../ai/chat/messages/FunctionMessage.java | 37 -- .../ai/chat/messages/MediaData.java | 46 --- .../ai/chat/messages/Message.java | 32 -- .../ai/chat/messages/MessageType.java | 52 --- .../ai/chat/messages/SystemMessage.java | 48 --- .../ai/chat/messages/UserMessage.java | 51 --- .../chat/metadata/ChatGenerationMetadata.java | 75 ---- .../chat/metadata/ChatResponseMetadata.java | 58 --- .../ai/chat/metadata/EmptyRateLimit.java | 59 --- .../ai/chat/metadata/EmptyUsage.java | 37 -- .../ai/chat/metadata/PromptMetadata.java | 136 ------ .../ai/chat/metadata/RateLimit.java | 84 ---- .../ai/chat/metadata/Usage.java | 66 --- .../springframework/ai/chat/package-info.java | 14 - .../chat/prompt/AssistantPromptTemplate.java | 55 --- .../ai/chat/prompt/ChatOptions.java | 40 -- .../ai/chat/prompt/ChatOptionsBuilder.java | 89 ---- .../ai/chat/prompt/ChatPromptTemplate.java | 87 ---- .../chat/prompt/FunctionPromptTemplate.java | 27 -- .../ai/chat/prompt/Prompt.java | 103 ----- .../ai/chat/prompt/PromptTemplate.java | 218 ---------- .../ai/chat/prompt/PromptTemplateActions.java | 34 -- .../prompt/PromptTemplateChatActions.java | 18 - .../prompt/PromptTemplateMessageActions.java | 24 -- .../prompt/PromptTemplateStringActions.java | 14 - .../ai/chat/prompt/SystemPromptTemplate.java | 55 --- .../ai/chat/prompt/TemplateFormat.java | 42 -- .../org/springframework/ai/image/Image.java | 77 ---- .../springframework/ai/image/ImageClient.java | 31 -- .../ai/image/ImageGeneration.java | 53 --- .../ai/image/ImageGenerationMetadata.java | 23 -- .../ai/image/ImageMessage.java | 63 --- .../ai/image/ImageOptions.java | 37 -- .../ai/image/ImageOptionsBuilder.java | 119 ------ .../springframework/ai/image/ImagePrompt.java | 85 ---- .../ai/image/ImageResponse.java | 75 ---- .../ai/image/ImageResponseMetadata.java | 31 -- .../springframework/ai/model/ModelClient.java | 40 -- .../ai/model/ModelOptions.java | 31 -- .../ai/model/ModelOptionsUtils.java | 387 ------------------ .../ai/model/ModelRequest.java | 51 --- .../ai/model/ModelResponse.java | 62 --- .../springframework/ai/model/ModelResult.java | 43 -- .../ai/model/ResponseMetadata.java | 34 -- .../ai/model/ResultMetadata.java | 31 -- .../ai/model/StreamingModelClient.java | 43 -- .../function/AbstractFunctionCallSupport.java | 163 -------- .../function/AbstractFunctionCallback.java | 159 ------- .../ai/model/function/FunctionCallback.java | 60 --- .../function/FunctionCallbackContext.java | 126 ------ .../function/FunctionCallbackWrapper.java | 140 ------- .../function/FunctionCallingOptions.java | 66 --- .../FunctionCallingOptionsBuilder.java | 150 ------- .../ai/model/function/TypeResolverHelper.java | 87 ---- .../ai/model/package-info.java | 11 - .../api/MidjourneyInteractionsApi.java | 4 +- .../ai/models/openai/OpenAiImageApi.java | 89 ---- .../ai/models/openai/OpenAiImageClient.java | 101 ----- .../ai/models/openai/OpenAiImageOptions.java | 95 ----- .../models/openai/api/OpenAiImageRequest.java | 58 --- .../openai/api/OpenAiImageResponse.java | 39 -- .../ai/models/tongyi/QianWenChatClient.java | 1 + .../ai/models/tongyi/QianWenOptions.java | 26 +- .../ai/models/xinghuo/XingHuoChatClient.java | 1 + .../ai/models/xinghuo/XingHuoOptions.java | 25 +- .../ai/models/yiyan/YiYanChatClient.java | 1 + .../ai/models/yiyan/YiYanOptions.java | 22 +- ...AbstractConversionServiceOutputParser.java | 42 -- .../AbstractMessageConverterOutputParser.java | 41 -- .../ai/parser/BeanOutputParser.java | 171 -------- .../ai/parser/FormatProvider.java | 33 -- .../ai/parser/ListOutputParser.java | 50 --- .../ai/parser/MapOutputParser.java | 60 --- .../ai/parser/OutputParser.java | 30 -- .../org/springframework/ai/parser/Parser.java | 24 -- .../org/springframework/ai/parser/README.md | 12 - .../ai/chat/QianWenChatClientTests.java | 4 +- .../openAiImage/OpenAiImageClientTests.java | 10 +- 96 files changed, 99 insertions(+), 5416 deletions(-) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models/openai => cn/iocoder/yudao/framework/ai/core}/enums/OpenAiImageModelEnum.java (89%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models/openai => cn/iocoder/yudao/framework/ai/core}/enums/OpenAiImageStyleEnum.java (92%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/chat => cn/iocoder/yudao/framework/ai/core/exception}/ChatException.java (78%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework => cn/iocoder/yudao/framework}/ai/package-info.java (95%) delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/ChatClient.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/ChatResponse.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/Generation.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/StreamingChatClient.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/AbstractMessage.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/AssistantMessage.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/ChatMessage.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/FunctionMessage.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/MediaData.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/Message.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/MessageType.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/SystemMessage.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/UserMessage.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/ChatGenerationMetadata.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/ChatResponseMetadata.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/EmptyRateLimit.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/EmptyUsage.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/PromptMetadata.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/RateLimit.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/Usage.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/package-info.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/AssistantPromptTemplate.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/ChatOptions.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/ChatOptionsBuilder.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/ChatPromptTemplate.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/FunctionPromptTemplate.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/Prompt.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplate.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateActions.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateChatActions.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateMessageActions.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateStringActions.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/SystemPromptTemplate.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/TemplateFormat.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/Image.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageClient.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageGeneration.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageGenerationMetadata.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageMessage.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageOptions.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageOptionsBuilder.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImagePrompt.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageResponse.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageResponseMetadata.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelClient.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelOptions.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelOptionsUtils.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelRequest.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelResponse.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelResult.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ResponseMetadata.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ResultMetadata.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/StreamingModelClient.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/AbstractFunctionCallSupport.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/AbstractFunctionCallback.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallback.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallbackContext.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallbackWrapper.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallingOptions.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallingOptionsBuilder.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/TypeResolverHelper.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/package-info.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/OpenAiImageApi.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/OpenAiImageClient.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/OpenAiImageOptions.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/api/OpenAiImageRequest.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/api/OpenAiImageResponse.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/AbstractConversionServiceOutputParser.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/AbstractMessageConverterOutputParser.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/BeanOutputParser.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/FormatProvider.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/ListOutputParser.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/MapOutputParser.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/OutputParser.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/Parser.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/README.md diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java index 9ea7900cb..58ba05659 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java @@ -28,7 +28,7 @@ public class AiChatMessageSendRespVO { @Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,你好啊") private String content; - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-05-12 12:51") + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalDallConfigVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalDallConfigVO.java index d77b4ec87..c828c9cf5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalDallConfigVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalDallConfigVO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.ai.dal.vo; -import org.springframework.ai.models.openai.enums.OpenAiImageStyleEnum; +import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageStyleEnum; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java index 4727127c9..20768c21e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java @@ -6,10 +6,8 @@ import cn.iocoder.yudao.framework.ai.core.exception.AiException; import org.springframework.ai.image.ImageGeneration; import org.springframework.ai.image.ImagePrompt; import org.springframework.ai.image.ImageResponse; -import org.springframework.ai.models.openai.OpenAiImageClient; -import org.springframework.ai.models.openai.OpenAiImageOptions; -import org.springframework.ai.models.openai.enums.OpenAiImageModelEnum; -import org.springframework.ai.models.openai.enums.OpenAiImageStyleEnum; +import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageModelEnum; +import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageStyleEnum; import org.springframework.ai.models.midjourney.api.MidjourneyInteractionsApi; import org.springframework.ai.models.midjourney.api.req.ReRollReq; import org.springframework.ai.models.midjourney.webSocket.MidjourneyWebSocketStarter; @@ -29,6 +27,8 @@ import cn.iocoder.yudao.module.ai.service.AiImageService; import jakarta.annotation.PostConstruct; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.ai.openai.OpenAiImageClient; +import org.springframework.ai.openai.OpenAiImageOptions; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -95,8 +95,8 @@ public class AiImageServiceImpl implements AiImageService { try { // 转换openai 参数 OpenAiImageOptions openAiImageOptions = new OpenAiImageOptions(); - openAiImageOptions.setModel(openAiImageModelEnum); - openAiImageOptions.setStyle(openAiImageStyleEnum); + openAiImageOptions.setModel(openAiImageModelEnum.getModel()); + openAiImageOptions.setStyle(openAiImageStyleEnum.getStyle()); openAiImageOptions.setSize(req.getSize()); ImageResponse imageResponse = openAiImageClient.call(new ImagePrompt(req.getPrompt(), openAiImageOptions)); // 发送 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java index d1ccc080e..c3c9d44d0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.service.midjourneyHandler; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; import org.springframework.ai.models.midjourney.MidjourneyMessage; import org.springframework.ai.models.midjourney.constants.MidjourneyGennerateStatusEnum; import org.springframework.ai.models.midjourney.webSocket.MidjourneyMessageHandler; @@ -11,7 +12,6 @@ import cn.iocoder.yudao.module.ai.convert.AiImageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiImageMapper; import cn.iocoder.yudao.module.ai.enums.AiImageDrawingStatusEnum; -import com.alibaba.fastjson2.JSON; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml index 2195b4bcc..2188ad908 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml @@ -12,139 +12,48 @@ yudao-spring-boot-starter-ai - - 21 - 21 - UTF-8 - - - org.springframework - spring-core + io.springboot.ai + spring-ai-core + 1.0.3 - com.fasterxml.jackson.core - jackson-databind + io.springboot.ai + spring-ai-openai + 1.0.3 + - org.springframework - spring-context - - - net.jodah - typetools - 0.6.3 - compile - - - com.github.victools - jsonschema-module-jackson - 4.31.1 - compile - - - com.github.victools - jsonschema-module-swagger-2 - 4.33.1 - - - com.github.victools - jsonschema-generator - 4.31.1 - compile - - - io.projectreactor - reactor-core - - - org.springframework.cloud - spring-cloud-function-context - 4.1.0 - compile - - - org.antlr - stringtemplate - 4.0.2 - compile - - - org.projectlombok - lombok - - - org.springframework - spring-web - - - org.springframework - spring-webflux - - - org.springframework.retry - spring-retry - - - junit - junit - test - - - cn.hutool - hutool-all - test - - - com.squareup.okhttp3 - okhttp - 4.12.0 - test - - - io.projectreactor.netty - reactor-netty - - - cn.hutool - hutool-all + cn.iocoder.boot + yudao-common + com.alibaba dashscope-sdk-java 2.11.0 + - org.apache.httpcomponents - httpclient - 4.5.14 - compile + junit + junit + test + + + org.springframework.boot spring-boot-starter-websocket - - - com.fasterxml.jackson.core - jackson-databind - - - com.alibaba.fastjson2 - fastjson2 - 2.0.45 - + com.squareup.okhttp3 okhttp - - com.google.guava - guava - net.dv8tion JDA @@ -156,10 +65,6 @@ - - cn.iocoder.boot - yudao-common - \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index 88581f88a..b37938d4a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -11,9 +11,6 @@ import org.springframework.ai.models.xinghuo.api.XingHuoApi; import org.springframework.ai.models.yiyan.YiYanChatClient; import org.springframework.ai.models.yiyan.YiYanOptions; import org.springframework.ai.models.yiyan.api.YiYanApi; -import org.springframework.ai.models.openai.OpenAiImageApi; -import org.springframework.ai.models.openai.OpenAiImageClient; -import org.springframework.ai.models.openai.OpenAiImageOptions; import org.springframework.ai.models.midjourney.MidjourneyConfig; import org.springframework.ai.models.midjourney.MidjourneyMessage; import org.springframework.ai.models.midjourney.api.MidjourneyInteractionsApi; @@ -22,6 +19,10 @@ import org.springframework.ai.models.midjourney.webSocket.MidjourneyWebSocketSta import org.springframework.ai.models.midjourney.webSocket.listener.MidjourneyMessageListener; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; +import org.springframework.ai.openai.OpenAiImageClient; +import org.springframework.ai.openai.OpenAiImageOptions; +import org.springframework.ai.openai.api.OpenAiImageApi; +import org.springframework.ai.retry.RetryUtils; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -72,10 +73,10 @@ public class YudaoAiAutoConfiguration { YudaoAiProperties.QianWenProperties qianWenProperties = yudaoAiProperties.getQianwen(); // 转换配置 QianWenOptions qianWenOptions = new QianWenOptions(); - qianWenOptions.setTopK(qianWenProperties.getTopK()); +// qianWenOptions.setTopK(qianWenProperties.getTopK()); TODO 芋艿:后续弄 qianWenOptions.setTopP(qianWenProperties.getTopP()); qianWenOptions.setMaxTokens(qianWenProperties.getMaxTokens()); - qianWenOptions.setTemperature(qianWenProperties.getTemperature()); +// qianWenOptions.setTemperature(qianWenProperties.getTemperature()); TODO 芋艿:后续弄 return new QianWenChatClient( new QianWenApi( qianWenProperties.getApiKey(), @@ -91,7 +92,7 @@ public class YudaoAiAutoConfiguration { YudaoAiProperties.YiYanProperties yiYanProperties = yudaoAiProperties.getYiyan(); // 转换配置 YiYanOptions yiYanOptions = new YiYanOptions(); - yiYanOptions.setTopK(yiYanProperties.getTopK()); +// yiYanOptions.setTopK(yiYanProperties.getTopK()); TODO 芋艿:后续弄 yiYanOptions.setTopP(yiYanProperties.getTopP()); yiYanOptions.setTemperature(yiYanProperties.getTemperature()); yiYanOptions.setMaxOutputTokens(yiYanProperties.getMaxTokens()); @@ -106,19 +107,19 @@ public class YudaoAiAutoConfiguration { ); } - @Bean @ConditionalOnProperty(value = "yudao.ai.openAiImage.enable", havingValue = "true") public OpenAiImageClient openAiImageClient(YudaoAiProperties yudaoAiProperties) { YudaoAiProperties.OpenAiImageProperties openAiImageProperties = yudaoAiProperties.getOpenAiImage(); + OpenAiImageOptions openAiImageOptions = new OpenAiImageOptions(); + openAiImageOptions.setModel(openAiImageProperties.getModel().getModel()); + openAiImageOptions.setStyle(openAiImageProperties.getStyle().getStyle()); + openAiImageOptions.setResponseFormat("url"); // TODO 芋艿:OpenAiImageOptions.ResponseFormatEnum.URL.getValue() // 创建 client return new OpenAiImageClient( new OpenAiImageApi(openAiImageProperties.getApiKey()), - new OpenAiImageOptions() - .setModel(openAiImageProperties.getModel()) - .setResponseFormat(OpenAiImageOptions.ResponseFormatEnum.URL.getValue()) - .setStyle(openAiImageProperties.getStyle()) - ); + openAiImageOptions, + RetryUtils.DEFAULT_RETRY_TEMPLATE); } @Bean @@ -157,7 +158,6 @@ public class YudaoAiAutoConfiguration { return new MidjourneyInteractionsApi(midjourneyConfig); } - private static @NotNull MidjourneyConfig getMidjourneyConfig(ApplicationContext applicationContext, YudaoAiProperties.MidjourneyProperties midjourneyProperties) { Map requestTemplates = new HashMap<>(); diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java index a23b9109c..a228a0045 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.framework.ai.config; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import org.springframework.ai.models.xinghuo.XingHuoChatModel; import org.springframework.ai.models.yiyan.YiYanChatModel; -import org.springframework.ai.models.openai.enums.OpenAiImageModelEnum; -import org.springframework.ai.models.openai.enums.OpenAiImageStyleEnum; +import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageModelEnum; +import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageStyleEnum; import lombok.Data; import lombok.experimental.Accessors; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -95,6 +95,7 @@ public class YudaoAiProperties { @Data @Accessors(chain = true) public static class OpenAiImageProperties { + private boolean enable = false; /** @@ -109,6 +110,7 @@ public class YudaoAiProperties { * 风格 */ private OpenAiImageStyleEnum style = OpenAiImageStyleEnum.VIVID; + } @Data diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/enums/OpenAiImageModelEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageModelEnum.java similarity index 89% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/enums/OpenAiImageModelEnum.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageModelEnum.java index 635c62bba..ea2767fcd 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/enums/OpenAiImageModelEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageModelEnum.java @@ -1,8 +1,9 @@ -package org.springframework.ai.models.openai.enums; +package cn.iocoder.yudao.framework.ai.core.enums; import lombok.AllArgsConstructor; import lombok.Getter; +// TODO 芋艿:待梳理 /** * open ai * diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/enums/OpenAiImageStyleEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageStyleEnum.java similarity index 92% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/enums/OpenAiImageStyleEnum.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageStyleEnum.java index d7999cd72..40cbdfc02 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/enums/OpenAiImageStyleEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageStyleEnum.java @@ -1,8 +1,9 @@ -package org.springframework.ai.models.openai.enums; +package cn.iocoder.yudao.framework.ai.core.enums; import lombok.AllArgsConstructor; import lombok.Getter; +// TODO 芋艿:待梳理 /** * open ai image style * diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/ChatException.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/exception/ChatException.java similarity index 78% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/ChatException.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/exception/ChatException.java index bc9222699..54e50b665 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/ChatException.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/exception/ChatException.java @@ -1,4 +1,4 @@ -package org.springframework.ai.chat; +package cn.iocoder.yudao.framework.ai.core.exception; /** * 聊天异常 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java similarity index 95% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/package-info.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java index b38419f6f..a132fdfc5 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/package-info.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/package-info.java @@ -12,4 +12,4 @@ * 2.4 openai 包:【OpenAI】ChatGPT,拷贝 spring-ai 提供的 models/openai 包 * 2.5 midjourney 包:Midjourney,参考 https://github.com/novicezk/midjourney-proxy 实现 */ -package org.springframework.ai; \ No newline at end of file +package cn.iocoder.yudao.framework.ai; \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/ChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/ChatClient.java deleted file mode 100644 index bd6aa3e56..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/ChatClient.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat; - - -import org.springframework.ai.chat.messages.UserMessage; -import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.model.ModelClient; - -@FunctionalInterface -public interface ChatClient extends ModelClient { - - default String call(String message) { - Prompt prompt = new Prompt(new UserMessage(message)); - Generation generation = call(prompt).getResult(); - return (generation != null) ? generation.getOutput().getContent() : ""; - } - - @Override - ChatResponse call(Prompt prompt); - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/ChatResponse.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/ChatResponse.java deleted file mode 100644 index 641212b97..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/ChatResponse.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.ai.chat; - -import org.springframework.ai.chat.metadata.ChatResponseMetadata; -import org.springframework.ai.model.ModelResponse; -import org.springframework.util.CollectionUtils; - -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -/** - * 人工智能提供商返回的聊天完成(例如生成)响应。 - * - * The chat completion (e.g. generation) response returned by an AI provider. - */ -public class ChatResponse implements ModelResponse { - - private final ChatResponseMetadata chatResponseMetadata; - - /** - * List of generated messages returned by the AI provider. - */ - private final List generations; - - /** - * Construct a new {@link ChatResponse} instance without metadata. - * @param generations the {@link List} of {@link Generation} returned by the AI - * provider. - */ - public ChatResponse(List generations) { - this(generations, ChatResponseMetadata.NULL); - } - - /** - * Construct a new {@link ChatResponse} instance. - * @param generations the {@link List} of {@link Generation} returned by the AI - * provider. - * @param chatResponseMetadata {@link ChatResponseMetadata} containing information - * about the use of the AI provider's API. - */ - public ChatResponse(List generations, ChatResponseMetadata chatResponseMetadata) { - this.chatResponseMetadata = chatResponseMetadata; -// this.generations = List.copyOf(generations); - this.generations = Collections.unmodifiableList(generations); - } - - /** - * The {@link List} of {@link Generation generated outputs}. - *

- * It is a {@link List} of {@link List lists} because the Prompt could request - * multiple output {@link Generation generations}. - * @return the {@link List} of {@link Generation generated outputs}. - */ - - @Override - public List getResults() { - return this.generations; - } - - /** - * @return Returns the first {@link Generation} in the generations list. - */ - public Generation getResult() { - if (CollectionUtils.isEmpty(this.generations)) { - return null; - } - return this.generations.get(0); - } - - /** - * @return Returns {@link ChatResponseMetadata} containing information about the use - * of the AI provider's API. - */ - @Override - public ChatResponseMetadata getMetadata() { - return this.chatResponseMetadata; - } - - @Override - public String toString() { - return "ChatResponse [metadata=" + chatResponseMetadata + ", generations=" + generations + "]"; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; -// if (!(o instanceof ChatResponse that)) -// return false; - if (!(o instanceof ChatResponse)) { - return false; - } - ChatResponse that = (ChatResponse) o; - return Objects.equals(chatResponseMetadata, that.chatResponseMetadata) - && Objects.equals(generations, that.generations); - } - - @Override - public int hashCode() { - return Objects.hash(chatResponseMetadata, generations); - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/Generation.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/Generation.java deleted file mode 100644 index ca1784835..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/Generation.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat; - -import org.springframework.ai.chat.messages.AssistantMessage; -import org.springframework.ai.chat.metadata.ChatGenerationMetadata; -import org.springframework.ai.model.ModelResult; -import org.springframework.lang.Nullable; - -import java.util.Map; -import java.util.Objects; - -/** - * 表示AI返回的响应。 - * - * Represents a response returned by the AI. - */ -public class Generation implements ModelResult { - - private AssistantMessage assistantMessage; - - private ChatGenerationMetadata chatGenerationMetadata; - - public Generation(String text) { - this.assistantMessage = new AssistantMessage(text); - } - - public Generation(String text, Map properties) { - this.assistantMessage = new AssistantMessage(text, properties); - } - - @Override - public AssistantMessage getOutput() { - return this.assistantMessage; - } - - @Override - public ChatGenerationMetadata getMetadata() { - ChatGenerationMetadata chatGenerationMetadata = this.chatGenerationMetadata; - return chatGenerationMetadata != null ? chatGenerationMetadata : ChatGenerationMetadata.NULL; - } - - public Generation withGenerationMetadata(@Nullable ChatGenerationMetadata chatGenerationMetadata) { - this.chatGenerationMetadata = chatGenerationMetadata; - return this; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - - if (!(o instanceof Generation)) { - return false; - } - Generation that = (Generation) o; - return Objects.equals(assistantMessage, that.assistantMessage) - && Objects.equals(chatGenerationMetadata, that.chatGenerationMetadata); - } - - @Override - public int hashCode() { - return Objects.hash(assistantMessage, chatGenerationMetadata); - } - - @Override - public String toString() { - return "Generation{" + "assistantMessage=" + assistantMessage + ", chatGenerationMetadata=" - + chatGenerationMetadata + '}'; - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/StreamingChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/StreamingChatClient.java deleted file mode 100644 index 079989db4..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/StreamingChatClient.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat; - -import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.model.StreamingModelClient; -import reactor.core.publisher.Flux; - -@FunctionalInterface -public interface StreamingChatClient extends StreamingModelClient { - - @Override - Flux stream(Prompt prompt); - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/AbstractMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/AbstractMessage.java deleted file mode 100644 index 7cc936072..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/AbstractMessage.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.messages; - -import org.springframework.core.io.Resource; -import org.springframework.util.Assert; -import org.springframework.util.StreamUtils; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -public abstract class AbstractMessage implements Message { - - protected final MessageType messageType; - - protected final String textContent; - - protected final List mediaData; - - /** - * Additional options for the message to influence the response, not a generative map. - */ - protected final Map properties; - - protected AbstractMessage(MessageType messageType, String content) { - this(messageType, content, Map.of()); - } - - protected AbstractMessage(MessageType messageType, String content, Map messageProperties) { - Assert.notNull(messageType, "Message type must not be null"); - // Assert.notNull(content, "Content must not be null"); - this.messageType = messageType; - this.textContent = content; - this.mediaData = new ArrayList<>(); - this.properties = messageProperties; - } - - protected AbstractMessage(MessageType messageType, String textContent, List mediaData) { - this(messageType, textContent, mediaData, Map.of()); - } - - protected AbstractMessage(MessageType messageType, String textContent, List mediaData, - Map messageProperties) { - - Assert.notNull(messageType, "Message type must not be null"); - Assert.notNull(textContent, "Content must not be null"); - Assert.notNull(mediaData, "media data must not be null"); - - this.messageType = messageType; - this.textContent = textContent; - this.mediaData = new ArrayList<>(mediaData); - this.properties = messageProperties; - } - - protected AbstractMessage(MessageType messageType, Resource resource) { - this(messageType, resource, Collections.emptyMap()); - } - - @SuppressWarnings("null") - protected AbstractMessage(MessageType messageType, Resource resource, Map messageProperties) { - Assert.notNull(messageType, "Message type must not be null"); - Assert.notNull(resource, "Resource must not be null"); - - this.messageType = messageType; - this.properties = messageProperties; - this.mediaData = new ArrayList<>(); - - try (InputStream inputStream = resource.getInputStream()) { - this.textContent = StreamUtils.copyToString(inputStream, Charset.defaultCharset()); - } - catch (IOException ex) { - throw new RuntimeException("Failed to read resource", ex); - } - } - - @Override - public String getContent() { - return this.textContent; - } - - @Override - public List getMediaData() { - return this.mediaData; - } - - @Override - public Map getProperties() { - return this.properties; - } - - @Override - public MessageType getMessageType() { - return this.messageType; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((mediaData == null) ? 0 : mediaData.hashCode()); - result = prime * result + ((properties == null) ? 0 : properties.hashCode()); - result = prime * result + ((messageType == null) ? 0 : messageType.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - AbstractMessage other = (AbstractMessage) obj; - if (mediaData == null) { - if (other.mediaData != null) - return false; - } - else if (!mediaData.equals(other.mediaData)) - return false; - if (properties == null) { - if (other.properties != null) - return false; - } - else if (!properties.equals(other.properties)) - return false; - if (messageType != other.messageType) - return false; - return true; - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/AssistantMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/AssistantMessage.java deleted file mode 100644 index 28710db1c..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/AssistantMessage.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.messages; - -import java.util.Map; - -/** - * 让生成人员知道内容是作为对用户的响应生成的。 - * 此角色指示生成者先前在会话中生成的消息。 - * 通过包括该系列中的辅助消息,您可以为生成的关于提供上下文之前在谈话中的交流。 - * - * Lets the generative know the content was generated as a response to the user. This role - * indicates messages that the generative has previously generated in the conversation. By - * including assistant messages in the series, you provide context to the generative about - * prior exchanges in the conversation. - */ -public class AssistantMessage extends AbstractMessage { - - public AssistantMessage(String content) { - super(MessageType.ASSISTANT, content); - } - - public AssistantMessage(String content, Map properties) { - super(MessageType.ASSISTANT, content, properties); - } - - @Override - public String toString() { - return "AssistantMessage{" + "content='" + getContent() + '\'' + ", properties=" + properties + ", messageType=" - + messageType + '}'; - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/ChatMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/ChatMessage.java deleted file mode 100644 index 194aa54af..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/ChatMessage.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.messages; - -import java.util.Map; - -public class ChatMessage extends AbstractMessage { - - public ChatMessage(String role, String content) { - super(MessageType.valueOf(role), content); - } - - public ChatMessage(String role, String content, Map properties) { - super(MessageType.valueOf(role), content, properties); - } - - public ChatMessage(MessageType messageType, String content) { - super(messageType, content); - } - - public ChatMessage(MessageType messageType, String content, Map properties) { - super(messageType, content, properties); - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/FunctionMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/FunctionMessage.java deleted file mode 100644 index 1faba6a79..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/FunctionMessage.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2023-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.messages; - -import java.util.Map; - -public class FunctionMessage extends AbstractMessage { - - public FunctionMessage(String content) { - super(MessageType.SYSTEM, content); - } - - public FunctionMessage(String content, Map properties) { - super(MessageType.SYSTEM, content, properties); - } - - @Override - public String toString() { - return "FunctionMessage{" + "content='" + getContent() + '\'' + ", properties=" + properties + ", messageType=" - + messageType + '}'; - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/MediaData.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/MediaData.java deleted file mode 100644 index 9acd9b151..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/MediaData.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.messages; - -import org.springframework.util.Assert; -import org.springframework.util.MimeType; - -/** - * @author Christian Tzolov - */ -public class MediaData { - - private final MimeType mimeType; - - private final Object data; - - public MediaData(MimeType mimeType, Object data) { - Assert.notNull(mimeType, "MimeType must not be null"); - // Assert.notNull(data, "Data must not be null"); - this.mimeType = mimeType; - this.data = data; - } - - public MimeType getMimeType() { - return this.mimeType; - } - - public Object getData() { - return this.data; - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/Message.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/Message.java deleted file mode 100644 index 10c893ad7..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/Message.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.messages; - -import java.util.List; -import java.util.Map; - -public interface Message { - - String getContent(); - - List getMediaData(); - - Map getProperties(); - - MessageType getMessageType(); - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/MessageType.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/MessageType.java deleted file mode 100644 index a227c4530..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/MessageType.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.ai.chat.messages; - -public enum MessageType { - - // 用户消息 - USER("user"), - - // 之前会话的消息 - ASSISTANT("assistant"), - - // 根据注释说明:您可以使用系统消息来指示具有生成性,表现得像某个角色或以特定的方式提供答案总体安排 - // 简单理解:在对话前,发送一条具有角色的信息让模型理解(如:你现在是一个10年拍摄经验的导演,拥有丰富的经验。 这样你就可以去问他,怎么拍一个短视频可以在抖音上火) - SYSTEM("system"), - - // 函数?根据引用现在不支持,会抛出一个异常 ---> throw new IllegalArgumentException("Tool execution results are not supported for Bedrock models"); - FUNCTION("function"); - - private final String value; - - MessageType(String value) { - this.value = value; - } - - public String getValue() { - return value; - } - - public static MessageType fromValue(String value) { - for (MessageType messageType : MessageType.values()) { - if (messageType.getValue().equals(value)) { - return messageType; - } - } - throw new IllegalArgumentException("Invalid MessageType value: " + value); - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/SystemMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/SystemMessage.java deleted file mode 100644 index f8c67f2b4..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/SystemMessage.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.messages; - -import org.springframework.core.io.Resource; - -/** - * 作为输入传递的“system”类型的消息。系统消息给出高级别对话说明。 - * 此角色通常提供高级说明对话。 - * 例如,您可以使用系统消息来指示具有生成性,表现得像某个角色或以特定的方式提供答案总体安排 - * - * A message of the type 'system' passed as input. The system message gives high level - * instructions for the conversation. This role typically provides high-level instructions - * for the conversation. For example, you might use a system message to instruct the - * generative to behave like a certain character or to provide answers in a specific - * format. - */ -public class SystemMessage extends AbstractMessage { - - public SystemMessage(String content) { - super(MessageType.SYSTEM, content); - } - - public SystemMessage(Resource resource) { - super(MessageType.SYSTEM, resource); - } - - @Override - public String toString() { - return "SystemMessage{" + "content='" + getContent() + '\'' + ", properties=" + properties + ", messageType=" - + messageType + '}'; - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/UserMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/UserMessage.java deleted file mode 100644 index ca7f360c2..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/messages/UserMessage.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.messages; - -import org.springframework.core.io.Resource; - -import java.util.List; - -/** - * 作为输入传递的“user”类型的消息具有用户角色的消息来自最终用户或开发者。 - * 它们表示问题、提示或您想要的任何输入产生反应的。 - * - * A message of the type 'user' passed as input Messages with the user role are from the - * end-user or developer. They represent questions, prompts, or any input that you want - * the generative to respond to. - */ -public class UserMessage extends AbstractMessage { - - public UserMessage(String message) { - super(MessageType.USER, message); - } - - public UserMessage(Resource resource) { - super(MessageType.USER, resource); - } - - public UserMessage(String textContent, List mediaDataList) { - super(MessageType.USER, textContent, mediaDataList); - } - - @Override - public String toString() { - return "UserMessage{" + "content='" + getContent() + '\'' + ", properties=" + properties + ", messageType=" - + messageType + '}'; - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/ChatGenerationMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/ChatGenerationMetadata.java deleted file mode 100644 index d9f5fc56e..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/ChatGenerationMetadata.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.metadata; - -import org.springframework.ai.model.ResultMetadata; -import org.springframework.lang.Nullable; - -/** - * Abstract Data Type (ADT) encapsulating information on the completion choices in the AI - * response. - * - * @author John Blum - * @since 0.7.0 - */ -public interface ChatGenerationMetadata extends ResultMetadata { - - ChatGenerationMetadata NULL = ChatGenerationMetadata.from(null, null); - - /** - * Factory method used to construct a new {@link ChatGenerationMetadata} from the - * given {@link String finish reason} and content filter metadata. - * @param finishReason {@link String} contain the reason for the choice completion. - * @param contentFilterMetadata underlying AI provider metadata for filtering applied - * to generation content. - * @return a new {@link ChatGenerationMetadata} from the given {@link String finish - * reason} and content filter metadata. - */ - static ChatGenerationMetadata from(String finishReason, Object contentFilterMetadata) { - return new ChatGenerationMetadata() { - - @Override - @SuppressWarnings("unchecked") - public T getContentFilterMetadata() { - return (T) contentFilterMetadata; - } - - @Override - public String getFinishReason() { - return finishReason; - } - }; - } - - /** - * Returns the underlying AI provider metadata for filtering applied to generation - * content. - * @param {@link Class Type} used to cast the filtered content metadata into the - * AI provider-specific type. - * @return the underlying AI provider metadata for filtering applied to generation - * content. - */ - @Nullable - T getContentFilterMetadata(); - - /** - * Get the {@link String reason} this choice completed for the generation. - * @return the {@link String reason} this choice completed for the generation. - */ - String getFinishReason(); - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/ChatResponseMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/ChatResponseMetadata.java deleted file mode 100644 index 38eb1fd59..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/ChatResponseMetadata.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.metadata; - - -import org.springframework.ai.model.ResponseMetadata; - -/** - * Abstract Data Type (ADT) modeling common AI provider metadata returned in an AI - * response. - * - * 抽象数据类型(ADT)建模AI响应中返回的常见AI提供者元数据。 - * - * @author John Blum - * @since 0.7.0 - */ -public interface ChatResponseMetadata extends ResponseMetadata { - - ChatResponseMetadata NULL = new ChatResponseMetadata() { - }; - - /** - * Returns AI provider specific metadata on rate limits. - * @return AI provider specific metadata on rate limits. - * @see RateLimit - */ - default RateLimit getRateLimit() { - return new EmptyRateLimit(); - } - - /** - * Returns AI provider specific metadata on API usage. - * @return AI provider specific metadata on API usage. - * @see Usage - */ - default Usage getUsage() { - return new EmptyUsage(); - } - - default PromptMetadata getPromptMetadata() { - return PromptMetadata.empty(); - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/EmptyRateLimit.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/EmptyRateLimit.java deleted file mode 100644 index 480a94d3e..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/EmptyRateLimit.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.metadata; - -import java.time.Duration; - -/** - * A RateLimit implementation that returns zero for all property getters - * - * @author John Blum - * @since 0.7.0 - */ -public class EmptyRateLimit implements RateLimit { - - @Override - public Long getRequestsLimit() { - return 0L; - } - - @Override - public Long getRequestsRemaining() { - return 0L; - } - - @Override - public Duration getRequestsReset() { - return Duration.ZERO; - } - - @Override - public Long getTokensLimit() { - return 0L; - } - - @Override - public Long getTokensRemaining() { - return 0L; - } - - @Override - public Duration getTokensReset() { - return Duration.ZERO; - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/EmptyUsage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/EmptyUsage.java deleted file mode 100644 index 027e30279..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/EmptyUsage.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.metadata; - -/** - * A EmpytUsage implementation that returns zero for all property getters - * - * @author John Blum - * @since 0.7.0 - */ -public class EmptyUsage implements Usage { - - @Override - public Long getPromptTokens() { - return 0L; - } - - @Override - public Long getGenerationTokens() { - return 0L; - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/PromptMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/PromptMetadata.java deleted file mode 100644 index becb12ded..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/PromptMetadata.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.ai.chat.metadata; - -import org.springframework.util.Assert; - -import java.util.Arrays; -import java.util.Optional; -import java.util.stream.StreamSupport; - -/** - * Abstract Data Type (ADT) modeling metadata gathered by the AI during request - * processing. - * - * @author John Blum - * @since 0.7.0 - */ -@FunctionalInterface -public interface PromptMetadata extends Iterable { - - /** - * Factory method used to create empty {@link PromptMetadata} when the information is - * not supplied by the AI provider. - * @return empty {@link PromptMetadata}. - */ - static PromptMetadata empty() { - return of(); - } - - /** - * Factory method used to create a new {@link PromptMetadata} composed of an array of - * {@link PromptFilterMetadata}. - * @param array array of {@link PromptFilterMetadata} used to compose the - * {@link PromptMetadata}. - * @return a new {@link PromptMetadata} composed of an array of - * {@link PromptFilterMetadata}. - */ - static PromptMetadata of(PromptFilterMetadata... array) { - return of(Arrays.asList(array)); - } - - /** - * Factory method used to create a new {@link PromptMetadata} composed of an - * {@link Iterable} of {@link PromptFilterMetadata}. - * @param iterable {@link Iterable} of {@link PromptFilterMetadata} used to compose - * the {@link PromptMetadata}. - * @return a new {@link PromptMetadata} composed of an {@link Iterable} of - * {@link PromptFilterMetadata}. - */ - static PromptMetadata of(Iterable iterable) { - Assert.notNull(iterable, "An Iterable of PromptFilterMetadata must not be null"); - return iterable::iterator; - } - - /** - * Returns an {@link Optional} {@link PromptFilterMetadata} at the given index. - * @param promptIndex index of the {@link PromptFilterMetadata} contained in this - * {@link PromptMetadata}. - * @return {@link Optional} {@link PromptFilterMetadata} at the given index. - * @throws IllegalArgumentException if the prompt index is less than 0. - */ - default Optional findByPromptIndex(int promptIndex) { - - Assert.isTrue(promptIndex > -1, "Prompt index [%d] must be greater than equal to 0".formatted(promptIndex)); - - return StreamSupport.stream(this.spliterator(), false) - .filter(promptFilterMetadata -> promptFilterMetadata.getPromptIndex() == promptIndex) - .findFirst(); - } - - /** - * Abstract Data Type (ADT) modeling filter metadata for all prompts sent during an AI - * request. - */ - interface PromptFilterMetadata { - - /** - * Factory method used to construct a new {@link PromptFilterMetadata} with the - * given prompt index and content filter metadata. - * @param promptIndex index of the prompt filter metadata contained in the AI - * response. - * @param contentFilterMetadata underlying AI provider metadata for filtering - * applied to prompt content. - * @return a new instance of {@link PromptFilterMetadata} with the given prompt - * index and content filter metadata. - */ - static PromptFilterMetadata from(int promptIndex, Object contentFilterMetadata) { - - return new PromptFilterMetadata() { - - @Override - public int getPromptIndex() { - return promptIndex; - } - - @Override - @SuppressWarnings("unchecked") - public T getContentFilterMetadata() { - return (T) contentFilterMetadata; - } - }; - } - - /** - * Index of the prompt filter metadata contained in the AI response. - * @return an {@link Integer index} fo the prompt filter metadata contained in the - * AI response. - */ - int getPromptIndex(); - - /** - * Returns the underlying AI provider metadata for filtering applied to prompt - * content. - * @param {@link Class Type} used to cast the filtered content metadata into - * the AI provider-specific type. - * @return the underlying AI provider metadata for filtering applied to prompt - * content. - */ - T getContentFilterMetadata(); - - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/RateLimit.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/RateLimit.java deleted file mode 100644 index 22dd64b18..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/RateLimit.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.metadata; - -import java.time.Duration; - -/** - * Abstract Data Type (ADT) encapsulating metadata from an AI provider's API rate limits - * granted to the API key in use and the API key's current balance. - * - * @author John Blum - * @since 0.7.0 - */ -public interface RateLimit { - - /** - * Returns the maximum number of requests that are permitted before exhausting the - * rate limit. - * @return an {@link Long} with the maximum number of requests that are permitted - * before exhausting the rate limit. - * @see #getRequestsRemaining() - */ - Long getRequestsLimit(); - - /** - * Returns the remaining number of requests that are permitted before exhausting the - * {@link #getRequestsLimit() rate limit}. - * @return an {@link Long} with the remaining number of requests that are permitted - * before exhausting the {@link #getRequestsLimit() rate limit}. - * @see #getRequestsLimit() - */ - Long getRequestsRemaining(); - - /** - * Returns the {@link Duration time} until the rate limit (based on requests) resets - * to its {@link #getRequestsLimit() initial state}. - * @return a {@link Duration} representing the time until the rate limit (based on - * requests) resets to its {@link #getRequestsLimit() initial state}. - * @see #getRequestsLimit() - */ - Duration getRequestsReset(); - - /** - * Returns the maximum number of tokens that are permitted before exhausting the rate - * limit. - * @return an {@link Long} with the maximum number of tokens that are permitted before - * exhausting the rate limit. - * @see #getTokensRemaining() - */ - Long getTokensLimit(); - - /** - * Returns the remaining number of tokens that are permitted before exhausting the - * {@link #getTokensLimit() rate limit}. - * @return an {@link Long} with the remaining number of tokens that are permitted - * before exhausting the {@link #getTokensLimit() rate limit}. - * @see #getTokensLimit() - */ - Long getTokensRemaining(); - - /** - * Returns the {@link Duration time} until the rate limit (based on tokens) resets to - * its {@link #getTokensLimit() initial state}. - * @return a {@link Duration} with the time until the rate limit (based on tokens) - * resets to its {@link #getTokensLimit() initial state}. - * @see #getTokensLimit() - */ - Duration getTokensReset(); - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/Usage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/Usage.java deleted file mode 100644 index de4fb9ac6..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/metadata/Usage.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.metadata; - -/** - * 抽象数据类型(ADT)封装关于人工智能提供商API使用的元数据根据AI请求。 - * - * Abstract Data Type (ADT) encapsulating metadata on the usage of an AI provider's API - * per AI request. - * - * @author John Blum - * @since 0.7.0 - */ -public interface Usage { - - /** - * 返回AI请求的{@literal prompt}中使用的令牌数。 - * @返回一个{@link Long},其中包含在的{@literal提示符}中使用的令牌数AI请求。 - * - * Returns the number of tokens used in the {@literal prompt} of the AI request. - * @return an {@link Long} with the number of tokens used in the {@literal prompt} of - * the AI request. - * @see #getGenerationTokens() - */ - Long getPromptTokens(); - - /** - * Returns the number of tokens returned in the {@literal generation (aka completion)} - * of the AI's response. - * @return an {@link Long} with the number of tokens returned in the - * {@literal generation (aka completion)} of the AI's response. - * @see #getPromptTokens() - */ - Long getGenerationTokens(); - - /** - * Return the total number of tokens from both the {@literal prompt} of an AI request - * and {@literal generation} of the AI's response. - * @return the total number of tokens from both the {@literal prompt} of an AI request - * and {@literal generation} of the AI's response. - * @see #getPromptTokens() - * @see #getGenerationTokens() - */ - default Long getTotalTokens() { - Long promptTokens = getPromptTokens(); - promptTokens = promptTokens != null ? promptTokens : 0; - Long completionTokens = getGenerationTokens(); - completionTokens = completionTokens != null ? completionTokens : 0; - return promptTokens + completionTokens; - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/package-info.java deleted file mode 100644 index 98d92eb71..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/package-info.java +++ /dev/null @@ -1,14 +0,0 @@ -/** - * The org.sf.ai.chat package represents the bounded context for the Chat Model within the - * AI generative model domain. This package extends the core domain defined in - * org.sf.ai.generative, providing implementations specific to chat-based generative AI - * interactions. - * - * In line with Domain-Driven Design principles, this package includes implementations of - * entities and value objects specific to the chat context, such as ChatPrompt and - * ChatResponse, adhering to the ubiquitous language of chat interactions in AI models. - * - * This bounded context is designed to encapsulate all aspects of chat-based AI - * functionalities, maintaining a clear boundary from other contexts within the AI domain. - */ -package org.springframework.ai.chat; \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/AssistantPromptTemplate.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/AssistantPromptTemplate.java deleted file mode 100644 index ae6373cf1..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/AssistantPromptTemplate.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.prompt; - -import org.springframework.ai.chat.messages.AssistantMessage; -import org.springframework.ai.chat.messages.Message; -import org.springframework.core.io.Resource; - -import java.util.Map; - -public class AssistantPromptTemplate extends PromptTemplate { - - public AssistantPromptTemplate(String template) { - super(template); - } - - public AssistantPromptTemplate(Resource resource) { - super(resource); - } - - @Override - public Prompt create() { - return new Prompt(new AssistantMessage(render())); - } - - @Override - public Prompt create(Map model) { - return new Prompt(new AssistantMessage(render(model))); - } - - @Override - public Message createMessage() { - return new AssistantMessage(render()); - } - - @Override - public Message createMessage(Map model) { - return new AssistantMessage(render(model)); - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/ChatOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/ChatOptions.java deleted file mode 100644 index 5c45a37ba..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/ChatOptions.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.prompt; - -import org.springframework.ai.model.ModelOptions; - -/** - * 聊天选项代表了常见的选项,可在不同的聊天模式中移植。 - * - * The ChatOptions represent the common options, portable across different chat models. - */ -public interface ChatOptions extends ModelOptions { - - Float getTemperature(); - - void setTemperature(Float temperature); - - Float getTopP(); - - void setTopP(Float topP); - - Integer getTopK(); - - void setTopK(Integer topK); - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/ChatOptionsBuilder.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/ChatOptionsBuilder.java deleted file mode 100644 index f702f6350..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/ChatOptionsBuilder.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.prompt; - -public class ChatOptionsBuilder { - - private class ChatOptionsImpl implements ChatOptions { - - private Float temperature; - - private Float topP; - - private Integer topK; - - @Override - public Float getTemperature() { - return temperature; - } - - @Override - public void setTemperature(Float temperature) { - this.temperature = temperature; - } - - @Override - public Float getTopP() { - return topP; - } - - @Override - public void setTopP(Float topP) { - this.topP = topP; - } - - @Override - public Integer getTopK() { - return topK; - } - - @Override - public void setTopK(Integer topK) { - this.topK = topK; - } - - } - - private final ChatOptionsImpl options = new ChatOptionsImpl(); - - private ChatOptionsBuilder() { - } - - public static ChatOptionsBuilder builder() { - return new ChatOptionsBuilder(); - } - - public ChatOptionsBuilder withTemperature(Float temperature) { - options.setTemperature(temperature); - return this; - } - - public ChatOptionsBuilder withTopP(Float topP) { - options.setTopP(topP); - return this; - } - - public ChatOptionsBuilder withTopK(Integer topK) { - options.setTopK(topK); - return this; - } - - public ChatOptions build() { - return options; - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/ChatPromptTemplate.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/ChatPromptTemplate.java deleted file mode 100644 index 15f9ca5d4..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/ChatPromptTemplate.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.prompt; - -import org.springframework.ai.chat.messages.Message; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * PromptTemplate,用于将角色指定为字符串实现及其角色不足以满足您的需求。 - * - * A PromptTemplate that lets you specify the role as a string should the current - * implementations and their roles not suffice for your needs. - */ -public class ChatPromptTemplate implements PromptTemplateActions, PromptTemplateChatActions { - - private final List promptTemplates; - - public ChatPromptTemplate(List promptTemplates) { - this.promptTemplates = promptTemplates; - } - - @Override - public String render() { - StringBuilder sb = new StringBuilder(); - for (PromptTemplate promptTemplate : promptTemplates) { - sb.append(promptTemplate.render()); - } - return sb.toString(); - } - - @Override - public String render(Map model) { - StringBuilder sb = new StringBuilder(); - for (PromptTemplate promptTemplate : promptTemplates) { - sb.append(promptTemplate.render(model)); - } - return sb.toString(); - } - - @Override - public List createMessages() { - List messages = new ArrayList<>(); - for (PromptTemplate promptTemplate : promptTemplates) { - messages.add(promptTemplate.createMessage()); - } - return messages; - } - - @Override - public List createMessages(Map model) { - List messages = new ArrayList<>(); - for (PromptTemplate promptTemplate : promptTemplates) { - messages.add(promptTemplate.createMessage(model)); - } - return messages; - } - - @Override - public Prompt create() { - List messages = createMessages(); - return new Prompt(messages); - } - - @Override - public Prompt create(Map model) { - List messages = createMessages(model); - return new Prompt(messages); - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/FunctionPromptTemplate.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/FunctionPromptTemplate.java deleted file mode 100644 index 4c7ce981f..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/FunctionPromptTemplate.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.prompt; - -public class FunctionPromptTemplate extends PromptTemplate { - - private String name; - - public FunctionPromptTemplate(String template) { - super(template); - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/Prompt.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/Prompt.java deleted file mode 100644 index a598b3c35..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/Prompt.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.prompt; - -import org.springframework.ai.chat.messages.Message; -import org.springframework.ai.chat.messages.UserMessage; -import org.springframework.ai.model.ModelOptions; -import org.springframework.ai.model.ModelRequest; - -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -/** - * 文字内容 - */ -public class Prompt implements ModelRequest> { - - private final List messages; - - private ChatOptions modelOptions; - - public Prompt(String contents) { - this(new UserMessage(contents)); - } - - public Prompt(Message message) { - this(Collections.singletonList(message)); - } - - public Prompt(List messages) { - this.messages = messages; - } - - public Prompt(String contents, ChatOptions modelOptions) { - this(new UserMessage(contents), modelOptions); - } - - public Prompt(Message message, ChatOptions modelOptions) { - this(Collections.singletonList(message), modelOptions); - } - - public Prompt(List messages, ChatOptions modelOptions) { - this.messages = messages; - this.modelOptions = modelOptions; - } - - public String getContents() { - StringBuilder sb = new StringBuilder(); - for (Message message : getInstructions()) { - sb.append(message.getContent()); - } - return sb.toString(); - } - - @Override - public ModelOptions getOptions() { - return this.modelOptions; - } - - @Override - public List getInstructions() { - return this.messages; - } - - @Override - public String toString() { - return "Prompt{" + "messages=" + this.messages + ", modelOptions=" + this.modelOptions + '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; -// if (!(o instanceof Prompt prompt)) -// return false; - if (!(o instanceof Prompt)) { - return false; - } - Prompt prompt = (Prompt) o; - return Objects.equals(this.messages, prompt.messages) && Objects.equals(this.modelOptions, prompt.modelOptions); - } - - @Override - public int hashCode() { - return Objects.hash(this.messages, this.modelOptions); - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplate.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplate.java deleted file mode 100644 index f1e910da0..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplate.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.prompt; - -import org.springframework.ai.chat.messages.Message; -import org.springframework.ai.chat.messages.UserMessage; -import org.springframework.ai.parser.OutputParser; -import org.antlr.runtime.Token; -import org.antlr.runtime.TokenStream; -import org.springframework.core.io.Resource; -import org.springframework.util.StreamUtils; -import org.stringtemplate.v4.ST; -import org.stringtemplate.v4.compiler.STLexer; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.Charset; -import java.util.*; -import java.util.Map.Entry; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -/** - * 用户输入的提示内容模板 - * - * 实现:提示词模板操作 提示词模板message相关操作 - */ -public class PromptTemplate implements PromptTemplateActions, PromptTemplateMessageActions { - - private ST st; - - private Map dynamicModel = new HashMap<>(); - - protected String template; - - protected TemplateFormat templateFormat = TemplateFormat.ST; - - private OutputParser outputParser; - - public PromptTemplate(Resource resource) { - try (InputStream inputStream = resource.getInputStream()) { - this.template = StreamUtils.copyToString(inputStream, Charset.defaultCharset()); - } - catch (IOException ex) { - throw new RuntimeException("Failed to read resource", ex); - } - try { - this.st = new ST(this.template, '{', '}'); - } - catch (Exception ex) { - throw new IllegalArgumentException("The template string is not valid.", ex); - } - } - - public PromptTemplate(String template) { - this.template = template; - // If the template string is not valid, an exception will be thrown - try { - this.st = new ST(this.template, '{', '}'); - } - catch (Exception ex) { - throw new IllegalArgumentException("The template string is not valid.", ex); - } - } - - public PromptTemplate(String template, Map model) { - this.template = template; - // If the template string is not valid, an exception will be thrown - try { - this.st = new ST(this.template, '{', '}'); - for (Entry entry : model.entrySet()) { - add(entry.getKey(), entry.getValue()); - dynamicModel.put(entry.getKey(), entry.getValue()); - } - } - catch (Exception ex) { - throw new IllegalArgumentException("The template string is not valid.", ex); - } - } - - public PromptTemplate(Resource resource, Map model) { - try (InputStream inputStream = resource.getInputStream()) { - this.template = StreamUtils.copyToString(inputStream, Charset.defaultCharset()); - } - catch (IOException ex) { - throw new RuntimeException("Failed to read resource", ex); - } - // If the template string is not valid, an exception will be thrown - try { - this.st = new ST(this.template, '{', '}'); - for (Entry entry : model.entrySet()) { - add(entry.getKey(), entry.getValue()); - dynamicModel.put(entry.getKey(), entry.getValue()); - } - } - catch (Exception ex) { - throw new IllegalArgumentException("The template string is not valid.", ex); - } - } - - public OutputParser getOutputParser() { - return outputParser; - } - - public void setOutputParser(OutputParser outputParser) { - Objects.requireNonNull(outputParser, "Output Parser can not be null"); - this.outputParser = outputParser; - } - - public void add(String name, Object value) { - this.st.add(name, value); - this.dynamicModel.put(name, value); - } - - public String getTemplate() { - return this.template; - } - - public TemplateFormat getTemplateFormat() { - return this.templateFormat; - } - - // Render Methods - @Override - public String render() { - validate(this.dynamicModel); - return st.render(); - } - - @Override - public String render(Map model) { - validate(model); - for (Entry entry : model.entrySet()) { - if (st.getAttribute(entry.getKey()) != null) { - st.remove(entry.getKey()); - } - if (entry.getValue() instanceof Resource) { - st.add(entry.getKey(), renderResource((Resource) entry.getValue())); - } - else { - st.add(entry.getKey(), entry.getValue()); - } - - } - return st.render(); - } - - private String renderResource(Resource resource) { - try { - return resource.getContentAsString(Charset.defaultCharset()); - } - catch (IOException e) { - throw new RuntimeException(e); - } - // try (InputStream inputStream = resource.getInputStream()) { - // return StreamUtils.copyToString(inputStream, Charset.defaultCharset()); - // } - // catch (IOException ex) { - // throw new RuntimeException(ex); - // } - } - - @Override - public Message createMessage() { - return new UserMessage(render()); - } - - @Override - public Message createMessage(Map model) { - return new UserMessage(render(model)); - } - - @Override - public Prompt create() { - return new Prompt(render(new HashMap<>())); - } - - @Override - public Prompt create(Map model) { - return new Prompt(render(model)); - } - - public Set getInputVariables() { - TokenStream tokens = this.st.impl.tokens; - return IntStream.range(0, tokens.range()) - .mapToObj(tokens::get) - .filter(token -> token.getType() == STLexer.ID) - .map(Token::getText) - .collect(Collectors.toSet()); - } - - protected void validate(Map model) { - Set dynamicVariableNames = new HashSet<>(this.dynamicModel.keySet()); - Set modelVariables = new HashSet<>(model.keySet()); - modelVariables.addAll(dynamicVariableNames); - Set missingEntries = new HashSet<>(getInputVariables()); - missingEntries.removeAll(modelVariables); - if (!missingEntries.isEmpty()) { - throw new IllegalStateException( - "All template variables were not replaced. Missing variable names are " + missingEntries); - } - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateActions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateActions.java deleted file mode 100644 index 8097e3f35..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateActions.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.prompt; - -import java.util.Map; - -/** - * 提示词模板操作 - */ -public interface PromptTemplateActions extends PromptTemplateStringActions { - - /** - * 创建 Prompt - * @return - */ - Prompt create(); - - Prompt create(Map model); - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateChatActions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateChatActions.java deleted file mode 100644 index 24d9f908c..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateChatActions.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.springframework.ai.chat.prompt; - -import org.springframework.ai.chat.messages.Message; - -import java.util.List; -import java.util.Map; - -/** - * 聊天操作 - * - */ -public interface PromptTemplateChatActions { - - List createMessages(); - - List createMessages(Map model); - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateMessageActions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateMessageActions.java deleted file mode 100644 index 17ff49286..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateMessageActions.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.springframework.ai.chat.prompt; - -import org.springframework.ai.chat.messages.Message; - -import java.util.Map; - -/** - * 用户输入的提示内容 模板信息操作 - */ -public interface PromptTemplateMessageActions { - - /** - * 创建一个 message - * @return - */ - Message createMessage(); - - /** - * 创建一个 message - * @return - */ - Message createMessage(Map model); - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateStringActions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateStringActions.java deleted file mode 100644 index 0cd9df3b2..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/PromptTemplateStringActions.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.springframework.ai.chat.prompt; - -import java.util.Map; - -/** - * 提示次模板字符串操作 - */ -public interface PromptTemplateStringActions { - - String render(); - - String render(Map model); - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/SystemPromptTemplate.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/SystemPromptTemplate.java deleted file mode 100644 index 539287d07..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/SystemPromptTemplate.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.prompt; - -import org.springframework.ai.chat.messages.Message; -import org.springframework.ai.chat.messages.SystemMessage; -import org.springframework.core.io.Resource; - -import java.util.Map; - -public class SystemPromptTemplate extends PromptTemplate { - - public SystemPromptTemplate(String template) { - super(template); - } - - public SystemPromptTemplate(Resource resource) { - super(resource); - } - - @Override - public Message createMessage() { - return new SystemMessage(render()); - } - - @Override - public Message createMessage(Map model) { - return new SystemMessage(render(model)); - } - - @Override - public Prompt create() { - return new Prompt(new SystemMessage(render())); - } - - @Override - public Prompt create(Map model) { - return new Prompt(new SystemMessage(render(model))); - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/TemplateFormat.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/TemplateFormat.java deleted file mode 100644 index 1001ee266..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/chat/prompt/TemplateFormat.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.chat.prompt; - -public enum TemplateFormat { - - ST("ST"); - - private final String value; - - TemplateFormat(String value) { - this.value = value; - } - - public String getValue() { - return value; - } - - public static TemplateFormat fromValue(String value) { - for (TemplateFormat templateFormat : TemplateFormat.values()) { - if (templateFormat.getValue().equals(value)) { - return templateFormat; - } - } - throw new IllegalArgumentException("Invalid TemplateFormat value: " + value); - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/Image.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/Image.java deleted file mode 100644 index 3c6ae1ea1..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/Image.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.image; - -import java.util.Objects; - -public class Image { - - /** - * 可以访问图像的URL。 - * - * The URL where the image can be accessed. - */ - private String url; - - /** - * Base64编码的图像字符串。 - * - * Base64 encoded image string. - */ - private String b64Json; - - public Image(String url, String b64Json) { - this.url = url; - this.b64Json = b64Json; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getB64Json() { - return b64Json; - } - - public void setB64Json(String b64Json) { - this.b64Json = b64Json; - } - - @Override - public String toString() { - return "Image{" + "url='" + url + '\'' + ", b64Json='" + b64Json + '\'' + '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (!(o instanceof Image image)) - return false; - return Objects.equals(url, image.url) && Objects.equals(b64Json, image.b64Json); - } - - @Override - public int hashCode() { - return Objects.hash(url, b64Json); - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageClient.java deleted file mode 100644 index 1993fbe92..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageClient.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.image; - - -import org.springframework.ai.model.ModelClient; - -public interface ImageClient extends ModelClient { - - /** - * 跟 chat一样 - * @param imagePrompt the request object to be sent to the AI model - * @return - */ - ImageResponse call(ImagePrompt imagePrompt); - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageGeneration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageGeneration.java deleted file mode 100644 index 924f5872a..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageGeneration.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.image; - - -import org.springframework.ai.model.ModelResult; - -public class ImageGeneration implements ModelResult { - - // metadata 信息为空现在 - private ImageGenerationMetadata imageGenerationMetadata; - - private Image image; - - public ImageGeneration(Image image) { - this.image = image; - } - - public ImageGeneration(Image image, ImageGenerationMetadata imageGenerationMetadata) { - this.image = image; - this.imageGenerationMetadata = imageGenerationMetadata; - } - - @Override - public Image getOutput() { - return image; - } - - @Override - public ImageGenerationMetadata getMetadata() { - return imageGenerationMetadata; - } - - @Override - public String toString() { - return "ImageGeneration{" + "imageGenerationMetadata=" + imageGenerationMetadata + ", image=" + image + '}'; - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageGenerationMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageGenerationMetadata.java deleted file mode 100644 index e140aa814..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageGenerationMetadata.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.image; - -import org.springframework.ai.model.ResultMetadata; - -public interface ImageGenerationMetadata extends ResultMetadata { - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageMessage.java deleted file mode 100644 index 51d378b8c..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageMessage.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.image; - -import java.util.Objects; - -public class ImageMessage { - - private String text; - - private Float weight; - - public ImageMessage(String text) { - this.text = text; - } - - public ImageMessage(String text, Float weight) { - this.text = text; - this.weight = weight; - } - - public String getText() { - return text; - } - - public Float getWeight() { - return weight; - } - - @Override - public String toString() { - return "mageMessage{" + "text='" + text + '\'' + ", weight=" + weight + '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (!(o instanceof ImageMessage that)) - return false; - return Objects.equals(text, that.text) && Objects.equals(weight, that.weight); - } - - @Override - public int hashCode() { - return Objects.hash(text, weight); - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageOptions.java deleted file mode 100644 index 428376364..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageOptions.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.image; - -import org.springframework.ai.model.ModelOptions; - -/** - * ImageOptions represent the common options, portable across different image generation - * models. - */ -public interface ImageOptions extends ModelOptions { - - Integer getN(); - - String getModel(); - - Integer getWidth(); - - Integer getHeight(); - - String getResponseFormat(); // openai - url or base64 : stability ai byte[] or base64 - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageOptionsBuilder.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageOptionsBuilder.java deleted file mode 100644 index 49dc3497d..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageOptionsBuilder.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.image; - -public class ImageOptionsBuilder { - - private class ImageModelOptionsImpl implements ImageOptions { - - private Integer n; - - private String model; - - private Integer width; - - private Integer height; - - private String responseFormat; - - @Override - public Integer getN() { - return n; - } - - public void setN(Integer n) { - this.n = n; - } - - @Override - public String getModel() { - return model; - } - - public void setModel(String model) { - this.model = model; - } - - @Override - public String getResponseFormat() { - return responseFormat; - } - - public void setResponseFormat(String responseFormat) { - this.responseFormat = responseFormat; - } - - @Override - public Integer getWidth() { - return width; - } - - public void setWidth(Integer width) { - this.width = width; - } - - @Override - public Integer getHeight() { - return height; - } - - public void setHeight(Integer height) { - this.height = height; - } - - } - - private final ImageModelOptionsImpl options = new ImageModelOptionsImpl(); - - private ImageOptionsBuilder() { - - } - - public static ImageOptionsBuilder builder() { - return new ImageOptionsBuilder(); - } - - public ImageOptionsBuilder withN(Integer n) { - options.setN(n); - return this; - } - - public ImageOptionsBuilder withModel(String model) { - options.setModel(model); - return this; - } - - public ImageOptionsBuilder withResponseFormat(String responseFormat) { - options.setResponseFormat(responseFormat); - return this; - } - - public ImageOptionsBuilder withWidth(Integer width) { - options.setWidth(width); - return this; - } - - public ImageOptionsBuilder withHeight(Integer height) { - options.setHeight(height); - return this; - } - - public ImageOptions build() { - return options; - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImagePrompt.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImagePrompt.java deleted file mode 100644 index 4f9dcdc59..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImagePrompt.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.image; - -import org.springframework.ai.model.ModelRequest; - -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -/** - * 图片内容 - */ -public class ImagePrompt implements ModelRequest> { - - private final List messages; - - private ImageOptions imageModelOptions; - - public ImagePrompt(List messages) { - this.messages = messages; - } - - public ImagePrompt(List messages, ImageOptions imageModelOptions) { - this.messages = messages; - this.imageModelOptions = imageModelOptions; - } - - public ImagePrompt(ImageMessage imageMessage, ImageOptions imageOptions) { - this(Collections.singletonList(imageMessage), imageOptions); - } - - public ImagePrompt(String instructions, ImageOptions imageOptions) { - this(new ImageMessage(instructions), imageOptions); - } - - public ImagePrompt(String instructions) { -// this(new ImageMessage(instructions), ImageOptionsBuilder.builder().build()); - this(new ImageMessage(instructions), null); - } - - @Override - public List getInstructions() { - return messages; - } - - @Override - public ImageOptions getOptions() { - return imageModelOptions; - } - - @Override - public String toString() { - return "NewImagePrompt{" + "messages=" + messages + ", imageModelOptions=" + imageModelOptions + '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (!(o instanceof ImagePrompt that)) - return false; - return Objects.equals(messages, that.messages) && Objects.equals(imageModelOptions, that.imageModelOptions); - } - - @Override - public int hashCode() { - return Objects.hash(messages, imageModelOptions); - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageResponse.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageResponse.java deleted file mode 100644 index d3e314526..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageResponse.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.image; - -import org.springframework.ai.model.ModelResponse; - -import java.util.List; -import java.util.Objects; - -public class ImageResponse implements ModelResponse { - - private final ImageResponseMetadata imageResponseMetadata; - - private final List imageGenerations; - - public ImageResponse(List generations) { - this(generations, ImageResponseMetadata.NULL); - } - - public ImageResponse(List generations, ImageResponseMetadata imageResponseMetadata) { - this.imageResponseMetadata = imageResponseMetadata; - this.imageGenerations = List.copyOf(generations); - } - - @Override - public ImageGeneration getResult() { - return imageGenerations.get(0); - } - - @Override - public List getResults() { - return imageGenerations; - } - - @Override - public ImageResponseMetadata getMetadata() { - return imageResponseMetadata; - } - - @Override - public String toString() { - return "ImageResponse{" + "imageResponseMetadata=" + imageResponseMetadata + ", imageGenerations=" - + imageGenerations + '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (!(o instanceof ImageResponse that)) - return false; - return Objects.equals(imageResponseMetadata, that.imageResponseMetadata) - && Objects.equals(imageGenerations, that.imageGenerations); - } - - @Override - public int hashCode() { - return Objects.hash(imageResponseMetadata, imageGenerations); - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageResponseMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageResponseMetadata.java deleted file mode 100644 index 78fa5e7de..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/image/ImageResponseMetadata.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.image; - - -import org.springframework.ai.model.ResponseMetadata; - -public interface ImageResponseMetadata extends ResponseMetadata { - - ImageResponseMetadata NULL = new ImageResponseMetadata() { - }; - - default Long created() { - return System.currentTimeMillis(); - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelClient.java deleted file mode 100644 index 03bec4c70..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelClient.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model; - -/** - * The ModelClient interface provides a generic API for invoking AI models. It is designed - * to handle the interaction with various types of AI models by abstracting the process of - * sending requests and receiving responses. The interface uses Java generics to - * accommodate different types of requests and responses, enhancing flexibility and - * adaptability across different AI model implementations. - * - * @param the generic type of the request to the AI model - * @param the generic type of the response from the AI model - * @author Mark Pollack - * @since 0.8.0 - */ -public interface ModelClient, TRes extends ModelResponse> { - - /** - * Executes a method call to the AI model. - * @param request the request object to be sent to the AI model - * @return the response from the AI model - */ - TRes call(TReq request) throws Throwable; - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelOptions.java deleted file mode 100644 index 96b301b79..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelOptions.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model; - -/** - * Interface representing the customizable options for AI model interactions. This marker - * interface allows for the specification of various settings and parameters that can - * influence the behavior and output of AI models. It is designed to provide flexibility - * and adaptability in different AI scenarios, ensuring that the AI models can be - * fine-tuned according to specific requirements. - * - * @author Mark Pollack - * @since 0.8.0 - */ -public interface ModelOptions { - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelOptionsUtils.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelOptionsUtils.java deleted file mode 100644 index 9360399b6..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelOptionsUtils.java +++ /dev/null @@ -1,387 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.github.victools.jsonschema.generator.*; -import com.github.victools.jsonschema.module.jackson.JacksonModule; -import com.github.victools.jsonschema.module.jackson.JacksonOption; -import com.github.victools.jsonschema.module.swagger2.Swagger2Module; -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.util.Assert; -import org.springframework.util.CollectionUtils; - -import java.beans.PropertyDescriptor; -import java.lang.reflect.Field; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; - -/** - * Utility class for manipulating {@link ModelOptions} objects. - * - * @author Christian Tzolov - * @since 0.8.0 - */ -public final class ModelOptionsUtils { - - private final static ObjectMapper OBJECT_MAPPER = new ObjectMapper() - .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) - .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); - - private final static List BEAN_MERGE_FIELD_EXCISIONS = List.of("class"); - - private static ConcurrentHashMap, List> REQUEST_FIELD_NAMES_PER_CLASS = new ConcurrentHashMap, List>(); - - private static AtomicReference SCHEMA_GENERATOR_CACHE = new AtomicReference<>(); - - private ModelOptionsUtils() { - - } - - /** - * Converts the given JSON string to a Map of String and Object. - * @param json the JSON string to convert to a Map. - * @return the converted Map. - */ - public static Map jsonToMap(String json) { - try { - return OBJECT_MAPPER.readValue(json, MAP_TYPE_REF); - } - catch (Exception e) { - throw new RuntimeException(e); - } - } - - private static TypeReference> MAP_TYPE_REF = new TypeReference>() { - }; - - /** - * Converts the given JSON string to an Object of the given type. - * @param the type of the object to return. - * @param json the JSON string to convert to an object. - * @param type the type of the object to return. - * @return Object instance of the given type. - */ - public static T jsonToObject(String json, Class type) { - try { - return OBJECT_MAPPER.readValue(json, type); - } - catch (Exception e) { - throw new RuntimeException("Failed to json: " + json, e); - } - } - - /** - * Converts the given object to a JSON string. - * @param object the object to convert to a JSON string. - * @return the JSON string. - */ - public static String toJsonString(Object object) { - try { - return OBJECT_MAPPER.writeValueAsString(object); - } - catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } - - /** - * Merges the source object into the target object and returns an object represented - * by the given class. The JSON property names are used to match the fields to merge. - * The source non-null values override the target values with the same field name. The - * source null values are ignored. If the acceptedFieldNames is not empty, only the - * fields with the given names are merged and returned. If the acceptedFieldNames is - * empty, use the {@code @JsonProperty} names, inferred from the provided clazz. - * @param they type of the class to return. - * @param source the source object to merge. - * @param target the target object to merge into. - * @param clazz the class to return. - * @param acceptedFieldNames the list of field names accepted for the target object. - * @return the merged object represented by the given class. - */ - public static T merge(Object source, Object target, Class clazz, List acceptedFieldNames) { - - if (source == null) { - source = Map.of(); - } - - List requestFieldNames = CollectionUtils.isEmpty(acceptedFieldNames) - ? REQUEST_FIELD_NAMES_PER_CLASS.computeIfAbsent(clazz, ModelOptionsUtils::getJsonPropertyValues) - : acceptedFieldNames; - - if (CollectionUtils.isEmpty(requestFieldNames)) { - throw new IllegalArgumentException("No @JsonProperty fields found in the " + clazz.getName()); - } - - Map sourceMap = ModelOptionsUtils.objectToMap(source); - Map targetMap = ModelOptionsUtils.objectToMap(target); - - targetMap.putAll(sourceMap.entrySet() - .stream() - .filter(e -> e.getValue() != null) - .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()))); - - targetMap = targetMap.entrySet() - .stream() - .filter(e -> requestFieldNames.contains(e.getKey())) - .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue())); - - return ModelOptionsUtils.mapToClass(targetMap, clazz); - } - - /** - * Merges the source object into the target object and returns an object represented - * by the given class. The JSON property names are used to match the fields to merge. - * The source non-null values override the target values with the same field name. The - * source null values are ignored. Returns the only field names that match the - * {@code @JsonProperty} names, inferred from the provided clazz. - * @param they type of the class to return. - * @param source the source object to merge. - * @param target the target object to merge into. - * @param clazz the class to return. - * @return the merged object represented by the given class. - */ - public static T merge(Object source, Object target, Class clazz) { - return ModelOptionsUtils.merge(source, target, clazz, null); - } - - /** - * Converts the given object to a Map. - * @param source the object to convert to a Map. - * @return the converted Map. - */ - public static Map objectToMap(Object source) { - if (source == null) { - return new HashMap<>(); - } - try { - String json = OBJECT_MAPPER.writeValueAsString(source); - return OBJECT_MAPPER.readValue(json, new TypeReference>() { - }) - .entrySet() - .stream() - .filter(e -> e.getValue() != null) - .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue())); - } - catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } - - /** - * Converts the given Map to the given class. - * @param the type of the class to return. - * @param source the Map to convert to the given class. - * @param clazz the class to convert the Map to. - * @return the converted class. - */ - public static T mapToClass(Map source, Class clazz) { - try { - String json = OBJECT_MAPPER.writeValueAsString(source); - return OBJECT_MAPPER.readValue(json, clazz); - } - catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } - - /** - * Returns the list of name values of the {@link JsonProperty} annotations. - * @param clazz the class that contains fields annotated with {@link JsonProperty}. - * @return the list of values of the {@link JsonProperty} annotations. - */ - public static List getJsonPropertyValues(Class clazz) { - List values = new ArrayList<>(); - Field[] fields = clazz.getDeclaredFields(); - for (Field field : fields) { - JsonProperty jsonPropertyAnnotation = field.getAnnotation(JsonProperty.class); - if (jsonPropertyAnnotation != null) { - values.add(jsonPropertyAnnotation.value()); - } - } - return values; - } - - /** - * Returns a new instance of the targetBeanClazz that copies the bean values from the - * sourceBean instance. - * @param sourceBean the source bean to copy the values from. - * @param sourceInterfaceClazz the source interface class. Only the fields with the - * same name as the interface methods are copied. This allow the source object to be a - * subclass of the source interface with additional, non-interface fields. - * @param targetBeanClazz the target class, a subclass of the ChatOptions, to convert - * into. - * @param the target class type. - * @return a new instance of the targetBeanClazz with the values from the sourceBean - * instance. - */ - public static T copyToTarget(S sourceBean, Class sourceInterfaceClazz, - Class targetBeanClazz) { - - Assert.notNull(sourceInterfaceClazz, "SourceOptionsClazz must not be null"); - Assert.notNull(targetBeanClazz, "TargetOptionsClazz must not be null"); - - if (sourceBean == null) { - return null; - } - - if (sourceBean.getClass().isAssignableFrom(targetBeanClazz)) { - return (T) sourceBean; - } - - try { - T targetOptions = targetBeanClazz.getConstructor().newInstance(); - - ModelOptionsUtils.mergeBeans(sourceBean, targetOptions, sourceInterfaceClazz, true); - - return targetOptions; - } - catch (Exception e) { - throw new RuntimeException( - "Failed to convert the " + sourceInterfaceClazz.getName() + " into " + targetBeanClazz.getName(), - e); - } - } - - /** - * Merges the source object into the target object. The source null values are - * ignored. Only objects with Getter and Setter methods are supported. - * @param the type of the source and target object. - * @param source the source object to merge. - * @param target the target object to merge into. - * @param sourceInterfaceClazz the source interface class. Only the fields with the - * same name as the interface methods are merged. This allow the source object to be a - * subclass of the source interface with additional, non-interface fields. - * @param overrideNonNullTargetValues if true, the source non-null values override the - * target values with the same field name. If false, the source non-null values are - * ignored. - * @return the merged target object. - */ - public static T mergeBeans(S source, T target, Class sourceInterfaceClazz, - boolean overrideNonNullTargetValues) { - Assert.notNull(source, "Source object must not be null"); - Assert.notNull(target, "Target object must not be null"); - - BeanWrapper sourceBeanWrap = new BeanWrapperImpl(source); - BeanWrapper targetBeanWrap = new BeanWrapperImpl(target); - - List interfaceNames = Arrays.stream(sourceInterfaceClazz.getMethods()).map(m -> m.getName()).toList(); - - for (PropertyDescriptor descriptor : sourceBeanWrap.getPropertyDescriptors()) { - - if (!BEAN_MERGE_FIELD_EXCISIONS.contains(descriptor.getName()) - && interfaceNames.contains(toGetName(descriptor.getName()))) { - - String propertyName = descriptor.getName(); - Object value = sourceBeanWrap.getPropertyValue(propertyName); - - // Copy value to the target object - if (value != null) { - var targetValue = targetBeanWrap.getPropertyValue(propertyName); - - if (targetValue == null || overrideNonNullTargetValues) { - targetBeanWrap.setPropertyValue(propertyName, value); - } - } - } - } - - return target; - } - - private static String toGetName(String name) { - return "get" + name.substring(0, 1).toUpperCase() + name.substring(1); - } - - /** - * Generates JSON Schema (version 2020_12) for the given class. - * @param clazz the class to generate JSON Schema for. - * @param toUpperCaseTypeValues if true, the type values are converted to upper case. - * @return the generated JSON Schema as a String. - */ - public static String getJsonSchema(Class clazz, boolean toUpperCaseTypeValues) { - - if (SCHEMA_GENERATOR_CACHE.get() == null) { - - JacksonModule jacksonModule = new JacksonModule(JacksonOption.RESPECT_JSONPROPERTY_REQUIRED); - Swagger2Module swaggerModule = new Swagger2Module(); - - SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(SchemaVersion.DRAFT_2020_12, - OptionPreset.PLAIN_JSON) - .with(Option.EXTRA_OPEN_API_FORMAT_VALUES) - .with(Option.PLAIN_DEFINITION_KEYS) - .with(swaggerModule) - .with(jacksonModule); - - SchemaGeneratorConfig config = configBuilder.build(); - SchemaGenerator generator = new SchemaGenerator(config); - SCHEMA_GENERATOR_CACHE.compareAndSet(null, generator); - } - - ObjectNode node = SCHEMA_GENERATOR_CACHE.get().generateSchema(clazz); - if (toUpperCaseTypeValues) { // Required for OpenAPI 3.0 (at least Vertex AI - // version of it). - toUpperCaseTypeValues(node); - } - - return node.toPrettyString(); - } - - public static void toUpperCaseTypeValues(ObjectNode node) { - if (node == null) { - return; - } - if (node.isObject()) { - node.fields().forEachRemaining(entry -> { - JsonNode value = entry.getValue(); - if (value.isObject()) { - toUpperCaseTypeValues((ObjectNode) value); - } - else if (value.isArray()) { - ((ArrayNode) value).elements().forEachRemaining(element -> { - if (element.isObject() || element.isArray()) { - toUpperCaseTypeValues((ObjectNode) element); - } - }); - } - else if (value.isTextual() && entry.getKey().equals("type")) { - String oldValue = ((ObjectNode) node).get("type").asText(); - ((ObjectNode) node).put("type", oldValue.toUpperCase()); - } - }); - } - else if (node.isArray()) { - node.elements().forEachRemaining(element -> { - if (element.isObject() || element.isArray()) { - toUpperCaseTypeValues((ObjectNode) element); - } - }); - } - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelRequest.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelRequest.java deleted file mode 100644 index b3c4969d4..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelRequest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model; - -/** - * 表示对AI模型的请求的接口。此接口封装了 与人工智能模型交互所需的必要信息,包括指令或 输入(通用类型T)和附加模型选项。它提供了一种标准化的方式 - * 向人工智能模型发送请求,确保包括所有必要的细节,并且可以易于管理。 - * - * Interface representing a request to an AI model. This interface encapsulates the - * necessary information required to interact with an AI model, including instructions or - * inputs (of generic type T) and additional model options. It provides a standardized way - * to send requests to AI models, ensuring that all necessary details are included and can - * be easily managed. - * - * @param the type of instructions or input required by the AI model - * @author Mark Pollack - * @since 0.8.0 - */ -public interface ModelRequest { - - /** - * 检索AI模型所需的指令或输入。 返回AI模型所需的指令或输入 - * - * Retrieves the instructions or input required by the AI model. - * @return the instructions or input required by the AI model - */ - T getInstructions(); // required input - - /** - * 检索人工智能模型交互的可自定义选项。 返回AI模型交互的自定义选项 - * - * Retrieves the customizable options for AI model interactions. - * @return the customizable options for AI model interactions - */ - ModelOptions getOptions(); - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelResponse.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelResponse.java deleted file mode 100644 index b3f40ffe7..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelResponse.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model; - -import java.util.List; - -/** - * - * 表示从AI模型接收到的响应的接口。此接口提供 访问AI模型生成的主要结果或结果列表的方法,以及 以及响应元数据。它是封装和管理的标准化方式 - * 人工智能模型的输出,确保轻松检索和处理生成的信息 - * - * Interface representing the response received from an AI model. This interface provides - * methods to access the main result or a list of results generated by the AI model, along - * with the response metadata. It serves as a standardized way to encapsulate and manage - * the output from AI models, ensuring easy retrieval and processing of the generated - * information. - * - * @param the type of the result(s) provided by the AI model - * @author Mark Pollack - * @since 0.8.0 - */ -public interface ModelResponse> { - - /** - * 检索AI模型的结果。 - * - * Retrieves the result of the AI model. - * @return the result generated by the AI model - */ - T getResult(); - - /** - * 检索AI模型生成的输出列表。 - * - * Retrieves the list of generated outputs by the AI model. - * @return the list of generated outputs - */ - List getResults(); - - /** - * 检索与AI模型的响应相关联的响应元数据。 - * - * Retrieves the response metadata associated with the AI model's response. - * @return the response metadata - */ - ResponseMetadata getMetadata(); - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelResult.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelResult.java deleted file mode 100644 index 5a5613a72..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ModelResult.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model; - -/** - * This interface provides methods to access the main output of the AI model and the - * metadata associated with this result. It is designed to offer a standardized and - * comprehensive way to handle and interpret the outputs generated by AI models, catering - * to diverse AI applications and use cases. - * - * @param the type of the output generated by the AI model - * @author Mark Pollack - * @since 0.8.0 - */ -public interface ModelResult { - - /** - * Retrieves the output generated by the AI model. - * @return the output generated by the AI model - */ - T getOutput(); - - /** - * Retrieves the metadata associated with the result of an AI model. - * @return the metadata associated with the result - */ - ResultMetadata getMetadata(); - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ResponseMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ResponseMetadata.java deleted file mode 100644 index 15e685d02..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ResponseMetadata.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model; - -/** - * 表示与AI模型的响应相关联的元数据的接口。此接口 旨在提供有关人工智能生成反应的附加信息 模型,包括处理细节和模型特定数据。它是一种价值 - * 核心领域内的对象,增强对人工智能模型的理解和管理 在各种应用中的响应。 - * - * Interface representing metadata associated with an AI model's response. This interface - * is designed to provide additional information about the generative response from an AI - * model, including processing details and model-specific data. It serves as a value - * object within the core domain, enhancing the understanding and management of AI model - * responses in various applications. - * - * @author Mark Pollack - * @since 0.8.0 - */ -public interface ResponseMetadata { - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ResultMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ResultMetadata.java deleted file mode 100644 index 78d5f7f6a..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/ResultMetadata.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model; - -/** - * Interface representing metadata associated with the results of an AI model. This - * interface focuses on providing additional context and insights into the results - * generated by AI models. It could include information like computation time, model - * version, or other relevant details that enhance understanding and management of AI - * model outputs in various applications. - * - * @author Mark Pollack - * @since 0.8.0 - */ -public interface ResultMetadata { - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/StreamingModelClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/StreamingModelClient.java deleted file mode 100644 index da1db1504..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/StreamingModelClient.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model; - -import reactor.core.publisher.Flux; - -/** - * The StreamingModelClient interface provides a generic API for invoking a AI models with - * streaming response. It abstracts the process of sending requests and receiving a - * streaming responses. The interface uses Java generics to accommodate different types of - * requests and responses, enhancing flexibility and adaptability across different AI - * model implementations. - * - * @param the generic type of the request to the AI model - * @param the generic type of a single item in the streaming response from the - * AI model - * @author Christian Tzolov - * @since 0.8.0 - */ -public interface StreamingModelClient, TResChunk extends ModelResponse> { - - /** - * Executes a method call to the AI model. - * @param request the request object to be sent to the AI model - * @return the streaming response from the AI model - */ - Flux stream(TReq request); - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/AbstractFunctionCallSupport.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/AbstractFunctionCallSupport.java deleted file mode 100644 index 67a34b1b1..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/AbstractFunctionCallSupport.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model.function; - -import org.springframework.util.CollectionUtils; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -/** - * @author Christian Tzolov - */ -public abstract class AbstractFunctionCallSupport { - - protected final static boolean IS_RUNTIME_CALL = true; - - /** - * 函数回调寄存器用于按名称解析函数回调。 - * - * The function callback register is used to resolve the function callbacks by name. - */ - protected final Map functionCallbackRegister = new ConcurrentHashMap<>(); - - /** - * 函数回调上下文用于按名称解析函数回调来自Spring上下文。 - * 它是可选的,通常与Spring一起使用自动配置。 - * - * The function callback context is used to resolve the function callbacks by name - * from the Spring context. It is optional and usually used with Spring - * auto-configuration. - */ - protected final FunctionCallbackContext functionCallbackContext; - - public AbstractFunctionCallSupport(FunctionCallbackContext functionCallbackContext) { - this.functionCallbackContext = functionCallbackContext; - } - - public Map getFunctionCallbackRegister() { - return this.functionCallbackRegister; - } - - protected Set handleFunctionCallbackConfigurations(FunctionCallingOptions options, boolean isRuntimeCall) { - - Set functionToCall = new HashSet<>(); - - if (options != null) { - if (!CollectionUtils.isEmpty(options.getFunctionCallbacks())) { - options.getFunctionCallbacks().stream().forEach(functionCallback -> { - - // Register the tool callback. - if (isRuntimeCall) { - this.functionCallbackRegister.put(functionCallback.getName(), functionCallback); - } - else { - this.functionCallbackRegister.putIfAbsent(functionCallback.getName(), functionCallback); - } - - // Automatically enable the function, usually from prompt callback. - if (isRuntimeCall) { - functionToCall.add(functionCallback.getName()); - } - }); - } - - // Add the explicitly enabled functions. - if (!CollectionUtils.isEmpty(options.getFunctions())) { - functionToCall.addAll(options.getFunctions()); - } - } - - return functionToCall; - } - - /** - * Resolve the function callbacks by name. Retrieve them from the registry or try to - * resolve them from the Application Context. - * @param functionNames Name of function callbacks to retrieve. - * @return list of resolved FunctionCallbacks. - */ - protected List resolveFunctionCallbacks(Set functionNames) { - - List retrievedFunctionCallbacks = new ArrayList<>(); - - for (String functionName : functionNames) { - if (!this.functionCallbackRegister.containsKey(functionName)) { - - if (this.functionCallbackContext != null) { - FunctionCallback functionCallback = this.functionCallbackContext.getFunctionCallback(functionName, - null); - if (functionCallback != null) { - this.functionCallbackRegister.put(functionName, functionCallback); - } - else { - throw new IllegalStateException( - "No function callback [" + functionName + "] fund in tht FunctionCallbackContext"); - } - } - else { - throw new IllegalStateException("No function callback found for name: " + functionName); - } - } - FunctionCallback functionCallback = this.functionCallbackRegister.get(functionName); - - retrievedFunctionCallbacks.add(functionCallback); - } - - return retrievedFunctionCallbacks; - } - - /// - protected Resp callWithFunctionSupport(Req request) { - Resp response = this.doChatCompletion(request); - return this.handleFunctionCallOrReturn(request, response); - } - - protected Resp handleFunctionCallOrReturn(Req request, Resp response) { - - if (!this.isToolFunctionCall(response)) { - return response; - } - - // The chat completion tool call requires the complete conversation - // history. Including the initial user message. - List conversationHistory = new ArrayList<>(); - - conversationHistory.addAll(this.doGetUserMessages(request)); - - Msg responseMessage = this.doGetToolResponseMessage(response); - - // Add the assistant response to the message conversation history. - conversationHistory.add(responseMessage); - - Req newRequest = this.doCreateToolResponseRequest(request, responseMessage, conversationHistory); - - return this.callWithFunctionSupport(newRequest); - } - - abstract protected Req doCreateToolResponseRequest(Req previousRequest, Msg responseMessage, - List conversationHistory); - - abstract protected List doGetUserMessages(Req request); - - abstract protected Msg doGetToolResponseMessage(Resp response); - - abstract protected Resp doChatCompletion(Req request); - - abstract protected boolean isToolFunctionCall(Resp response); - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/AbstractFunctionCallback.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/AbstractFunctionCallback.java deleted file mode 100644 index 801ea3c10..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/AbstractFunctionCallback.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model.function; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.util.Assert; - -import java.util.function.Function; - -/** - * Abstract implementation of the {@link FunctionCallback} for interacting with the - * Model's function calling protocol and a {@link Function} wrapping the interaction with - * the 3rd party service/function. - * - * Implement the {@code O apply(I request) } method to implement the interaction with the - * 3rd party service/function. - * - * The {@link #responseConverter} function is responsible to convert the 3rd party - * function's output type into a string expected by the LLM model. - * - * @param the 3rd party service input type. - * @param the 3rd party service output type. - * @author Christian Tzolov - */ -abstract class AbstractFunctionCallback implements Function, FunctionCallback { - - private final String name; - - private final String description; - - private final Class inputType; - - private final String inputTypeSchema; - - private final ObjectMapper objectMapper; - - private final Function responseConverter; - - /** - * Constructs a new {@link AbstractFunctionCallback} with the given name, description, - * input type and default object mapper. - * @param name Function name. Should be unique within the ChatClient's function - * registry. - * @param description Function description. Used as a "system prompt" by the model to - * decide if the function should be called. - * @param inputTypeSchema Used to compute, the argument's Schema (such as JSON Schema - * or OpenAPI Schema)required by the Model's function calling protocol. - * @param inputType Used to compute, the argument's JSON schema required by the - * Model's function calling protocol. - * @param responseConverter Used to convert the function's output type to a string. - * @param objectMapper Used to convert the function's input and output types to and - * from JSON. - */ - protected AbstractFunctionCallback(String name, String description, String inputTypeSchema, Class inputType, - Function responseConverter, ObjectMapper objectMapper) { - Assert.notNull(name, "Name must not be null"); - Assert.notNull(description, "Description must not be null"); - Assert.notNull(inputType, "InputType must not be null"); - Assert.notNull(inputTypeSchema, "InputTypeSchema must not be null"); - Assert.notNull(responseConverter, "ResponseConverter must not be null"); - Assert.notNull(objectMapper, "ObjectMapper must not be null"); - this.name = name; - this.description = description; - this.inputType = inputType; - this.inputTypeSchema = inputTypeSchema; - this.responseConverter = responseConverter; - this.objectMapper = objectMapper; - } - - @Override - public String getName() { - return this.name; - } - - @Override - public String getDescription() { - return this.description; - } - - @Override - public String getInputTypeSchema() { - return this.inputTypeSchema; - } - - @Override - public String call(String functionArguments) { - - // Convert the tool calls JSON arguments into a Java function request object. - I request = fromJson(functionArguments, inputType); - - // extend conversation with function response. - return this.andThen(this.responseConverter).apply(request); - } - - private T fromJson(String json, Class targetClass) { - try { - return this.objectMapper.readValue(json, targetClass); - } - catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + ((description == null) ? 0 : description.hashCode()); - result = prime * result + ((inputType == null) ? 0 : inputType.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - AbstractFunctionCallback other = (AbstractFunctionCallback) obj; - if (name == null) { - if (other.name != null) - return false; - } - else if (!name.equals(other.name)) - return false; - if (description == null) { - if (other.description != null) - return false; - } - else if (!description.equals(other.description)) - return false; - if (inputType == null) { - if (other.inputType != null) - return false; - } - else if (!inputType.equals(other.inputType)) - return false; - return true; - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallback.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallback.java deleted file mode 100644 index 91fc3ba8a..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallback.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model.function; - -/** - * - * 表示模型函数调用处理程序。实现已向注册对触发函数调用的提示进行建模和调用。 - * - * https://blog.csdn.net/weixin_37546425/article/details/136402740 - * - * https://www.163.com/dy/article/ICE2S20P05119NPR.html - * - * Represents a model function call handler. Implementations are registered with the - * Models and called on prompts that trigger the function call. - * - * @author Christian Tzolov - */ -public interface FunctionCallback { - - /** - * @return Returns the Function name. Unique within the model. - */ - public String getName(); - - /** - * @return Returns the function description. This description is used by the model do - * decide if the function should be called or not. - */ - public String getDescription(); - - /** - * @return Returns the JSON schema of the function input type. - */ - public String getInputTypeSchema(); - - /** - * Called when a model detects and triggers a function call. The model is responsible - * to pass the function arguments in the pre-configured JSON schema format. - * @param functionInput JSON string with the function arguments to be passed to the - * function. The arguments are defined as JSON schema usually registered with the the - * model. - * @return String containing the function call response. - */ - public String call(String functionInput); - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallbackContext.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallbackContext.java deleted file mode 100644 index 5524182bc..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallbackContext.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.ai.model.function; - -import com.fasterxml.jackson.annotation.JsonClassDescription; -import org.springframework.beans.BeansException; -import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; -import org.springframework.cloud.function.context.config.FunctionContextUtils; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.annotation.Description; -import org.springframework.context.support.GenericApplicationContext; -import org.springframework.lang.NonNull; -import org.springframework.lang.Nullable; -import org.springframework.util.StringUtils; - -import java.lang.reflect.Type; -import java.util.function.Function; - -/** - * A Spring {@link ApplicationContextAware} implementation that provides a way to retrieve - * a {@link Function} from the Spring context and wrap it into a {@link FunctionCallback}. - * - * The name of the function is determined by the bean name. - * - * The description of the function is determined by the following rules: - *

    - *
  • Provided as a default description
  • - *
  • Provided as a {@code @Description} annotation on the bean
  • - *
  • Provided as a {@code @JsonClassDescription} annotation on the input class
  • - *
- * - * @author Christian Tzolov - * @author Christopher Smith - */ -public class FunctionCallbackContext implements ApplicationContextAware { - - private GenericApplicationContext applicationContext; - - private FunctionCallbackWrapper.Builder.SchemaType schemaType = FunctionCallbackWrapper.Builder.SchemaType.JSON_SCHEMA; - - public void setSchemaType(FunctionCallbackWrapper.Builder.SchemaType schemaType) { - this.schemaType = schemaType; - } - - @Override - public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException { - this.applicationContext = (GenericApplicationContext) applicationContext; - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - public FunctionCallback getFunctionCallback(@NonNull String beanName, @Nullable String defaultDescription) { - - Type beanType = FunctionContextUtils.findType(this.applicationContext.getBeanFactory(), beanName); - - if (beanType == null) { - throw new IllegalArgumentException( - "Functional bean with name: " + beanName + " does not exist in the context."); - } - - if (!Function.class.isAssignableFrom(FunctionTypeUtils.getRawType(beanType))) { - throw new IllegalArgumentException( - "Function call Bean must be of type Function. Found: " + beanType.getTypeName()); - } - - Type functionInputType = TypeResolverHelper.getFunctionArgumentType(beanType, 0); - - Class functionInputClass = FunctionTypeUtils.getRawType(functionInputType); - String functionName = beanName; - String functionDescription = defaultDescription; - - if (!StringUtils.hasText(functionDescription)) { - // Look for a Description annotation on the bean - Description descriptionAnnotation = applicationContext.findAnnotationOnBean(beanName, Description.class); - - if (descriptionAnnotation != null) { - functionDescription = descriptionAnnotation.value(); - } - - if (!StringUtils.hasText(functionDescription)) { - // Look for a JsonClassDescription annotation on the input class - JsonClassDescription jsonClassDescriptionAnnotation = functionInputClass - .getAnnotation(JsonClassDescription.class); - if (jsonClassDescriptionAnnotation != null) { - functionDescription = jsonClassDescriptionAnnotation.value(); - } - } - - if (!StringUtils.hasText(functionDescription)) { - throw new IllegalStateException("Could not determine function description." - + "Please provide a description either as a default parameter, via @Description annotation on the bean " - + "or @JsonClassDescription annotation on the input class."); - } - } - - Object bean = this.applicationContext.getBean(beanName); - - // TODO: 2024/3/16 fansili 适配jdk8 - return null; -// if (bean instanceof Function function) { -// return FunctionCallbackWrapper.builder(function) -// .withName(functionName) -// .withSchemaType(this.schemaType) -// .withDescription(functionDescription) -// .withInputType(functionInputClass) -// .build(); -// } -// else { -// throw new IllegalArgumentException("Bean must be of type Function"); -// } - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallbackWrapper.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallbackWrapper.java deleted file mode 100644 index 23c981b0e..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallbackWrapper.java +++ /dev/null @@ -1,140 +0,0 @@ -package org.springframework.ai.model.function; - -import org.springframework.ai.model.ModelOptionsUtils; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.util.Assert; - -import java.util.function.Function; - -/** - * Note that the underlying function is responsible for converting the output into format - * that can be consumed by the Model. The default implementation converts the output into - * String before sending it to the Model. Provide a custom function responseConverter - * implementation to override this. - * - */ -public class FunctionCallbackWrapper extends AbstractFunctionCallback { - - private final Function function; - - private FunctionCallbackWrapper(String name, String description, String inputTypeSchema, Class inputType, - Function responseConverter, Function function) { - super(name, description, inputTypeSchema, inputType, responseConverter, - new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)); - Assert.notNull(function, "Function must not be null"); - this.function = function; - } - - @SuppressWarnings("unchecked") - private static Class resolveInputType(Function function) { - return (Class) TypeResolverHelper.getFunctionInputClass((Class>) function.getClass()); - } - - @Override - public O apply(I input) { - return this.function.apply(input); - } - - public static Builder builder(Function function) { - return new Builder<>(function); - } - - public static class Builder { - - public enum SchemaType { - - JSON_SCHEMA, OPEN_API_SCHEMA - - } - - private String name; - - private String description; - - private Class inputType; - - private final Function function; - - private SchemaType schemaType = SchemaType.JSON_SCHEMA; - - public Builder(Function function) { - Assert.notNull(function, "Function must not be null"); - this.function = function; - } - - // By default the response is converted to a JSON string. - private Function responseConverter = (response) -> ModelOptionsUtils.toJsonString(response); - - private String inputTypeSchema; - - private ObjectMapper objectMapper = new ObjectMapper() - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - - public Builder withName(String name) { - Assert.hasText(name, "Name must not be empty"); - this.name = name; - return this; - } - - public Builder withDescription(String description) { - Assert.hasText(description, "Description must not be empty"); - this.description = description; - return this; - } - - @SuppressWarnings("unchecked") - public Builder withInputType(Class inputType) { - this.inputType = (Class) inputType; - return this; - } - - public Builder withResponseConverter(Function responseConverter) { - Assert.notNull(responseConverter, "ResponseConverter must not be null"); - this.responseConverter = responseConverter; - return this; - } - - public Builder withInputTypeSchema(String inputTypeSchema) { - Assert.hasText(inputTypeSchema, "InputTypeSchema must not be empty"); - this.inputTypeSchema = inputTypeSchema; - return this; - } - - public Builder withObjectMapper(ObjectMapper objectMapper) { - Assert.notNull(objectMapper, "ObjectMapper must not be null"); - this.objectMapper = objectMapper; - return this; - } - - public Builder withSchemaType(SchemaType schemaType) { - Assert.notNull(schemaType, "SchemaType must not be null"); - this.schemaType = schemaType; - return this; - } - - public FunctionCallbackWrapper build() { - - Assert.hasText(this.name, "Name must not be empty"); - Assert.hasText(this.description, "Description must not be empty"); - // Assert.notNull(this.inputType, "InputType must not be null"); - Assert.notNull(this.function, "Function must not be null"); - Assert.notNull(this.responseConverter, "ResponseConverter must not be null"); - Assert.notNull(this.objectMapper, "ObjectMapper must not be null"); - - if (this.inputType == null) { - this.inputType = resolveInputType(this.function); - } - - if (this.inputTypeSchema == null) { - boolean upperCaseTypeValues = this.schemaType == SchemaType.OPEN_API_SCHEMA; - this.inputTypeSchema = ModelOptionsUtils.getJsonSchema(this.inputType, upperCaseTypeValues); - } - - return new FunctionCallbackWrapper<>(this.name, this.description, this.inputTypeSchema, this.inputType, - this.responseConverter, this.function); - } - - } - -} \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallingOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallingOptions.java deleted file mode 100644 index c66a4f5b1..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallingOptions.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model.function; - -import java.util.List; -import java.util.Set; - -/** - * @author Christian Tzolov - */ -public interface FunctionCallingOptions { - - /** - * Function Callbacks to be registered with the ChatClient. For Prompt Options the - * functionCallbacks are automatically enabled for the duration of the prompt - * execution. For Default Options the FunctionCallbacks are registered but disabled by - * default. You have to use "functions" property to list the function names from the - * ChatClient registry to be used in the chat completion requests. - * @return Return the Function Callbacks to be registered with the ChatClient. - */ - List getFunctionCallbacks(); - - /** - * Set the Function Callbacks to be registered with the ChatClient. - * @param functionCallbacks the Function Callbacks to be registered with the - * ChatClient. - */ - void setFunctionCallbacks(List functionCallbacks); - - /** - * @return List of function names from the ChatClient registry to be used in the next - * chat completion requests. - */ - Set getFunctions(); - - /** - * Set the list of function names from the ChatClient registry to be used in the next - * chat completion requests. - * @param functions the list of function names from the ChatClient registry to be used - * in the next chat completion requests. - */ - void setFunctions(Set functions); - - /** - * @return Returns FunctionCallingOptionsBuilder to create a new instance of - * FunctionCallingOptions. - */ - public static FunctionCallingOptionsBuilder builder() { - return new FunctionCallingOptionsBuilder(); - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallingOptionsBuilder.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallingOptionsBuilder.java deleted file mode 100644 index 44044400d..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/FunctionCallingOptionsBuilder.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model.function; - -import org.springframework.ai.chat.prompt.ChatOptions; -import org.springframework.util.Assert; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * Builder for {@link FunctionCallingOptions}. Using the {@link FunctionCallingOptions} - * permits options portability between different AI providers that support - * function-calling. - * - * @author Christian Tzolov - * @since 0.8.1 - */ -public class FunctionCallingOptionsBuilder { - - private final PortableFunctionCallingOptions options; - - public FunctionCallingOptionsBuilder() { - this.options = new PortableFunctionCallingOptions(); - } - - public FunctionCallingOptionsBuilder withFunctionCallbacks(List functionCallbacks) { - this.options.setFunctionCallbacks(functionCallbacks); - return this; - } - - public FunctionCallingOptionsBuilder withFunctionCallback(FunctionCallback functionCallback) { - Assert.notNull(functionCallback, "FunctionCallback must not be null"); - this.options.getFunctionCallbacks().add(functionCallback); - return this; - } - - public FunctionCallingOptionsBuilder withFunctions(Set functions) { - this.options.setFunctions(functions); - return this; - } - - public FunctionCallingOptionsBuilder withFunction(String function) { - Assert.notNull(function, "Function must not be null"); - this.options.getFunctions().add(function); - return this; - } - - public FunctionCallingOptionsBuilder withTemperature(Float temperature) { - this.options.setTemperature(temperature); - return this; - } - - public FunctionCallingOptionsBuilder withTopP(Float topP) { - this.options.setTopP(topP); - return this; - } - - public FunctionCallingOptionsBuilder withTopK(Integer topK) { - this.options.setTopK(topK); - return this; - } - - public PortableFunctionCallingOptions build() { - return this.options; - } - - public static class PortableFunctionCallingOptions implements FunctionCallingOptions, ChatOptions { - - private List functionCallbacks = new ArrayList<>(); - - private Set functions = new HashSet<>(); - - private Float temperature; - - private Float topP; - - private Integer topK; - - @Override - public List getFunctionCallbacks() { - return this.functionCallbacks; - } - - @Override - public void setFunctionCallbacks(List functionCallbacks) { - Assert.notNull(functionCallbacks, "FunctionCallbacks must not be null"); - this.functionCallbacks = functionCallbacks; - } - - @Override - public Set getFunctions() { - return this.functions; - } - - @Override - public void setFunctions(Set functions) { - Assert.notNull(functions, "Functions must not be null"); - this.functions = functions; - } - - @Override - public Float getTemperature() { - return this.temperature; - } - - @Override - public void setTemperature(Float temperature) { - this.temperature = temperature; - } - - @Override - public Float getTopP() { - return this.topP; - } - - @Override - public void setTopP(Float topP) { - this.topP = topP; - } - - @Override - public Integer getTopK() { - return this.topK; - } - - @Override - public void setTopK(Integer topK) { - this.topK = topK; - } - - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/TypeResolverHelper.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/TypeResolverHelper.java deleted file mode 100644 index 604ce0adc..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/function/TypeResolverHelper.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2024-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model.function; - -import net.jodah.typetools.TypeResolver; - -import java.lang.reflect.GenericArrayType; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.function.Function; - -/** - * @author Christian Tzolov - */ -public class TypeResolverHelper { - - public static Class getFunctionInputClass(Class> functionClass) { - return getFunctionArgumentClass(functionClass, 0); - } - - public static Class getFunctionOutputClass(Class> functionClass) { - return getFunctionArgumentClass(functionClass, 1); - } - - public static Class getFunctionArgumentClass(Class> functionClass, int argumentIndex) { - Type type = TypeResolver.reify(Function.class, functionClass); - - var argumentType = type instanceof ParameterizedType - ? ((ParameterizedType) type).getActualTypeArguments()[argumentIndex] : Object.class; - - return toRawClass(argumentType); - } - - public static Type getFunctionInputType(Class> functionClass) { - return getFunctionArgumentType(functionClass, 0); - } - - public static Type getFunctionOutputType(Class> functionClass) { - return getFunctionArgumentType(functionClass, 1); - } - - public static Type getFunctionArgumentType(Class> functionClass, int argumentIndex) { - Type functionType = TypeResolver.reify(Function.class, functionClass); - return getFunctionArgumentType(functionType, argumentIndex); - } - - public static Type getFunctionArgumentType(Type functionType, int argumentIndex) { - var argumentType = functionType instanceof ParameterizedType - ? ((ParameterizedType) functionType).getActualTypeArguments()[argumentIndex] : Object.class; - - return argumentType; - } - - /** - * Effectively converts {@link Type} which could be {@link ParameterizedType} to raw - * Class (no generics). - * @param type actual {@link Type} instance - * @return instance of {@link Class} as raw representation of the provided - * {@link Type} - */ - public static Class toRawClass(Type type) { - return type != null - ? TypeResolver.resolveRawClass(type instanceof GenericArrayType ? type : TypeResolver.reify(type), null) - : null; - } - - // public static void main(String[] args) { - // Class> clazz = MockWeatherService.class; - // System.out.println(getFunctionInputType(clazz)); - - // } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/package-info.java deleted file mode 100644 index 12eaa53b4..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/model/package-info.java +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Provides a set of interfaces and classes for a generic API designed to interact with - * various AI models. This package includes interfaces for handling AI model calls, - * requests, responses, results, and associated metadata. It is designed to offer a - * flexible and adaptable framework for interacting with different types of AI models, - * abstracting the complexities involved in model invocation and result processing. The - * use of generics enhances the API's capability to work with a wide range of models, - * ensuring a broad applicability across diverse AI scenarios. - * - */ -package org.springframework.ai.model; \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/MidjourneyInteractionsApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/MidjourneyInteractionsApi.java index 3771113d0..16d86a48f 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/MidjourneyInteractionsApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/MidjourneyInteractionsApi.java @@ -1,14 +1,14 @@ package org.springframework.ai.models.midjourney.api; import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import org.springframework.ai.models.midjourney.MidjourneyConfig; import org.springframework.ai.models.midjourney.api.req.AttachmentsReq; import org.springframework.ai.models.midjourney.api.req.DescribeReq; import org.springframework.ai.models.midjourney.api.req.ReRollReq; import org.springframework.ai.models.midjourney.api.res.UploadAttachmentsRes; import org.springframework.ai.models.midjourney.util.MidjourneyUtil; -import com.alibaba.fastjson2.JSON; -import com.alibaba.fastjson2.JSONObject; import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; import org.springframework.core.io.FileSystemResource; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/OpenAiImageApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/OpenAiImageApi.java deleted file mode 100644 index 6cde315e7..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/OpenAiImageApi.java +++ /dev/null @@ -1,89 +0,0 @@ -package org.springframework.ai.models.openai; - -import cn.hutool.json.JSONUtil; -import org.springframework.ai.models.openai.api.OpenAiImageRequest; -import org.springframework.ai.models.openai.api.OpenAiImageResponse; -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import io.netty.channel.ChannelOption; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpEntity; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.util.EntityUtils; -import org.springframework.http.client.reactive.ReactorClientHttpConnector; -import org.springframework.web.reactive.function.client.WebClient; -import reactor.netty.http.client.HttpClient; - -import java.io.IOException; -import java.net.URI; -import java.time.Duration; - -/** - * open ai image - *

- * author: fansili - * time: 2024/3/17 09:53 - */ -@Slf4j -public class OpenAiImageApi { - - private static final String DEFAULT_BASE_URL = "https://api.openai.com"; - private String apiKey = "your-api-key"; - // 发送请求 webClient - private final WebClient webClient; - - private CloseableHttpClient httpclient = HttpClients.createDefault(); - - public OpenAiImageApi(String apiKey) { - this.apiKey = apiKey; - // 创建一个HttpClient实例并设置超时 - HttpClient httpClient = HttpClient.create() - .responseTimeout(Duration.ofSeconds(300)) // 设置响应超时时间为30秒 - .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000 * 100); // 设置连接超时为5秒 - this.webClient = WebClient.builder() - .baseUrl(DEFAULT_BASE_URL) - .clientConnector(new ReactorClientHttpConnector(httpClient)) - .build(); - } - - public OpenAiImageResponse createImage(OpenAiImageRequest request) { - HttpPost httpPost = new HttpPost(); - httpPost.setURI(URI.create(DEFAULT_BASE_URL.concat("/v1/images/generations"))); - httpPost.setHeader("Content-Type", "application/json"); - httpPost.setHeader("Authorization", "Bearer " + apiKey); - httpPost.setEntity(new StringEntity(JsonUtils.toJsonString(request), "UTF-8")); - - CloseableHttpResponse response= null; - try { - response = httpclient.execute(httpPost); - HttpEntity entity = response.getEntity(); - String resultJson = EntityUtils.toString(entity); - log.info("openai 图片生成结果: {}", resultJson); - return JSONUtil.toBean(resultJson, OpenAiImageResponse.class); - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - if (response != null) { - try { - response.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - } -// String res = webClient.post() -// .uri(uriBuilder -> uriBuilder.path("/v1/images/generations").build()) -// .header("Content-Type", "application/json") -// .header("Authorization", "Bearer " + apiKey) -// // 设置请求体(这里假设jsonStr是一个JSON格式的字符串) -// .body(BodyInserters.fromValue(JacksonUtil.toJson(request))) -// // 发送请求并获取响应体 -// .retrieve() -// // 转换响应体为String类型 -// .bodyToMono(String.class) -// .block(); - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/OpenAiImageClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/OpenAiImageClient.java deleted file mode 100644 index 558a0e6e8..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/OpenAiImageClient.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.springframework.ai.models.openai; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.codec.Base64; -import cn.hutool.core.util.StrUtil; -import cn.hutool.http.HttpUtil; -import org.springframework.ai.chat.ChatException; -import org.springframework.ai.models.yiyan.exception.YiYanApiException; -import cn.iocoder.yudao.framework.ai.core.exception.AiException; -import org.springframework.ai.models.openai.api.OpenAiImageRequest; -import org.springframework.ai.models.openai.api.OpenAiImageResponse; -import lombok.extern.slf4j.Slf4j; -import org.jetbrains.annotations.NotNull; -import org.springframework.ai.image.*; -import org.springframework.retry.RetryCallback; -import org.springframework.retry.RetryContext; -import org.springframework.retry.RetryListener; -import org.springframework.retry.support.RetryTemplate; - -import java.time.Duration; - -/** - * open ai 生成 image - * - * author: fansili - * time: 2024/3/17 09:51 - */ -@Slf4j -public class OpenAiImageClient implements ImageClient { - - /** - * open image ai - */ - private OpenAiImageApi openAiImageApi; - /** - * 默认使用的 ImageOptions - */ - private OpenAiImageOptions defaultImageOptions; - - - public final RetryTemplate retryTemplate = RetryTemplate.builder() - // 最大重试次数 10 - .maxAttempts(10) - .retryOn(YiYanApiException.class) - // 最大重试5次,第一次间隔3000ms,第二次3000ms * 2,第三次3000ms * 3,以此类推,最大间隔3 * 60000ms - .exponentialBackoff(Duration.ofMillis(3000), 2, Duration.ofMillis(3 * 60000)) - .withListener(new RetryListener() { - @Override - public void onError(RetryContext context, - RetryCallback callback, Throwable throwable) { - log.warn("重试异常:" + context.getRetryCount(), throwable); - }; - }) - .build(); - - public OpenAiImageClient(OpenAiImageApi openAiImageApi, OpenAiImageOptions defaultImageOptions) { - this.openAiImageApi = openAiImageApi; - this.defaultImageOptions = defaultImageOptions; - } - - @Override - public ImageResponse call(ImagePrompt imagePrompt) { - return this.retryTemplate.execute(ctx -> { - OpenAiImageOptions openAiImageOptions = getOpenAiImageOptions(imagePrompt); - // 创建请求 - OpenAiImageRequest request = new OpenAiImageRequest(); - BeanUtil.copyProperties(openAiImageOptions, request); - request.setPrompt(imagePrompt.getInstructions().get(0).getText()); - request.setModel(openAiImageOptions.getModel()); - request.setStyle(openAiImageOptions.getStyle().getStyle()); - request.setSize(openAiImageOptions.getSize()); - // 发送请求 - OpenAiImageResponse response = openAiImageApi.createImage(request); - if (response.getError() != null && !StrUtil.isBlank(response.getError().getMessage())) { - // code 错误没有编码,就先根据 message 来进行判断 - throw new AiException("openAi 图片生成失败! " + response.getError().getMessage()); - } - return new ImageResponse(response.getData().stream().map(res -> { - byte[] bytes = HttpUtil.downloadBytes(res.getUrl()); - String base64 = Base64.encode(bytes); - return new ImageGeneration(new Image(res.getUrl(), base64)); - }).toList()); - }); - } - - private @NotNull OpenAiImageOptions getOpenAiImageOptions(ImagePrompt imagePrompt) { - // 检查是否配置了 OpenAiImageOptions - if (defaultImageOptions == null && imagePrompt.getOptions() == null) { - throw new ChatException("OpenAiImageOptions 未配置参数!"); - } - // 优先使用 request 中的 ImageOptions - ImageOptions useImageOptions = imagePrompt.getOptions() == null ? defaultImageOptions : imagePrompt.getOptions(); - if (!(useImageOptions instanceof OpenAiImageOptions)) { - throw new ChatException("配置信息不正确,传入的必须是 OpenAiImageOptions!"); - } - // 转换 OpenAiImageOptions - OpenAiImageOptions openAiImageOptions = (OpenAiImageOptions) useImageOptions; - return openAiImageOptions; - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/OpenAiImageOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/OpenAiImageOptions.java deleted file mode 100644 index c6c903031..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/OpenAiImageOptions.java +++ /dev/null @@ -1,95 +0,0 @@ -package org.springframework.ai.models.openai; - -import org.springframework.ai.image.ImageOptions; -import org.springframework.ai.models.openai.enums.OpenAiImageModelEnum; -import org.springframework.ai.models.openai.enums.OpenAiImageStyleEnum; -import lombok.Data; -import lombok.Getter; -import lombok.experimental.Accessors; - -/** - * open ai 配置文件 - * - * 文档地址:https://platform.openai.com/docs/api-reference/images/create - * - * author: fansili - * time: 2024/3/17 09:53 - */ -@Data -@Accessors(chain = true) -public class OpenAiImageOptions implements ImageOptions { - - // 必填字段,用于描述期望生成图像的文字说明。对于dall-e-2模型最大长度为1000个字符,对于dall-e-3模型最大长度为4000个字符。 - private String prompt; - - // 可选字段,默认为dall-e-2 - // 指定用于生成图像的模型名称。 - private OpenAiImageModelEnum model = OpenAiImageModelEnum.DALL_E_2; - - // 可选字段,默认为1 - // 生成图像的数量,必须在1到10之间。对于dall-e-3模型,目前仅支持n=1。 - private Integer n = 1; - - // 可选字段,默认为standard - // 设置生成图像的质量。hd质量将创建细节更丰富、图像整体一致性更高的图片。该参数仅对dall-e-3模型有效。 - private String quality = "standard"; - - // 可选字段,默认为url - // 返回生成图像的格式。必须是url或b64_json中的一种。URL链接的有效期是从生成图像后开始计算的60分钟内有效。 - private String responseFormat = "url"; - - // 可选字段,默认为1024x1024 - // 生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。 - private String size = "1024x1024"; - - // 可选字段,默认为vivid - // 图像生成的风格。可为vivid(生动)或natural(自然)。vivid会使模型偏向生成超现实和戏剧性的图像,而natural则会让模型产出更自然、不那么超现实的图像。该参数仅对dall-e-3模型有效。 - private OpenAiImageStyleEnum style = OpenAiImageStyleEnum.VIVID; - - // 可选字段 - // 代表您的终端用户的唯一标识符,有助于OpenAI监控并检测滥用行为。了解更多信息请参考官方文档。 - private String endUserId = "UID123456"; - - @Getter - public enum ResponseFormatEnum { - - URL("url"), - BASE64("b64_json"), - - ; - - ResponseFormatEnum(String value) { - this.value = value; - } - - private String value; - } - - // - // 适配 spring ai - - @Override - public Integer getN() { - return this.n; - } - - @Override - public String getModel() { - return this.model.getModel(); - } - - @Override - public Integer getWidth() { - return null; - } - - @Override - public Integer getHeight() { - return null; - } - - @Override - public String getResponseFormat() { - return this.responseFormat; - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/api/OpenAiImageRequest.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/api/OpenAiImageRequest.java deleted file mode 100644 index 0c01e1ea0..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/api/OpenAiImageRequest.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.springframework.ai.models.openai.api; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * open ai 配置文件 - * - * 文档地址:https://platform.openai.com/docs/api-reference/images/create - * - * author: fansili - * time: 2024/3/17 09:53 - */ -@Data -@Accessors(chain = true) -public class OpenAiImageRequest { - - // 必填字段,用于描述期望生成图像的文字说明。对于dall-e-2模型最大长度为1000个字符,对于dall-e-3模型最大长度为4000个字符。 - @JsonProperty("prompt") - private String prompt; - - // 可选字段,默认为dall-e-2、dall-e-3 - // 指定用于生成图像的模型名称。 - @JsonProperty("model") - private String model = "dall-e-2"; - - // 可选字段,默认为1 - // 生成图像的数量,必须在1到10之间。对于dall-e-3模型,目前仅支持n=1。 - @JsonProperty("n") - private Integer n = 1; - - // 可选字段,默认为standard - // 设置生成图像的质量。hd质量将创建细节更丰富、图像整体一致性更高的图片。该参数仅对dall-e-3模型有效。 - @JsonProperty("quality") - private String quality = "standard"; - - // 可选字段,默认为url - // 返回生成图像的格式。必须是url或b64_json中的一种。URL链接的有效期是从生成图像后开始计算的60分钟内有效。 - @JsonProperty("response_format") - private String responseFormat = "url"; - - // 可选字段,默认为1024x1024 - // 生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。 - @JsonProperty("size") - private String size = "1024x1024"; - - // 可选字段,默认为vivid - // 图像生成的风格。可为vivid(生动)或natural(自然)。vivid会使模型偏向生成超现实和戏剧性的图像,而natural则会让模型产出更自然、不那么超现实的图像。该参数仅对dall-e-3模型有效。 - @JsonProperty("style") - private String style = "vivid"; - - // 可选字段 - // 代表您的终端用户的唯一标识符,有助于OpenAI监控并检测滥用行为。了解更多信息请参考官方文档。 - @JsonProperty("user") - private String endUserId = "UID123123"; - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/api/OpenAiImageResponse.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/api/OpenAiImageResponse.java deleted file mode 100644 index beab4cdee..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/openai/api/OpenAiImageResponse.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.springframework.ai.models.openai.api; - -import lombok.Data; -import lombok.experimental.Accessors; - -import java.util.List; - -/** - * image 返回 - * - * author: fansili - * time: 2024/3/17 10:27 - */ -@Data -@Accessors(chain = true) -public class OpenAiImageResponse { - - private long created; - private List data; - private Error error; - - @Data - @Accessors(chain = true) - public static class Item { - - private String url; - private String b64_json; - - } - - @Data - @Accessors(chain = true) - public static class Error { - private String code; - private String message; - private String param; - private String type; - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java index c1d0d41bf..f038bc83e 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java @@ -1,5 +1,6 @@ package org.springframework.ai.models.tongyi; +import cn.iocoder.yudao.framework.ai.core.exception.ChatException; import org.springframework.ai.chat.*; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.prompt.Prompt; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenOptions.java index 9a677607d..39db36608 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenOptions.java @@ -41,25 +41,25 @@ public class QianWenOptions implements ChatOptions { return null; } - @Override - public void setTemperature(Float temperature) { - - } - - @Override - public void setTopP(Float topP) { - this.topP = topP; - } +// @Override +// public void setTemperature(Float temperature) { +// +// } +// +// @Override +// public void setTopP(Float topP) { +// this.topP = topP; +// } @Override public Integer getTopK() { return null; } - @Override - public void setTopK(Integer topK) { - - } +// @Override +// public void setTopK(Integer topK) { +// +// } @Data @Accessors diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoChatClient.java index 740d74910..0010a75fa 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoChatClient.java @@ -2,6 +2,7 @@ package org.springframework.ai.models.xinghuo; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.exceptions.ExceptionUtil; +import cn.iocoder.yudao.framework.ai.core.exception.ChatException; import org.springframework.ai.chat.*; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.prompt.Prompt; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoOptions.java index 8efa7527b..bdc671092 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoOptions.java @@ -49,28 +49,29 @@ public class XingHuoOptions implements ChatOptions { return this.temperature; } - @Override - public void setTemperature(Float temperature) { - this.temperature = temperature; - } +// @Override +// public void setTemperature(Float temperature) { +// this.temperature = temperature; +// } @Override public Float getTopP() { return null; } - @Override - public void setTopP(Float topP) { - - } +// @Override +// public void setTopP(Float topP) { +// +// } @Override public Integer getTopK() { return this.topK; } - @Override - public void setTopK(Integer topK) { - this.topK = topK; - } +// @Override +// public void setTopK(Integer topK) { +// this.topK = topK; +// } + } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatClient.java index 5d1dd4f76..e0da409ec 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatClient.java @@ -1,6 +1,7 @@ package org.springframework.ai.models.yiyan; import cn.hutool.core.bean.BeanUtil; +import cn.iocoder.yudao.framework.ai.core.exception.ChatException; import org.springframework.ai.chat.*; import org.springframework.ai.chat.messages.Message; import org.springframework.ai.chat.messages.MessageType; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanOptions.java index aac8e4949..0cb1481b3 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanOptions.java @@ -114,20 +114,20 @@ public class YiYanOptions implements ChatOptions { return this.temperature; } - @Override - public void setTemperature(Float temperature) { - this.temperature = temperature; - } +// @Override +// public void setTemperature(Float temperature) { +// this.temperature = temperature; +// } @Override public Float getTopP() { return topP; } - @Override - public void setTopP(Float topP) { - this.topP = topP; - } +// @Override +// public void setTopP(Float topP) { +// this.topP = topP; +// } // 百度么有 topK @@ -136,7 +136,7 @@ public class YiYanOptions implements ChatOptions { return null; } - @Override - public void setTopK(Integer topK) { - } +// @Override +// public void setTopK(Integer topK) { +// } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/AbstractConversionServiceOutputParser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/AbstractConversionServiceOutputParser.java deleted file mode 100644 index a06827f39..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/AbstractConversionServiceOutputParser.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.parser; - -import org.springframework.core.convert.support.DefaultConversionService; - -/** - * Abstract {@link OutputParser} implementation that uses a pre-configured - * {@link DefaultConversionService} to convert the LLM output into the desired type - * format. - * - * @param Specifies the desired response type. - * @author Mark Pollack - * @author Christian Tzolov - */ -public abstract class AbstractConversionServiceOutputParser implements OutputParser { - - private final DefaultConversionService conversionService; - - public AbstractConversionServiceOutputParser(DefaultConversionService conversionService) { - this.conversionService = conversionService; - } - - public DefaultConversionService getConversionService() { - return conversionService; - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/AbstractMessageConverterOutputParser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/AbstractMessageConverterOutputParser.java deleted file mode 100644 index 01dbadaf1..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/AbstractMessageConverterOutputParser.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.parser; - -import org.springframework.messaging.converter.MessageConverter; - -/** - * Abstract {@link OutputParser} implementation that uses a pre-configured - * {@link MessageConverter} to convert the LLM output into the desired type format. - * - * @param Specifies the desired response type. - * @author Mark Pollack - * @author Christian Tzolov - */ -public abstract class AbstractMessageConverterOutputParser implements OutputParser { - - private MessageConverter messageConverter; - - public AbstractMessageConverterOutputParser(MessageConverter messageConverter) { - this.messageConverter = messageConverter; - } - - public MessageConverter getMessageConverter() { - return this.messageConverter; - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/BeanOutputParser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/BeanOutputParser.java deleted file mode 100644 index fa09c26af..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/BeanOutputParser.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.parser; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.util.DefaultIndenter; -import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectWriter; -import com.github.victools.jsonschema.generator.SchemaGenerator; -import com.github.victools.jsonschema.generator.SchemaGeneratorConfig; -import com.github.victools.jsonschema.generator.SchemaGeneratorConfigBuilder; -import com.github.victools.jsonschema.module.jackson.JacksonModule; - -import java.util.Map; -import java.util.Objects; - -import static com.github.victools.jsonschema.generator.OptionPreset.PLAIN_JSON; -import static com.github.victools.jsonschema.generator.SchemaVersion.DRAFT_2020_12; - -/** - * An implementation of {@link OutputParser} that transforms the LLM output to a specific - * object type using JSON schema. This parser works by generating a JSON schema based on a - * given Java class, which is then used to validate and transform the LLM output into the - * desired type. - * - * @param The target type to which the output will be converted. - * @author Mark Pollack - * @author Christian Tzolov - * @author Sebastian Ullrich - * @author Kirk Lund - */ -public class BeanOutputParser implements OutputParser { - - /** Holds the generated JSON schema for the target type. */ - private String jsonSchema; - - /** The Java class representing the target type. */ - @SuppressWarnings({ "FieldMayBeFinal", "rawtypes" }) - private Class clazz; - - /** The object mapper used for deserialization and other JSON operations. */ - @SuppressWarnings("FieldMayBeFinal") - private ObjectMapper objectMapper; - - /** - * Constructor to initialize with the target type's class. - * @param clazz The target type's class. - */ - public BeanOutputParser(Class clazz) { - this(clazz, null); - } - - /** - * Constructor to initialize with the target type's class, a custom object mapper, and - * a line endings normalizer to ensure consistent line endings on any platform. - * @param clazz The target type's class. - * @param objectMapper Custom object mapper for JSON operations. endings. - */ - public BeanOutputParser(Class clazz, ObjectMapper objectMapper) { - Objects.requireNonNull(clazz, "Java Class cannot be null;"); - this.clazz = clazz; - this.objectMapper = objectMapper != null ? objectMapper : getObjectMapper(); - generateSchema(); - } - - /** - * Generates the JSON schema for the target type. - */ - private void generateSchema() { - JacksonModule jacksonModule = new JacksonModule(); - SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(DRAFT_2020_12, PLAIN_JSON) - .with(jacksonModule); - SchemaGeneratorConfig config = configBuilder.build(); - SchemaGenerator generator = new SchemaGenerator(config); - JsonNode jsonNode = generator.generateSchema(this.clazz); - ObjectWriter objectWriter = new ObjectMapper() - .writer(new DefaultPrettyPrinter().withObjectIndenter(new DefaultIndenter().withLinefeed("\n"))); - try { - this.jsonSchema = objectWriter.writeValueAsString(jsonNode); - } - catch (JsonProcessingException e) { - throw new RuntimeException("Could not pretty print json schema for " + this.clazz, e); - } - } - - @Override - /** - * Parses the given text to transform it to the desired target type. - * @param text The LLM output in string format. - * @return The parsed output in the desired target type. - */ - public T parse(String text) { - try { - // If the response is a JSON Schema, extract the properties and use them as - // the response. - text = this.jsonSchemaToInstance(text); - return (T) this.objectMapper.readValue(text, this.clazz); - } - catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } - - /** - * Converts a JSON Schema to an instance based on a given text. - * @param text The JSON Schema in string format. - * @return The JSON instance generated from the JSON Schema, or the original text if - * the input is not a JSON Schema. - */ - private String jsonSchemaToInstance(String text) { - try { - Map map = this.objectMapper.readValue(text, Map.class); - if (map.containsKey("$schema")) { - return this.objectMapper.writeValueAsString(map.get("properties")); - } - } - catch (Exception e) { - } - return text; - } - - /** - * Configures and returns an object mapper for JSON operations. - * @return Configured object mapper. - */ - protected ObjectMapper getObjectMapper() { - ObjectMapper mapper = new ObjectMapper(); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - return mapper; - } - - /** - * Provides the expected format of the response, instructing that it should adhere to - * the generated JSON schema. - * @return The instruction format string. - */ - @Override - public String getFormat() { -// String template = """ -// Your response should be in JSON format. -// Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation. -// Do not include markdown code blocks in your response. -// Here is the JSON Schema instance your output must adhere to: -// ```%s``` -// """; - String template = "Your response should be in JSON format.\n" + - "\t\t\t\tDo not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation.\n" + - "\t\t\t\tDo not include markdown code blocks in your response.\n" + - "\t\t\t\tHere is the JSON Schema instance your output must adhere to:\n" + - "\t\t\t\t```%s```"; - return String.format(template, this.jsonSchema); - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/FormatProvider.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/FormatProvider.java deleted file mode 100644 index 8d0cb76b0..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/FormatProvider.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.parser; - -/** - * Implementations of this interface provides instructions for how the output of a - * language generative should be formatted. - * - * @author Mark Pollack - */ -public interface FormatProvider { - - /** - * @return Returns a string containing instructions for how the output of a language - * generative should be formatted. - */ - String getFormat(); - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/ListOutputParser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/ListOutputParser.java deleted file mode 100644 index d11225797..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/ListOutputParser.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.ai.parser; - -import org.springframework.core.convert.support.DefaultConversionService; - -import java.util.List; - -/** - * {@link OutputParser} implementation that uses a {@link DefaultConversionService} to - * convert the LLM output into a {@link List} instance. - * - * @author Mark Pollack - * @author Christian Tzolov - */ -public class ListOutputParser extends AbstractConversionServiceOutputParser> { - - public ListOutputParser(DefaultConversionService defaultConversionService) { - super(defaultConversionService); - } - - @Override - public String getFormat() { -// return """ -// Your response should be a list of comma separated values -// eg: `foo, bar, baz` -// """; - return "Your response should be a list of comma separated values\n" + - "\t\t\t\teg: `foo, bar, baz`"; - } - - @Override - public List parse(String text) { - return getConversionService().convert(text, List.class); - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/MapOutputParser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/MapOutputParser.java deleted file mode 100644 index 90f017f79..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/MapOutputParser.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.parser; - -import org.springframework.messaging.Message; -import org.springframework.messaging.converter.MappingJackson2MessageConverter; -import org.springframework.messaging.support.MessageBuilder; - -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; - -/** - * {@link OutputParser} implementation that uses a pre-configured - * {@link MappingJackson2MessageConverter} to convert the LLM output into a - * java.util.Map<String, Object> instance. - * - * @author Mark Pollack - * @author Christian Tzolov - */ -public class MapOutputParser extends AbstractMessageConverterOutputParser> { - - public MapOutputParser() { - super(new MappingJackson2MessageConverter()); - } - - @Override - public Map parse(String text) { - Message message = MessageBuilder.withPayload(text.getBytes(StandardCharsets.UTF_8)).build(); - return (Map) getMessageConverter().fromMessage(message, HashMap.class); - } - - @Override - public String getFormat() { -// String raw = """ -// Your response should be in JSON format. -// The data structure for the JSON should match this Java class: %s -// Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation. -// """; - String raw = "Your response should be in JSON format.\n" + - "\t\t\t\tThe data structure for the JSON should match this Java class: %s\n" + - "\t\t\t\tDo not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation."; - return String.format(raw, "java.util.HashMap"); - } - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/OutputParser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/OutputParser.java deleted file mode 100644 index cbc7e6e5a..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/OutputParser.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.parser; - -/** - * Converts the (raw) LLM output into a structured responses of type. The - * {@link FormatProvider#getFormat()} method should provide the LLM prompt description of - * the desired format. - * - * @param Specifies the desired response type. - * @author Mark Pollack - * @author Christian Tzolov - */ -public interface OutputParser extends Parser, FormatProvider { - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/Parser.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/Parser.java deleted file mode 100644 index 559473f08..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/Parser.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.parser; - -@FunctionalInterface -public interface Parser { - - T parse(String text); - -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/README.md b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/README.md deleted file mode 100644 index 740e330f2..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/parser/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# Output Parsing - -* [Documentation](https://docs.spring.io/spring-ai/reference/concepts.html#_output_parsing) -* [Usage examples](https://github.com/spring-projects/spring-ai/blob/main/spring-ai-openai/src/test/java/org/springframework/ai/openai/client/ClientIT.java) - -The output of AI models traditionally arrives as a java.util.String, even if you ask for the reply to be in JSON. It may be the correct JSON, but it isn’t a JSON data structure. It is just a string. Also, asking "for JSON" as part of the prompt isn’t 100% accurate. - -This intricacy has led to the emergence of a specialized field involving the creation of prompts to yield the intended output, followed by parsing the resulting simple string into a usable data structure for application integration. - -Output parsing employs meticulously crafted prompts, often necessitating multiple interactions with the model to achieve the desired formatting. - -This challenge has prompted OpenAI to introduce 'OpenAI Functions' as a means to specify the desired output format from the model precisely. diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java index 0882f72a0..99e2b5f7a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java @@ -37,8 +37,8 @@ public class QianWenChatClientTests { QianWenApi qianWenApi = new QianWenApi("sk-Zsd81gZYg7", QianWenChatModal.QWEN_72B_CHAT); QianWenOptions qianWenOptions = new QianWenOptions(); qianWenOptions.setTopP(0.8F); - qianWenOptions.setTopK(3); - qianWenOptions.setTemperature(0.6F); +// qianWenOptions.setTopK(3); TODO 芋艿:临时处理 +// qianWenOptions.setTemperature(0.6F); TODO 芋艿:临时处理 qianWenChatClient = new QianWenChatClient( qianWenApi, qianWenOptions diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java index ba439c683..6944eed70 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java @@ -1,12 +1,12 @@ package cn.iocoder.yudao.framework.ai.openAiImage; -import org.springframework.ai.models.openai.OpenAiImageApi; -import org.springframework.ai.models.openai.OpenAiImageClient; -import org.springframework.ai.models.openai.OpenAiImageOptions; import org.springframework.ai.image.ImagePrompt; import org.springframework.ai.image.ImageResponse; import org.junit.Before; import org.junit.Test; +import org.springframework.ai.openai.OpenAiImageClient; +import org.springframework.ai.openai.OpenAiImageOptions; +import org.springframework.ai.openai.api.OpenAiImageApi; import javax.imageio.ImageIO; import javax.swing.*; @@ -29,8 +29,8 @@ public class OpenAiImageClientTests { public void setup() { // 初始化 openAiImageClient this.openAiImageClient = new OpenAiImageClient( - new OpenAiImageApi(""), - new OpenAiImageOptions().setResponseFormat(OpenAiImageOptions.ResponseFormatEnum.URL.getValue()) + new OpenAiImageApi("") +// new OpenAiImageOptions().setResponseFormat(OpenAiImageOptions.ResponseFormatEnum.URL.getValue()) TODO 芋艿:临时处理 ); } From 9de9e938bf6d113aac62f419e7db35518e8b4536 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 17 May 2024 22:16:57 +0800 Subject: [PATCH 287/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E5=A2=9E=E5=8A=A0=20ollama=20=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E7=9A=84=E6=8E=A5=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/config/AiChatClientFactory.java | 6 ++++ .../ai/service/impl/AiChatServiceImpl.java | 2 +- .../yudao-spring-boot-starter-ai/pom.xml | 6 ++++ .../ai/core/enums/AiPlatformEnum.java | 35 +++++++++---------- .../src/main/resources/application.yaml | 8 +++++ 5 files changed, 38 insertions(+), 19 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java index e15eff590..f93cdc9c7 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java @@ -6,6 +6,7 @@ import org.springframework.ai.chat.StreamingChatClient; import org.springframework.ai.models.tongyi.QianWenChatClient; import org.springframework.ai.models.xinghuo.XingHuoChatClient; import org.springframework.ai.models.yiyan.YiYanChatClient; +import org.springframework.ai.ollama.OllamaChatClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; @@ -36,12 +37,17 @@ public class AiChatClientFactory { // TODO yunai 要不再加一个接口,让他们拥有 ChatClient、StreamingChatClient 功能 public StreamingChatClient getStreamingChatClient(AiPlatformEnum platformEnum) { +// if (true) { +// return applicationContext.getBean(OllamaChatClient.class); +// } if (AiPlatformEnum.QIAN_WEN == platformEnum) { return applicationContext.getBean(QianWenChatClient.class); } else if (AiPlatformEnum.YI_YAN == platformEnum) { return applicationContext.getBean(YiYanChatClient.class); } else if (AiPlatformEnum.XING_HUO == platformEnum) { return applicationContext.getBean(XingHuoChatClient.class); + } else if (AiPlatformEnum.OLLAMA == platformEnum) { + return applicationContext.getBean(OllamaChatClient.class); } throw new IllegalArgumentException("不支持的 chat client!"); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index 1ab160bfc..6a6febfba 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -127,7 +127,7 @@ public class AiChatServiceImpl implements AiChatService { // 1.1 校验对话存在 AiChatConversationDO conversation = chatConversationService.validateExists(sendReqVO.getConversationId()); if (ObjUtil.notEqual(conversation.getUserId(), userId)) { - throw exception(CHAT_CONVERSATION_NOT_EXISTS); + throw exception(CHAT_CONVERSATION_NOT_EXISTS); // TODO 芋艿:异常情况的对接; } // 1.2 校验模型 AiChatModelDO model = chatModalService.validateChatModel(conversation.getModelId()); diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml index 2188ad908..5efa91126 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml @@ -24,6 +24,12 @@ 1.0.3 + + io.springboot.ai + spring-ai-ollama-spring-boot-starter + 1.0.3 + + cn.iocoder.boot yudao-common diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java index 590797d17..e9e1f418e 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java @@ -1,11 +1,8 @@ package cn.iocoder.yudao.framework.ai.core.enums; -import com.google.common.collect.Lists; import lombok.AllArgsConstructor; import lombok.Getter; -import java.util.List; - // TODO 芋艿:这块,看看要不要调整下; /** * ai 模型平台 @@ -17,29 +14,31 @@ import java.util.List; @AllArgsConstructor public enum AiPlatformEnum { + OPENAI("OpenAI", "OpenAI"), + OLLAMA("dall", "dall"), + YI_YAN("yiyan", "一言"), QIAN_WEN("qianwen", "千问"), XING_HUO("xinghuo", "星火"), - OPENAI("OpenAI", "OpenAI"), OPEN_AI_DALL("dall", "dall"), - MIDJOURNEY("midjourney", "midjourney"), + MIDJOURNEY("Ollama", "Ollama"), ; - private String platform; - private String name; + private final String platform; + private final String name; - public static List CHAT_PLATFORM_LIST = Lists.newArrayList( - AiPlatformEnum.YI_YAN, - AiPlatformEnum.QIAN_WEN, - AiPlatformEnum.XING_HUO, - AiPlatformEnum.OPENAI - ); - - public static List IMAGE_PLATFORM_LIST = Lists.newArrayList( - AiPlatformEnum.OPEN_AI_DALL, - AiPlatformEnum.MIDJOURNEY - ); +// public static List CHAT_PLATFORM_LIST = Lists.newArrayList( +// AiPlatformEnum.YI_YAN, +// AiPlatformEnum.QIAN_WEN, +// AiPlatformEnum.XING_HUO, +// AiPlatformEnum.OPENAI +// ); +// +// public static List IMAGE_PLATFORM_LIST = Lists.newArrayList( +// AiPlatformEnum.OPEN_AI_DALL, +// AiPlatformEnum.MIDJOURNEY +// ); public static AiPlatformEnum validatePlatform(String platform) { for (AiPlatformEnum platformEnum : AiPlatformEnum.values()) { diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 6cb5386e3..886644e74 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -142,6 +142,14 @@ spring: listener: missing-topics-fatal: false # 消费监听接口监听的主题不存在时,默认会报错。所以通过设置为 false ,解决报错 +--- #################### AI 相关配置 #################### + +spring.ai: + ollama: + base-url: http://127.0.0.1:11434 + chat: + model: llama3 + --- #################### 芋道相关配置 #################### yudao: From 275d1fb6275f18806158f4faba06baac34159011 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 17 May 2024 22:25:50 +0800 Subject: [PATCH 288/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E7=AE=80=E5=8C=96=20AiChatMessageDO=20=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E8=A1=A8=EF=BC=8C=E5=8E=BB=E9=99=A4=20tokens=E3=80=81?= =?UTF-8?q?temperature=E3=80=81maxTokens=E3=80=81maxContexts=20=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=EF=BC=8C=E5=9B=A0=E4=B8=BA=20spring-ai=20=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E8=BF=94=E5=9B=9E=20tokens=20=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E7=9A=84=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vo/message/AiChatMessageAddReqVO.java | 20 ----------- .../vo/message/AiChatMessageAddRespVO.java | 17 --------- .../chat/vo/message/AiChatMessageRespVO.java | 9 ----- .../dal/dataobject/chat/AiChatMessageDO.java | 25 ------------- .../ai/service/impl/AiChatServiceImpl.java | 36 +++++-------------- 5 files changed, 9 insertions(+), 98 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageAddReqVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageAddRespVO.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageAddReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageAddReqVO.java deleted file mode 100644 index 994472d03..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageAddReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 聊天消息发送 Request VO") -@Data -public class AiChatMessageAddReqVO { - - @Schema(description = "聊天对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "聊天对话编号不能为空") - private Long conversationId; - - @Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "帮我写个 Java 算法") - @NotEmpty(message = "聊天内容不能为空") - private String content; - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageAddRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageAddRespVO.java deleted file mode 100644 index 70cfb5b40..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageAddRespVO.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - AI 聊天消息 Add Response VO") -@Data -public class AiChatMessageAddRespVO { - - @Schema(description = "用户信息") - private AiChatMessageRespVO userMessage; - - @Schema(description = "系统信息") - private AiChatMessageRespVO systemMessage; -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java index c4863c735..9cd27dd3a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java @@ -21,9 +21,6 @@ public class AiChatMessageRespVO { @Schema(description = "用户编号", example = "4096") private Long userId; // 仅当 user 发送时非空 - @Schema(description = "用户头像", example = "http://xxx") - private Long avatarUrl; // 仅当 user 发送时非空 - @Schema(description = "角色编号", example = "888") private Long roleId; // 仅当 assistant 回复时非空 @@ -33,15 +30,9 @@ public class AiChatMessageRespVO { @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "123") private Long modelId; - @Schema(description = "模型图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "123") - private String modelImage; - @Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,你好啊") private String content; - @Schema(description = "消耗 Token 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "80") - private Integer tokens; - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-05-12 12:51") private LocalDateTime createTime; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java index 831b7622d..994947724 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java @@ -78,32 +78,7 @@ public class AiChatMessageDO extends BaseDO { * 聊天内容 */ private String content; - /** - * 消耗 Token 数量 - */ - private Integer tokens; // TODO 芋艿:是否作为上下文语料?use_context,待定 - // ========== 会话配置 ========== - - /** - * 温度参数 - * - * 冗余 {@link AiChatConversationDO#getTemperature()} - */ - private Double temperature; - /** - * 单条回复的最大 Token 数量 - * - * 冗余 {@link AiChatConversationDO#getMaxTokens()} - */ - private Integer maxTokens; - /** - * 上下文的最大 Message 数量 - * - * 冗余 {@link AiChatConversationDO#getMaxContexts()} - */ - private Integer maxContexts; - } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index 6a6febfba..1e9ff242a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -9,7 +9,6 @@ import org.springframework.ai.chat.ChatClient; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.StreamingChatClient; import org.springframework.ai.chat.messages.MessageType; -import org.springframework.ai.chat.prompt.ChatOptionsBuilder; import org.springframework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.config.AiChatClientFactory; @@ -72,8 +71,7 @@ public class AiChatServiceImpl implements AiChatService { AiPlatformEnum platformEnum = AiPlatformEnum.validatePlatform(chatModel.getPlatform()); // 保存 chat message insertChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(), - chatModel.getModel(), chatModel.getId(), req.getContent(), - null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); + chatModel.getModel(), chatModel.getId(), req.getContent()); String content = null; int tokens = 0; try { @@ -94,28 +92,21 @@ public class AiChatServiceImpl implements AiChatService { } finally { // 保存 chat message insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), - chatModel.getModel(), chatModel.getId(), content, - tokens, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); + chatModel.getModel(), chatModel.getId(), content); } return new AiChatMessageRespVO().setContent(content); } private AiChatMessageDO insertChatMessage(Long conversationId, MessageType messageType, Long loginUserId, Long roleId, - String model, Long modelId, String content, Integer tokens, Double temperature, - Integer maxTokens, Integer maxContexts) { + String model, Long modelId, String content) { AiChatMessageDO insertChatMessageDO = new AiChatMessageDO() - .setId(null) .setConversationId(conversationId) .setType(messageType.getValue()) .setUserId(loginUserId) .setRoleId(roleId) .setModel(model) .setModelId(modelId) - .setContent(content) - .setTokens(tokens) - .setTemperature(temperature) - .setMaxTokens(maxTokens) - .setMaxContexts(maxContexts); + .setContent(content); insertChatMessageDO.setCreateTime(LocalDateTime.now()); // 增加 chat message 记录 aiChatMessageMapper.insert(insertChatMessageDO); @@ -134,15 +125,13 @@ public class AiChatServiceImpl implements AiChatService { AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); StreamingChatClient chatClient = chatClientFactory.getStreamingChatClient(platform); - // 2. 插入 user 发送消息 TODO tokens 计算 + // 2. 插入 user 发送消息 AiChatMessageDO userMessage = insertChatMessage(conversation.getId(), MessageType.USER, userId, conversation.getRoleId(), - conversation.getModel(), conversation.getId(), sendReqVO.getContent(), - null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); + conversation.getModel(), conversation.getId(), sendReqVO.getContent()); // 3.1 插入 system 接收消息 AiChatMessageDO systemMessage = insertChatMessage(conversation.getId(), MessageType.SYSTEM, userId, conversation.getRoleId(), - conversation.getModel(), conversation.getId(), conversation.getSystemMessage(), - 0, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts()); + conversation.getModel(), conversation.getId(), conversation.getSystemMessage()); // 3.2 创建 chat 需要的 Prompt // TODO 消息上下文 Prompt prompt = new Prompt(sendReqVO.getContent()); @@ -150,11 +139,8 @@ public class AiChatServiceImpl implements AiChatService { Flux streamResponse = chatClient.stream(prompt); // 3.3 转换 flex AiChatMessageRespVO StringBuffer contentBuffer = new StringBuffer(); - AtomicInteger tokens = new AtomicInteger(0); // TODO token 计算不对; return streamResponse.map(res -> { contentBuffer.append(res.getResult().getOutput().getContent()); - tokens.incrementAndGet(); - AiChatMessageSendRespVO.Message send = new AiChatMessageSendRespVO.Message().setId(userMessage.getId()) .setType(MessageType.USER.getValue()).setCreateTime(userMessage.getCreateTime()) .setContent(sendReqVO.getContent()); @@ -167,17 +153,13 @@ public class AiChatServiceImpl implements AiChatService { // 保存 chat message aiChatMessageMapper.updateById(new AiChatMessageDO() .setId(systemMessage.getId()) - .setContent(contentBuffer.toString()) - .setTokens(tokens.get()) - ); + .setContent(contentBuffer.toString())); }).doOnError(throwable -> { log.error("发送错误 {}!", throwable.getMessage()); // 更新错误信息 TODO 貌似不应该更新异常 aiChatMessageMapper.updateById(new AiChatMessageDO() .setId(systemMessage.getId()) - .setContent(throwable.getMessage()) - .setTokens(tokens.get()) - ); + .setContent(throwable.getMessage())); }); } From 276ef98ff1b0387559225efb276f5509fc175873 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 18 May 2024 00:16:56 +0800 Subject: [PATCH 289/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9Aconversation=20=E5=8F=91=E9=80=81=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E5=A2=9E=E5=8A=A0=E4=B8=8A=E4=B8=8B=E6=96=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/vo/message/AiChatMessageRespVO.java | 4 +- .../dal/dataobject/chat/AiChatMessageDO.java | 4 - .../ai/service/impl/AiChatServiceImpl.java | 184 +++++++++--------- .../ai/core/enums/AiPlatformEnum.java | 4 +- 4 files changed, 98 insertions(+), 98 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java index 9cd27dd3a..49c7ee54b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java @@ -19,10 +19,10 @@ public class AiChatMessageRespVO { private String type; // 参见 MessageType 枚举类 @Schema(description = "用户编号", example = "4096") - private Long userId; // 仅当 user 发送时非空 + private Long userId; @Schema(description = "角色编号", example = "888") - private Long roleId; // 仅当 assistant 回复时非空 + private Long roleId; @Schema(description = "模型标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "gpt-3.5-turbo") private String model; // 参见 AiOpenAiModelEnum 枚举类 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java index 994947724..c66537673 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java @@ -47,16 +47,12 @@ public class AiChatMessageDO extends BaseDO { /** * 用户编号 * - * 仅当 user 发送时非空 - * * 关联 AdminUserDO 的 userId 字段 */ private Long userId; /** * 角色编号 * - * 仅当 assistant 回复时非空 - * * 关联 {@link AiChatRoleDO#getId()} 字段 */ private Long roleId; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index 1e9ff242a..335c20789 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -1,23 +1,22 @@ package cn.iocoder.yudao.module.ai.service.impl; -import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; -import org.springframework.ai.chat.ChatClient; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.StreamingChatClient; -import org.springframework.ai.chat.messages.MessageType; +import org.springframework.ai.chat.messages.*; +import org.springframework.ai.chat.prompt.ChatOptions; +import org.springframework.ai.chat.prompt.ChatOptionsBuilder; import org.springframework.ai.chat.prompt.Prompt; -import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.config.AiChatClientFactory; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatMessageMapper; import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService; import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; @@ -30,10 +29,7 @@ import org.springframework.transaction.annotation.Transactional; import reactor.core.publisher.Flux; import java.time.LocalDateTime; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.*; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -53,64 +49,49 @@ public class AiChatServiceImpl implements AiChatService { private final AiChatClientFactory chatClientFactory; - private final AiChatMessageMapper aiChatMessageMapper; + private final AiChatMessageMapper chatMessageMapper; + private final AiChatConversationService chatConversationService; private final AiChatModelService chatModalService; private final AiChatRoleService chatRoleService; @Transactional(rollbackFor = Exception.class) public AiChatMessageRespVO chat(AiChatMessageSendReqVO req) { - Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); - // 查询对话 - AiChatConversationDO conversation = chatConversationService.validateExists(req.getConversationId()); - // 获取对话模型 - AiChatModelDO chatModel = chatModalService.validateChatModel(conversation.getModelId()); - // 获取角色信息 - AiChatRoleDO chatRoleDO = conversation.getRoleId() != null ? chatRoleService.validateChatRole(conversation.getRoleId()) : null; - // 获取 client 类型 - AiPlatformEnum platformEnum = AiPlatformEnum.validatePlatform(chatModel.getPlatform()); - // 保存 chat message - insertChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(), - chatModel.getModel(), chatModel.getId(), req.getContent()); - String content = null; - int tokens = 0; - try { - // 创建 chat 需要的 Prompt - Prompt prompt = new Prompt(req.getContent()); - // TODO @芋艿 @范 看要不要支持这些 -// req.setTopK(req.getTopK()); -// req.setTopP(req.getTopP()); -// req.setTemperature(req.getTemperature()); - // 发送 call 调用 - ChatClient chatClient = chatClientFactory.getChatClient(platformEnum); - ChatResponse call = chatClient.call(prompt); - content = call.getResult().getOutput().getContent(); - tokens = call.getResults().size(); - // 更新 conversation - } catch (Exception e) { - content = ExceptionUtil.getMessage(e); - } finally { - // 保存 chat message - insertChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), - chatModel.getModel(), chatModel.getId(), content); - } - return new AiChatMessageRespVO().setContent(content); - } - - private AiChatMessageDO insertChatMessage(Long conversationId, MessageType messageType, Long loginUserId, Long roleId, - String model, Long modelId, String content) { - AiChatMessageDO insertChatMessageDO = new AiChatMessageDO() - .setConversationId(conversationId) - .setType(messageType.getValue()) - .setUserId(loginUserId) - .setRoleId(roleId) - .setModel(model) - .setModelId(modelId) - .setContent(content); - insertChatMessageDO.setCreateTime(LocalDateTime.now()); - // 增加 chat message 记录 - aiChatMessageMapper.insert(insertChatMessageDO); - return insertChatMessageDO; + return null; // TODO 芋艿:一起改 +// Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); +// // 查询对话 +// AiChatConversationDO conversation = chatConversationService.validateExists(req.getConversationId()); +// // 获取对话模型 +// AiChatModelDO chatModel = chatModalService.validateChatModel(conversation.getModelId()); +// // 获取角色信息 +// AiChatRoleDO chatRoleDO = conversation.getRoleId() != null ? chatRoleService.validateChatRole(conversation.getRoleId()) : null; +// // 获取 client 类型 +// AiPlatformEnum platformEnum = AiPlatformEnum.validatePlatform(chatModel.getPlatform()); +// // 保存 chat message +// createChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(), +// chatModel.getModel(), chatModel.getId(), req.getContent()); +// String content = null; +// int tokens = 0; +// try { +// // 创建 chat 需要的 Prompt +// Prompt prompt = new Prompt(req.getContent()); +// // TODO @芋艿 @范 看要不要支持这些 +//// req.setTopK(req.getTopK()); +//// req.setTopP(req.getTopP()); +//// req.setTemperature(req.getTemperature()); +// // 发送 call 调用 +// ChatClient chatClient = chatClientFactory.getChatClient(platformEnum); +// ChatResponse call = chatClient.call(prompt); +// content = call.getResult().getOutput().getContent(); +// // 更新 conversation +// } catch (Exception e) { +// content = ExceptionUtil.getMessage(e); +// } finally { +// // 保存 chat message +// createChatMessage(conversation.getId(), MessageType.SYSTEM, loginUserId, conversation.getRoleId(), +// chatModel.getModel(), chatModel.getId(), content); +// } +// return new AiChatMessageRespVO().setContent(content); } @Override @@ -120,55 +101,78 @@ public class AiChatServiceImpl implements AiChatService { if (ObjUtil.notEqual(conversation.getUserId(), userId)) { throw exception(CHAT_CONVERSATION_NOT_EXISTS); // TODO 芋艿:异常情况的对接; } + List historyMessages = chatMessageMapper.selectByConversationId(conversation.getId()); // 1.2 校验模型 AiChatModelDO model = chatModalService.validateChatModel(conversation.getModelId()); AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); StreamingChatClient chatClient = chatClientFactory.getStreamingChatClient(platform); // 2. 插入 user 发送消息 - AiChatMessageDO userMessage = insertChatMessage(conversation.getId(), MessageType.USER, userId, conversation.getRoleId(), - conversation.getModel(), conversation.getId(), sendReqVO.getContent()); + AiChatMessageDO userMessage = createChatMessage(conversation.getId(), model, + userId, conversation.getRoleId(), MessageType.USER, sendReqVO.getContent()); + + // 3.1 插入 assistant 接收消息 + AiChatMessageDO assistantMessage = createChatMessage(conversation.getId(), model, + userId, conversation.getRoleId(), MessageType.ASSISTANT, ""); - // 3.1 插入 system 接收消息 - AiChatMessageDO systemMessage = insertChatMessage(conversation.getId(), MessageType.SYSTEM, userId, conversation.getRoleId(), - conversation.getModel(), conversation.getId(), conversation.getSystemMessage()); // 3.2 创建 chat 需要的 Prompt // TODO 消息上下文 - Prompt prompt = new Prompt(sendReqVO.getContent()); -// ChatOptionsBuilder.builder().withTemperature(conversation.getTemperature().floatValue()).build() + Prompt prompt = buildPrompt(conversation, historyMessages, sendReqVO); Flux streamResponse = chatClient.stream(prompt); - // 3.3 转换 flex AiChatMessageRespVO + + // 3.3 流式返回 StringBuffer contentBuffer = new StringBuffer(); - return streamResponse.map(res -> { - contentBuffer.append(res.getResult().getOutput().getContent()); - AiChatMessageSendRespVO.Message send = new AiChatMessageSendRespVO.Message().setId(userMessage.getId()) - .setType(MessageType.USER.getValue()).setCreateTime(userMessage.getCreateTime()) - .setContent(sendReqVO.getContent()); - AiChatMessageSendRespVO.Message receive = new AiChatMessageSendRespVO.Message().setId(systemMessage.getId()) - .setType(MessageType.SYSTEM.getValue()).setCreateTime(systemMessage.getCreateTime()) - .setContent(res.getResult().getOutput().getContent()); - return new AiChatMessageSendRespVO().setSend(send).setReceive(receive); + return streamResponse.map(response -> { + String newContent = response.getResult().getOutput().getContent(); + contentBuffer.append(newContent); + // 响应结果 + return new AiChatMessageSendRespVO().setSend(BeanUtils.toBean(userMessage, AiChatMessageSendRespVO.Message.class)) + .setReceive(BeanUtils.toBean(userMessage, AiChatMessageSendRespVO.Message.class).setContent(newContent)); }).doOnComplete(() -> { - log.info("发送完成!"); - // 保存 chat message - aiChatMessageMapper.updateById(new AiChatMessageDO() - .setId(systemMessage.getId()) - .setContent(contentBuffer.toString())); + chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString())); }).doOnError(throwable -> { - log.error("发送错误 {}!", throwable.getMessage()); - // 更新错误信息 TODO 貌似不应该更新异常 - aiChatMessageMapper.updateById(new AiChatMessageDO() - .setId(systemMessage.getId()) - .setContent(throwable.getMessage())); + log.error("[sendChatMessageStream][userId({}) sendReqVO({}) 发生异常]", userId, sendReqVO, throwable); + chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(throwable.getMessage())); }); } + private Prompt buildPrompt(AiChatConversationDO conversation, List messages, AiChatMessageSendReqVO sendReqVO) { + // TODO 芋艿:1)保留 n 个上下文;2)每一轮 token 数量 +// if (conversation.getMaxContexts() != null && messages.size() > conversation.getMaxContexts()) { +// +// } + // 1. 构建 Prompt Message 列表 + List chatMessages = new ArrayList<>(); + // 1.1 system context 角色设定 + chatMessages.add(new SystemMessage(conversation.getSystemMessage())); + // 1.2 history message 历史消息 + messages.forEach(message -> chatMessages.add(new ChatMessage(message.getType().toUpperCase(), message.getContent()))); + // 1.3 user message 新发送消息 + chatMessages.add(new UserMessage(sendReqVO.getContent())); + + // 2. 构建 ChatOptions 对象 + ChatOptions chatOptions = ChatOptionsBuilder.builder().withTemperature(conversation.getTemperature().floatValue()).build(); + return new Prompt(chatMessages, chatOptions); + } + + private AiChatMessageDO createChatMessage(Long conversationId, AiChatModelDO model, + Long userId, Long roleId, + MessageType messageType, String content) { + AiChatMessageDO message = new AiChatMessageDO() + .setConversationId(conversationId).setModel(model.getModel()).setModelId(model.getId()) + .setUserId(userId).setRoleId(roleId) + .setType(messageType.getValue()).setContent(content); + message.setCreateTime(LocalDateTime.now()); + chatMessageMapper.insert(message); + return message; + } + @Override public List getMessageListByConversationId(Long conversationId) { // 校验对话是否存在 chatConversationService.validateExists(conversationId); // 获取对话所有 message - List aiChatMessageDOList = aiChatMessageMapper.selectByConversationId(conversationId); + List aiChatMessageDOList = chatMessageMapper.selectByConversationId(conversationId); // 获取模型信息 Set modalIds = aiChatMessageDOList.stream().map(AiChatMessageDO::getModelId).collect(Collectors.toSet()); List modalList = chatModalService.getModalByIds(modalIds); @@ -187,7 +191,7 @@ public class AiChatServiceImpl implements AiChatService { @Override public Boolean deleteMessage(Long id) { - return aiChatMessageMapper.deleteById(id) > 0; + return chatMessageMapper.deleteById(id) > 0; } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java index e9e1f418e..66228ff22 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java @@ -15,13 +15,13 @@ import lombok.Getter; public enum AiPlatformEnum { OPENAI("OpenAI", "OpenAI"), - OLLAMA("dall", "dall"), + OLLAMA("Ollama", "Ollama"), YI_YAN("yiyan", "一言"), QIAN_WEN("qianwen", "千问"), XING_HUO("xinghuo", "星火"), OPEN_AI_DALL("dall", "dall"), - MIDJOURNEY("Ollama", "Ollama"), + MIDJOURNEY("midjourney", "midjourney"), ; From 04021ce0682c9eea39cb2c06ac081d3c5c615db6 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 18 May 2024 09:34:17 +0800 Subject: [PATCH 290/684] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91AI=EF=BC=9A=E6=96=87=E5=BF=83=E4=B8=80?= =?UTF-8?q?=E8=A8=80=E7=9A=84=E6=8E=A5=E5=85=A5=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/config/AiChatClientFactory.java | 6 +- .../AiChatConversationRespVO.java | 8 +- .../module/ai/dal/vo/AiChatModalConfigVO.java | 2 +- .../ai/service/impl/AiChatServiceImpl.java | 6 +- .../service/model/AiChatRoleServiceImpl.java | 5 +- .../yudao-spring-boot-starter-ai/pom.xml | 19 +-- .../ai/config/YudaoAiAutoConfiguration.java | 8 +- .../ai/config/YudaoAiImageProperties.java | 2 +- .../ai/config/YudaoAiProperties.java | 2 +- .../ai/core/enums/AiPlatformEnum.java | 2 +- .../framework/ai/core/model/package-info.java | 12 ++ .../ai/core/model/yiyan/YiYanChatClient.java | 154 +++++++++++++++++ .../core/model/yiyan/YiYanChatOptions.java} | 42 ++--- .../ai/core/model}/yiyan/api/YiYanApi.java | 75 +++++---- .../model/yiyan/api/YiYanAuthResponse.java} | 10 +- .../yiyan/api/YiYanChatCompletionRequest.java | 12 +- .../api/YiYanChatCompletionResponse.java} | 11 +- .../core/model/yiyan/api}/YiYanChatModel.java | 28 ++-- .../yiyan/exception/YiYanApiException.java | 2 +- .../ai/models/tongyi/QianWenChatClient.java | 2 +- .../ai/models/yiyan/YiYanChatClient.java | 158 ------------------ .../yiyan/api/YiYanChatCompletionMessage.java | 8 - .../framework/ai/chat/YiYanChatTests.java | 10 +- .../src/main/resources/application-local.yaml | 11 -- .../src/main/resources/application.yaml | 13 ++ 25 files changed, 300 insertions(+), 308 deletions(-) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/package-info.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/YiYanChatClient.java rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models/yiyan/YiYanOptions.java => cn/iocoder/yudao/framework/ai/core/model/yiyan/YiYanChatOptions.java} (82%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models => cn/iocoder/yudao/framework/ai/core/model}/yiyan/api/YiYanApi.java (57%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models/yiyan/api/YiYanAuthRes.java => cn/iocoder/yudao/framework/ai/core/model/yiyan/api/YiYanAuthResponse.java} (78%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models => cn/iocoder/yudao/framework/ai/core/model}/yiyan/api/YiYanChatCompletionRequest.java (95%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models/yiyan/api/YiYanChatCompletion.java => cn/iocoder/yudao/framework/ai/core/model/yiyan/api/YiYanChatCompletionResponse.java} (93%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models/yiyan => cn/iocoder/yudao/framework/ai/core/model/yiyan/api}/YiYanChatModel.java (65%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models => cn/iocoder/yudao/framework/ai/core/model}/yiyan/exception/YiYanApiException.java (79%) delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatClient.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanChatCompletionMessage.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java index f93cdc9c7..d5863dbc2 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java @@ -5,7 +5,7 @@ import org.springframework.ai.chat.ChatClient; import org.springframework.ai.chat.StreamingChatClient; import org.springframework.ai.models.tongyi.QianWenChatClient; import org.springframework.ai.models.xinghuo.XingHuoChatClient; -import org.springframework.ai.models.yiyan.YiYanChatClient; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatClient; import org.springframework.ai.ollama.OllamaChatClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; @@ -27,7 +27,7 @@ public class AiChatClientFactory { public ChatClient getChatClient(AiPlatformEnum platformEnum) { if (AiPlatformEnum.QIAN_WEN == platformEnum) { return applicationContext.getBean(QianWenChatClient.class); - } else if (AiPlatformEnum.YI_YAN == platformEnum) { + } else if (AiPlatformEnum.YIYAN == platformEnum) { return applicationContext.getBean(YiYanChatClient.class); } else if (AiPlatformEnum.XING_HUO == platformEnum) { return applicationContext.getBean(XingHuoChatClient.class); @@ -42,7 +42,7 @@ public class AiChatClientFactory { // } if (AiPlatformEnum.QIAN_WEN == platformEnum) { return applicationContext.getBean(QianWenChatClient.class); - } else if (AiPlatformEnum.YI_YAN == platformEnum) { + } else if (AiPlatformEnum.YIYAN == platformEnum) { return applicationContext.getBean(YiYanChatClient.class); } else if (AiPlatformEnum.XING_HUO == platformEnum) { return applicationContext.getBean(XingHuoChatClient.class); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java index 78cd71365..e670ef9f9 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java @@ -1,20 +1,14 @@ package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelRespVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.TableField; import com.fhs.core.trans.anno.Trans; import com.fhs.core.trans.constant.TransType; import com.fhs.core.trans.vo.VO; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import lombok.Data; -import lombok.experimental.Accessors; import java.time.LocalDateTime; -import java.time.LocalTime; @Schema(description = "管理后台 - AI 聊天会话 Response VO") @Data @@ -58,7 +52,7 @@ public class AiChatConversationRespVO implements VO { @Schema(description = "上下文的最大 Message 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") private Integer maxContexts; - @Schema(description = "最后更新时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-05-16") + @Schema(description = "最后更新时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime updateTime; // ========== 关联 role 信息 ========== diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalConfigVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalConfigVO.java index ed5ecf217..723e5338f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalConfigVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalConfigVO.java @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import lombok.Data; import lombok.experimental.Accessors; import org.springframework.ai.models.xinghuo.XingHuoChatModel; -import org.springframework.ai.models.yiyan.YiYanChatModel; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanChatModel; /** * modal config diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index 335c20789..b56b16648 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -150,9 +150,9 @@ public class AiChatServiceImpl implements AiChatService { // 1.3 user message 新发送消息 chatMessages.add(new UserMessage(sendReqVO.getContent())); - // 2. 构建 ChatOptions 对象 - ChatOptions chatOptions = ChatOptionsBuilder.builder().withTemperature(conversation.getTemperature().floatValue()).build(); - return new Prompt(chatMessages, chatOptions); + // 2. 构建 ChatOptions 对象 TODO 芋艿:临时注释掉;等文心一言兼容了; +// ChatOptions chatOptions = ChatOptionsBuilder.builder().withTemperature(conversation.getTemperature().floatValue()).build(); + return new Prompt(chatMessages, null); } private AiChatMessageDO createChatMessage(Long conversationId, AiChatModelDO model, diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java index 4372003d0..cf6bcec96 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.ai.service.model; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -15,6 +16,8 @@ import org.springframework.stereotype.Service; import java.util.List; import java.util.Objects; +import java.util.function.Function; +import java.util.function.Predicate; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -134,7 +137,7 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { @Override public List getChatRoleCategoryList() { List list = chatRoleMapper.selectListGroupByCategory(CommonStatusEnum.ENABLE.getStatus()); - return convertList(list.stream().filter(Objects::nonNull).collect(Collectors.toList()), AiChatRoleDO::getCategory); + return convertList(list, AiChatRoleDO::getCategory, role -> StrUtil.isNotBlank(role.getCategory())); } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml index 5efa91126..37813feb7 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml @@ -10,32 +10,25 @@ yudao-spring-boot-starter-ai - - - io.springboot.ai - spring-ai-core - 1.0.3 - - - io.springboot.ai - spring-ai-openai - 1.0.3 - - io.springboot.ai spring-ai-ollama-spring-boot-starter 1.0.3 + + io.springboot.ai + spring-ai-openai-spring-boot-starter + 1.0.3 + cn.iocoder.boot yudao-common - + com.alibaba dashscope-sdk-java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index b37938d4a..67226ec60 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -8,9 +8,9 @@ import org.springframework.ai.models.tongyi.api.QianWenApi; import org.springframework.ai.models.xinghuo.XingHuoChatClient; import org.springframework.ai.models.xinghuo.XingHuoOptions; import org.springframework.ai.models.xinghuo.api.XingHuoApi; -import org.springframework.ai.models.yiyan.YiYanChatClient; -import org.springframework.ai.models.yiyan.YiYanOptions; -import org.springframework.ai.models.yiyan.api.YiYanApi; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatClient; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatOptions; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanApi; import org.springframework.ai.models.midjourney.MidjourneyConfig; import org.springframework.ai.models.midjourney.MidjourneyMessage; import org.springframework.ai.models.midjourney.api.MidjourneyInteractionsApi; @@ -91,7 +91,7 @@ public class YudaoAiAutoConfiguration { public YiYanChatClient yiYanChatClient(YudaoAiProperties yudaoAiProperties) { YudaoAiProperties.YiYanProperties yiYanProperties = yudaoAiProperties.getYiyan(); // 转换配置 - YiYanOptions yiYanOptions = new YiYanOptions(); + YiYanChatOptions yiYanOptions = new YiYanChatOptions(); // yiYanOptions.setTopK(yiYanProperties.getTopK()); TODO 芋艿:后续弄 yiYanOptions.setTopP(yiYanProperties.getTopP()); yiYanOptions.setTemperature(yiYanProperties.getTemperature()); diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiImageProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiImageProperties.java index 1f17a1203..1e6d9d9ec 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiImageProperties.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiImageProperties.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.framework.ai.config; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import org.springframework.ai.models.xinghuo.XingHuoChatModel; import org.springframework.ai.models.xinghuo.XingHuoOptions; -import org.springframework.ai.models.yiyan.YiYanChatModel; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanChatModel; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java index a228a0045..62bd1318d 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.framework.ai.config; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import org.springframework.ai.models.xinghuo.XingHuoChatModel; -import org.springframework.ai.models.yiyan.YiYanChatModel; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanChatModel; import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageModelEnum; import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageStyleEnum; import lombok.Data; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java index 66228ff22..cd60cc990 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java @@ -16,8 +16,8 @@ public enum AiPlatformEnum { OPENAI("OpenAI", "OpenAI"), OLLAMA("Ollama", "Ollama"), + YIYAN("YiYan", "文心一言"), - YI_YAN("yiyan", "一言"), QIAN_WEN("qianwen", "千问"), XING_HUO("xinghuo", "星火"), OPEN_AI_DALL("dall", "dall"), diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/package-info.java new file mode 100644 index 000000000..8a193f7df --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/package-info.java @@ -0,0 +1,12 @@ +/** + * model 包,接入各种大模型,对标 https://github.com/spring-projects/spring-ai/tree/main/models + * + * 1. yiyan 包:【百度】文心一言 + * 2. TODO 芋艿: + * tongyi 包:【阿里】通义千问,对标 spring-cloud-alibaba 提供的 ai 包 + * 2.2 + * 2.3 xinghuo 包:【讯飞】星火,自己实现 + * 2.4 openai 包:【OpenAI】ChatGPT,拷贝 spring-ai 提供的 models/openai 包 + * 2.5 midjourney 包:Midjourney,参考 https://github.com/novicezk/midjourney-proxy 实现 + */ +package cn.iocoder.yudao.framework.ai.core.model; \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/YiYanChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/YiYanChatClient.java new file mode 100644 index 000000000..a613af6db --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/YiYanChatClient.java @@ -0,0 +1,154 @@ +package cn.iocoder.yudao.framework.ai.core.model.yiyan; + +import cn.hutool.core.bean.BeanUtil; +import cn.iocoder.yudao.framework.ai.core.exception.ChatException; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanApi; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanChatCompletionResponse; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanChatCompletionRequest; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.exception.YiYanApiException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.Generation; +import org.springframework.ai.chat.StreamingChatClient; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.MessageType; +import org.springframework.ai.chat.prompt.ChatOptions; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.http.ResponseEntity; +import org.springframework.retry.RetryCallback; +import org.springframework.retry.RetryContext; +import org.springframework.retry.RetryListener; +import org.springframework.retry.support.RetryTemplate; +import org.springframework.util.Assert; +import reactor.core.publisher.Flux; + +import java.time.Duration; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 文心一言的 {@link ChatClient} 实现类 + * + * @author fansili + */ +@Slf4j +public class YiYanChatClient implements ChatClient, StreamingChatClient { + + private final YiYanApi yiYanApi; + + private YiYanChatOptions defaultOptions; + + // TODO @fan:参考 OpenAiChatClient 调整下 retryTemplate;使用 RetryUtils.DEFAULT_RETRY_TEMPLATE;加允许传入? + + public YiYanChatClient(YiYanApi yiYanApi) { + this.yiYanApi = yiYanApi; + // TODO @fan:这个情况,是不是搞个 defaultOptions;OpenAiChatOptions.builder().withModel(OpenAiApi.DEFAULT_CHAT_MODEL).withTemperature(0.7f).build() + } + + public YiYanChatClient(YiYanApi yiYanApi, YiYanChatOptions defaultOptions) { + Assert.notNull(yiYanApi, "OllamaApi must not be null"); + Assert.notNull(defaultOptions, "DefaultOptions must not be null"); + this.yiYanApi = yiYanApi; + this.defaultOptions = defaultOptions; + } + + public final RetryTemplate retryTemplate = RetryTemplate.builder() + .maxAttempts(10) + .retryOn(YiYanApiException.class) + .exponentialBackoff(Duration.ofMillis(3000), 2, Duration.ofMillis(3 * 60000)) + .withListener(new RetryListener() { + + @Override + public void onError(RetryContext context, + RetryCallback callback, Throwable throwable) { + log.warn("重试异常:" + context.getRetryCount(), throwable); + } + + }) + .build(); + + @Override + public ChatResponse call(Prompt prompt) { + YiYanChatCompletionRequest request = createRequest(prompt, false); + return this.retryTemplate.execute(ctx -> { + // 发送请求 + ResponseEntity response = yiYanApi.chatCompletionEntity(request); + // 获取结果封装 ChatResponse + YiYanChatCompletionResponse chatCompletion = response.getBody(); + // TODO @fan:为空时,参考 OpenAiChatClient 的封装; + // TODO @fan:chatResponseMetadata,参考 OpenAiChatResponseMetadata.from(completionEntity.getBody()) + return new ChatResponse(List.of(new Generation(chatCompletion.getResult()))); + }); + } + + @Override + public Flux stream(Prompt prompt) { + YiYanChatCompletionRequest request = this.createRequest(prompt, true); + // TODO @fan:return this.retryTemplate.execute(ctx -> { + // 调用 callWithFunctionSupport 发送请求 + Flux response = this.yiYanApi.chatCompletionStream(request); + // TODO @fan:下面的 doOnComplete 是不是可以删除哈? + response.doOnComplete(new Runnable() { + @Override + public void run() { + String a = ";"; + } + }); + return response.map(chunk -> { + // TODO @fan:ChatResponseMetadata chatResponseMetadata + return new ChatResponse(List.of(new Generation(chunk.getResult()))); + }); + } + + private YiYanChatCompletionRequest createRequest(Prompt prompt, boolean stream) { + // 参考 https://cloud.baidu.com/doc/WENXINWORKSHOP/s/clntwmv7t 文档,system 是独立字段 + // 1.1 获取 user 和 assistant + List messageList = prompt.getInstructions().stream() + // 过滤 system + .filter(msg -> MessageType.SYSTEM != msg.getMessageType()) + .map(message -> new YiYanChatCompletionRequest.Message() + .setRole(message.getMessageType().getValue()).setContent(message.getContent()) + ).toList(); + // 1.2 获取 system + String systemPrompt = prompt.getInstructions().stream() + .filter(message -> MessageType.SYSTEM == message.getMessageType()) + .map(Message::getContent) + .collect(Collectors.joining()); + + // 3. 创建 request + YiYanChatCompletionRequest request = new YiYanChatCompletionRequest(messageList); + // 复制 YiYanOptions 属性,到 request 中(这里 options 属性和 request 基本保持一致) + YiYanChatOptions useOptions = getYiYanOptions(prompt); + BeanUtil.copyProperties(useOptions, request); + request.setTop_p(useOptions.getTopP()) + .setMax_output_tokens(useOptions.getMaxOutputTokens()) + .setTemperature(useOptions.getTemperature()) + .setSystem(systemPrompt) + .setStream(stream); + return request; + } + + // TODO @fan:Options 的处理,参考下 OpenAiChatClient 的 createRequest + private YiYanChatOptions getYiYanOptions(Prompt prompt) { + // 两个都为null 则没有配置文件 + if (defaultOptions == null && prompt.getOptions() == null) { + // TODO @fan:IllegalArgumentException 参数更好哈 + throw new ChatException("ChatOptions 未配置参数!"); + } + // 优先使用 Prompt 里面的 ChatOptions + ChatOptions options = defaultOptions; + if (prompt.getOptions() != null) { + options = (ChatOptions) prompt.getOptions(); + } + // Prompt 里面是一个 ChatOptions,用户可以随意传入,这里做一下判断 + if (!(options instanceof YiYanChatOptions)) { + // TODO @fan:IllegalArgumentException 参数更好哈 + // TODO @fan:需要兼容 ChatOptionsBuilder 创建出来的 + throw new ChatException("Prompt 传入的不是 YiYanOptions!"); + } + // 转换 YiYanOptions + return (YiYanChatOptions) options; + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/YiYanChatOptions.java similarity index 82% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanOptions.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/YiYanChatOptions.java index 0cb1481b3..14146a322 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/YiYanChatOptions.java @@ -1,23 +1,22 @@ -package org.springframework.ai.models.yiyan; +package cn.iocoder.yudao.framework.ai.core.model.yiyan; -import org.springframework.ai.chat.prompt.ChatOptions; -import org.springframework.ai.models.yiyan.api.YiYanChatCompletionRequest; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanChatCompletionRequest; import lombok.Data; -import lombok.experimental.Accessors; +import org.springframework.ai.chat.prompt.ChatOptions; import java.util.List; +// TODO @fan:字段命名,penalty_score 类似的,建议改成驼峰原则 +// TODO @fan:字段的注释,可以都删除掉,让用户 https://cloud.baidu.com/doc/WENXINWORKSHOP/s/clntwmv7t 即可 /** - * 百度 问心一言 + * 文心一言的 {@link ChatOptions} 实现类 * - * 文档地址:https://cloud.baidu.com/doc/WENXINWORKSHOP/s/clntwmv7t + * 字段说明:参考 ERNIE-4.0-8K * - * author: fansili - * time: 2024/3/16 19:33 + * @author fansili */ @Data -@Accessors(chain = true) -public class YiYanOptions implements ChatOptions { +public class YiYanChatOptions implements ChatOptions { /** * 一个可触发函数的描述列表,说明: @@ -106,37 +105,24 @@ public class YiYanOptions implements ChatOptions { */ private String tool_choice; - // - // 以下兼容 spring-ai ChatOptions 暂时没有其他地方用到 - @Override public Float getTemperature() { return this.temperature; } -// @Override -// public void setTemperature(Float temperature) { -// this.temperature = temperature; -// } - @Override public Float getTopP() { return topP; } -// @Override -// public void setTopP(Float topP) { -// this.topP = topP; -// } - - // 百度么有 topK - + /** + * 百度么有 topK + * + * @return null + */ @Override public Integer getTopK() { return null; } -// @Override -// public void setTopK(Integer topK) { -// } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/api/YiYanApi.java similarity index 57% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanApi.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/api/YiYanApi.java index a8f4aa322..535901f25 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/api/YiYanApi.java @@ -1,8 +1,6 @@ -package org.springframework.ai.models.yiyan.api; +package cn.iocoder.yudao.framework.ai.core.model.yiyan.api; -import org.springframework.ai.models.yiyan.YiYanChatModel; -import org.springframework.ai.models.yiyan.exception.YiYanApiException; -import lombok.Data; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.exception.YiYanApiException; import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; import org.springframework.web.reactive.function.client.WebClient; @@ -10,47 +8,55 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; /** - * 文心一言 - *

- * author: fansili - * time: 2024/3/8 21:47 + * 文心一言 API + * + * @author fansili */ -@Data public class YiYanApi { private static final String DEFAULT_BASE_URL = "https://aip.baidubce.com"; private static final String AUTH_2_TOKEN_URI = "/oauth/2.0/token"; - public static final String DEFAULT_CHAT_MODEL = "ERNIE 4.0"; + public static final String DEFAULT_CHAT_MODEL = YiYanChatModel.ERNIE4_0.getModel(); - // 获取access_token流程 https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Ilkkrb0i5 - private String appKey; - private String secretKey; - private String token; - // token刷新时间(秒) + private final String appKey; + private final String secretKey; + /** + * TODO fan:这个是不是要有个刷新机制哈;如果目前不需要,可以删除掉 refreshTokenSecondTime;整体更简洁; + */ + private final String token; + /** + * token 刷新时间(秒) + */ private int refreshTokenSecondTime; - // 发送请求 webClient + /** + * 发送请求 webClient + */ private final WebClient webClient; - // 使用的模型 - private YiYanChatModel useChatModel; + /** + * 使用的模型 + */ + private final YiYanChatModel useChatModel; public YiYanApi(String appKey, String secretKey, YiYanChatModel useChatModel, int refreshTokenSecondTime) { this.appKey = appKey; this.secretKey = secretKey; this.useChatModel = useChatModel; this.refreshTokenSecondTime = refreshTokenSecondTime; - - this.webClient = WebClient.builder() - .baseUrl(DEFAULT_BASE_URL) - .build(); - + this.webClient = WebClient.builder().baseUrl(DEFAULT_BASE_URL).build(); + // 获取访问令牌 token = getToken(); } + /** + * 获得访问令牌 + * + * @see 文档地址 + * @return 访问令牌 + */ private String getToken() { - // 文档地址: https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Ilkkrb0i5 - ResponseEntity response = this.webClient.post() + ResponseEntity response = this.webClient.post() .uri(uriBuilder -> uriBuilder.path(AUTH_2_TOKEN_URI) .queryParam("grant_type", "client_credentials") .queryParam("client_id", appKey) @@ -58,17 +64,19 @@ public class YiYanApi { .build() ) .retrieve() - .toEntity(YiYanAuthRes.class) + .toEntity(YiYanAuthResponse.class) .block(); // 检查请求状态 - if (HttpStatusCode.valueOf(200) != response.getStatusCode()) { + // TODO @fan:可以使用 response.getStatusCode().is2xxSuccessful() + if (HttpStatusCode.valueOf(200) != response.getStatusCode() + || response.getBody() == null) { + // TODO @fan:可以使用 IllegalStateException 替代;另外,最好打印下返回;方便排错; throw new YiYanApiException("一言认证失败! api:https://aip.baidubce.com/oauth/2.0/token 请检查 client_id、client_secret 是否正确!"); } - YiYanAuthRes body = response.getBody(); - return body.getAccess_token(); + return response.getBody().getAccess_token(); } - public ResponseEntity chatCompletionEntity(YiYanChatCompletionRequest request) { + public ResponseEntity chatCompletionEntity(YiYanChatCompletionRequest request) { // TODO: 2024/3/10 小范 这里错误信息返回的结构不一样 // {"error_code":17,"error_msg":"Open api daily request limit reached"} return this.webClient.post() @@ -78,11 +86,11 @@ public class YiYanApi { .build()) .body(Mono.just(request), YiYanChatCompletionRequest.class) .retrieve() - .toEntity(YiYanChatCompletion.class) + .toEntity(YiYanChatCompletionResponse.class) .block(); } - public Flux chatCompletionStream(YiYanChatCompletionRequest request) { + public Flux chatCompletionStream(YiYanChatCompletionRequest request) { return this.webClient.post() .uri(uriBuilder -> uriBuilder.path(useChatModel.getUri()) @@ -90,6 +98,7 @@ public class YiYanApi { .build()) .body(Mono.just(request), YiYanChatCompletionRequest.class) .retrieve() - .bodyToFlux(YiYanChatCompletion.class); + .bodyToFlux(YiYanChatCompletionResponse.class); } + } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanAuthRes.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/api/YiYanAuthResponse.java similarity index 78% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanAuthRes.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/api/YiYanAuthResponse.java index f9f1f27db..134b33994 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanAuthRes.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/api/YiYanAuthResponse.java @@ -1,15 +1,15 @@ -package org.springframework.ai.models.yiyan.api; +package cn.iocoder.yudao.framework.ai.core.model.yiyan.api; import lombok.Data; +// TODO @fan:字段驼峰;字段注释都可以删除,贴个链接就好; /** - * 一言 获取access_token + * 获取文心一言的 access_token 的 Response * - * author: fansili - * time: 2024/3/10 08:51 + * @author fansili */ @Data -public class YiYanAuthRes { +public class YiYanAuthResponse { /** * 访问凭证 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanChatCompletionRequest.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/api/YiYanChatCompletionRequest.java similarity index 95% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanChatCompletionRequest.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/api/YiYanChatCompletionRequest.java index 22e918835..250131854 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanChatCompletionRequest.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/api/YiYanChatCompletionRequest.java @@ -1,16 +1,16 @@ -package org.springframework.ai.models.yiyan.api; +package cn.iocoder.yudao.framework.ai.core.model.yiyan.api; import lombok.Data; import java.util.List; +// TODO @fan:字段驼峰;字段注释都可以删除,贴个链接就好; /** - * 一言 Completion req + * 文心一言 Completion Request * - * 百度千帆文档:https://cloud.baidu.com/doc/WENXINWORKSHOP/s/jlil56u11 + * 百度千帆文档:https://cloud.baidu.com/doc/WENXINWORKSHOP/s/jlil56u11 * - * author: fansili - * time: 2024/3/9 10:34 + * @author fansili */ @Data public class YiYanChatCompletionRequest { @@ -114,9 +114,11 @@ public class YiYanChatCompletionRequest { @Data public static class Message { + private String role; private String content; + } @Data diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanChatCompletion.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/api/YiYanChatCompletionResponse.java similarity index 93% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanChatCompletion.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/api/YiYanChatCompletionResponse.java index 8e02db659..5082302f8 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanChatCompletion.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/api/YiYanChatCompletionResponse.java @@ -1,16 +1,16 @@ -package org.springframework.ai.models.yiyan.api; +package cn.iocoder.yudao.framework.ai.core.model.yiyan.api; import lombok.Data; /** - * 聊天返回 + * 文心一言 Completion Response + * * 百度链接: https://cloud.baidu.com/doc/WENXINWORKSHOP/s/clntwmv7t * - * author: fansili - * time: 2024/3/9 10:34 + * @author fansili */ @Data -public class YiYanChatCompletion { +public class YiYanChatCompletionResponse { /** * 本轮对话的id @@ -88,4 +88,5 @@ public class YiYanChatCompletion { */ private int total_tokens; } + } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatModel.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/api/YiYanChatModel.java similarity index 65% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatModel.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/api/YiYanChatModel.java index abed185e6..9b400cdad 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatModel.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/api/YiYanChatModel.java @@ -1,15 +1,14 @@ -package org.springframework.ai.models.yiyan; +package cn.iocoder.yudao.framework.ai.core.model.yiyan.api; import lombok.AllArgsConstructor; import lombok.Getter; /** - * 一言模型 + * 文心一言的模型枚举 * - * 可参考百度文档:https://cloud.baidu.com/doc/WENXINWORKSHOP/s/clntwmv7t + * 可参考 百度文档 * - * author: fansili - * time: 2024/3/9 12:01 + * @author fansili */ @Getter @AllArgsConstructor @@ -18,21 +17,24 @@ public enum YiYanChatModel { ERNIE4_0("ERNIE 4.0", "/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions_pro"), ERNIE4_3_5_8K("ERNIE-3.5-8K", "/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions"), ERNIE4_3_5_8K_0205("ERNIE-3.5-8K-0205", "/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-3.5-8k-0205"), - ERNIE4_3_5_8K_1222("ERNIE-3.5-8K-1222", "/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-3.5-8k-1222"), ERNIE4_BOT_8K("ERNIE-Bot-8K", "/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie_bot_8k"), ERNIE4_3_5_4K_0205("ERNIE-3.5-4K-0205", "/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-3.5-4k-0205"), - ; - private String model; - - private String uri; + /** + * 模型名 + */ + private final String model; + /** + * API URL + */ + private final String uri; public static YiYanChatModel valueOfModel(String model) { - for (YiYanChatModel itemEnum : YiYanChatModel.values()) { - if (itemEnum.getModel().equals(model)) { - return itemEnum; + for (YiYanChatModel modelEnum : YiYanChatModel.values()) { + if (modelEnum.getModel().equals(model)) { + return modelEnum; } } throw new IllegalArgumentException("Invalid MessageType value: " + model); diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/exception/YiYanApiException.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/exception/YiYanApiException.java similarity index 79% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/exception/YiYanApiException.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/exception/YiYanApiException.java index 94850f56a..f61badfcb 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/exception/YiYanApiException.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/exception/YiYanApiException.java @@ -1,4 +1,4 @@ -package org.springframework.ai.models.yiyan.exception; +package cn.iocoder.yudao.framework.ai.core.model.yiyan.exception; /** * 一言 api 调用异常 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java index f038bc83e..31e60d119 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java @@ -5,7 +5,7 @@ import org.springframework.ai.chat.*; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.models.tongyi.api.QianWenApi; -import org.springframework.ai.models.yiyan.exception.YiYanApiException; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.exception.YiYanApiException; import com.alibaba.dashscope.aigc.generation.GenerationResult; import com.alibaba.dashscope.aigc.generation.models.QwenParam; import com.alibaba.dashscope.common.Message; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatClient.java deleted file mode 100644 index e0da409ec..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/YiYanChatClient.java +++ /dev/null @@ -1,158 +0,0 @@ -package org.springframework.ai.models.yiyan; - -import cn.hutool.core.bean.BeanUtil; -import cn.iocoder.yudao.framework.ai.core.exception.ChatException; -import org.springframework.ai.chat.*; -import org.springframework.ai.chat.messages.Message; -import org.springframework.ai.chat.messages.MessageType; -import org.springframework.ai.chat.prompt.ChatOptions; -import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.models.yiyan.api.YiYanApi; -import org.springframework.ai.models.yiyan.api.YiYanChatCompletion; -import org.springframework.ai.models.yiyan.api.YiYanChatCompletionRequest; -import org.springframework.ai.models.yiyan.exception.YiYanApiException; -import lombok.extern.slf4j.Slf4j; -import org.jetbrains.annotations.NotNull; -import org.springframework.http.ResponseEntity; -import org.springframework.retry.RetryCallback; -import org.springframework.retry.RetryContext; -import org.springframework.retry.RetryListener; -import org.springframework.retry.support.RetryTemplate; -import reactor.core.publisher.Flux; - -import java.time.Duration; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 文心一言 - *

- * author: fansili - * time: 2024/3/8 19:11 - */ -@Slf4j -public class YiYanChatClient implements ChatClient, StreamingChatClient { - - private YiYanApi yiYanApi; - - private YiYanOptions yiYanOptions; - - public YiYanChatClient(YiYanApi yiYanApi) { - this.yiYanApi = yiYanApi; - } - - public YiYanChatClient(YiYanApi yiYanApi, YiYanOptions yiYanOptions) { - this.yiYanApi = yiYanApi; - this.yiYanOptions = yiYanOptions; - } - - public final RetryTemplate retryTemplate = RetryTemplate.builder() - // 最大重试次数 10 - .maxAttempts(10) - .retryOn(YiYanApiException.class) - // 最大重试5次,第一次间隔3000ms,第二次3000ms * 2,第三次3000ms * 3,以此类推,最大间隔3 * 60000ms - .exponentialBackoff(Duration.ofMillis(3000), 2, Duration.ofMillis(3 * 60000)) - .withListener(new RetryListener() { - @Override - public void onError(RetryContext context, - RetryCallback callback, Throwable throwable) { - log.warn("重试异常:" + context.getRetryCount(), throwable); - } - - ; - }) - .build(); - - @Override - public String call(String message) { - return ChatClient.super.call(message); - } - - @Override - public ChatResponse call(Prompt prompt) { - return this.retryTemplate.execute(ctx -> { - // ctx 会有重试的信息 - // 创建 request 请求,stream模式需要供应商支持 - YiYanChatCompletionRequest request = this.createRequest(prompt, false); - // 调用 callWithFunctionSupport 发送请求 - ResponseEntity response = yiYanApi.chatCompletionEntity(request); - // 获取结果封装 ChatResponse - YiYanChatCompletion chatCompletion = response.getBody(); - return new ChatResponse(List.of(new Generation(chatCompletion.getResult()))); - }); - } - - @Override - public Flux stream(Prompt prompt) { - // ctx 会有重试的信息 - // 创建 request 请求,stream模式需要供应商支持 - YiYanChatCompletionRequest request = this.createRequest(prompt, true); - // 调用 callWithFunctionSupport 发送请求 - Flux response = this.yiYanApi.chatCompletionStream(request); - response.doOnComplete(new Runnable() { - @Override - public void run() { - String a = ";"; - } - }); - return response.map(res -> { - // TODO @fan:这里缺少了 usage 的封装 - return new ChatResponse(List.of(new Generation(res.getResult()))); - }); - } - - private YiYanChatCompletionRequest createRequest(Prompt prompt, boolean stream) { - // 获取配置 - YiYanOptions useOptions = getYiYanOptions(prompt); - // 创建 request - - // tip: 百度的 system 不在 message 里面 - // tip:百度的 message 只有 user 和 assistant - // https://cloud.baidu.com/doc/WENXINWORKSHOP/s/clntwmv7t - - // 获取 user 和 assistant - List messageList = prompt.getInstructions().stream() - // 过滤 system - .filter(msg -> MessageType.SYSTEM != msg.getMessageType()) - .map(msg -> new YiYanChatCompletionRequest.Message() - .setRole(msg.getMessageType().getValue()) - .setContent(msg.getContent()) - ).toList(); - // 获取 system - String systemPrompt = prompt.getInstructions().stream() - .filter(msg -> MessageType.SYSTEM == msg.getMessageType()) - .map(Message::getContent) - .collect(Collectors.joining()); - - YiYanChatCompletionRequest request = new YiYanChatCompletionRequest(messageList); - // 复制 qianWenOptions 属性取 request(这里 options 属性和 request 基本保持一致) - // top: 由于遵循 spring-ai规范,支持在构建client的时候传入默认的 chatOptions - BeanUtil.copyProperties(useOptions, request); - request.setTop_p(useOptions.getTopP()); - request.setMax_output_tokens(useOptions.getMaxOutputTokens()); - request.setTemperature(useOptions.getTemperature()); - request.setSystem(systemPrompt); - // 设置 stream - request.setStream(stream); - return request; - } - - private @NotNull YiYanOptions getYiYanOptions(Prompt prompt) { - // 两个都为null 则没有配置文件 - if (yiYanOptions == null && prompt.getOptions() == null) { - throw new ChatException("ChatOptions 未配置参数!"); - } - // 优先使用 Prompt 里面的 ChatOptions - ChatOptions options = yiYanOptions; - if (prompt.getOptions() != null) { - options = (ChatOptions) prompt.getOptions(); - } - // Prompt 里面是一个 ChatOptions,用户可以随意传入,这里做一下判断 - if (!(options instanceof YiYanOptions)) { - throw new ChatException("Prompt 传入的不是 YiYanOptions!"); - } - // 转换 YiYanOptions - YiYanOptions useOptions = (YiYanOptions) options; - return useOptions; - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanChatCompletionMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanChatCompletionMessage.java deleted file mode 100644 index 278b1a7d6..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/yiyan/api/YiYanChatCompletionMessage.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.springframework.ai.models.yiyan.api; - -/** - * author: fansili - * time: 2024/3/9 10:37 - */ -public class YiYanChatCompletionMessage { -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java index f54ae39c8..55d16eab9 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java @@ -5,10 +5,10 @@ import org.springframework.ai.chat.messages.Message; import org.springframework.ai.chat.messages.SystemMessage; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.models.yiyan.YiYanChatClient; -import org.springframework.ai.models.yiyan.YiYanChatModel; -import org.springframework.ai.models.yiyan.YiYanOptions; -import org.springframework.ai.models.yiyan.api.YiYanApi; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatClient; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanChatModel; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatOptions; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanApi; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; @@ -35,7 +35,7 @@ public class YiYanChatTests { YiYanChatModel.ERNIE4_3_5_8K, 86400 ); - YiYanOptions yiYanOptions = new YiYanOptions(); + YiYanChatOptions yiYanOptions = new YiYanChatOptions(); yiYanOptions.setMaxOutputTokens(2048); yiYanOptions.setTopP(0.6f); yiYanOptions.setTemperature(0.85f); diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 2f5e70b27..93302bddf 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -230,17 +230,6 @@ yudao: appKey: cb6415c19d6162cda07b47316fcb0416 secretKey: Y2JiYTIxZjA3MDMxMjNjZjQzYzVmNzdh model: XING_HUO_3_5 - yiyan: - enable: true - aiPlatform: YI_YAN - max-tokens: 1500 - temperature: 0.85 - topP: 0.8 - topK: 0 - appKey: x0cuLZ7XsaTCU08vuJWO87Lg - secretKey: R9mYF9dl9KASgi5RUq0FQt3wRisSnOcK - refreshTokenSecondTime: 86400 - model: ERNIE4_3_5_8K openAiImage: enable: true api-key: ${OPEN_AI_KEY} diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 886644e74..52dea3fda 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -150,6 +150,19 @@ spring.ai: chat: model: llama3 +yudao.ai: + yiyan: + enable: true + aiPlatform: YIYAN # TODO @fan:建议每个都独立配置属性类 + max-tokens: 1500 + temperature: 0.85 + topP: 0.8 + topK: 0 + appKey: x0cuLZ7XsaTCU08vuJWO87Lg + secretKey: R9mYF9dl9KASgi5RUq0FQt3wRisSnOcK + refreshTokenSecondTime: 86400 + model: ERNIE4_3_5_8K + --- #################### 芋道相关配置 #################### yudao: From 645dfae003c723dd268ce0cacc0f0bfaea1a8314 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 18 May 2024 10:15:40 +0800 Subject: [PATCH 291/684] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91AI=EF=BC=9A=E8=AE=AF=E9=A3=9E=E6=98=9F?= =?UTF-8?q?=E7=81=AB=E7=9A=84=E6=8E=A5=E5=85=A5=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/config/AiChatClientFactory.java | 6 ++-- .../module/ai/dal/vo/AiChatModalConfigVO.java | 2 +- .../ai/config/YudaoAiAutoConfiguration.java | 6 ++-- .../ai/config/YudaoAiImageProperties.java | 4 +-- .../ai/config/YudaoAiProperties.java | 3 +- .../ai/core/enums/AiPlatformEnum.java | 13 ++++++-- .../model}/xinghuo/XingHuoChatClient.java | 9 +++--- .../core/model}/xinghuo/XingHuoChatModel.java | 2 +- .../core/model}/xinghuo/XingHuoOptions.java | 2 +- .../core/model}/xinghuo/api/XingHuoApi.java | 5 +-- .../xinghuo/api/XingHuoChatCompletion.java | 2 +- .../api/XingHuoChatCompletionMessage.java | 2 +- .../api/XingHuoChatCompletionRequest.java | 2 +- .../ai/chat/XingHuoChatClientMainTests.java | 4 +-- .../ai/chat/XingHuoChatClientTests.java | 8 ++--- .../framework/ai/chat/XingHuoOkHttpTests.java | 6 ++-- .../src/main/resources/application-local.yaml | 31 ------------------- .../src/main/resources/application.yaml | 31 ++++++++++++++++++- 18 files changed, 72 insertions(+), 66 deletions(-) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models => cn/iocoder/yudao/framework/ai/core/model}/xinghuo/XingHuoChatClient.java (93%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models => cn/iocoder/yudao/framework/ai/core/model}/xinghuo/XingHuoChatModel.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models => cn/iocoder/yudao/framework/ai/core/model}/xinghuo/XingHuoOptions.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models => cn/iocoder/yudao/framework/ai/core/model}/xinghuo/api/XingHuoApi.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models => cn/iocoder/yudao/framework/ai/core/model}/xinghuo/api/XingHuoChatCompletion.java (93%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models => cn/iocoder/yudao/framework/ai/core/model}/xinghuo/api/XingHuoChatCompletionMessage.java (61%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models => cn/iocoder/yudao/framework/ai/core/model}/xinghuo/api/XingHuoChatCompletionRequest.java (97%) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java index d5863dbc2..14dc2b8b5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import org.springframework.ai.chat.ChatClient; import org.springframework.ai.chat.StreamingChatClient; import org.springframework.ai.models.tongyi.QianWenChatClient; -import org.springframework.ai.models.xinghuo.XingHuoChatClient; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatClient; import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatClient; import org.springframework.ai.ollama.OllamaChatClient; import org.springframework.beans.factory.annotation.Autowired; @@ -27,7 +27,7 @@ public class AiChatClientFactory { public ChatClient getChatClient(AiPlatformEnum platformEnum) { if (AiPlatformEnum.QIAN_WEN == platformEnum) { return applicationContext.getBean(QianWenChatClient.class); - } else if (AiPlatformEnum.YIYAN == platformEnum) { + } else if (AiPlatformEnum.YI_YAN == platformEnum) { return applicationContext.getBean(YiYanChatClient.class); } else if (AiPlatformEnum.XING_HUO == platformEnum) { return applicationContext.getBean(XingHuoChatClient.class); @@ -42,7 +42,7 @@ public class AiChatClientFactory { // } if (AiPlatformEnum.QIAN_WEN == platformEnum) { return applicationContext.getBean(QianWenChatClient.class); - } else if (AiPlatformEnum.YIYAN == platformEnum) { + } else if (AiPlatformEnum.YI_YAN == platformEnum) { return applicationContext.getBean(YiYanChatClient.class); } else if (AiPlatformEnum.XING_HUO == platformEnum) { return applicationContext.getBean(XingHuoChatClient.class); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalConfigVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalConfigVO.java index 723e5338f..4ed060e22 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalConfigVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalConfigVO.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.ai.dal.vo; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import lombok.Data; import lombok.experimental.Accessors; -import org.springframework.ai.models.xinghuo.XingHuoChatModel; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanChatModel; /** diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index 67226ec60..13f8f71ed 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -5,9 +5,9 @@ import org.springframework.ai.models.tongyi.QianWenChatClient; import org.springframework.ai.models.tongyi.QianWenChatModal; import org.springframework.ai.models.tongyi.QianWenOptions; import org.springframework.ai.models.tongyi.api.QianWenApi; -import org.springframework.ai.models.xinghuo.XingHuoChatClient; -import org.springframework.ai.models.xinghuo.XingHuoOptions; -import org.springframework.ai.models.xinghuo.api.XingHuoApi; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatClient; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoOptions; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoApi; import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatClient; import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatOptions; import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanApi; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiImageProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiImageProperties.java index 1e6d9d9ec..ebae45ff1 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiImageProperties.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiImageProperties.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.framework.ai.config; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; -import org.springframework.ai.models.xinghuo.XingHuoChatModel; -import org.springframework.ai.models.xinghuo.XingHuoOptions; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoOptions; import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanChatModel; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java index 62bd1318d..16a6bc40e 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.framework.ai.config; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; -import org.springframework.ai.models.xinghuo.XingHuoChatModel; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanChatModel; import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageModelEnum; import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageStyleEnum; @@ -21,7 +21,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "yudao.ai") public class YudaoAiProperties { - private String initSource; private QianWenProperties qianwen; private XingHuoProperties xinghuo; private YiYanProperties yiyan; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java index cd60cc990..a85fffe9a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java @@ -16,16 +16,23 @@ public enum AiPlatformEnum { OPENAI("OpenAI", "OpenAI"), OLLAMA("Ollama", "Ollama"), - YIYAN("YiYan", "文心一言"), + YI_YAN("YiYan", "文心一言"), // 百度 + XING_HUO("XingHuo", "星火"), // 讯飞 + + QIAN_WEN("qianwen", "千问"), // 阿里 - QIAN_WEN("qianwen", "千问"), - XING_HUO("xinghuo", "星火"), OPEN_AI_DALL("dall", "dall"), MIDJOURNEY("midjourney", "midjourney"), ; + /** + * 平台 + */ private final String platform; + /** + * 平台名 + */ private final String name; // public static List CHAT_PLATFORM_LIST = Lists.newArrayList( diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/XingHuoChatClient.java similarity index 93% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoChatClient.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/XingHuoChatClient.java index 0010a75fa..5537fc1eb 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/XingHuoChatClient.java @@ -1,14 +1,14 @@ -package org.springframework.ai.models.xinghuo; +package cn.iocoder.yudao.framework.ai.core.model.xinghuo; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.exceptions.ExceptionUtil; import cn.iocoder.yudao.framework.ai.core.exception.ChatException; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoApi; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoChatCompletion; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoChatCompletionRequest; import org.springframework.ai.chat.*; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.models.xinghuo.api.XingHuoApi; -import org.springframework.ai.models.xinghuo.api.XingHuoChatCompletion; -import org.springframework.ai.models.xinghuo.api.XingHuoChatCompletionRequest; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.retry.RetryCallback; @@ -21,6 +21,7 @@ import java.time.Duration; import java.util.List; import java.util.stream.Collectors; +// TODO @fan:参考 yiyan 的修改建议,调整下 xinghuo 的实现;可以等 yiyan 修改完建议,然后我 review 完,再改这个哈; /** * 讯飞星火 client *

diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoChatModel.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/XingHuoChatModel.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoChatModel.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/XingHuoChatModel.java index 859e41c03..e9ef5ef35 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoChatModel.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/XingHuoChatModel.java @@ -1,4 +1,4 @@ -package org.springframework.ai.models.xinghuo; +package cn.iocoder.yudao.framework.ai.core.model.xinghuo; import lombok.Getter; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/XingHuoOptions.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoOptions.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/XingHuoOptions.java index bdc671092..cb4753833 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/XingHuoOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/XingHuoOptions.java @@ -1,4 +1,4 @@ -package org.springframework.ai.models.xinghuo; +package cn.iocoder.yudao.framework.ai.core.model.xinghuo; import org.springframework.ai.chat.prompt.ChatOptions; import lombok.Data; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/api/XingHuoApi.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoApi.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/api/XingHuoApi.java index 027e8a2d2..b267de84c 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/api/XingHuoApi.java @@ -1,8 +1,8 @@ -package org.springframework.ai.models.xinghuo.api; +package cn.iocoder.yudao.framework.ai.core.model.xinghuo.api; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONUtil; -import org.springframework.ai.models.xinghuo.XingHuoChatModel; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; import lombok.Data; import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; @@ -21,6 +21,7 @@ import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; +// TODO @fan:讯飞使用 spring websocket 接入,还是 okhttp?确认了,未使用的最好删除下,反正 git 也能找回 history /** * 讯飞星火 属性、api *

diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoChatCompletion.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/api/XingHuoChatCompletion.java similarity index 93% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoChatCompletion.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/api/XingHuoChatCompletion.java index e419d522e..46aff8717 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoChatCompletion.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/api/XingHuoChatCompletion.java @@ -1,4 +1,4 @@ -package org.springframework.ai.models.xinghuo.api; +package cn.iocoder.yudao.framework.ai.core.model.xinghuo.api; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoChatCompletionMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/api/XingHuoChatCompletionMessage.java similarity index 61% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoChatCompletionMessage.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/api/XingHuoChatCompletionMessage.java index f0e0f8d1e..f527b10d4 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoChatCompletionMessage.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/api/XingHuoChatCompletionMessage.java @@ -1,4 +1,4 @@ -package org.springframework.ai.models.xinghuo.api; +package cn.iocoder.yudao.framework.ai.core.model.xinghuo.api; /** * author: fansili diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoChatCompletionRequest.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/api/XingHuoChatCompletionRequest.java similarity index 97% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoChatCompletionRequest.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/api/XingHuoChatCompletionRequest.java index 3f2b211ff..f3ca1eb30 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/xinghuo/api/XingHuoChatCompletionRequest.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/api/XingHuoChatCompletionRequest.java @@ -1,4 +1,4 @@ -package org.springframework.ai.models.xinghuo.api; +package cn.iocoder.yudao.framework.ai.core.model.xinghuo.api; import lombok.Data; import lombok.Getter; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientMainTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientMainTests.java index 77cf9effc..524bd3e0d 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientMainTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientMainTests.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.framework.ai.chat; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONUtil; -import org.springframework.ai.models.xinghuo.api.XingHuoChatCompletion; -import org.springframework.ai.models.xinghuo.api.XingHuoChatCompletionRequest; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoChatCompletion; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoChatCompletionRequest; import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient; import org.springframework.web.reactive.socket.client.WebSocketClient; import reactor.core.publisher.Flux; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java index 44793907e..8d9cb38e0 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java @@ -5,10 +5,10 @@ import org.springframework.ai.chat.messages.Message; import org.springframework.ai.chat.messages.SystemMessage; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.models.xinghuo.XingHuoChatClient; -import org.springframework.ai.models.xinghuo.XingHuoChatModel; -import org.springframework.ai.models.xinghuo.XingHuoOptions; -import org.springframework.ai.models.xinghuo.api.XingHuoApi; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatClient; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoOptions; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoApi; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Flux; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoOkHttpTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoOkHttpTests.java index f45f96412..5a087412b 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoOkHttpTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoOkHttpTests.java @@ -2,9 +2,9 @@ package cn.iocoder.yudao.framework.ai.chat; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONUtil; -import org.springframework.ai.models.xinghuo.XingHuoChatClient; -import org.springframework.ai.models.xinghuo.api.XingHuoChatCompletion; -import org.springframework.ai.models.xinghuo.api.XingHuoChatCompletionRequest; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatClient; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoChatCompletion; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoChatCompletionRequest; import okhttp3.*; import org.jetbrains.annotations.NotNull; diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 93302bddf..99c888f31 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -209,37 +209,6 @@ wx: # 芋道配置项,设置当前项目所有自定义的配置 yudao: - ai: - initSource: yaml - qianwen: - enable: true - aiPlatform: QIAN_WEN - max-tokens: 1500 - temperature: 0.85 - topP: 0.8 - topK: 0 - api-key: sk-Zsd81gZYg7 - xinghuo: - enable: true - aiPlatform: XING_HUO - max-tokens: 1500 - temperature: 0.85 - topP: 0.8 - topK: 0 - appId: 13c8cca6 - appKey: cb6415c19d6162cda07b47316fcb0416 - secretKey: Y2JiYTIxZjA3MDMxMjNjZjQzYzVmNzdh - model: XING_HUO_3_5 - openAiImage: - enable: true - api-key: ${OPEN_AI_KEY} - model: dall_e_2 - style: vivid - midjourney: - enable: true - token: MTE4MjE3MjY2MjkxNTY3ODIzOA.GEV1SG.c49F8lZoGCUHwsj8O0UdodmM6nyQHvuD2fXflw - guild-id: 1237948819677904956 - channel-id: 1237948819677904960 captcha: enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试; security: diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 52dea3fda..549fd9edd 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -153,7 +153,7 @@ spring.ai: yudao.ai: yiyan: enable: true - aiPlatform: YIYAN # TODO @fan:建议每个都独立配置属性类 + aiPlatform: YI_YAN # TODO @fan:建议每个都独立配置属性类 max-tokens: 1500 temperature: 0.85 topP: 0.8 @@ -162,6 +162,35 @@ yudao.ai: secretKey: R9mYF9dl9KASgi5RUq0FQt3wRisSnOcK refreshTokenSecondTime: 86400 model: ERNIE4_3_5_8K + xinghuo: + enable: true + aiPlatform: XING_HUO # TODO @fan:建议每个都独立配置属性类 + max-tokens: 1500 + temperature: 0.85 + topP: 0.8 + topK: 0 + appId: 13c8cca6 + appKey: cb6415c19d6162cda07b47316fcb0416 + secretKey: Y2JiYTIxZjA3MDMxMjNjZjQzYzVmNzdh + model: XING_HUO_3_5 + qianwen: + enable: true + aiPlatform: QIAN_WEN + max-tokens: 1500 + temperature: 0.85 + topP: 0.8 + topK: 0 + api-key: sk-Zsd81gZYg7 + openAiImage: + enable: true + api-key: ${OPEN_AI_KEY} + model: dall_e_2 + style: vivid + midjourney: + enable: true + token: MTE4MjE3MjY2MjkxNTY3ODIzOA.GEV1SG.c49F8lZoGCUHwsj8O0UdodmM6nyQHvuD2fXflw + guild-id: 1237948819677904956 + channel-id: 1237948819677904960 --- #################### 芋道相关配置 #################### From f4a0058e88ab97b6c4af52a155ff1975dd7129b5 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 18 May 2024 10:36:25 +0800 Subject: [PATCH 292/684] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91AI=EF=BC=9Aqwen=20=E7=9A=84=E6=8E=A5=E5=85=A5?= =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/config/AiChatClientFactory.java | 2 +- .../framework/ai/config/YudaoAiAutoConfiguration.java | 8 ++++---- .../yudao/framework/ai/core/enums/AiPlatformEnum.java | 6 ++---- .../ai/core/model}/tongyi/QianWenChatClient.java | 6 +++--- .../framework/ai/core/model}/tongyi/QianWenChatModal.java | 2 +- .../framework/ai/core/model}/tongyi/QianWenOptions.java | 2 +- .../framework/ai/core/model}/tongyi/api/QianWenApi.java | 4 ++-- .../ai/core/model}/tongyi/api/QianWenChatCompletion.java | 2 +- .../model}/tongyi/api/QianWenChatCompletionMessage.java | 2 +- .../model}/tongyi/api/QianWenChatCompletionRequest.java | 2 +- .../framework/ai/core/model}/tongyi/package-info.java | 2 +- .../yudao/framework/ai/chat/QianWenChatClientTests.java | 8 ++++---- 12 files changed, 22 insertions(+), 24 deletions(-) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models => cn/iocoder/yudao/framework/ai/core/model}/tongyi/QianWenChatClient.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models => cn/iocoder/yudao/framework/ai/core/model}/tongyi/QianWenChatModal.java (96%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models => cn/iocoder/yudao/framework/ai/core/model}/tongyi/QianWenOptions.java (98%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models => cn/iocoder/yudao/framework/ai/core/model}/tongyi/api/QianWenApi.java (94%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models => cn/iocoder/yudao/framework/ai/core/model}/tongyi/api/QianWenChatCompletion.java (60%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models => cn/iocoder/yudao/framework/ai/core/model}/tongyi/api/QianWenChatCompletionMessage.java (61%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models => cn/iocoder/yudao/framework/ai/core/model}/tongyi/api/QianWenChatCompletionRequest.java (82%) rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/{org/springframework/ai/models => cn/iocoder/yudao/framework/ai/core/model}/tongyi/package-info.java (85%) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java index 14dc2b8b5..e7a64c214 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.ai.config; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import org.springframework.ai.chat.ChatClient; import org.springframework.ai.chat.StreamingChatClient; -import org.springframework.ai.models.tongyi.QianWenChatClient; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatClient; import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatClient; import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatClient; import org.springframework.ai.ollama.OllamaChatClient; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index 13f8f71ed..f942b12bd 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.framework.ai.config; import cn.hutool.core.io.IoUtil; -import org.springframework.ai.models.tongyi.QianWenChatClient; -import org.springframework.ai.models.tongyi.QianWenChatModal; -import org.springframework.ai.models.tongyi.QianWenOptions; -import org.springframework.ai.models.tongyi.api.QianWenApi; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatClient; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatModal; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenOptions; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.api.QianWenApi; import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatClient; import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoOptions; import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoApi; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java index a85fffe9a..fc41069a9 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java @@ -5,10 +5,9 @@ import lombok.Getter; // TODO 芋艿:这块,看看要不要调整下; /** - * ai 模型平台 + * AI 模型平台 * - * author: fansili - * time: 2024/3/11 10:12 + * @author fansili */ @Getter @AllArgsConstructor @@ -18,7 +17,6 @@ public enum AiPlatformEnum { OLLAMA("Ollama", "Ollama"), YI_YAN("YiYan", "文心一言"), // 百度 XING_HUO("XingHuo", "星火"), // 讯飞 - QIAN_WEN("qianwen", "千问"), // 阿里 OPEN_AI_DALL("dall", "dall"), diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatClient.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatClient.java index 31e60d119..85fa771bd 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatClient.java @@ -1,10 +1,10 @@ -package org.springframework.ai.models.tongyi; +package cn.iocoder.yudao.framework.ai.core.model.tongyi; import cn.iocoder.yudao.framework.ai.core.exception.ChatException; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.api.QianWenApi; import org.springframework.ai.chat.*; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.models.tongyi.api.QianWenApi; import cn.iocoder.yudao.framework.ai.core.model.yiyan.exception.YiYanApiException; import com.alibaba.dashscope.aigc.generation.GenerationResult; import com.alibaba.dashscope.aigc.generation.models.QwenParam; @@ -24,6 +24,7 @@ import java.time.Duration; import java.util.List; import java.util.stream.Collectors; +// TODO @芋艿:暂时不需要重构;等 spring cloud alibaba 的 ai 发布最新的 /** * 阿里 通义千问 client *

@@ -39,7 +40,6 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient { private QianWenOptions qianWenOptions; - public QianWenChatClient() { } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatModal.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatModal.java similarity index 96% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatModal.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatModal.java index 9474a8df5..e1cbcd5de 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenChatModal.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatModal.java @@ -1,4 +1,4 @@ -package org.springframework.ai.models.tongyi; +package cn.iocoder.yudao.framework.ai.core.model.tongyi; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenOptions.java similarity index 98% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenOptions.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenOptions.java index 39db36608..b6dba53c9 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/QianWenOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenOptions.java @@ -1,4 +1,4 @@ -package org.springframework.ai.models.tongyi; +package cn.iocoder.yudao.framework.ai.core.model.tongyi; import org.springframework.ai.chat.prompt.ChatOptions; import lombok.Data; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenApi.java similarity index 94% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenApi.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenApi.java index 2e905114f..6d3e7cd41 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenApi.java @@ -1,6 +1,6 @@ -package org.springframework.ai.models.tongyi.api; +package cn.iocoder.yudao.framework.ai.core.model.tongyi.api; -import org.springframework.ai.models.tongyi.QianWenChatModal; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatModal; import cn.iocoder.yudao.framework.ai.core.exception.AiException; import com.alibaba.dashscope.aigc.generation.Generation; import com.alibaba.dashscope.aigc.generation.GenerationResult; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletion.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletion.java similarity index 60% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletion.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletion.java index 1c3c6109b..1e7748ddc 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletion.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletion.java @@ -1,4 +1,4 @@ -package org.springframework.ai.models.tongyi.api; +package cn.iocoder.yudao.framework.ai.core.model.tongyi.api; /** diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionMessage.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletionMessage.java similarity index 61% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionMessage.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletionMessage.java index 4e5d02323..318829bb4 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionMessage.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletionMessage.java @@ -1,4 +1,4 @@ -package org.springframework.ai.models.tongyi.api; +package cn.iocoder.yudao.framework.ai.core.model.tongyi.api; /** * author: fansili diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionRequest.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletionRequest.java similarity index 82% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionRequest.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletionRequest.java index 04b69848f..b1d72d15f 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/api/QianWenChatCompletionRequest.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/api/QianWenChatCompletionRequest.java @@ -1,4 +1,4 @@ -package org.springframework.ai.models.tongyi.api; +package cn.iocoder.yudao.framework.ai.core.model.tongyi.api; import com.alibaba.dashscope.aigc.generation.models.QwenParam; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/package-info.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/package-info.java similarity index 85% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/package-info.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/package-info.java index 8d7793b34..11ed0c113 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/tongyi/package-info.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/package-info.java @@ -8,4 +8,4 @@ * author: fansili * time: 2024/3/13 21:05 */ -package org.springframework.ai.models.tongyi; \ No newline at end of file +package cn.iocoder.yudao.framework.ai.core.model.tongyi; \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java index 99e2b5f7a..a003d1bb7 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java @@ -4,10 +4,10 @@ import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.messages.SystemMessage; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.models.tongyi.QianWenChatClient; -import org.springframework.ai.models.tongyi.QianWenChatModal; -import org.springframework.ai.models.tongyi.QianWenOptions; -import org.springframework.ai.models.tongyi.api.QianWenApi; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatClient; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatModal; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenOptions; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.api.QianWenApi; import com.alibaba.dashscope.aigc.generation.GenerationResult; import com.alibaba.dashscope.aigc.generation.models.QwenParam; import com.alibaba.dashscope.common.Message; From fa9328112dcf130b82fbd92ed2039add2dbfbad6 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 18 May 2024 12:28:43 +0800 Subject: [PATCH 293/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9Aopenai=20=E6=8E=A5=E5=85=A5=E7=9A=84=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/config/AiChatClientFactory.java | 3 +++ .../ai/service/impl/AiChatServiceImpl.java | 7 ++++-- .../src/main/resources/application.properties | 11 ---------- .../openAiImage/OpenAiImageClientTests.java | 22 +++++++++++++++++++ .../src/main/resources/application.yaml | 7 ++++++ 5 files changed, 37 insertions(+), 13 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.properties diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java index e7a64c214..5efd264a9 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatClient; import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatClient; import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatClient; import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.ai.openai.OpenAiChatClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; @@ -48,6 +49,8 @@ public class AiChatClientFactory { return applicationContext.getBean(XingHuoChatClient.class); } else if (AiPlatformEnum.OLLAMA == platformEnum) { return applicationContext.getBean(OllamaChatClient.class); + } else if (AiPlatformEnum.OPENAI == platformEnum) { + return applicationContext.getBean(OpenAiChatClient.class); } throw new IllegalArgumentException("不支持的 chat client!"); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index b56b16648..9fd80d1c6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.ai.service.impl; import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO; @@ -123,7 +124,8 @@ public class AiChatServiceImpl implements AiChatService { // 3.3 流式返回 StringBuffer contentBuffer = new StringBuffer(); return streamResponse.map(response -> { - String newContent = response.getResult().getOutput().getContent(); + String newContent = response.getResult() != null ? response.getResult().getOutput().getContent() : null; + newContent = StrUtil.nullToDefault(newContent, ""); // 避免 null 的 情况 contentBuffer.append(newContent); // 响应结果 return new AiChatMessageSendRespVO().setSend(BeanUtils.toBean(userMessage, AiChatMessageSendRespVO.Message.class)) @@ -152,7 +154,8 @@ public class AiChatServiceImpl implements AiChatService { // 2. 构建 ChatOptions 对象 TODO 芋艿:临时注释掉;等文心一言兼容了; // ChatOptions chatOptions = ChatOptionsBuilder.builder().withTemperature(conversation.getTemperature().floatValue()).build(); - return new Prompt(chatMessages, null); +// return new Prompt(chatMessages, null); + return new Prompt(chatMessages); } private AiChatMessageDO createChatMessage(Long conversationId, AiChatModelDO model, diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.properties b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.properties deleted file mode 100644 index 6ec2672e6..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/application.properties +++ /dev/null @@ -1,11 +0,0 @@ -# open ai TODO @fansili?????????????? - -# openAI https://openai.com/ -spring.ai.openai.api-key=${OPEN_AI_KEY} -spring.ai.openai.chat.options.model=gpt-3.5-turbo -spring.ai.openai.chat.options.temperature=0.7 -#spring.ai.vectorstore.milvus.client.connect-timeout-ms=50000 -#spring.ai.vectorstore.milvus.client.keep-alive-timeout-ms=50000 -#spring.ai.vectorstore.milvus.client.keep-alive-time-ms=80000 -#spring.ai.vectorstore.pinecone.server-side-timeout=100s - diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java index 6944eed70..bf184a849 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java @@ -4,9 +4,12 @@ import org.springframework.ai.image.ImagePrompt; import org.springframework.ai.image.ImageResponse; import org.junit.Before; import org.junit.Test; +import org.springframework.ai.openai.OpenAiChatClient; import org.springframework.ai.openai.OpenAiImageClient; import org.springframework.ai.openai.OpenAiImageOptions; +import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.ai.openai.api.OpenAiImageApi; +import reactor.core.publisher.Flux; import javax.imageio.ImageIO; import javax.swing.*; @@ -15,6 +18,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Base64; import java.util.Scanner; +import java.util.function.Function; /** * author: fansili @@ -66,4 +70,22 @@ public class OpenAiImageClientTests { return null; } } + + public static void main(String[] args) { +// OpenAiApi api = new OpenAiApi("https://api.gptsapi.net", "sk-yzKea6d8e8212c3bdd99f9f44ced1cae37c097e5aa3BTS7z"); +// OpenAiApi api = new OpenAiApi("https://openkey.cloud", "sk-QmgIIPc5xiYd8lPb076b1b7774Ea49Af9eD2Ef172c8f7e43"); + OpenAiApi api = new OpenAiApi("https://api.chatanywhere.tech", "sk-gkgfYxhX9FxyZJznwxRZSJwKeGQYNPDVWjhby2PRRf17GHeT"); + OpenAiChatClient client = new OpenAiChatClient(api); +// String result = client.call("未来,英文是什么?"); +// System.out.println(result); + Flux result = client.stream("未来,英文是什么?"); + result.map(new Function() { + @Override + public String apply(String s) { + System.out.println(s); + return s; + } + }).blockLast(); + } + } diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 549fd9edd..e8e07c675 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -149,6 +149,13 @@ spring.ai: base-url: http://127.0.0.1:11434 chat: model: llama3 + openai: +# api-key: sk-QmgIIPc5xiYd8lPb076b1b7774Ea49Af9eD2Ef172c8f7e43 +# base-url: https://openkey.cloud +# api-key: sk-gkgfYxhX9FxyZJznwxRZSJwKeGQYNPDVWjhby2PRRf17GHeT +# base-url: https://api.chatanywhere.tech + api-key: sk-yzKea6d8e8212c3bdd99f9f44ced1cae37c097e5aa3BTS7z + base-url: https://api.gptsapi.net yudao.ai: yiyan: From 33e8c7ca2e4b3e7579361600ef9c10e47cf1d296 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 18 May 2024 20:42:48 +0800 Subject: [PATCH 294/684] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91MEMBER=EF=BC=9A=E5=AE=8C=E5=96=84=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E5=B0=8F=E7=A8=8B=E5=BA=8F=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/controller/app/social/AppSocialUserController.java | 1 + .../member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java | 1 + 2 files changed, 2 insertions(+) diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java index 6e3973525..2cf7b8641 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java @@ -71,6 +71,7 @@ public class AppSocialUserController { public CommonResult getWxQrcode(@RequestBody @Valid AppSocialWxQrcodeReqVO reqVO) { byte[] wxQrcode = socialClientApi.getWxaQrcode(BeanUtils.toBean(reqVO, SocialWxQrcodeReqDTO.class) .setEnvVersion(AppSocialWxQrcodeReqVO.ENV_VERSION)); + // TODO @puhui999:1)是不是 base64 返回,不拼接哈 data:image/png;base64;2)cn.hutool.core.codec.Base64.encode() return success("data:image/png;base64," + Base64.getEncoder().encodeToString(wxQrcode)); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java index 10321519c..aabdc72c9 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java @@ -10,6 +10,7 @@ import lombok.Data; public class AppSocialWxQrcodeReqVO { // TODO @puhui999: 没有默认值 getQrcodeService().createWxaCodeUnlimitBytes() 转类型会报错 🤣 + // TODO @puhui999:懂了哈;default 最好在 controller 搞;对于 VO 来说,不给默认值; public static String ENV_VERSION = "release"; // 小程序版本。正式版为 "release",体验版为 "trial",开发版为 "develop" private static String SCENE = ""; // 页面路径不能携带参数(参数请放在scene字段里) private static Integer WIDTH = 430; // 二维码宽度 From 8e5584821e722498b21523a38efe22eef57ae638 Mon Sep 17 00:00:00 2001 From: zhougang <921366807@qq.com> Date: Sun, 19 May 2024 15:34:45 +0800 Subject: [PATCH 295/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91=20?= =?UTF-8?q?protection=20=E6=A8=A1=E5=9D=97=E6=96=B0=E5=A2=9E=20signature?= =?UTF-8?q?=20=E5=AE=9E=E7=8E=B0=20API=20=E7=AD=BE=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pom.xml | 9 +- .../YudaoSignatureAutoConfiguration.java | 27 +++ .../signature/core/annotation/Signature.java | 57 ++++++ .../signature/core/aop/SignatureAspect.java | 170 ++++++++++++++++++ .../core/redis/SignatureRedisDAO.java | 56 ++++++ .../signature/core/SignatureTest.java | 136 ++++++++++++++ .../core/filter/CacheRequestBodyWrapper.java | 4 + 7 files changed, 458 insertions(+), 1 deletion(-) create mode 100644 yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/config/YudaoSignatureAutoConfiguration.java create mode 100644 yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/annotation/Signature.java create mode 100644 yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/aop/SignatureAspect.java create mode 100644 yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/redis/SignatureRedisDAO.java create mode 100644 yudao-framework/yudao-spring-boot-starter-protection/src/test/java/cn/iocoder/yudao/framework/signature/core/SignatureTest.java diff --git a/yudao-framework/yudao-spring-boot-starter-protection/pom.xml b/yudao-framework/yudao-spring-boot-starter-protection/pom.xml index bbb5b12eb..025bb7591 100644 --- a/yudao-framework/yudao-spring-boot-starter-protection/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-protection/pom.xml @@ -12,7 +12,7 @@ jar ${project.artifactId} - 服务保证,提供分布式锁、幂等、限流、熔断等等功能 + 服务保证,提供分布式锁、幂等、限流、熔断、API签名等等功能 https://github.com/YunaiV/ruoyi-vue-pro @@ -35,6 +35,13 @@ lock4j-redisson-spring-boot-starter true + + + + org.springframework.boot + spring-boot-starter-test + test + diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/config/YudaoSignatureAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/config/YudaoSignatureAutoConfiguration.java new file mode 100644 index 000000000..5b4b8e43e --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/config/YudaoSignatureAutoConfiguration.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.framework.signature.config; + +import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; +import cn.iocoder.yudao.framework.signature.core.aop.SignatureAspect; +import cn.iocoder.yudao.framework.signature.core.redis.SignatureRedisDAO; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.data.redis.core.StringRedisTemplate; + +/** + * @author Zhougang + */ +@AutoConfiguration(after = YudaoRedisAutoConfiguration.class) +public class YudaoSignatureAutoConfiguration { + + @Bean + public SignatureAspect signatureAspect(SignatureRedisDAO signatureRedisDAO) { + return new SignatureAspect(signatureRedisDAO); + } + + @Bean + @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") + public SignatureRedisDAO signatureRedisDAO(StringRedisTemplate stringRedisTemplate) { + return new SignatureRedisDAO(stringRedisTemplate); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/annotation/Signature.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/annotation/Signature.java new file mode 100644 index 000000000..1b7e12786 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/annotation/Signature.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.framework.signature.core.annotation; + +import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; + +import java.lang.annotation.*; + + +/** + * 签名注解 + * + * @author Zhougang + */ +@Inherited +@Documented +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Signature { + + /** + * 同一个请求多长时间内有效 默认 10分钟 + */ + long expireTime() default 600000L; + + // ========================== 签名参数 ========================== + + /** + * 提示信息,签名失败的提示 + * + * @see GlobalErrorCodeConstants#BAD_REQUEST + */ + String message() default "签名不正确"; // 为空时,使用 BAD_REQUEST 错误提示 + + /** + * 签名字段:appId 应用ID + */ + String appId() default "appId"; + + /** + * 签名字段:timestamp 时间戳 + */ + String timestamp() default "timestamp"; + + /** + * 签名字段:nonce 随机数,10 位以上 + */ + String nonce() default "nonce"; + + /** + * sign 客户端签名 + */ + String sign() default "sign"; + + /** + * url 客户端不需要传递,但是可以用来加签(如: /{id} 带有动态参数的 url ,如果没有动态参数可设置为 false 不进行加签) + */ + boolean urlEnable() default true; +} diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/aop/SignatureAspect.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/aop/SignatureAspect.java new file mode 100644 index 000000000..dc1510465 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/aop/SignatureAspect.java @@ -0,0 +1,170 @@ +package cn.iocoder.yudao.framework.signature.core.aop; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.SignUtil; +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.signature.core.annotation.Signature; +import cn.iocoder.yudao.framework.signature.core.redis.SignatureRedisDAO; +import cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyWrapper; +import jakarta.servlet.http.HttpServletRequest; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.springframework.util.Assert; + +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.Objects; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.concurrent.TimeUnit; + +/** + * 拦截声明了 {@link Signature} 注解的方法,实现签名 + * + * @author Zhougang + */ +@Aspect +@Slf4j +@AllArgsConstructor +public class SignatureAspect { + + private final SignatureRedisDAO signatureRedisDAO; + + @Before("@annotation(signature)") + public void beforePointCut(JoinPoint joinPoint, Signature signature) { + if (!verifySignature(signature, Objects.requireNonNull(ServletUtils.getRequest()))) { + log.info("[beforePointCut][方法{} 参数({}) 签名失败]", joinPoint.getSignature().toString(), + joinPoint.getArgs()); + String message = StrUtil.blankToDefault(signature.message(), + GlobalErrorCodeConstants.BAD_REQUEST.getMsg()); + throw new ServiceException(GlobalErrorCodeConstants.BAD_REQUEST.getCode(), message); + } + } + + private boolean verifySignature(Signature signature, HttpServletRequest request) { + if (!verifyHeaders(signature, request)) { + return false; + } + // 校验 appId 是否能获取到对应的 appSecret + String appId = request.getHeader(signature.appId()); + String appSecret = signatureRedisDAO.getAppSecret(appId); + Assert.notNull(appSecret, "找不到对应的 appSecret"); + // 请求头 + SortedMap headersMap = getRequestHeaders(signature, request); + // 如:/user/{id} url 带有动态参数的情况 + String urlParams = signature.urlEnable() ? request.getServletPath() : ""; + // 请求参数 + String requestParams = getRequestParams(request); + // 请求体 + String requestBody = getRequestBody(request); + // 生成服务端签名 + String serverSignature = SignUtil.signParamsSha256(headersMap, + urlParams + requestParams + requestBody + appSecret); + // 客户端签名 + String clientSignature = request.getHeader(signature.sign()); + if (!StrUtil.equals(clientSignature, serverSignature)) { + return false; + } + String nonce = headersMap.get(signature.nonce()); + // 将 nonce 记入缓存,防止重复使用(重点二:此处需要将 ttl 设定为允许 timestamp 时间差的值 x 2 ) + signatureRedisDAO.setNonce(nonce, signature.expireTime(), TimeUnit.MILLISECONDS); + return true; + } + + /** + * 校验请求头加签参数 + * 1.appId 是否为空 + * 2.timestamp 是否为空,请求是否已经超时,默认 10 分钟 + * 3.nonce 是否为空,随机数是否 10 位以上,是否在规定时间内已经访问过了 + * 4.sign 是否为空 + * + * @param signature signature + * @param request request + */ + private boolean verifyHeaders(Signature signature, HttpServletRequest request) { + String appId = request.getHeader(signature.appId()); + if (StrUtil.isBlank(appId)) { + return false; + } + String timestamp = request.getHeader(signature.timestamp()); + if (StrUtil.isBlank(timestamp)) { + return false; + } + String nonce = request.getHeader(signature.nonce()); + if (StrUtil.isBlank(nonce) || nonce.length() < 10) { + return false; + } + String sign = request.getHeader(signature.sign()); + if (StrUtil.isBlank(sign)) { + return false; + } + // 其他合法性校验 + long expireTime = signature.expireTime(); + long requestTimestamp = Long.parseLong(timestamp); + // 检查 timestamp 是否超出允许的范围 (重点一:此处需要取绝对值) + long timestampDisparity = Math.abs(System.currentTimeMillis() - requestTimestamp); + if (timestampDisparity > expireTime) { + return false; + } + String cacheNonce = signatureRedisDAO.getNonce(nonce); + return StrUtil.isBlank(cacheNonce); + } + + /** + * 获取请求头加签参数 + * + * @param request request + * @return signature params + */ + private SortedMap getRequestHeaders(Signature signature, HttpServletRequest request) { + SortedMap sortedMap = new TreeMap<>(); + sortedMap.put(signature.appId(), request.getHeader(signature.appId())); + sortedMap.put(signature.timestamp(), request.getHeader(signature.timestamp())); + sortedMap.put(signature.nonce(), request.getHeader(signature.nonce())); + return sortedMap; + } + + /** + * 获取 URL 参数 + * + * @param request request + * @return queryParams + */ + private String getRequestParams(HttpServletRequest request) { + if (CollUtil.isEmpty(request.getParameterMap())) { + return ""; + } + Map requestParams = request.getParameterMap(); + // 获取 URL 请求参数 + SortedMap sortParamsMap = new TreeMap<>(); + for (Map.Entry entry : requestParams.entrySet()) { + sortParamsMap.put(entry.getKey(), entry.getValue()[0]); + } + // 按 key 排序 + StringBuilder queryString = new StringBuilder(); + for (Map.Entry entry : sortParamsMap.entrySet()) { + queryString.append("&").append(entry.getKey()).append("=").append(entry.getValue()); + } + return queryString.substring(1); + } + + /** + * 获取请求体参数 + * + * @param request request + * @return body + */ + private String getRequestBody(HttpServletRequest request) { + CacheRequestBodyWrapper requestWrapper = new CacheRequestBodyWrapper(request); + // 获取 body + return new String(requestWrapper.getBody(), StandardCharsets.UTF_8); + } + +} + diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/redis/SignatureRedisDAO.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/redis/SignatureRedisDAO.java new file mode 100644 index 000000000..d00fe7f8d --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/redis/SignatureRedisDAO.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.framework.signature.core.redis; + +import lombok.AllArgsConstructor; +import org.springframework.data.redis.core.StringRedisTemplate; + +import java.util.concurrent.TimeUnit; + +/** + * API 签名 Redis DAO + * + * @author Zhougang + */ +@AllArgsConstructor +public class SignatureRedisDAO { + + private final StringRedisTemplate stringRedisTemplate; + + /** + * 验签随机数 + *

+ * KEY 格式:signature_nonce:%s // 参数为 随机数 + * VALUE 格式:String + * 过期时间:不固定 + */ + private static final String SIGNATURE_NONCE = "signature_nonce:%s"; + + /** + * 签名密钥 + *

+ * KEY 格式:signature_appid:%s // 参数为 appid + * VALUE 格式:String + * 过期时间:预加载到 redis 永不过期 + */ + private static final String SIGNATURE_APPID = "signature_appid:%s"; + + public String getAppSecret(String appId) { + return stringRedisTemplate.opsForValue().get(formatAppIdKey(appId)); + } + + public String getNonce(String nonce) { + return stringRedisTemplate.opsForValue().get(formatNonceKey(nonce)); + } + + public void setNonce(String nonce, long time, TimeUnit timeUnit) { + // 将 nonce 记入缓存,防止重复使用(重点二:此处需要将 ttl 设定为允许 timestamp 时间差的值 x 2 ) + stringRedisTemplate.opsForValue().set(formatNonceKey(nonce), nonce, time * 2, timeUnit); + } + + private static String formatAppIdKey(String key) { + return String.format(SIGNATURE_APPID, key); + } + + private static String formatNonceKey(String key) { + return String.format(SIGNATURE_NONCE, key); + } +} diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/test/java/cn/iocoder/yudao/framework/signature/core/SignatureTest.java b/yudao-framework/yudao-spring-boot-starter-protection/src/test/java/cn/iocoder/yudao/framework/signature/core/SignatureTest.java new file mode 100644 index 000000000..a253cd51a --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/test/java/cn/iocoder/yudao/framework/signature/core/SignatureTest.java @@ -0,0 +1,136 @@ +package cn.iocoder.yudao.framework.signature.core; + +import cn.hutool.core.lang.Snowflake; +import cn.hutool.crypto.digest.DigestUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.http.HttpUtil; +import org.junit.jupiter.api.Test; + +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +/** + * {@link SignatureTest} 的单元测试 + */ +public class SignatureTest { + + @Test + public void testSignatureGet() { + String appId = "xxxxxx"; + Snowflake snowflake = new Snowflake(); + + // 验签请求头前端需传入字段 + SortedMap headersMap = new TreeMap<>(); + headersMap.put("appId", appId); + headersMap.put("timestamp", String.valueOf(System.currentTimeMillis())); + headersMap.put("nonce", String.valueOf(snowflake.nextId())); + + // 客户端加签内容 + StringBuilder clientSignatureContent = new StringBuilder(); + // 请求头 + for (Map.Entry entry : headersMap.entrySet()) { + clientSignatureContent.append(entry.getKey()).append(entry.getValue()); + } + // 请求 url + clientSignatureContent.append("/admin-api/infra/demo01-contact/get"); + // 请求参数 + SortedMap paramsMap = new TreeMap<>(); + paramsMap.put("id", "100"); + paramsMap.put("name", "张三"); + StringBuilder queryString = new StringBuilder(); + for (Map.Entry entry : paramsMap.entrySet()) { + queryString.append("&").append(entry.getKey()).append("=").append(entry.getValue()); + } + clientSignatureContent.append(queryString.substring(1)); + // 密钥 + clientSignatureContent.append("d3cbeed9baf4e68673a1f69a2445359a20022b7c28ea2933dd9db9f3a29f902b"); + System.out.println("加签内容:" + clientSignatureContent); + // 加签 + headersMap.put("sign", DigestUtil.sha256Hex(clientSignatureContent.toString())); + headersMap.put("Authorization", "Bearer xxx"); + + HttpRequest get = HttpUtil.createGet("http://localhost:48080/admin-api/infra/demo01-contact/get?id=100&name=张三"); + get.addHeaders(headersMap); + System.out.println("执行结果==" + get.execute()); + } + + @Test + public void testSignaturePost() { + String appId = "xxxxxx"; + Snowflake snowflake = new Snowflake(); + + // 验签请求头前端需传入字段 + SortedMap headersMap = new TreeMap<>(); + headersMap.put("appId", appId); + headersMap.put("timestamp", String.valueOf(System.currentTimeMillis())); + headersMap.put("nonce", String.valueOf(snowflake.nextId())); + + // 客户端加签内容 + StringBuilder clientSignatureContent = new StringBuilder(); + // 请求头 + for (Map.Entry entry : headersMap.entrySet()) { + clientSignatureContent.append(entry.getKey()).append(entry.getValue()); + } + // 请求 url + clientSignatureContent.append("/admin-api/infra/demo01-contact/create"); + // 请求体 + String body = "{\n" + + " \"password\": \"1\",\n" + + " \"date\": \"2024-04-24 16:28:00\",\n" + + " \"user\": {\n" + + " \"area\": \"浦东新区\",\n" + + " \"1\": \"xx\",\n" + + " \"2\": \"xx\",\n" + + " \"province\": \"上海市\",\n" + + " \"data\": {\n" + + " \"99\": \"xx\",\n" + + " \"1\": \"xx\",\n" + + " \"100\": \"xx\",\n" + + " \"2\": \"xx\",\n" + + " \"3\": \"xx\",\n" + + " \"array\": [\n" + + " {\n" + + " \"3\": \"aa\",\n" + + " \"4\": \"aa\",\n" + + " \"2\": \"aa\",\n" + + " \"1\": \"aa\"\n" + + " },\n" + + " {\n" + + " \"99\": \"aa\",\n" + + " \"100\": \"aa\",\n" + + " \"88\": \"aa\",\n" + + " \"120\": \"aa\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"sex\": \"男\",\n" + + " \"name\": \"张三\",\n" + + " \"array\": [\n" + + " \"1\",\n" + + " \"3\",\n" + + " \"5\",\n" + + " \"2\"\n" + + " ]\n" + + " },\n" + + " \"username\": \"xiaoming\"\n" + + "}"; + clientSignatureContent.append(body); + + // 密钥 + clientSignatureContent.append("d3cbeed9baf4e68673a1f69a2445359a20022b7c28ea2933dd9db9f3a29f902b"); + System.out.println("加签内容:" + clientSignatureContent); + // 加签 + headersMap.put("sign", DigestUtil.sha256Hex(clientSignatureContent.toString())); + headersMap.put("Authorization", "Bearer xxx"); + + HttpRequest post = HttpUtil.createPost("http://localhost:48080/admin-api/infra/demo01-contact/create"); + post.addHeaders(headersMap); + post.body(body); + try (HttpResponse execute = post.execute()) { + System.out.println("执行结果==" + execute); + } + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java index 8e80fa591..e181edeb4 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java @@ -23,6 +23,10 @@ public class CacheRequestBodyWrapper extends HttpServletRequestWrapper { */ private final byte[] body; + public byte[] getBody() { + return body; + } + public CacheRequestBodyWrapper(HttpServletRequest request) { super(request); body = ServletUtils.getBodyBytes(request); From 5bc01901948de01ef94d6186389a566aa6b44858 Mon Sep 17 00:00:00 2001 From: zhougang <921366807@qq.com> Date: Sun, 19 May 2024 15:39:22 +0800 Subject: [PATCH 296/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91=20?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-framework/yudao-spring-boot-starter-protection/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-framework/yudao-spring-boot-starter-protection/pom.xml b/yudao-framework/yudao-spring-boot-starter-protection/pom.xml index 025bb7591..46326c63a 100644 --- a/yudao-framework/yudao-spring-boot-starter-protection/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-protection/pom.xml @@ -12,7 +12,7 @@ jar ${project.artifactId} - 服务保证,提供分布式锁、幂等、限流、熔断、API签名等等功能 + 服务保证,提供分布式锁、幂等、限流、熔断、API 签名等等功能 https://github.com/YunaiV/ruoyi-vue-pro From 9cc6528eba87cfe7539da4a61a69eb3fc31ef10c Mon Sep 17 00:00:00 2001 From: orchidblessing <63270044+orchidblessing@users.noreply.github.com> Date: Sun, 19 May 2024 18:05:38 +0800 Subject: [PATCH 297/684] =?UTF-8?q?fix=EF=BC=9A=E4=B8=8A=E4=BC=A0=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E6=B5=8B=E8=AF=95=E6=97=B6pg=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=BA=93=E5=AD=97=E6=AE=B5=E7=B1=BB=E5=9E=8B=E4=B8=8D=E4=B8=80?= =?UTF-8?q?=E8=87=B4=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 错误详情:Caused by: org.postgresql.util.PSQLException: ERROR: column "id" is of type bigint but expression is of type character varying --- .../yudao/module/infra/dal/dataobject/file/FileContentDO.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileContentDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileContentDO.java index eda8a7264..80e18fc56 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileContentDO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileContentDO.java @@ -28,8 +28,8 @@ public class FileContentDO extends BaseDO { /** * 编号,数据库自增 */ - @TableId(type = IdType.INPUT) - private String id; + @TableId + private Long id; /** * 配置编号 * From 6a6c30c375ce669cf074a5655eae3e1fac678e78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E9=AB=98?= <171376172@qq.com> Date: Mon, 20 May 2024 01:43:30 +0000 Subject: [PATCH 298/684] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E6=A1=88?= =?UTF-8?q?=E6=8F=8F=E8=BF=B0=E9=94=99=E8=AF=AF=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=96=87=E6=A1=88=E6=8F=8F=E8=BF=B0=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 高高 <171376172@qq.com> --- .../yudao/module/infra/job/logger/AccessLogCleanJob.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/job/logger/AccessLogCleanJob.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/job/logger/AccessLogCleanJob.java index 65727a3ca..23a277bdd 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/job/logger/AccessLogCleanJob.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/job/logger/AccessLogCleanJob.java @@ -35,7 +35,7 @@ public class AccessLogCleanJob implements JobHandler { public String execute(String param) { Integer count = apiAccessLogService.cleanAccessLog(JOB_CLEAN_RETAIN_DAY, DELETE_LIMIT); log.info("[execute][定时执行清理访问日志数量 ({}) 个]", count); - return String.format("定时执行清理错误日志数量 %s 个", count); + return String.format("定时执行清理访问日志数量 %s 个", count); } } From e0d8ac74a47ca78ba16e3715e7e96a778d8846a4 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 20 May 2024 13:43:21 +0800 Subject: [PATCH 299/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E5=A4=84=E7=90=86=20mj=20jdk21=E9=99=8D=E5=88=B0jdk17=E8=AF=AD?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/models/midjourney/api/MidjourneyInteractionsApi.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/MidjourneyInteractionsApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/MidjourneyInteractionsApi.java index 16d86a48f..96fddfa46 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/MidjourneyInteractionsApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/org/springframework/ai/models/midjourney/api/MidjourneyInteractionsApi.java @@ -113,7 +113,7 @@ public class MidjourneyInteractionsApi extends MidjourneyInteractions { // // 上传文件 - String uploadUrl = uploadAttachmentsRes.getAttachments().getFirst().getUploadUrl(); + String uploadUrl = uploadAttachmentsRes.getAttachments().get(0).getUploadUrl(); httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); HttpEntity fileSystemResourceHttpEntity = new HttpEntity<>(attachments.getFileSystemResource(), httpHeaders); ResponseEntity exchange = restTemplate.exchange(uploadUrl, HttpMethod.PUT, fileSystemResourceHttpEntity, String.class); From 3a10fedddb66851242e0d7e018fbe0e1d0b8ae43 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 20 May 2024 13:44:50 +0800 Subject: [PATCH 300/684] =?UTF-8?q?=E3=80=90todo=E3=80=91=E7=99=BE?= =?UTF-8?q?=E5=BA=A6=E6=96=87=E8=A8=80=E4=B8=80=E5=BF=83=EF=BC=8C=E8=A7=A3?= =?UTF-8?q?=E5=86=B3=20todo=EF=BC=8C=E5=88=A0=E9=99=A4=20doOnComplete?= =?UTF-8?q?=E3=80=81=E5=A2=9E=E5=8A=A0=20retryTemplate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/core/model/yiyan/YiYanChatClient.java | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/YiYanChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/YiYanChatClient.java index a613af6db..c7b0bf372 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/YiYanChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/YiYanChatClient.java @@ -85,22 +85,20 @@ public class YiYanChatClient implements ChatClient, StreamingChatClient { @Override public Flux stream(Prompt prompt) { YiYanChatCompletionRequest request = this.createRequest(prompt, true); - // TODO @fan:return this.retryTemplate.execute(ctx -> { - // 调用 callWithFunctionSupport 发送请求 - Flux response = this.yiYanApi.chatCompletionStream(request); - // TODO @fan:下面的 doOnComplete 是不是可以删除哈? - response.doOnComplete(new Runnable() { - @Override - public void run() { - String a = ";"; - } - }); - return response.map(chunk -> { - // TODO @fan:ChatResponseMetadata chatResponseMetadata - return new ChatResponse(List.of(new Generation(chunk.getResult()))); + // TODO done @fan:return this.retryTemplate.execute(ctx -> { + return retryTemplate.execute(ctx -> { + // 调用 callWithFunctionSupport 发送请求 + Flux response = this.yiYanApi.chatCompletionStream(request); + return response.map(chunk -> { +// System.err.println("---".concat(chunk.getResult())); + // TODO @fan:ChatResponseMetadata chatResponseMetadata + return new ChatResponse(List.of(new Generation(chunk.getResult()))); + }); }); } + + private YiYanChatCompletionRequest createRequest(Prompt prompt, boolean stream) { // 参考 https://cloud.baidu.com/doc/WENXINWORKSHOP/s/clntwmv7t 文档,system 是独立字段 // 1.1 获取 user 和 assistant From 802dee2fc353f41d16fb4c7176f7ededaf6f0fa2 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 21 May 2024 08:30:51 +0800 Subject: [PATCH 301/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E5=8F=91=E9=80=81=E6=B6=88=E6=81=AF=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=8A=E4=B8=8B=E6=96=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vo/message/AiChatMessageSendReqVO.java | 3 + .../dal/dataobject/chat/AiChatMessageDO.java | 17 ++++- .../ai/service/impl/AiChatServiceImpl.java | 71 ++++++++++++++----- 3 files changed, 72 insertions(+), 19 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendReqVO.java index 9592da347..89a84bcbd 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendReqVO.java @@ -19,4 +19,7 @@ public class AiChatMessageSendReqVO { @NotEmpty(message = "聊天内容不能为空") private String content; + @Schema(description = "是否携带上下文", example = "true") + private Boolean useContext; + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java index c66537673..1c915ed7c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.chat; +import com.baomidou.mybatisplus.annotation.TableId; import org.springframework.ai.chat.messages.MessageType; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; @@ -27,14 +28,23 @@ public class AiChatMessageDO extends BaseDO { /** * 编号,作为每条聊天记录的唯一标识符 */ + @TableId private Long id; /** * 会话编号 * - * 关联 {@link AiChatConversationDO#getId()} + * 关联 {@link AiChatConversationDO#getId()} 字段 */ private Long conversationId; + /** + * 回复消息编号 + * + * 关联 {@link #id} 字段 + * + * 大模型回复的消息编号,用于“问答”的关联 + */ + private Long replyId; /** * 消息类型 @@ -75,6 +85,9 @@ public class AiChatMessageDO extends BaseDO { */ private String content; - // TODO 芋艿:是否作为上下文语料?use_context,待定 + /** + * 是否携带上下文 + */ + private Boolean useContext; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index 9fd80d1c6..c45a1025e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -1,5 +1,9 @@ package cn.iocoder.yudao.module.ai.service.impl; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; @@ -109,15 +113,14 @@ public class AiChatServiceImpl implements AiChatService { StreamingChatClient chatClient = chatClientFactory.getStreamingChatClient(platform); // 2. 插入 user 发送消息 - AiChatMessageDO userMessage = createChatMessage(conversation.getId(), model, - userId, conversation.getRoleId(), MessageType.USER, sendReqVO.getContent()); + AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model, + userId, conversation.getRoleId(), MessageType.USER, sendReqVO.getContent(), sendReqVO.getUseContext()); // 3.1 插入 assistant 接收消息 - AiChatMessageDO assistantMessage = createChatMessage(conversation.getId(), model, - userId, conversation.getRoleId(), MessageType.ASSISTANT, ""); + AiChatMessageDO assistantMessage = createChatMessage(conversation.getId(), userMessage.getId(), model, + userId, conversation.getRoleId(), MessageType.ASSISTANT, "", sendReqVO.getUseContext()); // 3.2 创建 chat 需要的 Prompt - // TODO 消息上下文 Prompt prompt = buildPrompt(conversation, historyMessages, sendReqVO); Flux streamResponse = chatClient.stream(prompt); @@ -139,32 +142,66 @@ public class AiChatServiceImpl implements AiChatService { } private Prompt buildPrompt(AiChatConversationDO conversation, List messages, AiChatMessageSendReqVO sendReqVO) { - // TODO 芋艿:1)保留 n 个上下文;2)每一轮 token 数量 -// if (conversation.getMaxContexts() != null && messages.size() > conversation.getMaxContexts()) { -// -// } // 1. 构建 Prompt Message 列表 List chatMessages = new ArrayList<>(); // 1.1 system context 角色设定 chatMessages.add(new SystemMessage(conversation.getSystemMessage())); // 1.2 history message 历史消息 - messages.forEach(message -> chatMessages.add(new ChatMessage(message.getType().toUpperCase(), message.getContent()))); + List contextMessages = filterContextMessages(messages, conversation, sendReqVO); + contextMessages.forEach(message -> chatMessages.add(new ChatMessage(message.getType().toUpperCase(), message.getContent()))); // 1.3 user message 新发送消息 chatMessages.add(new UserMessage(sendReqVO.getContent())); // 2. 构建 ChatOptions 对象 TODO 芋艿:临时注释掉;等文心一言兼容了; + // TODO 每一轮 token 数量 // ChatOptions chatOptions = ChatOptionsBuilder.builder().withTemperature(conversation.getTemperature().floatValue()).build(); // return new Prompt(chatMessages, null); return new Prompt(chatMessages); } - private AiChatMessageDO createChatMessage(Long conversationId, AiChatModelDO model, - Long userId, Long roleId, - MessageType messageType, String content) { - AiChatMessageDO message = new AiChatMessageDO() - .setConversationId(conversationId).setModel(model.getModel()).setModelId(model.getId()) - .setUserId(userId).setRoleId(roleId) - .setType(messageType.getValue()).setContent(content); + /** + * 从历史消息中,获得倒序的 n 组消息作为消息上下文 + * + * n 组:指的是 user + assistant 形成一组 + * + * @param messages 消息列表 + * @param conversation 会话 + * @param sendReqVO 发送请求 + * @return 消息上下文 + */ + private List filterContextMessages(List messages, AiChatConversationDO conversation, AiChatMessageSendReqVO sendReqVO) { + if (conversation.getMaxContexts() == null || ObjUtil.notEqual(sendReqVO.getUseContext(), Boolean.TRUE)) { + return Collections.emptyList(); + } + List contextMessages = new ArrayList<>(conversation.getMaxContexts() * 2); + for (int i = messages.size() - 1; i >= 0; i--) { + AiChatMessageDO assistantMessage = CollUtil.get(messages, i); + if (assistantMessage == null || assistantMessage.getReplyId() == null) { + continue; + } + AiChatMessageDO userMessage = CollUtil.get(messages, i - 1); + if (userMessage == null || ObjUtil.notEqual(assistantMessage.getReplyId(), userMessage.getId()) + || StrUtil.isEmpty(assistantMessage.getContent())) { + continue; + } + // 由于后续要 reverse 反转,所以先添加 assistantMessage + contextMessages.add(assistantMessage); + contextMessages.add(userMessage); + // 超过最大上下文,结束 + if (contextMessages.size() >= conversation.getMaxContexts() * 2) { + break; + } + } + Collections.reverse(contextMessages); + return contextMessages; + } + + private AiChatMessageDO createChatMessage(Long conversationId, Long replyId, + AiChatModelDO model, Long userId, Long roleId, + MessageType messageType, String content, Boolean useContext) { + AiChatMessageDO message = new AiChatMessageDO().setConversationId(conversationId).setReplyId(replyId) + .setModel(model.getModel()).setModelId(model.getId()).setUserId(userId).setRoleId(roleId) + .setType(messageType.getValue()).setContent(content).setUseContext(useContext); message.setCreateTime(LocalDateTime.now()); chatMessageMapper.insert(message); return message; From 983742fd7416e57aabf3ba866eef7616f7e49f96 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 21 May 2024 09:35:05 +0800 Subject: [PATCH 302/684] =?UTF-8?q?=E3=80=90=E8=A1=A5=E5=85=85=E3=80=91?= =?UTF-8?q?=E8=A1=A5=E5=85=85pom=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-module-ai/pom.xml | 4 ++-- yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/yudao-module-ai/pom.xml b/yudao-module-ai/pom.xml index ad49018f0..04244f21e 100644 --- a/yudao-module-ai/pom.xml +++ b/yudao-module-ai/pom.xml @@ -18,8 +18,8 @@ - 21 - 21 + 17 + 17 UTF-8 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml index 37813feb7..9a19270db 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml @@ -53,6 +53,10 @@ com.squareup.okhttp3 okhttp + + io.projectreactor.netty + reactor-netty + net.dv8tion JDA From 3633c7415b0dbc85887a646fccc5480e86403b6d Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 21 May 2024 10:59:28 +0800 Subject: [PATCH 303/684] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91ai=20=E5=AF=B9=E8=AF=9D=E6=94=B9=E4=B8=BA=E5=8D=87?= =?UTF-8?q?=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/dal/mysql/chat/AiChatConversationMapper.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java index 5d41fb080..181b136ef 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.ai.dal.mysql.chat; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import org.apache.ibatis.annotations.Mapper; import java.util.List; @@ -16,7 +16,11 @@ import java.util.List; public interface AiChatConversationMapper extends BaseMapperX { default List selectListByUserId(Long userId) { - return selectList(AiChatConversationDO::getUserId, userId); + return selectList( + new LambdaQueryWrapperX() + .eq(AiChatConversationDO::getUserId, userId) + .orderByAsc(AiChatConversationDO::getCreateTime) + ); } } From 19bd0c66ffea0ada9ace56137bbc808605a42144 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 21 May 2024 12:11:07 +0800 Subject: [PATCH 304/684] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91AI=20chat=20=E8=BF=94=E5=9B=9E=E7=9A=84=20message=20?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E4=B8=8D=E6=AD=A3=E7=A1=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index c45a1025e..e1fe760f0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -132,7 +132,7 @@ public class AiChatServiceImpl implements AiChatService { contentBuffer.append(newContent); // 响应结果 return new AiChatMessageSendRespVO().setSend(BeanUtils.toBean(userMessage, AiChatMessageSendRespVO.Message.class)) - .setReceive(BeanUtils.toBean(userMessage, AiChatMessageSendRespVO.Message.class).setContent(newContent)); + .setReceive(BeanUtils.toBean(assistantMessage, AiChatMessageSendRespVO.Message.class).setContent(newContent)); }).doOnComplete(() -> { chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString())); }).doOnError(throwable -> { From 041a00b27fa94c662485c0682495494a828b9136 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 21 May 2024 17:18:33 +0800 Subject: [PATCH 305/684] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91=E5=A6=82=E6=9E=9C=E9=BB=98=E8=AE=A4=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E4=BA=86=20role=20=EF=BC=8C=E5=88=99=E4=BD=BF=E7=94=A8=20role?= =?UTF-8?q?=20=E4=BD=9C=E4=B8=BA=20title?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/service/chat/AiChatConversationServiceImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java index 85dd57afd..1e3bd52ce 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java @@ -56,8 +56,9 @@ public class AiChatConversationServiceImpl implements AiChatConversationService validateChatModel(model); // 2. 创建 AiChatConversationDO 聊天对话 + String title = createReqVO.getRoleId() == null ? AiChatConversationDO.TITLE_DEFAULT : role.getName(); AiChatConversationDO conversation = new AiChatConversationDO() - .setUserId(userId).setTitle(AiChatConversationDO.TITLE_DEFAULT).setPinned(false) + .setUserId(userId).setTitle(title).setPinned(false) .setRoleId(role.getId()).setModelId(model.getId()).setModel(model.getModel()).setSystemMessage(role.getSystemMessage()) .setTemperature(model.getTemperature()).setMaxTokens(model.getMaxTokens()).setMaxContexts(model.getMaxContexts()); chatConversationMapper.insert(conversation); From 99b6f240923b05357b5f31f37dd9907764d6012a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 21 May 2024 19:55:29 +0800 Subject: [PATCH 306/684] =?UTF-8?q?=E3=80=90=E4=BF=AE=E5=A4=8D=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E8=A7=A3=E5=86=B3=20spring-ai=20=E4=B8=8E=20webflux?= =?UTF-8?q?=20=E9=9B=86=E6=88=90=E6=97=B6=EF=BC=8CSSE=20=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=E4=B9=B1=E5=BA=8F=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/chat/AiChatMessageController.http | 7 +++---- .../mysql/chat/AiChatConversationMapper.java | 9 ++++----- .../ai/service/impl/AiChatServiceImpl.java | 6 ++++-- .../ai/openAiImage/OpenAiImageClientTests.java | 17 ----------------- .../src/main/resources/application.yaml | 3 +++ 5 files changed, 14 insertions(+), 28 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.http b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.http index 2d417a55f..463e61207 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.http @@ -6,7 +6,7 @@ Authorization: {{token}} { "conversationId": "1781604279872581649", - "content": "中国好看吗?" + "content": "你是 OpenAI 么?" } @@ -16,11 +16,10 @@ Content-Type: application/json Authorization: {{token}} { - "conversationId": "1781604279872581651", - "content": "苹果是什么颜色?" + "conversationId": "1781604279872581690", + "content": "1+1=?" } - ### message list GET {{baseUrl}}/admin-api/ai/chat/message/list-by-conversation-id?conversationId=1781604279872581649 Authorization: {{token}} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java index 181b136ef..dd4901bdf 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java @@ -15,12 +15,11 @@ import java.util.List; @Mapper public interface AiChatConversationMapper extends BaseMapperX { + // TODO @fan:建议这里不排序哈;交给他们前端排序 default List selectListByUserId(Long userId) { - return selectList( - new LambdaQueryWrapperX() - .eq(AiChatConversationDO::getUserId, userId) - .orderByAsc(AiChatConversationDO::getCreateTime) - ); + return selectList(new LambdaQueryWrapperX() + .eq(AiChatConversationDO::getUserId, userId) + .orderByAsc(AiChatConversationDO::getCreateTime)); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index e1fe760f0..7c7e37954 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -32,6 +32,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import reactor.core.publisher.Flux; +import reactor.core.scheduler.Schedulers; import java.time.LocalDateTime; import java.util.*; @@ -125,9 +126,10 @@ public class AiChatServiceImpl implements AiChatService { Flux streamResponse = chatClient.stream(prompt); // 3.3 流式返回 + // 注意:Schedulers.immediate() 目的是,避免默认 Schedulers.parallel() 并发消费 chunk 导致 SSE 响应前端会乱序问题 StringBuffer contentBuffer = new StringBuffer(); - return streamResponse.map(response -> { - String newContent = response.getResult() != null ? response.getResult().getOutput().getContent() : null; + return streamResponse.publishOn(Schedulers.immediate()).map(chunk -> { + String newContent = chunk.getResult() != null ? chunk.getResult().getOutput().getContent() : null; newContent = StrUtil.nullToDefault(newContent, ""); // 避免 null 的 情况 contentBuffer.append(newContent); // 响应结果 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java index bf184a849..828f7dc2d 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/openAiImage/OpenAiImageClientTests.java @@ -71,21 +71,4 @@ public class OpenAiImageClientTests { } } - public static void main(String[] args) { -// OpenAiApi api = new OpenAiApi("https://api.gptsapi.net", "sk-yzKea6d8e8212c3bdd99f9f44ced1cae37c097e5aa3BTS7z"); -// OpenAiApi api = new OpenAiApi("https://openkey.cloud", "sk-QmgIIPc5xiYd8lPb076b1b7774Ea49Af9eD2Ef172c8f7e43"); - OpenAiApi api = new OpenAiApi("https://api.chatanywhere.tech", "sk-gkgfYxhX9FxyZJznwxRZSJwKeGQYNPDVWjhby2PRRf17GHeT"); - OpenAiChatClient client = new OpenAiChatClient(api); -// String result = client.call("未来,英文是什么?"); -// System.out.println(result); - Flux result = client.stream("未来,英文是什么?"); - result.map(new Function() { - @Override - public String apply(String s) { - System.out.println(s); - return s; - } - }).blockLast(); - } - } diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index e8e07c675..6bb087d81 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -156,6 +156,9 @@ spring.ai: # base-url: https://api.chatanywhere.tech api-key: sk-yzKea6d8e8212c3bdd99f9f44ced1cae37c097e5aa3BTS7z base-url: https://api.gptsapi.net +# chat: +# options: +# model: gpt-4-0125-preview yudao.ai: yiyan: From 12d3c0a9af9ba7733a10830f1b03ecaa965abae2 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 21 May 2024 22:46:59 +0800 Subject: [PATCH 307/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91AI?= =?UTF-8?q?=20=E8=A7=92=E8=89=B2=E5=88=86=E7=B1=BB=EF=BC=8C=E5=A4=84?= =?UTF-8?q?=E7=90=86=20role=20=E7=A9=BA=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/service/model/AiChatRoleServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java index cf6bcec96..e0192ffe4 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java @@ -137,7 +137,7 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { @Override public List getChatRoleCategoryList() { List list = chatRoleMapper.selectListGroupByCategory(CommonStatusEnum.ENABLE.getStatus()); - return convertList(list, AiChatRoleDO::getCategory, role -> StrUtil.isNotBlank(role.getCategory())); + return convertList(list, AiChatRoleDO::getCategory, role -> role != null && StrUtil.isNotBlank(role.getCategory())); } } From 747b2ebce529ec0374d7ca05afda455fd3565fb7 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 22 May 2024 09:57:20 +0800 Subject: [PATCH 308/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91AI?= =?UTF-8?q?=20Chat=20=E5=A2=9E=E5=8A=A0=E6=B8=85=E7=A9=BA=E6=B6=88?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/chat/AiChatMessageController.java | 6 +++++ .../ai/dal/mysql/AiChatMessageMapper.java | 8 ++++++ .../module/ai/service/AiChatService.java | 7 +++++ .../ai/service/impl/AiChatServiceImpl.java | 26 +++++++++---------- 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java index 47f35f4ea..ad9375f39 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java @@ -55,4 +55,10 @@ public class AiChatMessageController { return success(chatService.deleteMessage(id)); } + @Operation(summary = "删除消息-对于对话全部消息") + @DeleteMapping("/delete-by-conversation-id") + @Parameter(name = "id", required = true, description = "消息编号", example = "1024") + public CommonResult deleteByConversationId(@RequestParam("conversationId") Long conversationId) { + return success(chatService.deleteByConversationId(conversationId)); + } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java index fef19af12..6c9c22ad0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java @@ -32,4 +32,12 @@ public interface AiChatMessageMapper extends BaseMapperX { ); } + /** + * 删除 - 根据 conversationId + * + * @param conversationId + */ + default int deleteByConversationId(Long conversationId) { + return this.delete(new LambdaQueryWrapperX().eq(AiChatMessageDO::getConversationId, conversationId)); + } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java index 57d848eea..f8924cb63 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java @@ -47,4 +47,11 @@ public interface AiChatService { */ Flux sendChatMessageStream(AiChatMessageSendReqVO sendReqVO, Long userId); + /** + * 删除消息-对于对话全部消息 + * + * @param conversationId + * @return + */ + Boolean deleteByConversationId(Long conversationId); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index 7c7e37954..0a52681c6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -1,34 +1,29 @@ package cn.iocoder.yudao.module.ai.service.impl; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.collection.ListUtil; -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; -import org.springframework.ai.chat.ChatResponse; -import org.springframework.ai.chat.StreamingChatClient; -import org.springframework.ai.chat.messages.*; -import org.springframework.ai.chat.prompt.ChatOptions; -import org.springframework.ai.chat.prompt.ChatOptionsBuilder; -import org.springframework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.module.ai.config.AiChatClientFactory; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO; import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatMessageMapper; -import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService; -import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; import cn.iocoder.yudao.module.ai.service.AiChatService; +import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService; import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; +import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.StreamingChatClient; +import org.springframework.ai.chat.messages.*; +import org.springframework.ai.chat.prompt.Prompt; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import reactor.core.publisher.Flux; @@ -143,6 +138,11 @@ public class AiChatServiceImpl implements AiChatService { }); } + @Override + public Boolean deleteByConversationId(Long conversationId) { + return chatMessageMapper.deleteByConversationId(conversationId) > 0; + } + private Prompt buildPrompt(AiChatConversationDO conversation, List messages, AiChatMessageSendReqVO sendReqVO) { // 1. 构建 Prompt Message 列表 List chatMessages = new ArrayList<>(); From cad1ce4852f449785fee1b3d2fc9d7bc3acc42e1 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 22 May 2024 10:30:37 +0800 Subject: [PATCH 309/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91AI?= =?UTF-8?q?=20message=20=E5=A2=9E=E5=8A=A0=E7=94=A8=E6=88=B7=E5=A4=B4?= =?UTF-8?q?=E5=83=8F=E3=80=81role=E5=A4=B4=E5=83=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/vo/message/AiChatMessageRespVO.java | 7 +++++++ .../ai/service/impl/AiChatServiceImpl.java | 21 ++++++++++++------- .../ai/service/model/AiChatRoleService.java | 9 ++++++++ .../service/model/AiChatRoleServiceImpl.java | 6 ++++++ 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java index 49c7ee54b..e4e878e40 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java @@ -36,4 +36,11 @@ public class AiChatMessageRespVO { @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-05-12 12:51") private LocalDateTime createTime; + // ========= 扩展字段 + + @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://xxx") + private String userAvatar; + + @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://xxx") + private String roleAvatar; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index 0a52681c6..c603f43e8 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.dal.mysql.AiChatMessageMapper; import cn.iocoder.yudao.module.ai.service.AiChatService; import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService; @@ -216,16 +217,22 @@ public class AiChatServiceImpl implements AiChatService { // 获取对话所有 message List aiChatMessageDOList = chatMessageMapper.selectByConversationId(conversationId); // 获取模型信息 - Set modalIds = aiChatMessageDOList.stream().map(AiChatMessageDO::getModelId).collect(Collectors.toSet()); - List modalList = chatModalService.getModalByIds(modalIds); - Map modalIdMap = modalList.stream().collect(Collectors.toMap(AiChatModelDO::getId, o -> o)); + Set roleIds = aiChatMessageDOList.stream().map(AiChatMessageDO::getRoleId).collect(Collectors.toSet()); + List roleList; + if (!CollUtil.isEmpty(roleIds)) { + roleList = chatRoleService.getChatRoles(roleIds); + } else { + roleList = Collections.emptyList(); + } + Map roleMap = roleList.stream().collect(Collectors.toMap(AiChatRoleDO::getId, o -> o)); // 转换 AiChatMessageRespVO List aiChatMessageRespList = AiChatMessageConvert.INSTANCE.convertAiChatMessageRespVOList(aiChatMessageDOList); - // 设置用户头像 和 模型头像 todo @芋艿 这里需要转换 用户头像、模型头像 + // 设置用户头像 和 模型头像 return aiChatMessageRespList.stream().map(item -> { - if (modalIdMap.containsKey(item.getModelId())) { -// modalIdMap.get(item.getModelId()); -// item.setModelImage() + // 设置 role 头像 + if (roleMap.containsKey(item.getRoleId())) { + AiChatRoleDO role = roleMap.get(item.getRoleId()); + item.setRoleAvatar(role.getAvatar()); } return item; }).collect(Collectors.toList()); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java index 7206fd104..228b1ee6e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java @@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import jakarta.validation.Valid; import java.util.List; +import java.util.Set; /** * AI 聊天角色 Service 接口 @@ -72,6 +73,14 @@ public interface AiChatRoleService { */ AiChatRoleDO getChatRole(Long id); + /** + * 获得聊天角色 - 根据 ids + * + * @param roleIds + * @return + */ + List getChatRoles(Set roleIds); + /** * 校验聊天角色是否合法 * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java index e0192ffe4..1413dd8ce 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java @@ -16,6 +16,7 @@ import org.springframework.stereotype.Service; import java.util.List; import java.util.Objects; +import java.util.Set; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -105,6 +106,11 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { return chatRoleMapper.selectById(id); } + @Override + public List getChatRoles(Set roleIds) { + return chatRoleMapper.selectBatchIds(roleIds); + } + @Override public AiChatRoleDO validateChatRole(Long id) { AiChatRoleDO chatRole = validateChatRoleExists(id); From ccd7928a6b638090dac7b39e618de5ba83fdc0d8 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 22 May 2024 10:53:25 +0800 Subject: [PATCH 310/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=94=A8=E6=88=B7=E5=A4=B4=E5=83=8F=E8=BF=94?= =?UTF-8?q?=E5=9B=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/system/api/user/dto/AdminUserRespDTO.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/dto/AdminUserRespDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/dto/AdminUserRespDTO.java index ac13c3a8b..d86f3e548 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/dto/AdminUserRespDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/dto/AdminUserRespDTO.java @@ -40,5 +40,9 @@ public class AdminUserRespDTO { * 手机号码 */ private String mobile; + /** + * 用户头像 + */ + private String avatar; } From 2a01f6b9fca6826331e3cea2de549d8514667896 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 22 May 2024 10:58:29 +0800 Subject: [PATCH 311/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91AI?= =?UTF-8?q?=20Chat=20stream=20=E5=A2=9E=E5=8A=A0=E5=A4=B4=E5=83=8F?= =?UTF-8?q?=E8=BF=94=E5=9B=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vo/message/AiChatMessageSendRespVO.java | 7 +++++++ .../ai/service/impl/AiChatServiceImpl.java | 18 ++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java index 58ba05659..3314b1d32 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java @@ -31,6 +31,13 @@ public class AiChatMessageSendRespVO { @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; + // ========= 扩展字段 + + @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://xxx") + private String userAvatar; + + @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://xxx") + private String roleAvatar; } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index c603f43e8..f0cbb807e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -5,6 +5,7 @@ import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.config.AiChatClientFactory; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; @@ -19,6 +20,8 @@ import cn.iocoder.yudao.module.ai.service.AiChatService; import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService; import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.chat.ChatResponse; @@ -56,6 +59,7 @@ public class AiChatServiceImpl implements AiChatService { private final AiChatConversationService chatConversationService; private final AiChatModelService chatModalService; private final AiChatRoleService chatRoleService; + private final AdminUserApi adminUserApi; @Transactional(rollbackFor = Exception.class) public AiChatMessageRespVO chat(AiChatMessageSendReqVO req) { @@ -124,13 +128,17 @@ public class AiChatServiceImpl implements AiChatService { // 3.3 流式返回 // 注意:Schedulers.immediate() 目的是,避免默认 Schedulers.parallel() 并发消费 chunk 导致 SSE 响应前端会乱序问题 StringBuffer contentBuffer = new StringBuffer(); + + // 3.4 获取用户头像、角色头像 + AdminUserRespDTO user = adminUserApi.getUser(SecurityFrameworkUtils.getLoginUserId()); + AiChatRoleDO chatRole = chatRoleService.getChatRole(assistantMessage.getRoleId()); return streamResponse.publishOn(Schedulers.immediate()).map(chunk -> { String newContent = chunk.getResult() != null ? chunk.getResult().getOutput().getContent() : null; newContent = StrUtil.nullToDefault(newContent, ""); // 避免 null 的 情况 contentBuffer.append(newContent); // 响应结果 - return new AiChatMessageSendRespVO().setSend(BeanUtils.toBean(userMessage, AiChatMessageSendRespVO.Message.class)) - .setReceive(BeanUtils.toBean(assistantMessage, AiChatMessageSendRespVO.Message.class).setContent(newContent)); + return new AiChatMessageSendRespVO().setSend(BeanUtils.toBean(userMessage, AiChatMessageSendRespVO.Message.class).setUserAvatar(user.getAvatar())) + .setReceive(BeanUtils.toBean(assistantMessage, AiChatMessageSendRespVO.Message.class).setContent(newContent).setRoleAvatar(chatRole == null ? null : chatRole.getAvatar())); }).doOnComplete(() -> { chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString())); }).doOnError(throwable -> { @@ -227,6 +235,8 @@ public class AiChatServiceImpl implements AiChatService { Map roleMap = roleList.stream().collect(Collectors.toMap(AiChatRoleDO::getId, o -> o)); // 转换 AiChatMessageRespVO List aiChatMessageRespList = AiChatMessageConvert.INSTANCE.convertAiChatMessageRespVOList(aiChatMessageDOList); + // 获取用户信息 + AdminUserRespDTO user = adminUserApi.getUser(SecurityFrameworkUtils.getLoginUserId()); // 设置用户头像 和 模型头像 return aiChatMessageRespList.stream().map(item -> { // 设置 role 头像 @@ -234,6 +244,10 @@ public class AiChatServiceImpl implements AiChatService { AiChatRoleDO role = roleMap.get(item.getRoleId()); item.setRoleAvatar(role.getAvatar()); } + // 设置 user 头像 + if (user != null) { + item.setUserAvatar(user.getAvatar()); + } return item; }).collect(Collectors.toList()); } From 2fefcf8834ede9c73fbd64a16d04fe2ffd25a425 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 22 May 2024 12:37:21 +0800 Subject: [PATCH 312/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E9=80=9A=E8=BF=87=20AiClientFactory=20=E6=8F=90?= =?UTF-8?q?=E4=BE=9B=20chatclient?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/config/AiChatClientFactory.java | 57 ------ .../ai/service/impl/AiChatServiceImpl.java | 55 +++--- .../ai/service/model/AiApiKeyService.java | 11 ++ .../ai/service/model/AiApiKeyServiceImpl.java | 15 ++ .../ai/config/YudaoAiAutoConfiguration.java | 30 ++-- .../ai/core/factory/AiClientFactory.java | 47 +++++ .../ai/core/factory/AiClientFactoryImpl.java | 167 ++++++++++++++++++ .../ai/core/model/tongyi/QianWenOptions.java | 2 + .../ai/core/model/xinghuo/XingHuoOptions.java | 2 +- .../ai/core/model/yiyan/YiYanChatOptions.java | 1 + .../ai/core/model/yiyan/api/YiYanApi.java | 3 +- .../src/main/resources/application.yaml | 7 - 12 files changed, 289 insertions(+), 108 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactory.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java deleted file mode 100644 index 5efd264a9..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.iocoder.yudao.module.ai.config; - -import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; -import org.springframework.ai.chat.ChatClient; -import org.springframework.ai.chat.StreamingChatClient; -import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatClient; -import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatClient; -import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatClient; -import org.springframework.ai.ollama.OllamaChatClient; -import org.springframework.ai.openai.OpenAiChatClient; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.stereotype.Component; - -/** - * factory - * - * @author fansili - * @time 2024/4/25 17:36 - * @since 1.0 - */ -@Component -public class AiChatClientFactory { - - @Autowired - private ApplicationContext applicationContext; - - public ChatClient getChatClient(AiPlatformEnum platformEnum) { - if (AiPlatformEnum.QIAN_WEN == platformEnum) { - return applicationContext.getBean(QianWenChatClient.class); - } else if (AiPlatformEnum.YI_YAN == platformEnum) { - return applicationContext.getBean(YiYanChatClient.class); - } else if (AiPlatformEnum.XING_HUO == platformEnum) { - return applicationContext.getBean(XingHuoChatClient.class); - } - throw new IllegalArgumentException("不支持的 chat client!"); - } - - // TODO yunai 要不再加一个接口,让他们拥有 ChatClient、StreamingChatClient 功能 - public StreamingChatClient getStreamingChatClient(AiPlatformEnum platformEnum) { -// if (true) { -// return applicationContext.getBean(OllamaChatClient.class); -// } - if (AiPlatformEnum.QIAN_WEN == platformEnum) { - return applicationContext.getBean(QianWenChatClient.class); - } else if (AiPlatformEnum.YI_YAN == platformEnum) { - return applicationContext.getBean(YiYanChatClient.class); - } else if (AiPlatformEnum.XING_HUO == platformEnum) { - return applicationContext.getBean(XingHuoChatClient.class); - } else if (AiPlatformEnum.OLLAMA == platformEnum) { - return applicationContext.getBean(OllamaChatClient.class); - } else if (AiPlatformEnum.OPENAI == platformEnum) { - return applicationContext.getBean(OpenAiChatClient.class); - } - throw new IllegalArgumentException("不支持的 chat client!"); - } -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index c603f43e8..32511141c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -4,13 +4,20 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; +import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactory; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.config.AiChatClientFactory; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; +import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; +import jakarta.annotation.Resource; +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.StreamingChatClient; +import org.springframework.ai.chat.messages.*; +import org.springframework.ai.chat.prompt.ChatOptions; +import org.springframework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO; import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; @@ -19,12 +26,7 @@ import cn.iocoder.yudao.module.ai.service.AiChatService; import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService; import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; -import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.ai.chat.ChatResponse; -import org.springframework.ai.chat.StreamingChatClient; -import org.springframework.ai.chat.messages.*; -import org.springframework.ai.chat.prompt.Prompt; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import reactor.core.publisher.Flux; @@ -46,16 +48,22 @@ import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_CONVERSATION_NO */ @Slf4j @Service -@AllArgsConstructor public class AiChatServiceImpl implements AiChatService { - private final AiChatClientFactory chatClientFactory; + @Resource + private AiChatMessageMapper chatMessageMapper; - private final AiChatMessageMapper chatMessageMapper; + @Resource + private AiClientFactory clientFactory; - private final AiChatConversationService chatConversationService; - private final AiChatModelService chatModalService; - private final AiChatRoleService chatRoleService; + @Resource + private AiChatConversationService chatConversationService; + @Resource + private AiChatModelService chatModalService; + @Resource + private AiChatRoleService chatRoleService; + @Resource + private AiApiKeyService apiKeyService; @Transactional(rollbackFor = Exception.class) public AiChatMessageRespVO chat(AiChatMessageSendReqVO req) { @@ -106,8 +114,7 @@ public class AiChatServiceImpl implements AiChatService { List historyMessages = chatMessageMapper.selectByConversationId(conversation.getId()); // 1.2 校验模型 AiChatModelDO model = chatModalService.validateChatModel(conversation.getModelId()); - AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); - StreamingChatClient chatClient = chatClientFactory.getStreamingChatClient(platform); + StreamingChatClient chatClient = apiKeyService.getStreamingChatClient(model.getKeyId()); // 2. 插入 user 发送消息 AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model, @@ -118,13 +125,13 @@ public class AiChatServiceImpl implements AiChatService { userId, conversation.getRoleId(), MessageType.ASSISTANT, "", sendReqVO.getUseContext()); // 3.2 创建 chat 需要的 Prompt - Prompt prompt = buildPrompt(conversation, historyMessages, sendReqVO); + Prompt prompt = buildPrompt(conversation, historyMessages, model, sendReqVO); Flux streamResponse = chatClient.stream(prompt); // 3.3 流式返回 // 注意:Schedulers.immediate() 目的是,避免默认 Schedulers.parallel() 并发消费 chunk 导致 SSE 响应前端会乱序问题 StringBuffer contentBuffer = new StringBuffer(); - return streamResponse.publishOn(Schedulers.immediate()).map(chunk -> { + return streamResponse.publishOn(Schedulers.single()).map(chunk -> { String newContent = chunk.getResult() != null ? chunk.getResult().getOutput().getContent() : null; newContent = StrUtil.nullToDefault(newContent, ""); // 避免 null 的 情况 contentBuffer.append(newContent); @@ -144,7 +151,8 @@ public class AiChatServiceImpl implements AiChatService { return chatMessageMapper.deleteByConversationId(conversationId) > 0; } - private Prompt buildPrompt(AiChatConversationDO conversation, List messages, AiChatMessageSendReqVO sendReqVO) { + private Prompt buildPrompt(AiChatConversationDO conversation, List messages, + AiChatModelDO model, AiChatMessageSendReqVO sendReqVO) { // 1. 构建 Prompt Message 列表 List chatMessages = new ArrayList<>(); // 1.1 system context 角色设定 @@ -156,10 +164,11 @@ public class AiChatServiceImpl implements AiChatService { chatMessages.add(new UserMessage(sendReqVO.getContent())); // 2. 构建 ChatOptions 对象 TODO 芋艿:临时注释掉;等文心一言兼容了; - // TODO 每一轮 token 数量 -// ChatOptions chatOptions = ChatOptionsBuilder.builder().withTemperature(conversation.getTemperature().floatValue()).build(); -// return new Prompt(chatMessages, null); - return new Prompt(chatMessages); + AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); + ChatOptions chatOptions = clientFactory.buildChatOptions(platform, model.getModel(), + conversation.getTemperature(), conversation.getMaxTokens()); + return new Prompt(chatMessages, chatOptions); +// return new Prompt(chatMessages); } /** diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java index 331dd62e2..8056eab78 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageR import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; import jakarta.validation.Valid; +import org.springframework.ai.chat.StreamingChatClient; import java.util.List; @@ -68,4 +69,14 @@ public interface AiApiKeyService { */ List getApiKeyList(); + // ========== 与 spring-ai 集成 ========== + + /** + * 获得 StreamingChatClient 对象 + * + * @param id 编号 + * @return StreamingChatClient 对象 + */ + StreamingChatClient getStreamingChatClient(Long id); + } \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java index f8a83ce57..e4db8125b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.ai.service.model; +import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; +import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactory; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -8,6 +10,7 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveR import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; import cn.iocoder.yudao.module.ai.dal.mysql.model.AiApiKeyMapper; import jakarta.annotation.Resource; +import org.springframework.ai.chat.StreamingChatClient; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -28,6 +31,9 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { @Resource private AiApiKeyMapper apiKeyMapper; + @Resource + private AiClientFactory clientFactory; + @Override public Long createApiKey(AiApiKeySaveReqVO createReqVO) { // 插入 @@ -86,4 +92,13 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { return apiKeyMapper.selectList(); } + // ========== 与 spring-ai 集成 ========== + + @Override + public StreamingChatClient getStreamingChatClient(Long id) { + AiApiKeyDO apiKey = validateApiKey(id); + AiPlatformEnum platform = AiPlatformEnum.validatePlatform(apiKey.getPlatform()); + return clientFactory.getOrCreateStreamingChatClient(platform, apiKey.getApiKey(), apiKey.getUrl()); + } + } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index f942b12bd..55705c40f 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.framework.ai.config; import cn.hutool.core.io.IoUtil; +import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactory; +import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactoryImpl; import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatClient; import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatModal; import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenOptions; @@ -36,17 +38,22 @@ import java.util.HashMap; import java.util.Map; /** - * ai 自动配置 + * 芋道 AI 自动配置 * * @author fansili - * @time 2024/4/12 16:29 - * @since 1.0 */ -@Slf4j @AutoConfiguration @EnableConfigurationProperties(YudaoAiProperties.class) +@Slf4j public class YudaoAiAutoConfiguration { + @Bean + public AiClientFactory aiClientFactory() { + return new AiClientFactoryImpl(); + } + + // ========== 各种 AI Client 创建 ========== + @Bean @ConditionalOnProperty(value = "yudao.ai.xinghuo.enable", havingValue = "true") public XingHuoChatClient xingHuoChatClient(YudaoAiProperties yudaoAiProperties) { @@ -107,21 +114,6 @@ public class YudaoAiAutoConfiguration { ); } - @Bean - @ConditionalOnProperty(value = "yudao.ai.openAiImage.enable", havingValue = "true") - public OpenAiImageClient openAiImageClient(YudaoAiProperties yudaoAiProperties) { - YudaoAiProperties.OpenAiImageProperties openAiImageProperties = yudaoAiProperties.getOpenAiImage(); - OpenAiImageOptions openAiImageOptions = new OpenAiImageOptions(); - openAiImageOptions.setModel(openAiImageProperties.getModel().getModel()); - openAiImageOptions.setStyle(openAiImageProperties.getStyle().getStyle()); - openAiImageOptions.setResponseFormat("url"); // TODO 芋艿:OpenAiImageOptions.ResponseFormatEnum.URL.getValue() - // 创建 client - return new OpenAiImageClient( - new OpenAiImageApi(openAiImageProperties.getApiKey()), - openAiImageOptions, - RetryUtils.DEFAULT_RETRY_TEMPLATE); - } - @Bean @ConditionalOnMissingBean(value = MidjourneyMessageHandler.class) public MidjourneyMessageHandler defaultMidjourneyMessageHandler() { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactory.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactory.java new file mode 100644 index 000000000..98707fdc8 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactory.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.framework.ai.core.factory; + +import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; +import org.springframework.ai.chat.StreamingChatClient; +import org.springframework.ai.chat.prompt.ChatOptions; + +/** + * AI 客户端工厂的接口类 + * + * @author fansili + */ +public interface AiClientFactory { + + /** + * 基于指定配置,获得 StreamingChatClient 对象 + * + * 如果不存在,则进行创建 + * + * @param platform 平台 + * @param apiKey API KEY + * @param url API URL + * @return StreamingChatClient 对象 + */ + StreamingChatClient getOrCreateStreamingChatClient(AiPlatformEnum platform, String apiKey, String url); + + /** + * 基于默认配置,获得 StreamingChatClient 对象 + * + * 默认配置,指的是在 application.yaml 配置文件中的 spring.ai 相关的配置 + * + * @param platform 平台 + * @return StreamingChatClient 对象 + */ + StreamingChatClient getDefaultStreamingChatClient(AiPlatformEnum platform); + + /** + * 创建 Chat 参数 + * + * @param platform 平台 + * @param model 模型 + * @param temperature 温度 + * @param maxTokens 生成的最大 Token + * @return Chat 参数 + */ + ChatOptions buildChatOptions(AiPlatformEnum platform, String model, Double temperature, Integer maxTokens); + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java new file mode 100644 index 000000000..b005d7c3e --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java @@ -0,0 +1,167 @@ +package cn.iocoder.yudao.framework.ai.core.factory; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.lang.Singleton; +import cn.hutool.core.lang.func.Func0; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; +import cn.iocoder.yudao.framework.ai.config.YudaoAiAutoConfiguration; +import cn.iocoder.yudao.framework.ai.config.YudaoAiProperties; +import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatClient; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatModal; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenOptions; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.api.QianWenApi; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatClient; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoOptions; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoApi; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatClient; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatOptions; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanApi; +import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration; +import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; +import org.springframework.ai.chat.StreamingChatClient; +import org.springframework.ai.chat.prompt.ChatOptions; +import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.ai.ollama.api.OllamaApi; +import org.springframework.ai.ollama.api.OllamaOptions; +import org.springframework.ai.openai.OpenAiChatClient; +import org.springframework.ai.openai.OpenAiChatOptions; +import org.springframework.ai.openai.api.ApiUtils; +import org.springframework.ai.openai.api.OpenAiApi; + +import java.util.List; + +/** + * AI 客户端工厂的实现类 + * + * @author 芋道源码 + */ +public class AiClientFactoryImpl implements AiClientFactory { + + @Override + public StreamingChatClient getOrCreateStreamingChatClient(AiPlatformEnum platform, String apiKey, String url) { + String cacheKey = buildClientCacheKey(StreamingChatClient.class, platform, apiKey, url); + return Singleton.get(cacheKey, (Func0) () -> { + //noinspection EnhancedSwitchMigration + switch (platform) { + case OPENAI: + return buildOpenAiChatClient(apiKey, url); + case OLLAMA: + return buildOllamaChatClient(url); + case YI_YAN: + return buildYiYanChatClient(apiKey); + case XING_HUO: + return buildXingHuoChatClient(apiKey); + case QIAN_WEN: + return buildQianWenChatClient(apiKey); + default: + throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); + } + }); + } + + @Override + public StreamingChatClient getDefaultStreamingChatClient(AiPlatformEnum platform) { + //noinspection EnhancedSwitchMigration + switch (platform) { + case OPENAI: + return SpringUtil.getBean(OpenAiChatClient.class); + case OLLAMA: + return SpringUtil.getBean(OllamaChatClient.class); + case YI_YAN: + return SpringUtil.getBean(YiYanChatClient.class); + case XING_HUO: + return SpringUtil.getBean(XingHuoChatClient.class); + case QIAN_WEN: + return SpringUtil.getBean(QianWenChatClient.class); + default: + throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); + } + } + + private static String buildClientCacheKey(Class clazz, Object... params) { + if (ArrayUtil.isEmpty(params)) { + return clazz.getName(); + } + return StrUtil.format("{}#{}", clazz.getName(), ArrayUtil.join(params, "_")); + } + + @Override + public ChatOptions buildChatOptions(AiPlatformEnum platform, String model, Double temperature, Integer maxTokens) { + Float temperatureF = temperature != null ? temperature.floatValue() : null; + //noinspection EnhancedSwitchMigration + switch (platform) { + case OPENAI: + return OpenAiChatOptions.builder().withModel(model).withTemperature(temperatureF).withMaxTokens(maxTokens).build(); + case OLLAMA: + return OllamaOptions.create().withModel(model).withTemperature(temperatureF).withNumPredict(maxTokens); + case YI_YAN: + // TODO @fan:增加一个 model + return new YiYanChatOptions().setTemperature(temperatureF).setMaxOutputTokens(maxTokens); + case XING_HUO: + return new XingHuoOptions().setChatModel(XingHuoChatModel.valueOfModel(model)).setTemperature(temperatureF) + .setMaxTokens(maxTokens); + case QIAN_WEN: + // TODO @fan:增加 model、temperature 参数 + return new QianWenOptions().setMaxTokens(maxTokens); + default: + throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); + } + } + + // ========== 各种创建 spring-ai 客户端的方法 ========== + + /** + * 可参考 {@link OpenAiAutoConfiguration} + */ + private static OpenAiChatClient buildOpenAiChatClient(String openAiToken, String url) { + url = StrUtil.blankToDefault(url, ApiUtils.DEFAULT_BASE_URL); + OpenAiApi openAiApi = new OpenAiApi(url, openAiToken); + return new OpenAiChatClient(openAiApi); + } + + /** + * 可参考 {@link OllamaAutoConfiguration} + */ + private static OllamaChatClient buildOllamaChatClient(String url) { + OllamaApi ollamaApi = new OllamaApi(url); + return new OllamaChatClient(ollamaApi); + } + + /** + * 可参考 {@link YudaoAiAutoConfiguration#yiYanChatClient(YudaoAiProperties)} + */ + private static YiYanChatClient buildYiYanChatClient(String key) { + List keys = StrUtil.split(key, '|'); + Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式"); + String appKey = keys.get(0); + String secretKey = keys.get(1); + YiYanApi yiYanApi = new YiYanApi(appKey, secretKey, YiYanApi.DEFAULT_CHAT_MODEL, 0); + return new YiYanChatClient(yiYanApi); + } + + /** + * 可参考 {@link YudaoAiAutoConfiguration#xingHuoChatClient(YudaoAiProperties)} + */ + private static XingHuoChatClient buildXingHuoChatClient(String key) { + List keys = StrUtil.split(key, '|'); + Assert.equals(keys.size(), 2, "XingHuoChatClient 的密钥需要 (appKey|secretKey) 格式"); + String appId = keys.get(0); + String appKey = keys.get(1); + String secretKey = keys.get(2); + XingHuoApi xingHuoApi = new XingHuoApi(appId, appKey, secretKey); + return new XingHuoChatClient(xingHuoApi); + } + + /** + * 可参考 {@link YudaoAiAutoConfiguration#qianWenChatClient(YudaoAiProperties)} + */ + private static QianWenChatClient buildQianWenChatClient(String key) { + QianWenApi qianWenApi = new QianWenApi(key, QianWenChatModal.QWEN_72B_CHAT); + return new QianWenChatClient(qianWenApi); + } + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenOptions.java index b6dba53c9..4f7632c97 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenOptions.java @@ -6,6 +6,8 @@ import lombok.experimental.Accessors; import java.util.List; +// TODO @fan:增加一个 model 参数 +// TODO @fan:增加一个 Temperature 参数 /** * 阿里云 千问 属性 * diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/XingHuoOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/XingHuoOptions.java index cb4753833..ccec8598d 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/XingHuoOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/XingHuoOptions.java @@ -14,6 +14,7 @@ import lombok.experimental.Accessors; @Accessors(chain = true) public class XingHuoOptions implements ChatOptions { + // TODO @fan:这里 model 参数,然后使用 string /** * https://www.xfyun.cn/doc/spark/Web.html#_1-%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E *

@@ -43,7 +44,6 @@ public class XingHuoOptions implements ChatOptions { */ private String chatId; - @Override public Float getTemperature() { return this.temperature; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/YiYanChatOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/YiYanChatOptions.java index 14146a322..a84b0ec98 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/YiYanChatOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/YiYanChatOptions.java @@ -6,6 +6,7 @@ import org.springframework.ai.chat.prompt.ChatOptions; import java.util.List; +// TODO @fan:增加一个 model // TODO @fan:字段命名,penalty_score 类似的,建议改成驼峰原则 // TODO @fan:字段的注释,可以都删除掉,让用户 https://cloud.baidu.com/doc/WENXINWORKSHOP/s/clntwmv7t 即可 /** diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/api/YiYanApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/api/YiYanApi.java index 535901f25..93cd13fe1 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/api/YiYanApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/api/YiYanApi.java @@ -18,7 +18,7 @@ public class YiYanApi { private static final String AUTH_2_TOKEN_URI = "/oauth/2.0/token"; - public static final String DEFAULT_CHAT_MODEL = YiYanChatModel.ERNIE4_0.getModel(); + public static final YiYanChatModel DEFAULT_CHAT_MODEL = YiYanChatModel.ERNIE4_0; private final String appKey; private final String secretKey; @@ -39,6 +39,7 @@ public class YiYanApi { */ private final YiYanChatModel useChatModel; + // TODO fan:看看是不是去掉 refreshTokenSecondTime 字段 public YiYanApi(String appKey, String secretKey, YiYanChatModel useChatModel, int refreshTokenSecondTime) { this.appKey = appKey; this.secretKey = secretKey; diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 6bb087d81..cc5ed76a3 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -150,15 +150,8 @@ spring.ai: chat: model: llama3 openai: -# api-key: sk-QmgIIPc5xiYd8lPb076b1b7774Ea49Af9eD2Ef172c8f7e43 -# base-url: https://openkey.cloud -# api-key: sk-gkgfYxhX9FxyZJznwxRZSJwKeGQYNPDVWjhby2PRRf17GHeT -# base-url: https://api.chatanywhere.tech api-key: sk-yzKea6d8e8212c3bdd99f9f44ced1cae37c097e5aa3BTS7z base-url: https://api.gptsapi.net -# chat: -# options: -# model: gpt-4-0125-preview yudao.ai: yiyan: From 3b02bcf4f84b11cf72c2573dad91924f322e4110 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 22 May 2024 12:39:55 +0800 Subject: [PATCH 313/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E9=80=9A=E8=BF=87=20AiClientFactory=20=E6=8F=90?= =?UTF-8?q?=E4=BE=9B=20chatclient?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java index d2682eba8..a67517fed 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java @@ -18,7 +18,6 @@ import org.springframework.ai.chat.messages.*; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; -import cn.iocoder.yudao.module.ai.config.AiChatClientFactory; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert; From a48287611358f7b885ca0e7b99e14ede39af6347 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 22 May 2024 13:12:54 +0800 Subject: [PATCH 314/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E8=81=8A=E5=A4=A9=E6=B6=88=E6=81=AF=E7=9A=84=20Servic?= =?UTF-8?q?e=20=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/ErrorCodeConstants.java | 4 +- .../admin/chat/AiChatMessageController.java | 64 +++++++++--- .../vo/message/AiChatMessageSendRespVO.java | 7 +- .../ai/convert/AiChatMessageConvert.java | 30 ------ .../ai/dal/mysql/AiChatMessageMapper.java | 43 -------- .../ai/dal/mysql/AiChatModelMapper.java | 6 -- .../module/ai/dal/mysql/AiImageMapper.java | 1 - .../dal/mysql/chat/AiChatMessageMapper.java | 24 +++++ .../module/ai/service/AiChatService.java | 57 ----------- .../ai/service/chat/AiChatMessageService.java | 57 +++++++++++ .../AiChatMessageServiceImpl.java} | 99 ++++++++----------- .../ai/service/model/AiChatRoleService.java | 18 ++-- .../service/model/AiChatRoleServiceImpl.java | 15 +-- 13 files changed, 198 insertions(+), 227 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatMessageMapper.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/{impl/AiChatServiceImpl.java => chat/AiChatMessageServiceImpl.java} (77%) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index 4542c0787..cd1985f81 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -30,8 +30,8 @@ public interface ErrorCodeConstants { ErrorCode CHAT_CONVERSATION_UPDATE_MAX_TOKENS_ERROR = new ErrorCode(1_040_003_002, "更新对话失败,最大 Token 超过上限"); ErrorCode CHAT_CONVERSATION_UPDATE_MAX_CONTEXTS_ERROR = new ErrorCode(1_040_003_002, "更新对话失败,最大 Context 超过上限"); - // chat - ErrorCode AI_CHAT_MESSAGE_NOT_EXIST = new ErrorCode(1_022_000_100, "提问的 MessageId 不存在!"); + // ========== API 聊天消息 1-040-004-000 ========== + ErrorCode AI_CHAT_MESSAGE_NOT_EXIST = new ErrorCode(1_040_004_000, "消息不存在!"); // midjourney diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java index ad9375f39..2522d0dc0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java @@ -1,8 +1,19 @@ package cn.iocoder.yudao.module.ai.controller.admin.chat; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.*; -import cn.iocoder.yudao.module.ai.service.AiChatService; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; +import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService; +import cn.iocoder.yudao.module.ai.service.chat.AiChatMessageService; +import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -14,9 +25,12 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Flux; +import java.util.Collections; import java.util.List; +import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @Tag(name = "管理后台 - 聊天消息") @@ -26,39 +40,65 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti public class AiChatMessageController { @Resource - private AiChatService chatService; + private AiChatMessageService chatMessageService; + @Resource + private AiChatConversationService chatConversationService; + @Resource + private AiChatRoleService chatRoleService; + + @Resource + private AdminUserApi adminUserApi; @Operation(summary = "发送消息(段式)", description = "一次性返回,响应较慢") @PostMapping("/send") public CommonResult sendMessage(@Validated @RequestBody AiChatMessageSendReqVO sendReqVO) { - return success(chatService.chat(sendReqVO)); + return success(chatMessageService.sendMessage(sendReqVO)); } @Operation(summary = "发送消息(流式)", description = "流式返回,响应较快") @PostMapping(value = "/send-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) @PermitAll // 解决 SSE 最终响应的时候,会被 Access Denied 拦截的问题 public Flux sendChatMessageStream(@Validated @RequestBody AiChatMessageSendReqVO sendReqVO) { - return chatService.sendChatMessageStream(sendReqVO, getLoginUserId()); + return chatMessageService.sendChatMessageStream(sendReqVO, getLoginUserId()); } @Operation(summary = "获得指定会话的消息列表") @GetMapping("/list-by-conversation-id") @Parameter(name = "conversationId", required = true, description = "会话编号", example = "1024") - public CommonResult> getMessageListByConversationId(@RequestParam("conversationId") Long conversationId) { - return success(chatService.getMessageListByConversationId(conversationId)); + public CommonResult> getChatMessageListByConversationId( + @RequestParam("conversationId") Long conversationId) { + AiChatConversationDO conversation = chatConversationService.getChatConversation(conversationId); + if (conversation == null || ObjUtil.notEqual(conversation.getUserId(), getLoginUserId())) { + return success(Collections.emptyList()); + } + List messageList = chatMessageService.getChatMessageListByConversationId(conversationId); + if (CollUtil.isEmpty(messageList)) { + return success(Collections.emptyList()); + } + + // 拼接数据 + Map roleMap = chatRoleService.getChatRoleMap(convertSet(messageList, AiChatMessageDO::getRoleId)); + AdminUserRespDTO user = adminUserApi.getUser(getLoginUserId()); + return success(BeanUtils.toBean(messageList, AiChatMessageRespVO.class, respVO -> { + MapUtils.findAndThen(roleMap, respVO.getRoleId(), role -> respVO.setRoleAvatar(role.getAvatar())); + respVO.setUserAvatar(user.getAvatar()); + })); } @Operation(summary = "删除消息") @DeleteMapping("/delete") @Parameter(name = "id", required = true, description = "消息编号", example = "1024") - public CommonResult deleteMessage(@RequestParam("id") Long id) { - return success(chatService.deleteMessage(id)); + public CommonResult deleteChatMessage(@RequestParam("id") Long id) { + chatMessageService.deleteMessage(id, getLoginUserId()); + return success(true); } - @Operation(summary = "删除消息-对于对话全部消息") + @Operation(summary = "删除指定会话的消息") @DeleteMapping("/delete-by-conversation-id") - @Parameter(name = "id", required = true, description = "消息编号", example = "1024") - public CommonResult deleteByConversationId(@RequestParam("conversationId") Long conversationId) { - return success(chatService.deleteByConversationId(conversationId)); + @Parameter(name = "conversationId", required = true, description = "会话编号", example = "1024") + public CommonResult deleteChatMessageByConversationId(@RequestParam("conversationId") Long conversationId) { + chatMessageService.deleteChatMessageByConversationId(conversationId, getLoginUserId()); + return success(true); } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java index 3314b1d32..fbc31eea5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java @@ -31,13 +31,14 @@ public class AiChatMessageSendRespVO { @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; - // ========= 扩展字段 + // ========== 扩展字段 ========== - @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://xxx") + @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://iocoder.cn/1.png") private String userAvatar; - @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://xxx") + @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://iocoder.cn/2.png") private String roleAvatar; + } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java deleted file mode 100644 index eda556358..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiChatMessageConvert.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.module.ai.convert; - -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * 聊天 对话 convert - * - * @author fansili - * @time 2024/4/18 16:39 - * @since 1.0 - */ -@Mapper -public interface AiChatMessageConvert { - - AiChatMessageConvert INSTANCE = Mappers.getMapper(AiChatMessageConvert.class); - - /** - * 转换 AiChatMessageRespVO - * - * @param aiChatMessageDOList - * @return - */ - List convertAiChatMessageRespVOList(List aiChatMessageDOList); - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java deleted file mode 100644 index 6c9c22ad0..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatMessageMapper.java +++ /dev/null @@ -1,43 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql; - -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; -import org.apache.ibatis.annotations.Mapper; -import org.springframework.stereotype.Repository; - -import java.util.List; - -/** - * message mapper - * - * @fansili - * @since v1.0 - */ -@Repository -@Mapper -public interface AiChatMessageMapper extends BaseMapperX { - - /** - * 查询 - 根据 对话id查询 - * - * @param conversationId - */ - default List selectByConversationId(Long conversationId) { - return this.selectList( - new LambdaQueryWrapperX() - .eq(AiChatMessageDO::getConversationId, conversationId) - .orderByAsc(AiChatMessageDO::getId) - ); - } - - /** - * 删除 - 根据 conversationId - * - * @param conversationId - */ - default int deleteByConversationId(Long conversationId) { - return this.delete(new LambdaQueryWrapperX().eq(AiChatMessageDO::getConversationId, conversationId)); - } -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java index 3c959e961..25687d0e0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java @@ -1,18 +1,13 @@ package cn.iocoder.yudao.module.ai.dal.mysql; -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelPageReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.apache.ibatis.annotations.Mapper; -import java.util.List; - import java.util.Collection; import java.util.List; @@ -42,7 +37,6 @@ public interface AiChatModelMapper extends BaseMapperX { return this.selectList(new LambdaQueryWrapperX().eq(AiChatModelDO::getId, modalIds)); } - default PageResult selectPage(AiChatModelPageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() .likeIfPresent(AiChatModelDO::getName, reqVO.getName()) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiImageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiImageMapper.java index 1ee5b436d..d353fea5a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiImageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiImageMapper.java @@ -13,7 +13,6 @@ import org.springframework.stereotype.Repository; * @time 2024/4/28 14:01 * @since 1.0 */ -@Repository @Mapper public interface AiImageMapper extends BaseMapperX { diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatMessageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatMessageMapper.java new file mode 100644 index 000000000..7b3e9c493 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatMessageMapper.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.ai.dal.mysql.chat; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * AI 聊天对话 Mapper + * + * @author fansili + */ +@Mapper +public interface AiChatMessageMapper extends BaseMapperX { + + default List selectListByConversationId(Long conversationId) { + return selectList(new LambdaQueryWrapperX() + .eq(AiChatMessageDO::getConversationId, conversationId) + .orderByAsc(AiChatMessageDO::getId)); + } + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java deleted file mode 100644 index f8924cb63..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiChatService.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.iocoder.yudao.module.ai.service; - -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.*; -import reactor.core.publisher.Flux; - -import java.util.List; - -/** - * 聊天 chat - * - * @author fansili - * @time 2024/4/14 15:55 - * @since 1.0 - */ -public interface AiChatService { - - /** - * chat - * - * @param sendReqVO - * @return - */ - AiChatMessageRespVO chat(AiChatMessageSendReqVO sendReqVO); - - /** - * 获取 - 获取对话 message list - * - * @param conversationId - * @return - */ - List getMessageListByConversationId(Long conversationId); - - /** - * 删除 - 删除message - * - * @param id - * @return - */ - Boolean deleteMessage(Long id); - - /** - * 发送消息 - * - * @param sendReqVO - * @param userId - * @return - */ - Flux sendChatMessageStream(AiChatMessageSendReqVO sendReqVO, Long userId); - - /** - * 删除消息-对于对话全部消息 - * - * @param conversationId - * @return - */ - Boolean deleteByConversationId(Long conversationId); -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java new file mode 100644 index 000000000..e9dc43ec9 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.ai.service.chat; + +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.*; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; +import reactor.core.publisher.Flux; + +import java.util.List; + +/** + * AI 聊天消息 Service 接口 + * + * @author fansili + */ +public interface AiChatMessageService { + + /** + * 发送消息 + * + * @param sendReqVO 发送信息 + * @return 发送结果 + */ + AiChatMessageRespVO sendMessage(AiChatMessageSendReqVO sendReqVO); + + /** + * 发送消息 + * + * @param sendReqVO 发送信息 + * @param userId 用户编号 + * @return 发送结果 + */ + Flux sendChatMessageStream(AiChatMessageSendReqVO sendReqVO, Long userId); + + /** + * 获得指定会话的消息列表 + * + * @param conversationId 会话编号 + * @return 消息列表 + */ + List getChatMessageListByConversationId(Long conversationId); + + /** + * 删除消息 + * + * @param id 消息编号 + * @param userId 用户编号 + */ + void deleteMessage(Long id, Long userId); + + /** + * 删除指定会话的消息 + * + * @param conversationId 会话编号 + * @param userId 用户编号 + */ + void deleteChatMessageByConversationId(Long conversationId, Long userId); + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java similarity index 77% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java index a67517fed..3e4f60258 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.service.impl; +package cn.iocoder.yudao.module.ai.service.chat; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; @@ -20,13 +20,10 @@ import org.springframework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; -import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.dal.mysql.AiChatMessageMapper; -import cn.iocoder.yudao.module.ai.service.AiChatService; -import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService; +import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatMessageMapper; import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; import lombok.extern.slf4j.Slf4j; @@ -37,21 +34,20 @@ import reactor.core.scheduler.Schedulers; import java.time.LocalDateTime; import java.util.*; -import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.AI_CHAT_MESSAGE_NOT_EXIST; import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_CONVERSATION_NOT_EXISTS; /** - * 聊天 service + * AI 聊天消息 Service 实现类 * * @author fansili - * @time 2024/4/14 15:55 - * @since 1.0 */ -@Slf4j @Service -public class AiChatServiceImpl implements AiChatService { +@Slf4j +public class AiChatMessageServiceImpl implements AiChatMessageService { @Resource private AiChatMessageMapper chatMessageMapper; @@ -72,7 +68,7 @@ public class AiChatServiceImpl implements AiChatService { private AdminUserApi adminUserApi; @Transactional(rollbackFor = Exception.class) - public AiChatMessageRespVO chat(AiChatMessageSendReqVO req) { + public AiChatMessageRespVO sendMessage(AiChatMessageSendReqVO req) { return null; // TODO 芋艿:一起改 // Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // // 查询对话 @@ -117,10 +113,13 @@ public class AiChatServiceImpl implements AiChatService { if (ObjUtil.notEqual(conversation.getUserId(), userId)) { throw exception(CHAT_CONVERSATION_NOT_EXISTS); // TODO 芋艿:异常情况的对接; } - List historyMessages = chatMessageMapper.selectByConversationId(conversation.getId()); + List historyMessages = chatMessageMapper.selectListByConversationId(conversation.getId()); // 1.2 校验模型 AiChatModelDO model = chatModalService.validateChatModel(conversation.getModelId()); StreamingChatClient chatClient = apiKeyService.getStreamingChatClient(model.getKeyId()); + // 1.3 获取用户头像、角色头像 + AdminUserRespDTO user = adminUserApi.getUser(SecurityFrameworkUtils.getLoginUserId()); + AiChatRoleDO role = conversation.getRoleId() != null ? chatRoleService.getChatRole(conversation.getRoleId()) : null; // 2. 插入 user 发送消息 AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model, @@ -136,19 +135,17 @@ public class AiChatServiceImpl implements AiChatService { // 3.3 流式返回 // 注意:Schedulers.immediate() 目的是,避免默认 Schedulers.parallel() 并发消费 chunk 导致 SSE 响应前端会乱序问题 - - // 3.4 获取用户头像、角色头像 - AdminUserRespDTO user = adminUserApi.getUser(SecurityFrameworkUtils.getLoginUserId()); - AiChatRoleDO chatRole = chatRoleService.getChatRole(assistantMessage.getRoleId()); - StringBuffer contentBuffer = new StringBuffer(); return streamResponse.publishOn(Schedulers.single()).map(chunk -> { String newContent = chunk.getResult() != null ? chunk.getResult().getOutput().getContent() : null; newContent = StrUtil.nullToDefault(newContent, ""); // 避免 null 的 情况 contentBuffer.append(newContent); // 响应结果 - return new AiChatMessageSendRespVO().setSend(BeanUtils.toBean(userMessage, AiChatMessageSendRespVO.Message.class).setUserAvatar(user.getAvatar())) - .setReceive(BeanUtils.toBean(assistantMessage, AiChatMessageSendRespVO.Message.class).setContent(newContent).setRoleAvatar(chatRole == null ? null : chatRole.getAvatar())); + AiChatMessageSendRespVO.Message send = BeanUtils.toBean(userMessage, AiChatMessageSendRespVO.Message.class, + o -> o.setUserAvatar(user.getAvatar())); + AiChatMessageSendRespVO.Message receive = BeanUtils.toBean(assistantMessage, AiChatMessageSendRespVO.Message.class, + o -> o.setRoleAvatar(role != null ? role.getAvatar() : null)).setContent(newContent); + return new AiChatMessageSendRespVO().setSend(send).setReceive(receive); }).doOnComplete(() -> { chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString())); }).doOnError(throwable -> { @@ -157,11 +154,6 @@ public class AiChatServiceImpl implements AiChatService { }); } - @Override - public Boolean deleteByConversationId(Long conversationId) { - return chatMessageMapper.deleteByConversationId(conversationId) > 0; - } - private Prompt buildPrompt(AiChatConversationDO conversation, List messages, AiChatModelDO model, AiChatMessageSendReqVO sendReqVO) { // 1. 构建 Prompt Message 列表 @@ -174,12 +166,11 @@ public class AiChatServiceImpl implements AiChatService { // 1.3 user message 新发送消息 chatMessages.add(new UserMessage(sendReqVO.getContent())); - // 2. 构建 ChatOptions 对象 TODO 芋艿:临时注释掉;等文心一言兼容了; + // 2. 构建 ChatOptions 对象 AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); ChatOptions chatOptions = clientFactory.buildChatOptions(platform, model.getModel(), conversation.getTemperature(), conversation.getMaxTokens()); return new Prompt(chatMessages, chatOptions); -// return new Prompt(chatMessages); } /** @@ -231,42 +222,30 @@ public class AiChatServiceImpl implements AiChatService { } @Override - public List getMessageListByConversationId(Long conversationId) { - // 校验对话是否存在 - chatConversationService.validateExists(conversationId); - // 获取对话所有 message - List aiChatMessageDOList = chatMessageMapper.selectByConversationId(conversationId); - // 获取模型信息 - Set roleIds = aiChatMessageDOList.stream().map(AiChatMessageDO::getRoleId).collect(Collectors.toSet()); - List roleList; - if (!CollUtil.isEmpty(roleIds)) { - roleList = chatRoleService.getChatRoles(roleIds); - } else { - roleList = Collections.emptyList(); - } - Map roleMap = roleList.stream().collect(Collectors.toMap(AiChatRoleDO::getId, o -> o)); - // 转换 AiChatMessageRespVO - List aiChatMessageRespList = AiChatMessageConvert.INSTANCE.convertAiChatMessageRespVOList(aiChatMessageDOList); - // 获取用户信息 - AdminUserRespDTO user = adminUserApi.getUser(SecurityFrameworkUtils.getLoginUserId()); - // 设置用户头像 和 模型头像 - return aiChatMessageRespList.stream().map(item -> { - // 设置 role 头像 - if (roleMap.containsKey(item.getRoleId())) { - AiChatRoleDO role = roleMap.get(item.getRoleId()); - item.setRoleAvatar(role.getAvatar()); - } - // 设置 user 头像 - if (user != null) { - item.setUserAvatar(user.getAvatar()); - } - return item; - }).collect(Collectors.toList()); + public List getChatMessageListByConversationId(Long conversationId) { + return chatMessageMapper.selectListByConversationId(conversationId); } @Override - public Boolean deleteMessage(Long id) { - return chatMessageMapper.deleteById(id) > 0; + public void deleteMessage(Long id, Long userId) { + // 1. 校验消息存在 + AiChatMessageDO message = chatMessageMapper.selectById(id); + if (message == null || ObjUtil.notEqual(message.getUserId(), userId)) { + throw exception(AI_CHAT_MESSAGE_NOT_EXIST); + } + // 2. 执行删除 + chatMessageMapper.deleteById(id); + } + + @Override + public void deleteChatMessageByConversationId(Long conversationId, Long userId) { + // 1. 校验消息存在 + List messages = chatMessageMapper.selectListByConversationId(conversationId); + if (CollUtil.isEmpty(messages) || ObjUtil.notEqual(messages.get(0).getUserId(), userId)) { + throw exception(AI_CHAT_MESSAGE_NOT_EXIST); + } + // 2. 执行删除 + chatMessageMapper.deleteBatchIds(convertList(messages, AiChatMessageDO::getId)); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java index 228b1ee6e..a7bc2501a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java @@ -4,12 +4,14 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRolePageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveMyReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import jakarta.validation.Valid; +import java.util.Collection; import java.util.List; -import java.util.Set; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; /** * AI 聊天角色 Service 接口 @@ -74,12 +76,16 @@ public interface AiChatRoleService { AiChatRoleDO getChatRole(Long id); /** - * 获得聊天角色 - 根据 ids + * 获得聊天角色列表 * - * @param roleIds - * @return + * @param ids 编号数组 + * @return 聊天角色列表 */ - List getChatRoles(Set roleIds); + List getChatRoleList(Collection ids); + + default Map getChatRoleMap(Collection ids) { + return convertMap(getChatRoleList(ids), AiChatRoleDO::getId); + } /** * 校验聊天角色是否合法 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java index 1413dd8ce..d3083ec9f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.ai.service.model; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; @@ -14,12 +15,9 @@ import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.util.Collection; +import java.util.Collections; import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @@ -107,8 +105,11 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { } @Override - public List getChatRoles(Set roleIds) { - return chatRoleMapper.selectBatchIds(roleIds); + public List getChatRoleList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return chatRoleMapper.selectBatchIds(ids); } @Override From b227b039c961d04ba49af8f022278c784b4c3431 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Thu, 23 May 2024 17:14:35 +0800 Subject: [PATCH 315/684] =?UTF-8?q?MEMBER:=20=E6=A0=B9=E6=8D=AE=E3=80=90?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E8=AF=84=E5=AE=A1=E3=80=91=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E5=B0=8F=E7=A8=8B=E5=BA=8F=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/social/AppSocialUserController.java | 22 ++++++++++++++----- .../app/social/vo/AppSocialWxQrcodeReqVO.java | 19 +++++----------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java index 2cf7b8641..722da6dab 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.member.controller.app.social; +import cn.hutool.core.codec.Base64; +import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -22,8 +24,6 @@ import jakarta.validation.Valid; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.util.Base64; - import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -33,6 +33,13 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti @Validated public class AppSocialUserController { + public static final String ENV_VERSION = "release"; // 小程序版本。正式版为 "release",体验版为 "trial",开发版为 "develop" + private static final String SCENE = ""; // 页面路径不能携带参数(参数请放在scene字段里) + private static final Integer WIDTH = 430; // 二维码宽度 + private static final Boolean AUTO_COLOR = true; // 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 + private static final Boolean CHECK_PATH = true; // 默认true 检查 page 是否存在 + private static final Boolean HYALINE = true; // 是否需要透明底色, hyaline 为true时,生成透明底色的小程序码 + @Resource private SocialUserApi socialUserApi; @Resource @@ -69,10 +76,13 @@ public class AppSocialUserController { @PostMapping("/wxa-qrcode") @Operation(summary = "获得微信小程序码(base64 image)") public CommonResult getWxQrcode(@RequestBody @Valid AppSocialWxQrcodeReqVO reqVO) { - byte[] wxQrcode = socialClientApi.getWxaQrcode(BeanUtils.toBean(reqVO, SocialWxQrcodeReqDTO.class) - .setEnvVersion(AppSocialWxQrcodeReqVO.ENV_VERSION)); - // TODO @puhui999:1)是不是 base64 返回,不拼接哈 data:image/png;base64;2)cn.hutool.core.codec.Base64.encode() - return success("data:image/png;base64," + Base64.getEncoder().encodeToString(wxQrcode)); + byte[] wxQrcode = socialClientApi.getWxaQrcode(new SocialWxQrcodeReqDTO().setPath(reqVO.getPath()) + .setEnvVersion(ENV_VERSION).setWidth(ObjUtil.defaultIfNull(reqVO.getWidth(), WIDTH)) + .setScene(ObjUtil.defaultIfNull(reqVO.getScene(), SCENE)) + .setAutoColor(ObjUtil.defaultIfNull(reqVO.getAutoColor(), AUTO_COLOR)) + .setHyaline(ObjUtil.defaultIfNull(reqVO.getHyaline(), HYALINE)) + .setCheckPath(ObjUtil.defaultIfNull(reqVO.getCheckPath(), CHECK_PATH))); + return success(Base64.encode(wxQrcode)); } } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java index aabdc72c9..8927a34c9 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java @@ -9,20 +9,11 @@ import lombok.Data; @Data public class AppSocialWxQrcodeReqVO { - // TODO @puhui999: 没有默认值 getQrcodeService().createWxaCodeUnlimitBytes() 转类型会报错 🤣 - // TODO @puhui999:懂了哈;default 最好在 controller 搞;对于 VO 来说,不给默认值; - public static String ENV_VERSION = "release"; // 小程序版本。正式版为 "release",体验版为 "trial",开发版为 "develop" - private static String SCENE = ""; // 页面路径不能携带参数(参数请放在scene字段里) - private static Integer WIDTH = 430; // 二维码宽度 - private static Boolean AUTO_COLOR = true; // 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 - private static Boolean CHECK_PATH = true; // 默认true 检查 page 是否存在 - private static Boolean HYALINE = true; // 是否需要透明底色, is_hyaline 为true时,生成透明底色的小程序码 - /** * 页面路径不能携带参数(参数请放在scene字段里) */ @Schema(description = "场景值", requiredMode = Schema.RequiredMode.REQUIRED, example = "1001") - private String scene = SCENE; + private String scene; /** * 默认是主页,页面 page,例如 pages/index/index,根路径前不要填加 /,不能携带参数(参数请放在scene字段里), @@ -33,15 +24,15 @@ public class AppSocialWxQrcodeReqVO { private String path; @Schema(description = "二维码宽度", requiredMode = Schema.RequiredMode.REQUIRED, example = "430") - private Integer width = WIDTH; + private Integer width; @Schema(description = "是/否自动配置线条颜色", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - private Boolean autoColor = AUTO_COLOR; + private Boolean autoColor; @Schema(description = "是/否检查 page 是否存在", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - private Boolean checkPath = CHECK_PATH; + private Boolean checkPath; @Schema(description = "是/否需要透明底色", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - private Boolean hyaline = HYALINE; + private Boolean hyaline; } From e39513c6b2e8fa320ee0b5038be499316dc813b7 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 24 May 2024 14:25:00 +0800 Subject: [PATCH 316/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E5=A4=84=E7=90=86=20QianWen=20topP=20=E4=B8=BA=E7=A9=BA?= =?UTF-8?q?=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/core/model/tongyi/QianWenChatClient.java | 2 +- .../ai/core/model/tongyi/QianWenOptions.java | 17 +++-------------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatClient.java index 85fa771bd..63f3af776 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatClient.java @@ -106,7 +106,7 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient { .messages(messageList) .maxTokens(chatOptions.getMaxTokens()) .resultFormat(QwenParam.ResultFormat.MESSAGE) - .topP(Double.valueOf(chatOptions.getTopP())) + .topP(chatOptions.getTopP() == null ? null : Double.valueOf(chatOptions.getTopP())) .topK(chatOptions.getTopK()) .temperature(chatOptions.getTemperature()) // 控制流式输出模式,即后面的内容会包含已经输出的内容;设置为True,将开启增量输出模式,后面的输出不会包含已经输出的内容,您需要自行拼接整体输出 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenOptions.java index 4f7632c97..07805cf11 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenOptions.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenOptions.java @@ -43,25 +43,14 @@ public class QianWenOptions implements ChatOptions { return null; } -// @Override -// public void setTemperature(Float temperature) { -// -// } -// -// @Override -// public void setTopP(Float topP) { -// this.topP = topP; -// } - @Override public Integer getTopK() { return null; } -// @Override -// public void setTopK(Integer topK) { -// -// } + public Float getTopP() { + return topP; + } @Data @Accessors From f0e4e535f48ad30a0f74536f2d7eaa45c0412537 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 24 May 2024 14:27:08 +0800 Subject: [PATCH 317/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E5=A4=84=E7=90=86=20AI=20stream=20=E8=BF=94=E5=9B=9E=EF=BC=8C?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=20map?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/service/chat/AiChatMessageServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java index 3e4f60258..e5afe6444 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java @@ -136,7 +136,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { // 3.3 流式返回 // 注意:Schedulers.immediate() 目的是,避免默认 Schedulers.parallel() 并发消费 chunk 导致 SSE 响应前端会乱序问题 StringBuffer contentBuffer = new StringBuffer(); - return streamResponse.publishOn(Schedulers.single()).map(chunk -> { + return streamResponse.map(chunk -> { String newContent = chunk.getResult() != null ? chunk.getResult().getOutput().getContent() : null; newContent = StrUtil.nullToDefault(newContent, ""); // 避免 null 的 情况 contentBuffer.append(newContent); From 8f0c5998aad17f50faca1ae857616c98e1bc47f6 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 24 May 2024 14:49:05 +0800 Subject: [PATCH 318/684] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91Chat=20Stream=20=E5=A4=84=E7=90=86=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/iocoder/yudao/module/ai/ErrorCodeConstants.java | 1 + .../controller/admin/chat/AiChatMessageController.java | 2 +- .../module/ai/service/chat/AiChatMessageService.java | 3 ++- .../ai/service/chat/AiChatMessageServiceImpl.java | 10 ++++++++-- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index cd1985f81..ca0af92f4 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -32,6 +32,7 @@ public interface ErrorCodeConstants { // ========== API 聊天消息 1-040-004-000 ========== ErrorCode AI_CHAT_MESSAGE_NOT_EXIST = new ErrorCode(1_040_004_000, "消息不存在!"); + ErrorCode AI_CHAT_STREAM_ERROR = new ErrorCode(1_040_004_001, "Stream 对话异常!"); // midjourney diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java index 2522d0dc0..8a2dba003 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java @@ -58,7 +58,7 @@ public class AiChatMessageController { @Operation(summary = "发送消息(流式)", description = "流式返回,响应较快") @PostMapping(value = "/send-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) @PermitAll // 解决 SSE 最终响应的时候,会被 Access Denied 拦截的问题 - public Flux sendChatMessageStream(@Validated @RequestBody AiChatMessageSendReqVO sendReqVO) { + public Flux> sendChatMessageStream(@Validated @RequestBody AiChatMessageSendReqVO sendReqVO) { return chatMessageService.sendChatMessageStream(sendReqVO, getLoginUserId()); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java index e9dc43ec9..fcf97a73f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.ai.service.chat; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.*; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import reactor.core.publisher.Flux; @@ -28,7 +29,7 @@ public interface AiChatMessageService { * @param userId 用户编号 * @return 发送结果 */ - Flux sendChatMessageStream(AiChatMessageSendReqVO sendReqVO, Long userId); + Flux> sendChatMessageStream(AiChatMessageSendReqVO sendReqVO, Long userId); /** * 获得指定会话的消息列表 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java index e5afe6444..edc11995d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java @@ -5,13 +5,17 @@ import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactory; +import cn.iocoder.yudao.framework.common.exception.ErrorCode; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import jakarta.annotation.Resource; +import org.reactivestreams.Publisher; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.StreamingChatClient; import org.springframework.ai.chat.messages.*; @@ -107,7 +111,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { } @Override - public Flux sendChatMessageStream(AiChatMessageSendReqVO sendReqVO, Long userId) { + public Flux> sendChatMessageStream(AiChatMessageSendReqVO sendReqVO, Long userId) { // 1.1 校验对话存在 AiChatConversationDO conversation = chatConversationService.validateExists(sendReqVO.getConversationId()); if (ObjUtil.notEqual(conversation.getUserId(), userId)) { @@ -145,12 +149,14 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { o -> o.setUserAvatar(user.getAvatar())); AiChatMessageSendRespVO.Message receive = BeanUtils.toBean(assistantMessage, AiChatMessageSendRespVO.Message.class, o -> o.setRoleAvatar(role != null ? role.getAvatar() : null)).setContent(newContent); - return new AiChatMessageSendRespVO().setSend(send).setReceive(receive); + return CommonResult.success(new AiChatMessageSendRespVO().setSend(send).setReceive(receive)); }).doOnComplete(() -> { chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString())); }).doOnError(throwable -> { log.error("[sendChatMessageStream][userId({}) sendReqVO({}) 发生异常]", userId, sendReqVO, throwable); chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(throwable.getMessage())); + }).onErrorResume( error -> { + return Flux.just(CommonResult.error(ErrorCodeConstants.AI_CHAT_STREAM_ERROR)); }); } From 5618313d65b342ff2ae413a970e3ad0f93501aa6 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 24 May 2024 15:05:00 +0800 Subject: [PATCH 319/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E5=A4=84=E7=90=86=20build=20xing=20huo=20key=20size=20?= =?UTF-8?q?=E5=88=A4=E6=96=AD=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ai/core/factory/AiClientFactoryImpl.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java index b005d7c3e..50d714960 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java @@ -20,6 +20,7 @@ import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoApi; import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatClient; import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatOptions; import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanApi; +import com.google.cloud.vertexai.VertexAI; import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration; import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; import org.springframework.ai.chat.StreamingChatClient; @@ -31,6 +32,8 @@ import org.springframework.ai.openai.OpenAiChatClient; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.api.ApiUtils; import org.springframework.ai.openai.api.OpenAiApi; +import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatClient; +import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatOptions; import java.util.List; @@ -57,6 +60,8 @@ public class AiClientFactoryImpl implements AiClientFactory { return buildXingHuoChatClient(apiKey); case QIAN_WEN: return buildQianWenChatClient(apiKey); + case GEMIR: + return buildGoogleGemir(apiKey); default: throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); } @@ -148,7 +153,7 @@ public class AiClientFactoryImpl implements AiClientFactory { */ private static XingHuoChatClient buildXingHuoChatClient(String key) { List keys = StrUtil.split(key, '|'); - Assert.equals(keys.size(), 2, "XingHuoChatClient 的密钥需要 (appKey|secretKey) 格式"); + Assert.equals(keys.size(), 3, "XingHuoChatClient 的密钥需要 (appid|appKey|secretKey) 格式"); String appId = keys.get(0); String appKey = keys.get(1); String secretKey = keys.get(2); From 10ca7a93ac660b03a13ac2a04bfe58bbfa1bc9d4 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 24 May 2024 15:06:36 +0800 Subject: [PATCH 320/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20google=20gemini?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml | 5 +++++ .../yudao/framework/ai/core/enums/AiPlatformEnum.java | 1 + .../ai/core/factory/AiClientFactoryImpl.java | 11 +++++++++++ 3 files changed, 17 insertions(+) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml index 9a19270db..e7a4cf245 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml @@ -22,6 +22,11 @@ spring-ai-openai-spring-boot-starter 1.0.3 + + io.springboot.ai + spring-ai-vertex-ai-gemini + 1.0.3 + cn.iocoder.boot diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java index fc41069a9..cd7012298 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java @@ -21,6 +21,7 @@ public enum AiPlatformEnum { OPEN_AI_DALL("dall", "dall"), MIDJOURNEY("midjourney", "midjourney"), + GEMIR ("gemir ", "gemir "), // google gemir ; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java index 50d714960..0f83a99ee 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java @@ -169,4 +169,15 @@ public class AiClientFactoryImpl implements AiClientFactory { return new QianWenChatClient(qianWenApi); } + + private static VertexAiGeminiChatClient buildGoogleGemir(String key) { + List keys = StrUtil.split(key, '|'); + Assert.equals(keys.size(), 2, "VertexAiGeminiChatClient 的密钥需要 (projectId|location) 格式"); + VertexAI vertexApi = new VertexAI(keys.get(0), keys.get(1)); + return new VertexAiGeminiChatClient(vertexApi, + VertexAiGeminiChatOptions.builder() + .withTemperature(0.4F) + .build()); + } + } From 48c3210f5f0a2e95b006b609d0880deb93dc8eff Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 24 May 2024 15:38:56 +0800 Subject: [PATCH 321/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E6=96=B0=E5=BB=BA=E5=AF=B9=E8=AF=9D=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E4=B8=8D=E4=BD=BF=E7=94=A8=E9=BB=98=E8=AE=A4=E8=A7=92=E8=89=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/dal/mysql/AiChatRoleMapper.java | 8 -------- .../chat/AiChatConversationServiceImpl.java | 17 +++++++++-------- .../service/chat/AiChatMessageServiceImpl.java | 4 +++- .../ai/service/model/AiChatRoleService.java | 9 --------- .../ai/service/model/AiChatRoleServiceImpl.java | 10 ---------- 5 files changed, 12 insertions(+), 36 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java index c2a9631dc..42a3cb195 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java @@ -20,14 +20,6 @@ import java.util.List; @Mapper public interface AiChatRoleMapper extends BaseMapperX { - default AiChatRoleDO selectFirstByPublicStatusAndStatus(Boolean publicStatus, Integer status) { - return selectOne(new QueryWrapperX() - .eq("status", status) - .eq("public_status", publicStatus) - .limitN(1) - .orderByAsc("sort")); - } - default PageResult selectPage(AiChatRolePageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() .likeIfPresent(AiChatRoleDO::getName, reqVO.getName()) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java index 1e3bd52ce..3a3b16aea 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java @@ -46,21 +46,22 @@ public class AiChatConversationServiceImpl implements AiChatConversationService @Override public Long createChatConversationMy(AiChatConversationCreateMyReqVO createReqVO, Long userId) { // 1.1 获得 AiChatRoleDO 聊天角色 - AiChatRoleDO role = createReqVO.getRoleId() != null ? chatRoleService.validateChatRole(createReqVO.getRoleId()) - : chatRoleService.getRequiredDefaultChatRole(); - Assert.notNull(role, "必须找到聊天角色"); + AiChatRoleDO role = createReqVO.getRoleId() != null ? chatRoleService.validateChatRole(createReqVO.getRoleId()) : null; // 1.2 获得 AiChatModelDO 聊天模型 - AiChatModelDO model = role.getModelId() != null ? chatModalService.validateChatModel(role.getModelId()) + AiChatModelDO model = role != null && role.getModelId() != null ? chatModalService.validateChatModel(role.getModelId()) : chatModalService.getRequiredDefaultChatModel(); Assert.notNull(model, "必须找到默认模型"); validateChatModel(model); // 2. 创建 AiChatConversationDO 聊天对话 - String title = createReqVO.getRoleId() == null ? AiChatConversationDO.TITLE_DEFAULT : role.getName(); - AiChatConversationDO conversation = new AiChatConversationDO() - .setUserId(userId).setTitle(title).setPinned(false) - .setRoleId(role.getId()).setModelId(model.getId()).setModel(model.getModel()).setSystemMessage(role.getSystemMessage()) + AiChatConversationDO conversation = new AiChatConversationDO().setUserId(userId).setPinned(false) + .setModelId(model.getId()).setModel(model.getModel()) .setTemperature(model.getTemperature()).setMaxTokens(model.getMaxTokens()).setMaxContexts(model.getMaxContexts()); + if (role != null) { + conversation.setTitle(role.getName()).setRoleId(role.getId()).setSystemMessage(role.getSystemMessage()); + } else { + conversation.setTitle(AiChatConversationDO.TITLE_DEFAULT); + } chatConversationMapper.insert(conversation); return conversation.getId(); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java index edc11995d..a6861243a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java @@ -165,7 +165,9 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { // 1. 构建 Prompt Message 列表 List chatMessages = new ArrayList<>(); // 1.1 system context 角色设定 - chatMessages.add(new SystemMessage(conversation.getSystemMessage())); + if (StrUtil.isNotBlank(conversation.getSystemMessage())) { + chatMessages.add(new SystemMessage(conversation.getSystemMessage())); + } // 1.2 history message 历史消息 List contextMessages = filterContextMessages(messages, conversation, sendReqVO); contextMessages.forEach(message -> chatMessages.add(new ChatMessage(message.getType().toUpperCase(), message.getContent()))); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java index a7bc2501a..a602d6537 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java @@ -94,15 +94,6 @@ public interface AiChatRoleService { */ AiChatRoleDO validateChatRole(Long id); - /** - * 获得默认的聊天角色 - * - * 如果获取不到,则抛出 {@link cn.iocoder.yudao.framework.common.exception.ServiceException} 业务异常 - * - * @return 聊天角色 - */ - AiChatRoleDO getRequiredDefaultChatRole(); - /** * 获得聊天角色分页 * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java index d3083ec9f..8313e12a1 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java @@ -121,16 +121,6 @@ public class AiChatRoleServiceImpl implements AiChatRoleService { return chatRole; } - @Override - public AiChatRoleDO getRequiredDefaultChatRole() { - AiChatRoleDO chatRole = chatRoleMapper.selectFirstByPublicStatusAndStatus( - true, CommonStatusEnum.ENABLE.getStatus()); - if (chatRole == null) { - throw exception(CHAT_ROLE_DEFAULT_NOT_EXISTS); - } - return chatRole; - } - @Override public PageResult getChatRolePage(AiChatRolePageReqVO pageReqVO) { return chatRoleMapper.selectPage(pageReqVO); From 546b522c4884b1f1574eee2ae4d331a1d96520ee Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 24 May 2024 16:10:23 +0800 Subject: [PATCH 322/684] =?UTF-8?q?=E3=80=90=E6=B7=BB=E5=8A=A0todo?= =?UTF-8?q?=E3=80=91google=20gemini=20=E5=88=9D=E5=A7=8B=E5=8C=96=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/core/factory/AiClientFactoryImpl.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java index 0f83a99ee..b60435968 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java @@ -20,9 +20,12 @@ import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoApi; import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatClient; import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatOptions; import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanApi; +import com.google.auth.oauth2.GoogleCredentials; import com.google.cloud.vertexai.VertexAI; import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration; import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; +import org.springframework.ai.autoconfigure.vertexai.gemini.VertexAiGeminiConnectionProperties; +import org.springframework.ai.autoconfigure.vertexai.palm2.VertexAiPalm2ConnectionProperties; import org.springframework.ai.chat.StreamingChatClient; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.ollama.OllamaChatClient; @@ -35,6 +38,7 @@ import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatClient; import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatOptions; +import java.io.IOException; import java.util.List; /** @@ -169,15 +173,23 @@ public class AiClientFactoryImpl implements AiClientFactory { return new QianWenChatClient(qianWenApi); } - private static VertexAiGeminiChatClient buildGoogleGemir(String key) { List keys = StrUtil.split(key, '|'); Assert.equals(keys.size(), 2, "VertexAiGeminiChatClient 的密钥需要 (projectId|location) 格式"); - VertexAI vertexApi = new VertexAI(keys.get(0), keys.get(1)); +// VertexAiGeminiConnectionProperties connectionProperties = new VertexAiGeminiConnectionProperties(); +// connectionProperties.setApiKey("AIzaSyBpe376HTA8uPKJN_OJTh7MEO3v6LMqfXU"); +// +// GoogleCredentials credentials = GoogleCredentials.fromStream(connectionProperties.getCredentialsUri().getInputStream()); + // todo @芋艿 google gemini 没找到对于初始化 client 方式,文档中说是用过 GoogleCredentials 来初始化凭证 + // api-key: AIzaSyBpe376HTA8uPKJN_OJTh7MEO3v6LMqfXU + VertexAI vertexApi = new VertexAI( + "skilled-snow-409401", + "us-central1" + ); return new VertexAiGeminiChatClient(vertexApi, VertexAiGeminiChatOptions.builder() .withTemperature(0.4F) + .withModel(VertexAiGeminiChatClient.ChatModel.GEMINI_PRO.getValue()) .build()); } - } From 17afb14c88432a2a12fcf7513dd938068d9ab86d Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 24 May 2024 16:39:47 +0800 Subject: [PATCH 323/684] =?UTF-8?q?=E3=80=90=E6=B3=A8=E9=87=8Agoogle=20gam?= =?UTF-8?q?i=E3=80=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao-spring-boot-starter-ai/pom.xml | 10 ++-- .../ai/core/factory/AiClientFactoryImpl.java | 49 ++++++++----------- 2 files changed, 26 insertions(+), 33 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml index e7a4cf245..85f5fa63d 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml @@ -22,11 +22,11 @@ spring-ai-openai-spring-boot-starter 1.0.3 - - io.springboot.ai - spring-ai-vertex-ai-gemini - 1.0.3 - + + + + + cn.iocoder.boot diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java index b60435968..44a76dd49 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java @@ -20,12 +20,8 @@ import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoApi; import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatClient; import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatOptions; import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanApi; -import com.google.auth.oauth2.GoogleCredentials; -import com.google.cloud.vertexai.VertexAI; import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration; import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; -import org.springframework.ai.autoconfigure.vertexai.gemini.VertexAiGeminiConnectionProperties; -import org.springframework.ai.autoconfigure.vertexai.palm2.VertexAiPalm2ConnectionProperties; import org.springframework.ai.chat.StreamingChatClient; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.ollama.OllamaChatClient; @@ -35,10 +31,7 @@ import org.springframework.ai.openai.OpenAiChatClient; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.api.ApiUtils; import org.springframework.ai.openai.api.OpenAiApi; -import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatClient; -import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatOptions; -import java.io.IOException; import java.util.List; /** @@ -64,8 +57,8 @@ public class AiClientFactoryImpl implements AiClientFactory { return buildXingHuoChatClient(apiKey); case QIAN_WEN: return buildQianWenChatClient(apiKey); - case GEMIR: - return buildGoogleGemir(apiKey); +// case GEMIR: +// return buildGoogleGemir(apiKey); default: throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); } @@ -172,24 +165,24 @@ public class AiClientFactoryImpl implements AiClientFactory { QianWenApi qianWenApi = new QianWenApi(key, QianWenChatModal.QWEN_72B_CHAT); return new QianWenChatClient(qianWenApi); } - - private static VertexAiGeminiChatClient buildGoogleGemir(String key) { - List keys = StrUtil.split(key, '|'); - Assert.equals(keys.size(), 2, "VertexAiGeminiChatClient 的密钥需要 (projectId|location) 格式"); -// VertexAiGeminiConnectionProperties connectionProperties = new VertexAiGeminiConnectionProperties(); -// connectionProperties.setApiKey("AIzaSyBpe376HTA8uPKJN_OJTh7MEO3v6LMqfXU"); // -// GoogleCredentials credentials = GoogleCredentials.fromStream(connectionProperties.getCredentialsUri().getInputStream()); - // todo @芋艿 google gemini 没找到对于初始化 client 方式,文档中说是用过 GoogleCredentials 来初始化凭证 - // api-key: AIzaSyBpe376HTA8uPKJN_OJTh7MEO3v6LMqfXU - VertexAI vertexApi = new VertexAI( - "skilled-snow-409401", - "us-central1" - ); - return new VertexAiGeminiChatClient(vertexApi, - VertexAiGeminiChatOptions.builder() - .withTemperature(0.4F) - .withModel(VertexAiGeminiChatClient.ChatModel.GEMINI_PRO.getValue()) - .build()); - } +// private static VertexAiGeminiChatClient buildGoogleGemir(String key) { +// List keys = StrUtil.split(key, '|'); +// Assert.equals(keys.size(), 2, "VertexAiGeminiChatClient 的密钥需要 (projectId|location) 格式"); +//// VertexAiGeminiConnectionProperties connectionProperties = new VertexAiGeminiConnectionProperties(); +//// connectionProperties.setApiKey("AIzaSyBpe376HTA8uPKJN_OJTh7MEO3v6LMqfXU"); +//// +//// GoogleCredentials credentials = GoogleCredentials.fromStream(connectionProperties.getCredentialsUri().getInputStream()); +// // todo @芋艿 google gemini 没找到对于初始化 client 方式,文档中说是用过 GoogleCredentials 来初始化凭证 +// // api-key: AIzaSyBpe376HTA8uPKJN_OJTh7MEO3v6LMqfXU +// VertexAI vertexApi = new VertexAI( +// "skilled-snow-409401", +// "us-central1" +// ); +// return new VertexAiGeminiChatClient(vertexApi, +// VertexAiGeminiChatOptions.builder() +// .withTemperature(0.4F) +// .withModel(VertexAiGeminiChatClient.ChatModel.GEMINI_PRO.getValue()) +// .build()); +// } } From 4fddec5f0217b3aa4895f136a2066134942a3b10 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 24 May 2024 20:56:21 +0800 Subject: [PATCH 324/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E8=B0=83=E6=95=B4=20image=20=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E7=9A=84=E5=8C=85=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/chat/AiChatMessageController.java | 2 +- .../admin/image/AiImageController.java | 2 +- .../admin/model/AiChatModelController.java | 3 +- .../dal/mysql/{ => image}/AiImageMapper.java | 3 +- .../mysql/{ => model}/AiChatModelMapper.java | 14 ++------ .../mysql/{ => model}/AiChatRoleMapper.java | 2 +- .../ai/service/chat/AiChatMessageService.java | 2 +- .../chat/AiChatMessageServiceImpl.java | 12 ++++--- .../service/{ => image}/AiImageService.java | 2 +- .../{impl => image}/AiImageServiceImpl.java | 5 ++- .../YuDaoMidjourneyMessageHandler.java | 4 +-- .../AiChatModelConfigTypeHandler.java | 0 .../vo/AiChatModalChatConfigVO.java | 2 +- .../vo/AiChatModalConfigVO.java | 2 +- .../vo/AiChatModalDallConfigVO.java | 2 +- .../vo/AiChatModalMidjourneyConfigVO.java | 2 +- .../ai/service/model/AiChatModelService.java | 11 +++--- .../service/model/AiChatModelServiceImpl.java | 11 +++--- .../service/model/AiChatRoleServiceImpl.java | 2 +- .../ai/core/factory/AiClientFactoryImpl.java | 36 ++++++++----------- .../core/model/tongyi/QianWenChatClient.java | 1 + 21 files changed, 52 insertions(+), 68 deletions(-) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/{ => image}/AiImageMapper.java (93%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/{ => model}/AiChatModelMapper.java (81%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/{ => model}/AiChatRoleMapper.java (97%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/{ => image}/AiImageService.java (95%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/{impl => image}/AiImageServiceImpl.java (98%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/{ => image}/midjourneyHandler/YuDaoMidjourneyMessageHandler.java (97%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{dal/vo => service/image/midjourneyHandler}/typeHandler/AiChatModelConfigTypeHandler.java (100%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{dal => service/image/midjourneyHandler}/vo/AiChatModalChatConfigVO.java (91%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{dal => service/image/midjourneyHandler}/vo/AiChatModalConfigVO.java (90%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{dal => service/image/midjourneyHandler}/vo/AiChatModalDallConfigVO.java (96%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/{dal => service/image/midjourneyHandler}/vo/AiChatModalMidjourneyConfigVO.java (78%) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java index 8a2dba003..7211f0664 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java @@ -89,7 +89,7 @@ public class AiChatMessageController { @DeleteMapping("/delete") @Parameter(name = "id", required = true, description = "消息编号", example = "1024") public CommonResult deleteChatMessage(@RequestParam("id") Long id) { - chatMessageService.deleteMessage(id, getLoginUserId()); + chatMessageService.deleteChatMessage(id, getLoginUserId()); return success(true); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index 7df2592f9..fd9ea0802 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.ai.controller.admin.image; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; -import cn.iocoder.yudao.module.ai.service.AiImageService; +import cn.iocoder.yudao.module.ai.service.image.AiImageService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java index 1b50be79d..08a53b286 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatModelController.java @@ -18,7 +18,6 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.List; -import java.util.function.Function; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @@ -77,7 +76,7 @@ public class AiChatModelController { @Operation(summary = "获得聊天模型列表") @Parameter(name = "status", description = "状态", required = true, example = "1") public CommonResult> getChatModelSimpleList(@RequestParam("status") Integer status) { - List list = chatModelService.getChatModelList(status); + List list = chatModelService.getChatModelListByStatus(status); return success(convertList(list, model -> new AiChatModelRespVO().setId(model.getId()) .setName(model.getName()).setModel(model.getModel()))); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiImageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java similarity index 93% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiImageMapper.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java index d353fea5a..9e75cb436 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiImageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.dal.mysql; +package cn.iocoder.yudao.module.ai.dal.mysql.image; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; @@ -26,4 +26,5 @@ public interface AiImageMapper extends BaseMapperX { default void updateByMjNonce(Long mjNonceId, AiImageDO aiImageDO) { this.update(aiImageDO, new LambdaQueryWrapperX().eq(AiImageDO::getMjNonceId, mjNonceId)); } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiChatModelMapper.java similarity index 81% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiChatModelMapper.java index 25687d0e0..a3136fa9f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatModelMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiChatModelMapper.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.dal.mysql; +package cn.iocoder.yudao.module.ai.dal.mysql.model; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; @@ -26,17 +26,6 @@ public interface AiChatModelMapper extends BaseMapperX { .orderByAsc("sort")); } - // TODO 芋艿:不需要哈 - /** - * 查询 - 根据 ids - * - * @param modalIds - * @return - */ - default List selectByIds(Collection modalIds) { - return this.selectList(new LambdaQueryWrapperX().eq(AiChatModelDO::getId, modalIds)); - } - default PageResult selectPage(AiChatModelPageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() .likeIfPresent(AiChatModelDO::getName, reqVO.getName()) @@ -50,4 +39,5 @@ public interface AiChatModelMapper extends BaseMapperX { .eq(AiChatModelDO::getStatus, status) .orderByAsc(AiChatModelDO::getSort)); } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiChatRoleMapper.java similarity index 97% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiChatRoleMapper.java index 42a3cb195..1ddef8345 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/AiChatRoleMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiChatRoleMapper.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.dal.mysql; +package cn.iocoder.yudao.module.ai.dal.mysql.model; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java index fcf97a73f..d7f3e8078 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java @@ -45,7 +45,7 @@ public interface AiChatMessageService { * @param id 消息编号 * @param userId 用户编号 */ - void deleteMessage(Long id, Long userId); + void deleteChatMessage(Long id, Long userId); /** * 删除指定会话的消息 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java index a6861243a..8da9110ba 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java @@ -40,6 +40,8 @@ import java.time.LocalDateTime; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.AI_CHAT_MESSAGE_NOT_EXIST; import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_CONVERSATION_NOT_EXISTS; @@ -138,7 +140,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { Flux streamResponse = chatClient.stream(prompt); // 3.3 流式返回 - // 注意:Schedulers.immediate() 目的是,避免默认 Schedulers.parallel() 并发消费 chunk 导致 SSE 响应前端会乱序问题 + // TODO 注意:Schedulers.immediate() 目的是,避免默认 Schedulers.parallel() 并发消费 chunk 导致 SSE 响应前端会乱序问题 StringBuffer contentBuffer = new StringBuffer(); return streamResponse.map(chunk -> { String newContent = chunk.getResult() != null ? chunk.getResult().getOutput().getContent() : null; @@ -149,14 +151,14 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { o -> o.setUserAvatar(user.getAvatar())); AiChatMessageSendRespVO.Message receive = BeanUtils.toBean(assistantMessage, AiChatMessageSendRespVO.Message.class, o -> o.setRoleAvatar(role != null ? role.getAvatar() : null)).setContent(newContent); - return CommonResult.success(new AiChatMessageSendRespVO().setSend(send).setReceive(receive)); + return success(new AiChatMessageSendRespVO().setSend(send).setReceive(receive)); }).doOnComplete(() -> { chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString())); }).doOnError(throwable -> { log.error("[sendChatMessageStream][userId({}) sendReqVO({}) 发生异常]", userId, sendReqVO, throwable); chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(throwable.getMessage())); - }).onErrorResume( error -> { - return Flux.just(CommonResult.error(ErrorCodeConstants.AI_CHAT_STREAM_ERROR)); + }).onErrorResume(error -> { + return Flux.just(error(ErrorCodeConstants.AI_CHAT_STREAM_ERROR)); }); } @@ -235,7 +237,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { } @Override - public void deleteMessage(Long id, Long userId) { + public void deleteChatMessage(Long id, Long userId) { // 1. 校验消息存在 AiChatMessageDO message = chatMessageMapper.selectById(id); if (message == null || ObjUtil.notEqual(message.getUserId(), userId)) { diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java similarity index 95% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java index b58201056..836f37dfb 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.service; +package cn.iocoder.yudao.module.ai.service.image; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java similarity index 98% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index 20768c21e..f4521af84 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.service.impl; +package cn.iocoder.yudao.module.ai.service.image; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; @@ -21,9 +21,8 @@ import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; import cn.iocoder.yudao.module.ai.convert.AiImageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; -import cn.iocoder.yudao.module.ai.dal.mysql.AiImageMapper; +import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper; import cn.iocoder.yudao.module.ai.enums.AiImageDrawingStatusEnum; -import cn.iocoder.yudao.module.ai.service.AiImageService; import jakarta.annotation.PostConstruct; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/YuDaoMidjourneyMessageHandler.java similarity index 97% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/YuDaoMidjourneyMessageHandler.java index c3c9d44d0..5327d65ff 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/midjourneyHandler/YuDaoMidjourneyMessageHandler.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/YuDaoMidjourneyMessageHandler.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.service.midjourneyHandler; +package cn.iocoder.yudao.module.ai.service.image.midjourneyHandler; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; @@ -10,7 +10,7 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyOperationsVO; import cn.iocoder.yudao.module.ai.convert.AiImageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; -import cn.iocoder.yudao.module.ai.dal.mysql.AiImageMapper; +import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper; import cn.iocoder.yudao.module.ai.enums.AiImageDrawingStatusEnum; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/typeHandler/AiChatModelConfigTypeHandler.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/typeHandler/AiChatModelConfigTypeHandler.java similarity index 100% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/typeHandler/AiChatModelConfigTypeHandler.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/typeHandler/AiChatModelConfigTypeHandler.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalChatConfigVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalChatConfigVO.java similarity index 91% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalChatConfigVO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalChatConfigVO.java index 79cce7ad4..c3d2b77cc 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalChatConfigVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalChatConfigVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.dal.vo; +package cn.iocoder.yudao.module.ai.service.image.midjourneyHandler.vo; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalConfigVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalConfigVO.java similarity index 90% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalConfigVO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalConfigVO.java index 4ed060e22..426641a0d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalConfigVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalConfigVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.dal.vo; +package cn.iocoder.yudao.module.ai.service.image.midjourneyHandler.vo; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import lombok.Data; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalDallConfigVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalDallConfigVO.java similarity index 96% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalDallConfigVO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalDallConfigVO.java index c828c9cf5..f07b44647 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalDallConfigVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalDallConfigVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.dal.vo; +package cn.iocoder.yudao.module.ai.service.image.midjourneyHandler.vo; import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageStyleEnum; import lombok.Data; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalMidjourneyConfigVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalMidjourneyConfigVO.java similarity index 78% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalMidjourneyConfigVO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalMidjourneyConfigVO.java index 543c58705..6c91ca652 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/vo/AiChatModalMidjourneyConfigVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalMidjourneyConfigVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.dal.vo; +package cn.iocoder.yudao.module.ai.service.image.midjourneyHandler.vo; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelService.java index 08f0110fe..f83ac73c9 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelService.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatMode import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import jakarta.validation.Valid; +import java.util.Collection; import java.util.List; import java.util.Set; @@ -79,13 +80,13 @@ public interface AiChatModelService { * @param status 状态 * @return 聊天模型列表 */ - List getChatModelList(Integer status); + List getChatModelListByStatus(Integer status); /** - * 获取 - 根据多个 ids 获取 + * 获得聊天模型列表 * - * @param modalIds - * @return + * @param ids 编号数组 + * @return 模型列表 */ - List getModalByIds(Set modalIds); + List getChatModelList(Collection ids); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java index 59298f9fe..31d048c70 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java @@ -7,15 +7,14 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelPageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatModel.AiChatModelSaveReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; -import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModelMapper; +import cn.iocoder.yudao.module.ai.dal.mysql.model.AiChatModelMapper; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import java.util.Collection; import java.util.List; -import java.util.Set; - import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.*; @@ -103,13 +102,13 @@ public class AiChatModelServiceImpl implements AiChatModelService { } @Override - public List getChatModelList(Integer status) { + public List getChatModelListByStatus(Integer status) { return chatModelMapper.selectList(status); } @Override - public List getModalByIds(Set modalIds) { - return chatModelMapper.selectByIds(modalIds); + public List getChatModelList(Collection ids) { + return chatModelMapper.selectBatchIds(ids); } } \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java index 8313e12a1..faee09d06 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java @@ -10,7 +10,7 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleP import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveMyReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.dal.mysql.AiChatRoleMapper; +import cn.iocoder.yudao.module.ai.dal.mysql.model.AiChatRoleMapper; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java index 44a76dd49..ba496adb0 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java @@ -20,6 +20,7 @@ import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoApi; import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatClient; import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatOptions; import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanApi; +import com.google.cloud.vertexai.VertexAI; import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration; import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; import org.springframework.ai.chat.StreamingChatClient; @@ -31,6 +32,8 @@ import org.springframework.ai.openai.OpenAiChatClient; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.api.ApiUtils; import org.springframework.ai.openai.api.OpenAiApi; +import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatClient; +import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatOptions; import java.util.List; @@ -57,8 +60,8 @@ public class AiClientFactoryImpl implements AiClientFactory { return buildXingHuoChatClient(apiKey); case QIAN_WEN: return buildQianWenChatClient(apiKey); -// case GEMIR: -// return buildGoogleGemir(apiKey); + case GEMIR: + return buildGoogleGemir(apiKey); default: throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); } @@ -165,24 +168,13 @@ public class AiClientFactoryImpl implements AiClientFactory { QianWenApi qianWenApi = new QianWenApi(key, QianWenChatModal.QWEN_72B_CHAT); return new QianWenChatClient(qianWenApi); } -// -// private static VertexAiGeminiChatClient buildGoogleGemir(String key) { -// List keys = StrUtil.split(key, '|'); -// Assert.equals(keys.size(), 2, "VertexAiGeminiChatClient 的密钥需要 (projectId|location) 格式"); -//// VertexAiGeminiConnectionProperties connectionProperties = new VertexAiGeminiConnectionProperties(); -//// connectionProperties.setApiKey("AIzaSyBpe376HTA8uPKJN_OJTh7MEO3v6LMqfXU"); -//// -//// GoogleCredentials credentials = GoogleCredentials.fromStream(connectionProperties.getCredentialsUri().getInputStream()); -// // todo @芋艿 google gemini 没找到对于初始化 client 方式,文档中说是用过 GoogleCredentials 来初始化凭证 -// // api-key: AIzaSyBpe376HTA8uPKJN_OJTh7MEO3v6LMqfXU -// VertexAI vertexApi = new VertexAI( -// "skilled-snow-409401", -// "us-central1" -// ); -// return new VertexAiGeminiChatClient(vertexApi, -// VertexAiGeminiChatOptions.builder() -// .withTemperature(0.4F) -// .withModel(VertexAiGeminiChatClient.ChatModel.GEMINI_PRO.getValue()) -// .build()); -// } + + + private static VertexAiGeminiChatClient buildGoogleGemir(String key) { + List keys = StrUtil.split(key, '|'); + Assert.equals(keys.size(), 2, "VertexAiGeminiChatClient 的密钥需要 (projectId|location) 格式"); + VertexAI vertexApi = new VertexAI(keys.get(0), keys.get(1)); + return new VertexAiGeminiChatClient(vertexApi); + } + } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatClient.java index 63f3af776..02a25cef4 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatClient.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.ai.core.model.tongyi; +import cn.hutool.core.util.NumberUtil; import cn.iocoder.yudao.framework.ai.core.exception.ChatException; import cn.iocoder.yudao.framework.ai.core.model.tongyi.api.QianWenApi; import org.springframework.ai.chat.*; From 2d11f085c8a1d65d3e7af6e1f196acc3936d1ac8 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 25 May 2024 00:08:27 +0800 Subject: [PATCH 325/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E5=AF=B9=E8=AF=9D=E7=AE=A1=E7=90=86=2050%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/AiChatConversationController.java | 50 ++++++++++++++----- .../admin/chat/AiChatMessageController.java | 12 +++-- .../AiChatConversationCreateMyReqVO.java | 2 +- .../AiChatConversationPageReqVO.java | 26 ++++++++++ .../AiChatConversationRespVO.java | 24 ++++++--- .../AiChatConversationUpdateMyReqVO.java | 8 +-- .../chat/vo/message/AiChatMessageRespVO.java | 2 +- .../dataobject/chat/AiChatConversationDO.java | 6 +-- .../dal/dataobject/chat/AiChatMessageDO.java | 2 +- .../dal/dataobject/model/AiChatModelDO.java | 2 +- .../mysql/chat/AiChatConversationMapper.java | 16 ++++++ .../dal/mysql/chat/AiChatMessageMapper.java | 22 ++++++++ .../chat/AiChatConversationService.java | 33 ++++++------ .../chat/AiChatConversationServiceImpl.java | 29 +++++++---- .../ai/service/chat/AiChatMessageService.java | 18 +++++-- .../chat/AiChatMessageServiceImpl.java | 12 +++-- 16 files changed, 196 insertions(+), 68 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationPageReqVO.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java index 9d0cd74c8..ad57460ca 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java @@ -1,27 +1,35 @@ package cn.iocoder.yudao.module.ai.controller.admin.chat; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateMyReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateMyReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService; +import cn.iocoder.yudao.module.ai.service.chat.AiChatMessageService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.List; +import java.util.Map; +import java.util.function.Consumer; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -@Tag(name = "管理后台 - AI 聊天会话") +@Tag(name = "管理后台 - AI 聊天对话") @RestController @RequestMapping("/ai/chat/conversation") @Validated @@ -29,30 +37,32 @@ public class AiChatConversationController { @Resource private AiChatConversationService chatConversationService; + @Resource + private AiChatMessageService chatMessageService; @PostMapping("/create-my") - @Operation(summary = "创建【我的】聊天会话") + @Operation(summary = "创建【我的】聊天对话") public CommonResult createChatConversationMy(@RequestBody @Valid AiChatConversationCreateMyReqVO createReqVO) { return success(chatConversationService.createChatConversationMy(createReqVO, getLoginUserId())); } @PutMapping("/update-my") - @Operation(summary = "更新【我的】聊天会话") + @Operation(summary = "更新【我的】聊天对话") public CommonResult updateChatConversationMy(@RequestBody @Valid AiChatConversationUpdateMyReqVO updateReqVO) { chatConversationService.updateChatConversationMy(updateReqVO, getLoginUserId()); return success(true); } @GetMapping("/my-list") - @Operation(summary = "获得【我的】聊天会话列表") + @Operation(summary = "获得【我的】聊天对话列表") public CommonResult> getChatConversationMyList() { List list = chatConversationService.getChatConversationListByUserId(getLoginUserId()); return success(BeanUtils.toBean(list, AiChatConversationRespVO.class)); } @GetMapping("/get-my") - @Operation(summary = "获得【我的】聊天会话") - @Parameter(name = "id", required = true, description = "会话编号", example = "1024") + @Operation(summary = "获得【我的】聊天对话") + @Parameter(name = "id", required = true, description = "对话编号", example = "1024") public CommonResult getChatConversationMy(@RequestParam("id") Long id) { AiChatConversationDO conversation = chatConversationService.getChatConversation(id); if (conversation != null && ObjUtil.notEqual(conversation.getUserId(), getLoginUserId())) { @@ -62,20 +72,36 @@ public class AiChatConversationController { } @DeleteMapping("/delete-my") - @Operation(summary = "删除聊天会话") - @Parameter(name = "id", required = true, description = "会话编号", example = "1024") + @Operation(summary = "删除聊天对话") + @Parameter(name = "id", required = true, description = "对话编号", example = "1024") public CommonResult deleteChatConversationMy(@RequestParam("id") Long id) { chatConversationService.deleteChatConversationMy(id, getLoginUserId()); return success(true); } + // TODO 芋艿:这个 url 可以改下 @DeleteMapping("/delete-my-all-except-pinned") @Operation(summary = "删除所有对话(置顶除外)") - @Parameter(name = "id", required = true, description = "会话编号", example = "1024") - public CommonResult deleteMyAllExceptPinned() { - chatConversationService.deleteMyAllExceptPinned(getLoginUserId()); + public CommonResult deleteChatConversationMyByUnpinned() { + chatConversationService.deleteChatConversationMyByUnpinned(getLoginUserId()); return success(true); } - // ========== 会话管理 ========== + + // ========== 对话管理 ========== + + @GetMapping("/page") + @Operation(summary = "获得对话分页", description = "用于【对话管理】菜单") + @PreAuthorize("@ss.hasPermission('ai:chat-conversation:query')") + public CommonResult> getChatConversationPage(AiChatConversationPageReqVO pageReqVO) { + PageResult pageResult = chatConversationService.getChatConversationPage(pageReqVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty()); + } + // 拼接关联数据 + Map messageCountMap = chatMessageService.getChatMessageCountMap( + convertList(pageResult.getList(), AiChatConversationDO::getId)); + return success(BeanUtils.toBean(pageResult, AiChatConversationRespVO.class, + conversation -> conversation.setMessageCount(messageCountMap.getOrDefault(conversation.getId(), 0)))); + } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java index 7211f0664..68559c776 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java @@ -62,9 +62,9 @@ public class AiChatMessageController { return chatMessageService.sendChatMessageStream(sendReqVO, getLoginUserId()); } - @Operation(summary = "获得指定会话的消息列表") + @Operation(summary = "获得指定对话的消息列表") @GetMapping("/list-by-conversation-id") - @Parameter(name = "conversationId", required = true, description = "会话编号", example = "1024") + @Parameter(name = "conversationId", required = true, description = "对话编号", example = "1024") public CommonResult> getChatMessageListByConversationId( @RequestParam("conversationId") Long conversationId) { AiChatConversationDO conversation = chatConversationService.getChatConversation(conversationId); @@ -93,12 +93,16 @@ public class AiChatMessageController { return success(true); } - @Operation(summary = "删除指定会话的消息") + @Operation(summary = "删除指定对话的消息") @DeleteMapping("/delete-by-conversation-id") - @Parameter(name = "conversationId", required = true, description = "会话编号", example = "1024") + @Parameter(name = "conversationId", required = true, description = "对话编号", example = "1024") public CommonResult deleteChatMessageByConversationId(@RequestParam("conversationId") Long conversationId) { chatMessageService.deleteChatMessageByConversationId(conversationId, getLoginUserId()); return success(true); } + // ========== 对话管理 ========== + + + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateMyReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateMyReqVO.java index d64ea7f61..c13200b6a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateMyReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateMyReqVO.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -@Schema(description = "管理后台 - AI 聊天会话创建【我的】 Request VO") +@Schema(description = "管理后台 - AI 聊天对话创建【我的】 Request VO") @Data public class AiChatConversationCreateMyReqVO { diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationPageReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationPageReqVO.java new file mode 100644 index 000000000..967e866ea --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationPageReqVO.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - AI 聊天对话的分页 Request VO") +@Data +public class AiChatConversationPageReqVO extends PageParam { + + @Schema(description = "用户编号", example = "1024") + private Long userId; + + @Schema(description = "对话标题", example = "你好") + private String title; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java index e670ef9f9..66eb24db5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java @@ -10,24 +10,24 @@ import lombok.Data; import java.time.LocalDateTime; -@Schema(description = "管理后台 - AI 聊天会话 Response VO") +@Schema(description = "管理后台 - AI 聊天对话 Response VO") @Data public class AiChatConversationRespVO implements VO { - @Schema(description = "会话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @Schema(description = "对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Long id; @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") private Long userId; - @Schema(description = "会话标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是一个标题") + @Schema(description = "对话标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是一个标题") private String title; @Schema(description = "是否置顶", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") private Boolean pinned; - @Schema(description = "角色编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1") - @Trans(type = TransType.SIMPLE, target = AiChatRoleDO.class, fields = "avatar", ref = "roleAvatar") + @Schema(description = "角色编号", example = "1") + @Trans(type = TransType.SIMPLE, target = AiChatRoleDO.class, fields = {"name", "avatar"}, refs = {"roleName", "roleAvatar"}) private Long roleId; @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @@ -52,12 +52,20 @@ public class AiChatConversationRespVO implements VO { @Schema(description = "上下文的最大 Message 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") private Integer maxContexts; - @Schema(description = "最后更新时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime updateTime; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; // ========== 关联 role 信息 ========== - @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @Schema(description = "角色头像", example = "https://www.iocoder.cn/1.png") private String roleAvatar; + @Schema(description = "角色名字", example = "小黄") + private String roleName; + + // ========== 仅在【对话管理】时加载 ========== + + @Schema(description = "消息数量", example = "20") + private Integer messageCount; + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateMyReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateMyReqVO.java index 36e95d298..f9ce64bae 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateMyReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateMyReqVO.java @@ -4,15 +4,15 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; -@Schema(description = "管理后台 - AI 聊天会话更新【我的】 Request VO") +@Schema(description = "管理后台 - AI 聊天对话更新【我的】 Request VO") @Data public class AiChatConversationUpdateMyReqVO { - @Schema(description = "会话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "会话编号不能为空") + @Schema(description = "对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "对话编号不能为空") private Long id; - @Schema(description = "会话标题", example = "我是一个标题") + @Schema(description = "对话标题", example = "我是一个标题") private String title; @Schema(description = "是否置顶", example = "true") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java index e4e878e40..2cb0f9c5c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java @@ -12,7 +12,7 @@ public class AiChatMessageRespVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Long id; - @Schema(description = "会话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") + @Schema(description = "对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") private Long conversationId; @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "role") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java index b92e66143..8e582f621 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java @@ -13,7 +13,7 @@ import java.time.LocalDateTime; import java.util.Date; /** - * AI Chat 会话 DO + * AI Chat 对话 DO * * 用户每次发起 Chat 聊天时,会创建一个 {@link AiChatConversationDO} 对象,将它的消息关联在一起 * @@ -45,7 +45,7 @@ public class AiChatConversationDO extends BaseDO { private Long userId; /** - * 会话标题 + * 对话标题 * * 默认由系统自动生成,可用户手动修改 */ @@ -79,7 +79,7 @@ public class AiChatConversationDO extends BaseDO { */ private String model; - // ========== 会话配置 ========== + // ========== 对话配置 ========== /** * 角色设定 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java index 1c915ed7c..455a428a7 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java @@ -32,7 +32,7 @@ public class AiChatMessageDO extends BaseDO { private Long id; /** - * 会话编号 + * 对话编号 * * 关联 {@link AiChatConversationDO#getId()} 字段 */ diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModelDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModelDO.java index c943f7ea6..7197f8b58 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModelDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatModelDO.java @@ -62,7 +62,7 @@ public class AiChatModelDO extends BaseDO { */ private Integer status; - // ========== 会话配置 ========== + // ========== 对话配置 ========== /** * 温度参数 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java index dd4901bdf..6400297d8 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java @@ -1,7 +1,9 @@ package cn.iocoder.yudao.module.ai.dal.mysql.chat; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import org.apache.ibatis.annotations.Mapper; @@ -22,4 +24,18 @@ public interface AiChatConversationMapper extends BaseMapperX selectListByUserIdAndPinned(Long userId, boolean pinned) { + return selectList(new LambdaQueryWrapperX() + .eq(AiChatConversationDO::getUserId, userId) + .eq(AiChatConversationDO::getPinned, pinned)); + } + + default PageResult selectChatConversationPage(AiChatConversationPageReqVO pageReqVO) { + return selectPage(pageReqVO, new LambdaQueryWrapperX() + .eqIfPresent(AiChatConversationDO::getUserId, pageReqVO.getUserId()) + .likeIfPresent(AiChatConversationDO::getTitle, pageReqVO.getTitle()) + .betweenIfPresent(AiChatConversationDO::getCreateTime, pageReqVO.getCreateTime()) + .orderByDesc(AiChatConversationDO::getId)); + } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatMessageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatMessageMapper.java index 7b3e9c493..76db130be 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatMessageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatMessageMapper.java @@ -1,11 +1,18 @@ package cn.iocoder.yudao.module.ai.dal.mysql.chat; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.map.MapUtil; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.apache.ibatis.annotations.Mapper; +import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.Map; /** * AI 聊天对话 Mapper @@ -21,4 +28,19 @@ public interface AiChatMessageMapper extends BaseMapperX { .orderByAsc(AiChatMessageDO::getId)); } + default Map selectCountMapByConversationId(Collection conversationIds) { + // SQL count 查询 + List> result = selectMaps(new QueryWrapper() + .select("COUNT(id) AS count, conversation_id AS conversationId") + .in("conversation_id", conversationIds) + .groupBy("conversation_id")); + if (CollUtil.isEmpty(result)) { + return Collections.emptyMap(); + } + // 转换数据 + return CollectionUtils.convertMap(result, + record -> MapUtil.getLong(record, "conversationId"), + record -> MapUtil.getInt(record, "count" )); + } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java index f93572e66..42678a2f9 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.ai.service.chat; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateMyReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateMyReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; @@ -14,7 +16,7 @@ import java.util.List; public interface AiChatConversationService { /** - * 创建【我的】聊天会话 + * 创建【我的】聊天对话 * * @param createReqVO 创建信息 * @param userId 用户编号 @@ -23,7 +25,7 @@ public interface AiChatConversationService { Long createChatConversationMy(AiChatConversationCreateMyReqVO createReqVO, Long userId); /** - * 更新【我的】聊天会话 + * 更新【我的】聊天对话 * * @param updateReqVO 更新信息 * @param userId 用户编号 @@ -31,23 +33,23 @@ public interface AiChatConversationService { void updateChatConversationMy(AiChatConversationUpdateMyReqVO updateReqVO, Long userId); /** - * 获得【我的】聊天会话列表 + * 获得【我的】聊天对话列表 * * @param userId 用户编号 - * @return 聊天会话列表 + * @return 聊天对话列表 */ List getChatConversationListByUserId(Long userId); /** - * 获得聊天会话 + * 获得聊天对话 * * @param id 编号 - * @return 聊天会话 + * @return 聊天对话 */ AiChatConversationDO getChatConversation(Long id); /** - * 删除【我的】聊天会话 + * 删除【我的】聊天对话 * * @param id 编号 * @param userId 用户编号 @@ -55,17 +57,20 @@ public interface AiChatConversationService { void deleteChatConversationMy(Long id, Long userId); /** - * 校验 - 是否存在 + * 校验聊天对话是否存在 * - * @param id - * @return + * @param id 编号 + * @return 聊天对话 */ - AiChatConversationDO validateExists(Long id); + AiChatConversationDO validateChatConversationExists(Long id); /** - * 删除 - 所有对话,置顶除外 + * 删除【我的】 + 非置顶的聊天对话 * - * @param loginUserId + * @param userId 用户编号 */ - void deleteMyAllExceptPinned(Long loginUserId); + void deleteChatConversationMyByUnpinned(Long userId); + + PageResult getChatConversationPage(AiChatConversationPageReqVO pageReqVO); + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java index 3a3b16aea..41417fbcd 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java @@ -1,11 +1,13 @@ package cn.iocoder.yudao.module.ai.service.chat; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateMyReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateMyReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; @@ -22,6 +24,8 @@ import java.time.LocalDateTime; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_CONVERSATION_MODEL_ERROR; import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_CONVERSATION_NOT_EXISTS; @@ -69,7 +73,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService @Override public void updateChatConversationMy(AiChatConversationUpdateMyReqVO updateReqVO, Long userId) { // 1.1 校验对话是否存在 - AiChatConversationDO conversation = validateExists(updateReqVO.getId()); + AiChatConversationDO conversation = validateChatConversationExists(updateReqVO.getId()); if (ObjUtil.notEqual(conversation.getUserId(), userId)) { throw exception(CHAT_CONVERSATION_NOT_EXISTS); } @@ -103,7 +107,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService @Override public void deleteChatConversationMy(Long id, Long userId) { // 1. 校验对话是否存在 - AiChatConversationDO conversation = validateExists(id); + AiChatConversationDO conversation = validateChatConversationExists(id); if (ObjUtil.notEqual(conversation.getUserId(), userId)) { throw exception(CHAT_CONVERSATION_NOT_EXISTS); } @@ -119,7 +123,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService throw exception(CHAT_CONVERSATION_MODEL_ERROR); } - public AiChatConversationDO validateExists(Long id) { + public AiChatConversationDO validateChatConversationExists(Long id) { AiChatConversationDO conversation = chatConversationMapper.selectById(id); if (conversation == null) { throw exception(CHAT_CONVERSATION_NOT_EXISTS); @@ -128,12 +132,17 @@ public class AiChatConversationServiceImpl implements AiChatConversationService } @Override - public void deleteMyAllExceptPinned(Long loginUserId) { - chatConversationMapper.delete( - new LambdaQueryWrapperX() - .eq(AiChatConversationDO::getUserId, loginUserId) - .eq(AiChatConversationDO::getPinned, false) - ); + public void deleteChatConversationMyByUnpinned(Long userId) { + List list = chatConversationMapper.selectListByUserIdAndPinned(userId, false); + if (CollUtil.isEmpty(list)) { + return; + } + chatConversationMapper.deleteBatchIds(convertList(list, AiChatConversationDO::getId)); + } + + @Override + public PageResult getChatConversationPage(AiChatConversationPageReqVO pageReqVO) { + return chatConversationMapper.selectChatConversationPage(pageReqVO); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java index d7f3e8078..329e2cb1b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java @@ -5,7 +5,9 @@ import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.*; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import reactor.core.publisher.Flux; +import java.util.Collection; import java.util.List; +import java.util.Map; /** * AI 聊天消息 Service 接口 @@ -32,9 +34,9 @@ public interface AiChatMessageService { Flux> sendChatMessageStream(AiChatMessageSendReqVO sendReqVO, Long userId); /** - * 获得指定会话的消息列表 + * 获得指定对话的消息列表 * - * @param conversationId 会话编号 + * @param conversationId 对话编号 * @return 消息列表 */ List getChatMessageListByConversationId(Long conversationId); @@ -48,11 +50,19 @@ public interface AiChatMessageService { void deleteChatMessage(Long id, Long userId); /** - * 删除指定会话的消息 + * 删除指定对话的消息 * - * @param conversationId 会话编号 + * @param conversationId 对话编号 * @param userId 用户编号 */ void deleteChatMessageByConversationId(Long conversationId, Long userId); + /** + * 获得聊天对话的消息数量 Map + * + * @param conversationIds 对话编号数组 + * @return 消息数量 Map + */ + Map getChatMessageCountMap(Collection conversationIds); + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java index 8da9110ba..55ae7a7a3 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java @@ -5,7 +5,6 @@ import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactory; -import cn.iocoder.yudao.framework.common.exception.ErrorCode; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; @@ -15,7 +14,6 @@ import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import jakarta.annotation.Resource; -import org.reactivestreams.Publisher; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.StreamingChatClient; import org.springframework.ai.chat.messages.*; @@ -34,7 +32,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import reactor.core.publisher.Flux; -import reactor.core.scheduler.Schedulers; import java.time.LocalDateTime; import java.util.*; @@ -115,7 +112,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { @Override public Flux> sendChatMessageStream(AiChatMessageSendReqVO sendReqVO, Long userId) { // 1.1 校验对话存在 - AiChatConversationDO conversation = chatConversationService.validateExists(sendReqVO.getConversationId()); + AiChatConversationDO conversation = chatConversationService.validateChatConversationExists(sendReqVO.getConversationId()); if (ObjUtil.notEqual(conversation.getUserId(), userId)) { throw exception(CHAT_CONVERSATION_NOT_EXISTS); // TODO 芋艿:异常情况的对接; } @@ -189,7 +186,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { * n 组:指的是 user + assistant 形成一组 * * @param messages 消息列表 - * @param conversation 会话 + * @param conversation 对话 * @param sendReqVO 发送请求 * @return 消息上下文 */ @@ -258,4 +255,9 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { chatMessageMapper.deleteBatchIds(convertList(messages, AiChatMessageDO::getId)); } + @Override + public Map getChatMessageCountMap(Collection conversationIds) { + return chatMessageMapper.selectCountMapByConversationId(conversationIds); + } + } From 12b82b72e33e8ba00c7ef75d79c80953dec2ee45 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 25 May 2024 09:00:04 +0800 Subject: [PATCH 326/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E5=AF=B9=E8=AF=9D=E7=AE=A1=E7=90=86=20100%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/AiChatConversationController.java | 9 ++++++ .../admin/chat/AiChatMessageController.java | 27 +++++++++++++++++ .../vo/message/AiChatMessagePageReqVO.java | 29 +++++++++++++++++++ .../chat/vo/message/AiChatMessageRespVO.java | 14 +++++++-- .../dal/mysql/chat/AiChatMessageMapper.java | 13 +++++++++ .../chat/AiChatConversationService.java | 14 +++++++++ .../chat/AiChatConversationServiceImpl.java | 13 +++++++-- .../ai/service/chat/AiChatMessageService.java | 17 +++++++++++ .../chat/AiChatMessageServiceImpl.java | 19 ++++++++++++ 9 files changed, 151 insertions(+), 4 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessagePageReqVO.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java index ad57460ca..ed22acf69 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java @@ -104,4 +104,13 @@ public class AiChatConversationController { conversation -> conversation.setMessageCount(messageCountMap.getOrDefault(conversation.getId(), 0)))); } + @Operation(summary = "管理员删除对话") + @DeleteMapping("/delete-by-admin") + @Parameter(name = "id", required = true, description = "对话编号", example = "1024") + @PreAuthorize("@ss.hasPermission('ai:chat-conversation:delete')") + public CommonResult deleteChatConversationByAdmin(@RequestParam("id") Long id) { + chatConversationService.deleteChatConversationByAdmin(id); + return success(true); + } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java index 68559c776..dccc3bfa3 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java @@ -3,8 +3,11 @@ package cn.iocoder.yudao.module.ai.controller.admin.chat; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.*; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; @@ -21,6 +24,7 @@ import jakarta.annotation.Resource; import jakarta.annotation.security.PermitAll; import lombok.extern.slf4j.Slf4j; import org.springframework.http.MediaType; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Flux; @@ -30,6 +34,7 @@ import java.util.List; import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -103,6 +108,28 @@ public class AiChatMessageController { // ========== 对话管理 ========== + @GetMapping("/page") + @Operation(summary = "获得消息分页", description = "用于【对话管理】菜单") + @PreAuthorize("@ss.hasPermission('ai:chat-conversation:query')") + public CommonResult> getChatMessagePage(AiChatMessagePageReqVO pageReqVO) { + PageResult pageResult = chatMessageService.getChatMessagePage(pageReqVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty()); + } + // 拼接数据 + Map roleMap = chatRoleService.getChatRoleMap( + convertSet(pageResult.getList(), AiChatMessageDO::getRoleId)); + return success(BeanUtils.toBean(pageResult, AiChatMessageRespVO.class, + respVO -> MapUtils.findAndThen(roleMap, respVO.getRoleId(), role -> respVO.setRoleName(role.getName())))); + } + @Operation(summary = "管理员删除消息") + @DeleteMapping("/delete-by-admin") + @Parameter(name = "id", required = true, description = "消息编号", example = "1024") + @PreAuthorize("@ss.hasPermission('ai:chat-message:delete')") + public CommonResult deleteChatMessageByAdmin(@RequestParam("id") Long id) { + chatMessageService.deleteChatMessageByAdmin(id); + return success(true); + } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessagePageReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessagePageReqVO.java new file mode 100644 index 000000000..7ccb6aa0b --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessagePageReqVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - AI 聊天消息的分页 Request VO") +@Data +public class AiChatMessagePageReqVO extends PageParam { + + @Schema(description = "对话编号", example = "2048") + private Long conversationId; + + @Schema(description = "用户编号", example = "1024") + private Long userId; + + @Schema(description = "消息内容", example = "你好") + private String content; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java index 2cb0f9c5c..918609a53 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java @@ -15,6 +15,9 @@ public class AiChatMessageRespVO { @Schema(description = "对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") private Long conversationId; + @Schema(description = "回复消息编号", example = "1024") + private Long replyId; + @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "role") private String type; // 参见 MessageType 枚举类 @@ -33,14 +36,21 @@ public class AiChatMessageRespVO { @Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,你好啊") private String content; + @Schema(description = "是否携带上下文", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean useContext; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-05-12 12:51") private LocalDateTime createTime; - // ========= 扩展字段 + // ========== 仅在【对话管理】时加载 ========== @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://xxx") private String userAvatar; - @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://xxx") + @Schema(description = "角色名字", example = "小黄") + private String roleName; + + @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") private String roleAvatar; + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatMessageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatMessageMapper.java index 76db130be..5020f3944 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatMessageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatMessageMapper.java @@ -2,9 +2,13 @@ package cn.iocoder.yudao.module.ai.dal.mysql.chat; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.map.MapUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.apache.ibatis.annotations.Mapper; @@ -43,4 +47,13 @@ public interface AiChatMessageMapper extends BaseMapperX { record -> MapUtil.getInt(record, "count" )); } + default PageResult selectPage(AiChatMessagePageReqVO pageReqVO) { + return selectPage(pageReqVO, new LambdaQueryWrapperX() + .eqIfPresent(AiChatMessageDO::getConversationId, pageReqVO.getConversationId()) + .eqIfPresent(AiChatMessageDO::getUserId, pageReqVO.getUserId()) + .likeIfPresent(AiChatMessageDO::getContent, pageReqVO.getContent()) + .betweenIfPresent(AiChatMessageDO::getCreateTime, pageReqVO.getCreateTime()) + .orderByDesc(AiChatMessageDO::getId)); + } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java index 42678a2f9..bce6d435d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationService.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateMyReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateMyReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import java.util.List; @@ -56,6 +57,13 @@ public interface AiChatConversationService { */ void deleteChatConversationMy(Long id, Long userId); + /** + * 【管理员】删除聊天对话 + * + * @param id 编号 + */ + void deleteChatConversationByAdmin(Long id); + /** * 校验聊天对话是否存在 * @@ -71,6 +79,12 @@ public interface AiChatConversationService { */ void deleteChatConversationMyByUnpinned(Long userId); + /** + * 获得聊天对话的分页列表 + * + * @param pageReqVO 分页查询 + * @return 聊天对话的分页列表 + */ PageResult getChatConversationPage(AiChatConversationPageReqVO pageReqVO); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java index 41417fbcd..85349b760 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java @@ -25,7 +25,6 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_CONVERSATION_MODEL_ERROR; import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_CONVERSATION_NOT_EXISTS; @@ -108,10 +107,20 @@ public class AiChatConversationServiceImpl implements AiChatConversationService public void deleteChatConversationMy(Long id, Long userId) { // 1. 校验对话是否存在 AiChatConversationDO conversation = validateChatConversationExists(id); - if (ObjUtil.notEqual(conversation.getUserId(), userId)) { + if (conversation == null || ObjUtil.notEqual(conversation.getUserId(), userId)) { throw exception(CHAT_CONVERSATION_NOT_EXISTS); } + // 2. 执行删除 + chatConversationMapper.deleteById(id); + } + @Override + public void deleteChatConversationByAdmin(Long id) { + // 1. 校验对话是否存在 + AiChatConversationDO conversation = validateChatConversationExists(id); + if (conversation == null) { + throw exception(CHAT_CONVERSATION_NOT_EXISTS); + } // 2. 执行删除 chatConversationMapper.deleteById(id); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java index 329e2cb1b..a529a9716 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.ai.service.chat; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.*; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import reactor.core.publisher.Flux; @@ -57,6 +59,13 @@ public interface AiChatMessageService { */ void deleteChatMessageByConversationId(Long conversationId, Long userId); + /** + * 【管理员】删除消息 + * + * @param id 消息编号 + */ + void deleteChatMessageByAdmin(Long id); + /** * 获得聊天对话的消息数量 Map * @@ -65,4 +74,12 @@ public interface AiChatMessageService { */ Map getChatMessageCountMap(Collection conversationIds); + /** + * 获得聊天消息的分页 + * + * @param pageReqVO 分页查询 + * @return 聊天消息的分页 + */ + PageResult getChatMessagePage(AiChatMessagePageReqVO pageReqVO); + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java index 55ae7a7a3..5cd9ae94e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java @@ -6,8 +6,11 @@ import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactory; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; @@ -255,9 +258,25 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { chatMessageMapper.deleteBatchIds(convertList(messages, AiChatMessageDO::getId)); } + @Override + public void deleteChatMessageByAdmin(Long id) { + // 1. 校验消息存在 + AiChatMessageDO message = chatMessageMapper.selectById(id); + if (message == null) { + throw exception(AI_CHAT_MESSAGE_NOT_EXIST); + } + // 2. 执行删除 + chatMessageMapper.deleteById(id); + } + @Override public Map getChatMessageCountMap(Collection conversationIds) { return chatMessageMapper.selectCountMapByConversationId(conversationIds); } + @Override + public PageResult getChatMessagePage(AiChatMessagePageReqVO pageReqVO) { + return chatMessageMapper.selectPage(pageReqVO); + } + } From 17103201142db3317a73cfdad4f422a689cbeeb9 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 25 May 2024 11:51:05 +0800 Subject: [PATCH 327/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E5=AF=B9=E8=AF=9D=E7=9A=84=E5=A4=B4=E5=83=8F=E4=BA=A4?= =?UTF-8?q?=E7=BB=99=E5=89=8D=E7=AB=AF=E6=8B=BC=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/chat/AiChatMessageController.java | 25 +++----------- .../chat/vo/message/AiChatMessageRespVO.java | 6 ---- .../mysql/chat/AiChatConversationMapper.java | 5 +-- .../chat/AiChatMessageServiceImpl.java | 33 +++++++------------ 4 files changed, 17 insertions(+), 52 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java index dccc3bfa3..c0a116216 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java @@ -6,17 +6,16 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.*; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService; import cn.iocoder.yudao.module.ai.service.chat.AiChatMessageService; import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; -import cn.iocoder.yudao.module.system.api.user.AdminUserApi; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -34,7 +33,6 @@ import java.util.List; import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -51,9 +49,6 @@ public class AiChatMessageController { @Resource private AiChatRoleService chatRoleService; - @Resource - private AdminUserApi adminUserApi; - @Operation(summary = "发送消息(段式)", description = "一次性返回,响应较慢") @PostMapping("/send") public CommonResult sendMessage(@Validated @RequestBody AiChatMessageSendReqVO sendReqVO) { @@ -77,17 +72,7 @@ public class AiChatMessageController { return success(Collections.emptyList()); } List messageList = chatMessageService.getChatMessageListByConversationId(conversationId); - if (CollUtil.isEmpty(messageList)) { - return success(Collections.emptyList()); - } - - // 拼接数据 - Map roleMap = chatRoleService.getChatRoleMap(convertSet(messageList, AiChatMessageDO::getRoleId)); - AdminUserRespDTO user = adminUserApi.getUser(getLoginUserId()); - return success(BeanUtils.toBean(messageList, AiChatMessageRespVO.class, respVO -> { - MapUtils.findAndThen(roleMap, respVO.getRoleId(), role -> respVO.setRoleAvatar(role.getAvatar())); - respVO.setUserAvatar(user.getAvatar()); - })); + return success(BeanUtils.toBean(messageList, AiChatMessageRespVO.class)); } @Operation(summary = "删除消息") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java index 918609a53..1f7e33fc3 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java @@ -44,13 +44,7 @@ public class AiChatMessageRespVO { // ========== 仅在【对话管理】时加载 ========== - @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://xxx") - private String userAvatar; - @Schema(description = "角色名字", example = "小黄") private String roleName; - @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") - private String roleAvatar; - } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java index 6400297d8..ce9da2f24 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java @@ -17,11 +17,8 @@ import java.util.List; @Mapper public interface AiChatConversationMapper extends BaseMapperX { - // TODO @fan:建议这里不排序哈;交给他们前端排序 default List selectListByUserId(Long userId) { - return selectList(new LambdaQueryWrapperX() - .eq(AiChatConversationDO::getUserId, userId) - .orderByAsc(AiChatConversationDO::getCreateTime)); + return selectList(AiChatConversationDO::getUserId, userId); } default List selectListByUserIdAndPinned(Long userId, boolean pinned) { diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java index 5cd9ae94e..97984045d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java @@ -9,29 +9,25 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO; import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; +import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatMessageMapper; import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; -import cn.iocoder.yudao.module.system.api.user.AdminUserApi; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; +import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.StreamingChatClient; import org.springframework.ai.chat.messages.*; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.prompt.Prompt; -import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatMessageMapper; -import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; -import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; -import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import reactor.core.publisher.Flux; @@ -70,9 +66,6 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { @Resource private AiApiKeyService apiKeyService; - @Resource - private AdminUserApi adminUserApi; - @Transactional(rollbackFor = Exception.class) public AiChatMessageRespVO sendMessage(AiChatMessageSendReqVO req) { return null; // TODO 芋艿:一起改 @@ -124,7 +117,6 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { AiChatModelDO model = chatModalService.validateChatModel(conversation.getModelId()); StreamingChatClient chatClient = apiKeyService.getStreamingChatClient(model.getKeyId()); // 1.3 获取用户头像、角色头像 - AdminUserRespDTO user = adminUserApi.getUser(SecurityFrameworkUtils.getLoginUserId()); AiChatRoleDO role = conversation.getRoleId() != null ? chatRoleService.getChatRole(conversation.getRoleId()) : null; // 2. 插入 user 发送消息 @@ -147,11 +139,8 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { newContent = StrUtil.nullToDefault(newContent, ""); // 避免 null 的 情况 contentBuffer.append(newContent); // 响应结果 - AiChatMessageSendRespVO.Message send = BeanUtils.toBean(userMessage, AiChatMessageSendRespVO.Message.class, - o -> o.setUserAvatar(user.getAvatar())); - AiChatMessageSendRespVO.Message receive = BeanUtils.toBean(assistantMessage, AiChatMessageSendRespVO.Message.class, - o -> o.setRoleAvatar(role != null ? role.getAvatar() : null)).setContent(newContent); - return success(new AiChatMessageSendRespVO().setSend(send).setReceive(receive)); + return success(new AiChatMessageSendRespVO().setSend(BeanUtils.toBean(userMessage, AiChatMessageSendRespVO.Message.class)) + .setReceive(BeanUtils.toBean(assistantMessage, AiChatMessageSendRespVO.Message.class).setContent(newContent))); }).doOnComplete(() -> { chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString())); }).doOnError(throwable -> { From ca4ee3be1f0381e0bbbd3376be604852da76f29b Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 25 May 2024 13:31:07 +0800 Subject: [PATCH 328/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91AI?= =?UTF-8?q?=EF=BC=9AAI=20=E7=9B=B8=E5=85=B3=20SQL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- sql/mysql/ruoyi-vue-pro.sql | 392 +++--------------- .../chat/AiChatMessageServiceImpl.java | 1 + .../ai/core/enums/AiPlatformEnum.java | 9 +- yudao-server/pom.xml | 13 +- 5 files changed, 75 insertions(+), 342 deletions(-) diff --git a/pom.xml b/pom.xml index 1606182b4..0623ce85c 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,6 @@ yudao-module-system yudao-module-infra - yudao-module-ai @@ -24,6 +23,7 @@ + yudao-module-ai ${project.artifactId} diff --git a/sql/mysql/ruoyi-vue-pro.sql b/sql/mysql/ruoyi-vue-pro.sql index a4f642547..48c8fb9ca 100644 --- a/sql/mysql/ruoyi-vue-pro.sql +++ b/sql/mysql/ruoyi-vue-pro.sql @@ -11,307 +11,12 @@ Target Server Version : 80200 (8.2.0) File Encoding : 65001 - Date: 30/04/2024 09:54:18 + Date: 25/05/2024 13:29:34 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; --- ---------------------------- --- Table structure for QRTZ_BLOB_TRIGGERS --- ---------------------------- -DROP TABLE IF EXISTS `QRTZ_BLOB_TRIGGERS`; -CREATE TABLE `QRTZ_BLOB_TRIGGERS` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `TRIGGER_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `TRIGGER_GROUP` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `BLOB_DATA` blob NULL, - PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, - INDEX `SCHED_NAME`(`SCHED_NAME` ASC, `TRIGGER_NAME` ASC, `TRIGGER_GROUP` ASC) USING BTREE, - CONSTRAINT `qrtz_blob_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; - --- ---------------------------- --- Records of QRTZ_BLOB_TRIGGERS --- ---------------------------- -BEGIN; -COMMIT; - --- ---------------------------- --- Table structure for QRTZ_CALENDARS --- ---------------------------- -DROP TABLE IF EXISTS `QRTZ_CALENDARS`; -CREATE TABLE `QRTZ_CALENDARS` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `CALENDAR_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `CALENDAR` blob NOT NULL, - PRIMARY KEY (`SCHED_NAME`, `CALENDAR_NAME`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; - --- ---------------------------- --- Records of QRTZ_CALENDARS --- ---------------------------- -BEGIN; -COMMIT; - --- ---------------------------- --- Table structure for QRTZ_CRON_TRIGGERS --- ---------------------------- -DROP TABLE IF EXISTS `QRTZ_CRON_TRIGGERS`; -CREATE TABLE `QRTZ_CRON_TRIGGERS` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `TRIGGER_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `TRIGGER_GROUP` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `CRON_EXPRESSION` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `TIME_ZONE_ID` varchar(80) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL, - PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, - CONSTRAINT `qrtz_cron_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; - --- ---------------------------- --- Records of QRTZ_CRON_TRIGGERS --- ---------------------------- -BEGIN; -INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'accessLogCleanJob', 'DEFAULT', '0 0 0 * * ?', 'Asia/Shanghai'); -INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'brokerageRecordUnfreezeJob', 'DEFAULT', '0 * * * * ?', 'Asia/Shanghai'); -INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'errorLogCleanJob', 'DEFAULT', '0 0 0 * * ?', 'Asia/Shanghai'); -INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'jobLogCleanJob', 'DEFAULT', '0 0 0 * * ?', 'Asia/Shanghai'); -INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', '* * * * * ?', 'Asia/Shanghai'); -INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'payOrderExpireJob', 'DEFAULT', '0 0/1 * * * ?', 'Asia/Shanghai'); -INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'payOrderSyncJob', 'DEFAULT', '0 0/1 * * * ?', 'Asia/Shanghai'); -INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'payRefundSyncJob', 'DEFAULT', '0 0/1 * * * ?', 'Asia/Shanghai'); -INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'tradeOrderAutoCancelJob', 'DEFAULT', '0 * * * * ?', 'Asia/Shanghai'); -INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'tradeOrderAutoCommentJob', 'DEFAULT', '0 * * * * ?', 'Asia/Shanghai'); -INSERT INTO `QRTZ_CRON_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `CRON_EXPRESSION`, `TIME_ZONE_ID`) VALUES ('schedulerName', 'tradeOrderAutoReceiveJob', 'DEFAULT', '0 * * * * ?', 'Asia/Shanghai'); -COMMIT; - --- ---------------------------- --- Table structure for QRTZ_FIRED_TRIGGERS --- ---------------------------- -DROP TABLE IF EXISTS `QRTZ_FIRED_TRIGGERS`; -CREATE TABLE `QRTZ_FIRED_TRIGGERS` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `ENTRY_ID` varchar(95) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `TRIGGER_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `TRIGGER_GROUP` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `INSTANCE_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `FIRED_TIME` bigint NOT NULL, - `SCHED_TIME` bigint NOT NULL, - `PRIORITY` int NOT NULL, - `STATE` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `JOB_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL, - `JOB_GROUP` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL, - `IS_NONCONCURRENT` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL, - `REQUESTS_RECOVERY` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL, - PRIMARY KEY (`SCHED_NAME`, `ENTRY_ID`) USING BTREE, - INDEX `IDX_QRTZ_FT_TRIG_INST_NAME`(`SCHED_NAME` ASC, `INSTANCE_NAME` ASC) USING BTREE, - INDEX `IDX_QRTZ_FT_INST_JOB_REQ_RCVRY`(`SCHED_NAME` ASC, `INSTANCE_NAME` ASC, `REQUESTS_RECOVERY` ASC) USING BTREE, - INDEX `IDX_QRTZ_FT_J_G`(`SCHED_NAME` ASC, `JOB_NAME` ASC, `JOB_GROUP` ASC) USING BTREE, - INDEX `IDX_QRTZ_FT_JG`(`SCHED_NAME` ASC, `JOB_GROUP` ASC) USING BTREE, - INDEX `IDX_QRTZ_FT_T_G`(`SCHED_NAME` ASC, `TRIGGER_NAME` ASC, `TRIGGER_GROUP` ASC) USING BTREE, - INDEX `IDX_QRTZ_FT_TG`(`SCHED_NAME` ASC, `TRIGGER_GROUP` ASC) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; - --- ---------------------------- --- Records of QRTZ_FIRED_TRIGGERS --- ---------------------------- -BEGIN; -COMMIT; - --- ---------------------------- --- Table structure for QRTZ_JOB_DETAILS --- ---------------------------- -DROP TABLE IF EXISTS `QRTZ_JOB_DETAILS`; -CREATE TABLE `QRTZ_JOB_DETAILS` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `JOB_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `JOB_GROUP` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `DESCRIPTION` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL, - `JOB_CLASS_NAME` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `IS_DURABLE` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `IS_NONCONCURRENT` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `IS_UPDATE_DATA` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `REQUESTS_RECOVERY` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `JOB_DATA` blob NULL, - PRIMARY KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) USING BTREE, - INDEX `IDX_QRTZ_J_REQ_RECOVERY`(`SCHED_NAME` ASC, `REQUESTS_RECOVERY` ASC) USING BTREE, - INDEX `IDX_QRTZ_J_GRP`(`SCHED_NAME` ASC, `JOB_GROUP` ASC) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; - --- ---------------------------- --- Records of QRTZ_JOB_DETAILS --- ---------------------------- -BEGIN; -INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'accessLogCleanJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000197400104A4F425F48414E444C45525F4E414D457400116163636573734C6F67436C65616E4A6F627800); -INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'brokerageRecordUnfreezeJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000187400104A4F425F48414E444C45525F4E414D4574001A62726F6B65726167655265636F7264556E667265657A654A6F627800); -INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'errorLogCleanJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B0200007870000000000000001A7400104A4F425F48414E444C45525F4E414D457400106572726F724C6F67436C65616E4A6F627800); -INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'jobLogCleanJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B0200007870000000000000001B7400104A4F425F48414E444C45525F4E414D4574000E6A6F624C6F67436C65616E4A6F627800); -INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000057400104A4F425F48414E444C45525F4E414D4574000C7061794E6F746966794A6F627800); -INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'payOrderExpireJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000127400104A4F425F48414E444C45525F4E414D457400117061794F726465724578706972654A6F627800); -INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'payOrderSyncJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000117400104A4F425F48414E444C45525F4E414D4574000F7061794F7264657253796E634A6F627800); -INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'payRefundSyncJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000137400104A4F425F48414E444C45525F4E414D45740010706179526566756E6453796E634A6F627800); -INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'tradeOrderAutoCancelJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000157400104A4F425F48414E444C45525F4E414D4574001774726164654F726465724175746F43616E63656C4A6F627800); -INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'tradeOrderAutoCommentJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000177400104A4F425F48414E444C45525F4E414D4574001874726164654F726465724175746F436F6D6D656E744A6F627800); -INSERT INTO `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `JOB_CLASS_NAME`, `IS_DURABLE`, `IS_NONCONCURRENT`, `IS_UPDATE_DATA`, `REQUESTS_RECOVERY`, `JOB_DATA`) VALUES ('schedulerName', 'tradeOrderAutoReceiveJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000167400104A4F425F48414E444C45525F4E414D4574001874726164654F726465724175746F526563656976654A6F627800); -COMMIT; - --- ---------------------------- --- Table structure for QRTZ_LOCKS --- ---------------------------- -DROP TABLE IF EXISTS `QRTZ_LOCKS`; -CREATE TABLE `QRTZ_LOCKS` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `LOCK_NAME` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - PRIMARY KEY (`SCHED_NAME`, `LOCK_NAME`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; - --- ---------------------------- --- Records of QRTZ_LOCKS --- ---------------------------- -BEGIN; -INSERT INTO `QRTZ_LOCKS` (`SCHED_NAME`, `LOCK_NAME`) VALUES ('schedulerName', 'STATE_ACCESS'); -INSERT INTO `QRTZ_LOCKS` (`SCHED_NAME`, `LOCK_NAME`) VALUES ('schedulerName', 'TRIGGER_ACCESS'); -COMMIT; - --- ---------------------------- --- Table structure for QRTZ_PAUSED_TRIGGER_GRPS --- ---------------------------- -DROP TABLE IF EXISTS `QRTZ_PAUSED_TRIGGER_GRPS`; -CREATE TABLE `QRTZ_PAUSED_TRIGGER_GRPS` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `TRIGGER_GROUP` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - PRIMARY KEY (`SCHED_NAME`, `TRIGGER_GROUP`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; - --- ---------------------------- --- Records of QRTZ_PAUSED_TRIGGER_GRPS --- ---------------------------- -BEGIN; -COMMIT; - --- ---------------------------- --- Table structure for QRTZ_SCHEDULER_STATE --- ---------------------------- -DROP TABLE IF EXISTS `QRTZ_SCHEDULER_STATE`; -CREATE TABLE `QRTZ_SCHEDULER_STATE` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `INSTANCE_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `LAST_CHECKIN_TIME` bigint NOT NULL, - `CHECKIN_INTERVAL` bigint NOT NULL, - PRIMARY KEY (`SCHED_NAME`, `INSTANCE_NAME`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; - --- ---------------------------- --- Records of QRTZ_SCHEDULER_STATE --- ---------------------------- -BEGIN; -INSERT INTO `QRTZ_SCHEDULER_STATE` (`SCHED_NAME`, `INSTANCE_NAME`, `LAST_CHECKIN_TIME`, `CHECKIN_INTERVAL`) VALUES ('schedulerName', 'MacBook-Pro.local1713489703551', 1713742509534, 15000); -COMMIT; - --- ---------------------------- --- Table structure for QRTZ_SIMPLE_TRIGGERS --- ---------------------------- -DROP TABLE IF EXISTS `QRTZ_SIMPLE_TRIGGERS`; -CREATE TABLE `QRTZ_SIMPLE_TRIGGERS` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `TRIGGER_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `TRIGGER_GROUP` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `REPEAT_COUNT` bigint NOT NULL, - `REPEAT_INTERVAL` bigint NOT NULL, - `TIMES_TRIGGERED` bigint NOT NULL, - PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, - CONSTRAINT `qrtz_simple_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; - --- ---------------------------- --- Records of QRTZ_SIMPLE_TRIGGERS --- ---------------------------- -BEGIN; -COMMIT; - --- ---------------------------- --- Table structure for QRTZ_SIMPROP_TRIGGERS --- ---------------------------- -DROP TABLE IF EXISTS `QRTZ_SIMPROP_TRIGGERS`; -CREATE TABLE `QRTZ_SIMPROP_TRIGGERS` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `TRIGGER_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `TRIGGER_GROUP` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `STR_PROP_1` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL, - `STR_PROP_2` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL, - `STR_PROP_3` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL, - `INT_PROP_1` int NULL DEFAULT NULL, - `INT_PROP_2` int NULL DEFAULT NULL, - `LONG_PROP_1` bigint NULL DEFAULT NULL, - `LONG_PROP_2` bigint NULL DEFAULT NULL, - `DEC_PROP_1` decimal(13, 4) NULL DEFAULT NULL, - `DEC_PROP_2` decimal(13, 4) NULL DEFAULT NULL, - `BOOL_PROP_1` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL, - `BOOL_PROP_2` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL, - PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, - CONSTRAINT `qrtz_simprop_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; - --- ---------------------------- --- Records of QRTZ_SIMPROP_TRIGGERS --- ---------------------------- -BEGIN; -COMMIT; - --- ---------------------------- --- Table structure for QRTZ_TRIGGERS --- ---------------------------- -DROP TABLE IF EXISTS `QRTZ_TRIGGERS`; -CREATE TABLE `QRTZ_TRIGGERS` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `TRIGGER_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `TRIGGER_GROUP` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `JOB_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `JOB_GROUP` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `DESCRIPTION` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL, - `NEXT_FIRE_TIME` bigint NULL DEFAULT NULL, - `PREV_FIRE_TIME` bigint NULL DEFAULT NULL, - `PRIORITY` int NULL DEFAULT NULL, - `TRIGGER_STATE` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `TRIGGER_TYPE` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `START_TIME` bigint NOT NULL, - `END_TIME` bigint NULL DEFAULT NULL, - `CALENDAR_NAME` varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL, - `MISFIRE_INSTR` smallint NULL DEFAULT NULL, - `JOB_DATA` blob NULL, - PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, - INDEX `IDX_QRTZ_T_J`(`SCHED_NAME` ASC, `JOB_NAME` ASC, `JOB_GROUP` ASC) USING BTREE, - INDEX `IDX_QRTZ_T_JG`(`SCHED_NAME` ASC, `JOB_GROUP` ASC) USING BTREE, - INDEX `IDX_QRTZ_T_C`(`SCHED_NAME` ASC, `CALENDAR_NAME` ASC) USING BTREE, - INDEX `IDX_QRTZ_T_G`(`SCHED_NAME` ASC, `TRIGGER_GROUP` ASC) USING BTREE, - INDEX `IDX_QRTZ_T_STATE`(`SCHED_NAME` ASC, `TRIGGER_STATE` ASC) USING BTREE, - INDEX `IDX_QRTZ_T_N_STATE`(`SCHED_NAME` ASC, `TRIGGER_NAME` ASC, `TRIGGER_GROUP` ASC, `TRIGGER_STATE` ASC) USING BTREE, - INDEX `IDX_QRTZ_T_N_G_STATE`(`SCHED_NAME` ASC, `TRIGGER_GROUP` ASC, `TRIGGER_STATE` ASC) USING BTREE, - INDEX `IDX_QRTZ_T_NEXT_FIRE_TIME`(`SCHED_NAME` ASC, `NEXT_FIRE_TIME` ASC) USING BTREE, - INDEX `IDX_QRTZ_T_NFT_ST`(`SCHED_NAME` ASC, `TRIGGER_STATE` ASC, `NEXT_FIRE_TIME` ASC) USING BTREE, - INDEX `IDX_QRTZ_T_NFT_MISFIRE`(`SCHED_NAME` ASC, `MISFIRE_INSTR` ASC, `NEXT_FIRE_TIME` ASC) USING BTREE, - INDEX `IDX_QRTZ_T_NFT_ST_MISFIRE`(`SCHED_NAME` ASC, `MISFIRE_INSTR` ASC, `NEXT_FIRE_TIME` ASC, `TRIGGER_STATE` ASC) USING BTREE, - INDEX `IDX_QRTZ_T_NFT_ST_MISFIRE_GRP`(`SCHED_NAME` ASC, `MISFIRE_INSTR` ASC, `NEXT_FIRE_TIME` ASC, `TRIGGER_GROUP` ASC, `TRIGGER_STATE` ASC) USING BTREE, - CONSTRAINT `qrtz_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) REFERENCES `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; - --- ---------------------------- --- Records of QRTZ_TRIGGERS --- ---------------------------- -BEGIN; -INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'accessLogCleanJob', 'DEFAULT', 'accessLogCleanJob', 'DEFAULT', NULL, 1696348800000, -1, 5, 'PAUSED', 'CRON', 1696301981000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D7400007400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E547371007E000A000000037800); -INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'brokerageRecordUnfreezeJob', 'DEFAULT', 'brokerageRecordUnfreezeJob', 'DEFAULT', NULL, 1695909720000, -1, 5, 'PAUSED', 'CRON', 1695909706000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D7400007400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E547371007E000A000000037800); -INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'errorLogCleanJob', 'DEFAULT', 'errorLogCleanJob', 'DEFAULT', NULL, 1696348800000, -1, 5, 'PAUSED', 'CRON', 1696302043000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D7400007400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E547371007E000A000000037800); -INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'jobLogCleanJob', 'DEFAULT', 'jobLogCleanJob', 'DEFAULT', NULL, 1696348800000, -1, 5, 'PAUSED', 'CRON', 1696302092000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D7400007400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E547371007E000A000000037800); -INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', 'payNotifyJob', 'DEFAULT', NULL, 1688907102000, 1688907101000, 5, 'PAUSED', 'CRON', 1635294882000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800); -INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'payOrderExpireJob', 'DEFAULT', 'payOrderExpireJob', 'DEFAULT', NULL, 1690011600000, -1, 5, 'PAUSED', 'CRON', 1690011553000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800); -INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'payOrderSyncJob', 'DEFAULT', 'payOrderSyncJob', 'DEFAULT', NULL, 1690011600000, 1690011540000, 5, 'PAUSED', 'CRON', 1690007785000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800); -INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'payRefundSyncJob', 'DEFAULT', 'payRefundSyncJob', 'DEFAULT', NULL, 1690117560000, 1690117500000, 5, 'PAUSED', 'CRON', 1690117424000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800); -INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'tradeOrderAutoCancelJob', 'DEFAULT', 'tradeOrderAutoCancelJob', 'DEFAULT', NULL, 1695727440000, 1695727380000, 5, 'PAUSED', 'CRON', 1695656605000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D7400007400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E547371007E000A000000037800); -INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'tradeOrderAutoCommentJob', 'DEFAULT', 'tradeOrderAutoCommentJob', 'DEFAULT', NULL, 1695783840000, 1695783780000, 5, 'PAUSED', 'CRON', 1695742709000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D7400007400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E547371007E000A000000037800); -INSERT INTO `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `JOB_NAME`, `JOB_GROUP`, `DESCRIPTION`, `NEXT_FIRE_TIME`, `PREV_FIRE_TIME`, `PRIORITY`, `TRIGGER_STATE`, `TRIGGER_TYPE`, `START_TIME`, `END_TIME`, `CALENDAR_NAME`, `MISFIRE_INSTR`, `JOB_DATA`) VALUES ('schedulerName', 'tradeOrderAutoReceiveJob', 'DEFAULT', 'tradeOrderAutoReceiveJob', 'DEFAULT', NULL, 1695742740000, 1695742680000, 5, 'PAUSED', 'CRON', 1695727433000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D7400007400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E547371007E000A000000037800); -COMMIT; - -- ---------------------------- -- Table structure for infra_api_access_log -- ---------------------------- @@ -344,7 +49,7 @@ CREATE TABLE `infra_api_access_log` ( `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_create_time`(`create_time` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 35934 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'API 访问日志表'; +) ENGINE = InnoDB AUTO_INCREMENT = 35940 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'API 访问日志表'; -- ---------------------------- -- Records of infra_api_access_log @@ -358,24 +63,24 @@ COMMIT; DROP TABLE IF EXISTS `infra_api_error_log`; CREATE TABLE `infra_api_error_log` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '编号', - `trace_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '链路追踪编号\n *\n * 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。', + `trace_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '链路追踪编号', `user_id` int NOT NULL DEFAULT 0 COMMENT '用户编号', `user_type` tinyint NOT NULL DEFAULT 0 COMMENT '用户类型', - `application_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '应用名\n *\n * 目前读取 spring.application.name', + `application_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '应用名', `request_method` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '请求方法名', `request_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '请求地址', `request_params` varchar(8000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '请求参数', `user_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户 IP', `user_agent` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '浏览器 UA', `exception_time` datetime NOT NULL COMMENT '异常发生时间', - `exception_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '异常名\n *\n * {@link Throwable#getClass()} 的类全名', - `exception_message` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异常导致的消息\n *\n * {@link cn.iocoder.common.framework.util.ExceptionUtil#getMessage(Throwable)}', - `exception_root_cause_message` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异常导致的根消息\n *\n * {@link cn.iocoder.common.framework.util.ExceptionUtil#getRootCauseMessage(Throwable)}', - `exception_stack_trace` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异常的栈轨迹\n *\n * {@link cn.iocoder.common.framework.util.ExceptionUtil#getServiceException(Exception)}', - `exception_class_name` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异常发生的类全名\n *\n * {@link StackTraceElement#getClassName()}', - `exception_file_name` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异常发生的类文件\n *\n * {@link StackTraceElement#getFileName()}', - `exception_method_name` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异常发生的方法名\n *\n * {@link StackTraceElement#getMethodName()}', - `exception_line_number` int NOT NULL COMMENT '异常发生的方法所在行\n *\n * {@link StackTraceElement#getLineNumber()}', + `exception_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '异常名', + `exception_message` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异常导致的消息', + `exception_root_cause_message` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异常导致的根消息', + `exception_stack_trace` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异常的栈轨迹', + `exception_class_name` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异常发生的类全名', + `exception_file_name` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异常发生的类文件', + `exception_method_name` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异常发生的方法名', + `exception_line_number` int NOT NULL COMMENT '异常发生的方法所在行', `process_status` tinyint NOT NULL COMMENT '处理状态', `process_time` datetime NULL DEFAULT NULL COMMENT '处理时间', `process_user_id` int NULL DEFAULT 0 COMMENT '处理用户编号', @@ -386,7 +91,7 @@ CREATE TABLE `infra_api_error_log` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 16530 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; +) ENGINE = InnoDB AUTO_INCREMENT = 17651 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; -- ---------------------------- -- Records of infra_api_error_log @@ -423,7 +128,7 @@ CREATE TABLE `infra_codegen_column` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 2305 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义'; +) ENGINE = InnoDB AUTO_INCREMENT = 2397 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义'; -- ---------------------------- -- Records of infra_codegen_column @@ -461,7 +166,7 @@ CREATE TABLE `infra_codegen_table` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 176 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义'; +) ENGINE = InnoDB AUTO_INCREMENT = 182 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义'; -- ---------------------------- -- Records of infra_codegen_table @@ -545,7 +250,7 @@ CREATE TABLE `infra_file` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1307 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1322 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; -- ---------------------------- -- Records of infra_file @@ -691,7 +396,7 @@ CREATE TABLE `system_dept` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 114 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '部门表'; +) ENGINE = InnoDB AUTO_INCREMENT = 115 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '部门表'; -- ---------------------------- -- Records of system_dept @@ -733,7 +438,7 @@ CREATE TABLE `system_dict_data` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1537 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1542 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表'; -- ---------------------------- -- Records of system_dict_data @@ -1104,6 +809,11 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1534, 1, '赢单', '1', 'crm_business_end_status_type', 0, 'success', '', '', '1', '2024-04-13 23:26:57', '1', '2024-04-13 23:26:57', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1535, 2, '输单', '2', 'crm_business_end_status_type', 0, 'primary', '', '', '1', '2024-04-13 23:27:31', '1', '2024-04-13 23:27:31', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1536, 3, '无效', '3', 'crm_business_end_status_type', 0, 'info', '', '', '1', '2024-04-13 23:27:59', '1', '2024-04-13 23:27:59', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1537, 1, 'OpenAI', 'OpenAI', 'ai_platform', 0, '', '', '', '1', '2024-05-09 22:33:47', '1', '2024-05-09 22:58:46', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1538, 2, 'Ollama', 'Ollama', 'ai_platform', 0, '', '', '', '1', '2024-05-17 23:02:55', '1', '2024-05-17 23:02:55', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1539, 3, '文心一言', 'YiYan', 'ai_platform', 0, '', '', '', '1', '2024-05-18 09:24:20', '1', '2024-05-18 09:29:01', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1540, 4, '讯飞星火', 'XingHuo', 'ai_platform', 0, '', '', '', '1', '2024-05-18 10:08:56', '1', '2024-05-18 10:08:56', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1541, 5, '通义千问', 'QianWen', 'ai_platform', 0, '', '', '', '1', '2024-05-18 10:32:29', '1', '2024-05-25 13:18:31', b'0'); COMMIT; -- ---------------------------- @@ -1122,9 +832,8 @@ CREATE TABLE `system_dict_type` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `deleted_time` datetime NULL DEFAULT NULL COMMENT '删除时间', - PRIMARY KEY (`id`) USING BTREE, - UNIQUE INDEX `dict_type`(`type` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 620 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表'; + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 621 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表'; -- ---------------------------- -- Records of system_dict_type @@ -1213,6 +922,7 @@ INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creat INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (615, 'BPM 监听器值类型', 'bpm_process_listener_value_type', 0, '', '1', '2024-03-23 13:00:31', '1', '2024-03-23 13:00:31', b'0', '1970-01-01 00:00:00'); INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (616, '时间间隔', 'date_interval', 0, '', '1', '2024-03-29 22:50:09', '1', '2024-03-29 22:50:09', b'0', '1970-01-01 00:00:00'); INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (619, 'CRM 商机结束状态类型', 'crm_business_end_status_type', 0, '', '1', '2024-04-13 23:23:00', '1', '2024-04-13 23:23:00', b'0', '1970-01-01 00:00:00'); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (620, 'AI 模型平台', 'ai_platform', 0, '', '1', '2024-05-09 22:27:38', '1', '2024-05-09 22:27:38', b'0', '1970-01-01 00:00:00'); COMMIT; -- ---------------------------- @@ -1236,7 +946,7 @@ CREATE TABLE `system_login_log` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 3104 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; +) ENGINE = InnoDB AUTO_INCREMENT = 3152 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; -- ---------------------------- -- Records of system_login_log @@ -1367,7 +1077,7 @@ CREATE TABLE `system_menu` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 2758 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表'; +) ENGINE = InnoDB AUTO_INCREMENT = 2783 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表'; -- ---------------------------- -- Records of system_menu @@ -1377,7 +1087,7 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, '基础设施', '', 1, 20, 0, '/infra', 'ep:monitor', NULL, NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-03-01 08:28:40', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5, 'OA 示例', '', 1, 40, 1185, 'oa', 'fa:road', NULL, NULL, 0, b'1', b'1', b'1', 'admin', '2021-09-20 16:26:19', '1', '2024-02-29 12:38:13', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (100, '用户管理', 'system:user:list', 2, 1, 1, 'user', 'ep:avatar', 'system/user/index', 'SystemUser', 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:02:04', b'0'); -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (101, '角色管理', '', 2, 2, 1, 'role', 'ep:user', 'system/role/index', 'SystemRole', 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:03:28', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (101, '角色管理', '', 2, 2, 1, 'role', 'ep:user', 'system/role/index', 'SystemRole', 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-05-01 18:35:29', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (102, '菜单管理', '', 2, 3, 1, 'menu', 'ep:menu', 'system/menu/index', 'SystemMenu', 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:03:50', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (103, '部门管理', '', 2, 4, 1, 'dept', 'fa:address-card', 'system/dept/index', 'SystemDept', 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:06:28', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (104, '岗位管理', '', 2, 5, 1, 'post', 'fa:address-book-o', 'system/post/index', 'SystemPost', 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:06:39', b'0'); @@ -1902,7 +1612,7 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2445, '装修页面更新', 'promotion:diy-page:update', 3, 3, 2442, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 14:19:26', '', '2023-10-29 14:19:26', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2446, '装修页面删除', 'promotion:diy-page:delete', 3, 4, 2442, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 14:19:26', '', '2023-10-29 14:19:26', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2447, '三方登录', '', 1, 10, 1, 'social', 'fa:rocket', '', '', 0, b'1', b'1', b'1', '1', '2023-11-04 12:12:01', '1', '2024-02-29 01:14:05', b'0'); -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2448, '三方应用', '', 2, 1, 2447, 'client', 'ep:set-up', 'views/system/social/client/index.vue', 'SocialClient', 0, b'1', b'1', b'1', '1', '2023-11-04 12:17:19', '1', '2023-11-04 12:17:19', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2448, '三方应用', '', 2, 1, 2447, 'client', 'ep:set-up', 'system/social/client/index.vue', 'SocialClient', 0, b'1', b'1', b'1', '1', '2023-11-04 12:17:19', '1', '2024-05-04 19:09:54', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2449, '三方应用查询', 'system:social-client:query', 3, 1, 2448, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-11-04 12:43:12', '1', '2023-11-04 12:43:33', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2450, '三方应用创建', 'system:social-client:create', 3, 2, 2448, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-11-04 12:43:58', '1', '2023-11-04 12:43:58', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2451, '三方应用更新', 'system:social-client:update', 3, 3, 2448, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-11-04 12:44:27', '1', '2023-11-04 12:44:27', b'0'); @@ -2118,7 +1828,7 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2709, '客户公海配置查询', 'crm:customer-pool-config:query', 3, 2, 2516, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-02-24 16:45:19', '1', '2024-02-24 16:45:28', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2710, '合同配置更新', 'crm:contract-config:update', 3, 1, 2708, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-02-24 16:45:56', '1', '2024-02-24 16:45:56', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2711, '合同配置查询', 'crm:contract-config:query', 3, 2, 2708, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-02-24 16:46:16', '1', '2024-02-24 16:46:16', b'0'); -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2712, '客户分析', 'crm:statistics-customer:query', 2, 0, 2560, 'customer', 'ep:avatar', 'views/crm/statistics/customer/index.vue', 'CrmStatisticsCustomer', 0, b'1', b'1', b'1', '1', '2024-03-09 16:43:56', '1', '2024-04-24 19:42:52', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2712, '客户分析', 'crm:statistics-customer:query', 2, 0, 2560, 'customer', 'ep:avatar', 'crm/statistics/customer/index.vue', 'CrmStatisticsCustomer', 0, b'1', b'1', b'1', '1', '2024-03-09 16:43:56', '1', '2024-05-04 20:38:50', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2713, '抄送我的', 'bpm:process-instance-cc:query', 2, 30, 1200, 'copy', 'ep:copy-document', 'bpm/task/copy/index', 'BpmProcessInstanceCopy', 0, b'1', b'1', b'1', '1', '2024-03-17 21:50:23', '1', '2024-04-24 19:55:12', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2714, '流程分类', '', 2, 3, 1186, 'category', 'fa:object-ungroup', 'bpm/category/index', 'BpmCategory', 0, b'1', b'1', b'1', '', '2024-03-08 02:00:51', '1', '2024-03-21 23:51:18', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2715, '分类查询', 'bpm:category:query', 3, 1, 2714, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-03-08 02:00:51', '1', '2024-03-19 14:36:25', b'0'); @@ -2163,6 +1873,29 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2755, '删除项目', 'report:go-view-project:delete', 3, 2, 2153, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-04-24 20:01:37', '1', '2024-04-24 20:01:37', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2756, '会员等级记录查询', 'member:level-record:query', 3, 10, 2325, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-04-24 20:02:32', '1', '2024-04-24 20:02:32', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2757, '会员经验记录查询', 'member:experience-record:query', 3, 11, 2325, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-04-24 20:02:51', '1', '2024-04-24 20:02:51', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2758, 'AI 大模型', '', 1, 400, 0, '/ai', 'fa:apple', '', '', 0, b'1', b'1', b'1', '1', '2024-05-07 15:07:56', '1', '2024-05-25 12:36:12', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2759, 'AI 对话', '', 2, 1, 2758, 'chat', 'ep:message', 'ai/chat/index.vue', 'AiChat', 0, b'1', b'1', b'1', '1', '2024-05-07 15:09:14', '1', '2024-05-25 12:37:15', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2760, '控制台', '', 1, 100, 2758, 'console', 'ep:setting', '', '', 0, b'1', b'1', b'1', '1', '2024-05-09 22:39:09', '1', '2024-05-24 23:34:21', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2761, 'API 密钥', '', 2, 0, 2760, 'api-key', 'ep:key', 'ai/model/apiKey/index.vue', 'AiApiKey', 0, b'1', b'1', b'1', '', '2024-05-09 14:52:56', '1', '2024-05-10 22:44:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2762, 'API 密钥查询', 'ai:api-key:query', 3, 1, 2761, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-05-09 14:52:56', '1', '2024-05-13 20:36:32', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2763, 'API 密钥创建', 'ai:api-key:create', 3, 2, 2761, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-05-09 14:52:56', '1', '2024-05-13 20:36:26', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2764, 'API 密钥更新', 'ai:api-key:update', 3, 3, 2761, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-05-09 14:52:56', '1', '2024-05-13 20:36:42', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2765, 'API 密钥删除', 'ai:api-key:delete', 3, 4, 2761, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-05-09 14:52:56', '1', '2024-05-13 20:36:48', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2767, '聊天模型', '', 2, 0, 2760, 'chat-model', 'fa-solid:abacus', 'ai/model/chatModel/index.vue', 'AiChatModel', 0, b'1', b'1', b'1', '', '2024-05-10 14:42:48', '1', '2024-05-10 22:44:16', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2768, '聊天模型查询', 'ai:chat-model:query', 3, 1, 2767, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-05-10 14:42:48', '1', '2024-05-13 20:37:02', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2769, '聊天模型创建', 'ai:chat-model:create', 3, 2, 2767, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-05-10 14:42:48', '1', '2024-05-13 20:37:12', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2770, '聊天模型更新', 'ai:chat-model:update', 3, 3, 2767, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-05-10 14:42:48', '1', '2024-05-13 20:37:18', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2771, '聊天模型删除', 'ai:chat-model:delete', 3, 4, 2767, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-05-10 14:42:48', '1', '2024-05-13 20:37:23', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2773, '聊天角色', '', 2, 0, 2760, 'chat-role', 'fa:user-secret', 'ai/model/chatRole/index.vue', 'AiChatRole', 0, b'1', b'1', b'1', '', '2024-05-13 12:39:28', '1', '2024-05-13 20:41:45', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2774, '聊天角色查询', 'ai:chat-role:query', 3, 1, 2773, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-05-13 12:39:28', '', '2024-05-13 12:39:28', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2775, '聊天角色创建', 'ai:chat-role:create', 3, 2, 2773, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-05-13 12:39:28', '', '2024-05-13 12:39:28', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2776, '聊天角色更新', 'ai:chat-role:update', 3, 3, 2773, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-05-13 12:39:28', '', '2024-05-13 12:39:28', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2777, '聊天角色删除', 'ai:chat-role:delete', 3, 4, 2773, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-05-13 21:43:38', '1', '2024-05-13 21:43:38', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2778, '聊天管理', '', 2, 0, 2760, 'chat-conversation', 'ep:chat-square', 'ai/chat/manager/index.vue', 'ChatConversation', 0, b'1', b'1', b'1', '', '2024-05-24 15:39:18', '1', '2024-05-24 23:44:11', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2779, '会话查询', 'ai:chat-conversation:query', 3, 1, 2778, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-05-24 15:39:18', '1', '2024-05-25 08:38:30', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2780, '会话删除', 'ai:chat-conversation:delete', 3, 2, 2778, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-05-24 15:39:18', '1', '2024-05-25 08:38:40', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2781, '消息查询', 'ai:chat-message:query', 3, 11, 2778, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-05-25 08:38:56', '1', '2024-05-25 08:38:56', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2782, '消息删除', 'ai:chat-message:delete', 3, 12, 2778, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-05-25 08:39:10', '1', '2024-05-25 08:39:10', b'0'); COMMIT; -- ---------------------------- @@ -2284,7 +2017,7 @@ CREATE TABLE `system_oauth2_access_token` ( PRIMARY KEY (`id`) USING BTREE, INDEX `idx_access_token`(`access_token` ASC) USING BTREE, INDEX `idx_refresh_token`(`refresh_token` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 6620 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; +) ENGINE = InnoDB AUTO_INCREMENT = 7123 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; -- ---------------------------- -- Records of system_oauth2_access_token @@ -2406,7 +2139,7 @@ CREATE TABLE `system_oauth2_refresh_token` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1483 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; +) ENGINE = InnoDB AUTO_INCREMENT = 1521 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; -- ---------------------------- -- Records of system_oauth2_refresh_token @@ -3410,7 +3143,7 @@ CREATE TABLE `system_sms_code` ( `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_mobile`(`mobile` ASC) USING BTREE COMMENT '手机号' -) ENGINE = InnoDB AUTO_INCREMENT = 614 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码'; +) ENGINE = InnoDB AUTO_INCREMENT = 615 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码'; -- ---------------------------- -- Records of system_sms_code @@ -3451,7 +3184,7 @@ CREATE TABLE `system_sms_log` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 962 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志'; +) ENGINE = InnoDB AUTO_INCREMENT = 963 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志'; -- ---------------------------- -- Records of system_sms_log @@ -3616,8 +3349,8 @@ CREATE TABLE `system_tenant` ( -- ---------------------------- BEGIN; INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'www.iocoder.cn', 0, '2099-02-19 17:14:16', 9999, '1', '2021-01-05 17:03:47', '1', '2023-11-06 11:41:41', b'0'); -INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'zsxq.iocoder.cn', 111, '2024-03-11 00:00:00', 20, '1', '2022-02-22 00:56:14', '1', '2023-11-06 11:41:47', b'0'); -INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'test.iocoder.cn', 111, '2022-04-30 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2023-11-06 11:41:53', b'0'); +INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'zsxq.iocoder.cn', 111, '2024-03-11 00:00:00', 20, '1', '2022-02-22 00:56:14', '1', '2024-05-04 22:37:03', b'0'); +INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'test.iocoder.cn', 111, '2022-04-29 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2024-05-04 22:36:09', b'0'); COMMIT; -- ---------------------------- @@ -3739,15 +3472,14 @@ CREATE TABLE `system_users` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', - PRIMARY KEY (`id`) USING BTREE, - UNIQUE INDEX `idx_username`(`username` ASC, `update_time` ASC, `tenant_id` ASC) USING BTREE + PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 139 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户信息表'; -- ---------------------------- -- Records of system_users -- ---------------------------- BEGIN; -INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '18818260277', 2, 'http://test.yudao.iocoder.cn/96c787a2ce88bf6d0ce3cd8b6cf5314e80e7703cd41bf4af8cd2e2909dbd6b6d.png', 0, '0:0:0:0:0:0:0:1', '2024-04-29 21:50:32', 'admin', '2021-01-05 17:03:47', NULL, '2024-04-29 21:50:32', b'0', 1); +INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '18818260277', 2, 'http://test.yudao.iocoder.cn/96c787a2ce88bf6d0ce3cd8b6cf5314e80e7703cd41bf4af8cd2e2909dbd6b6d.png', 0, '0:0:0:0:0:0:0:1', '2024-05-19 11:11:07', 'admin', '2021-01-05 17:03:47', NULL, '2024-05-19 11:11:07', b'0', 1); INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (100, 'yudao', '$2a$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 1, '127.0.0.1', '2022-07-09 23:03:33', '', '2021-01-07 09:07:17', NULL, '2022-07-09 23:03:33', b'0', 1); INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (103, 'yuanma', '$2a$10$YMpimV4T6BtDhIaA8jSW.u8UTGBeGhc/qwXP4oxoMr4mOw9.qttt6', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '0:0:0:0:0:0:0:1', '2024-03-18 21:09:04', '', '2021-01-13 23:50:35', NULL, '2024-03-18 21:09:04', b'0', 1); INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (104, 'test', '$2a$04$KhExCYl7lx6eWWZYKsibKOZ8IBJRyuNuCcEOLQ11RYhJKgHmlSwK.', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, '', 0, '0:0:0:0:0:0:0:1', '2024-03-26 07:11:35', '', '2021-01-21 02:13:53', NULL, '2024-03-26 07:11:35', b'0', 1); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java index 97984045d..93d8167ca 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java @@ -144,6 +144,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { }).doOnComplete(() -> { chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString())); }).doOnError(throwable -> { + // TODO @芋艿:失败的情况下,要不要删除消息 log.error("[sendChatMessageStream][userId({}) sendReqVO({}) 发生异常]", userId, sendReqVO, throwable); chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(throwable.getMessage())); }).onErrorResume(error -> { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java index cd7012298..63b8834b8 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java @@ -17,12 +17,11 @@ public enum AiPlatformEnum { OLLAMA("Ollama", "Ollama"), YI_YAN("YiYan", "文心一言"), // 百度 XING_HUO("XingHuo", "星火"), // 讯飞 - QIAN_WEN("qianwen", "千问"), // 阿里 - - OPEN_AI_DALL("dall", "dall"), - MIDJOURNEY("midjourney", "midjourney"), - GEMIR ("gemir ", "gemir "), // google gemir + QIAN_WEN("QianWen", "千问"), // 阿里 + GEMIR ("gemir ", "gemir "), // 谷歌 + OPEN_AI_DALL("dall", "dall"), // TODO OpenAI 提供的绘图,接入中 + MIDJOURNEY("midjourney", "midjourney"), // TODO MJ 提供的绘图,接入中 ; /** diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index bb71ddddd..7e44995da 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -32,12 +32,6 @@ ${revision} - - cn.iocoder.boot - yudao-module-ai-biz - ${revision} - - @@ -107,6 +101,13 @@ + + + cn.iocoder.boot + yudao-module-ai-biz + ${revision} + + org.springframework.boot From 22e12366e84736c812eccee4787b812b47e81f96 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 25 May 2024 13:38:39 +0800 Subject: [PATCH 329/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91AI?= =?UTF-8?q?=EF=BC=9AAI=20=E7=9B=B8=E5=85=B3=20SQL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-server/src/main/resources/application.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index cc5ed76a3..37e0f5b59 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -152,6 +152,11 @@ spring.ai: openai: api-key: sk-yzKea6d8e8212c3bdd99f9f44ced1cae37c097e5aa3BTS7z base-url: https://api.gptsapi.net + vertex: + ai: + gemini: + project-id: 1 # TODO 芋艿:缺配置 + location: 2 yudao.ai: yiyan: From d695219534649d279178fb44e5b8f5f7366f25ab Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 25 May 2024 14:28:43 +0800 Subject: [PATCH 330/684] =?UTF-8?q?=E3=80=90=E5=A4=84=E7=90=86=E3=80=91Goo?= =?UTF-8?q?gleGemir=20=E5=85=88=E6=B3=A8=E9=87=8A=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=EF=BC=8C=E4=B8=8D=E7=84=B6=E8=B7=91=E4=B8=8D=E8=B5=B7=E6=9D=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/core/factory/AiClientFactoryImpl.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java index ba496adb0..615cfac1d 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java @@ -60,8 +60,8 @@ public class AiClientFactoryImpl implements AiClientFactory { return buildXingHuoChatClient(apiKey); case QIAN_WEN: return buildQianWenChatClient(apiKey); - case GEMIR: - return buildGoogleGemir(apiKey); +// case GEMIR: +// return buildGoogleGemir(apiKey); default: throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); } @@ -170,11 +170,11 @@ public class AiClientFactoryImpl implements AiClientFactory { } - private static VertexAiGeminiChatClient buildGoogleGemir(String key) { - List keys = StrUtil.split(key, '|'); - Assert.equals(keys.size(), 2, "VertexAiGeminiChatClient 的密钥需要 (projectId|location) 格式"); - VertexAI vertexApi = new VertexAI(keys.get(0), keys.get(1)); - return new VertexAiGeminiChatClient(vertexApi); - } +// private static VertexAiGeminiChatClient buildGoogleGemir(String key) { +// List keys = StrUtil.split(key, '|'); +// Assert.equals(keys.size(), 2, "VertexAiGeminiChatClient 的密钥需要 (projectId|location) 格式"); +// VertexAI vertexApi = new VertexAI(keys.get(0), keys.get(1)); +// return new VertexAiGeminiChatClient(vertexApi); +// } } From 3afb3089b536edf4b48295b8153be3013343cd63 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 25 May 2024 14:29:06 +0800 Subject: [PATCH 331/684] =?UTF-8?q?=E3=80=90=E5=A4=84=E7=90=86=E3=80=91Goo?= =?UTF-8?q?gleGemir=20=E5=85=88=E6=B3=A8=E9=87=8A=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=EF=BC=8C=E4=B8=8D=E7=84=B6=E8=B7=91=E4=B8=8D=E8=B5=B7=E6=9D=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/framework/ai/core/factory/AiClientFactoryImpl.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java index 615cfac1d..99fef7436 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java @@ -20,7 +20,6 @@ import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoApi; import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatClient; import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatOptions; import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanApi; -import com.google.cloud.vertexai.VertexAI; import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration; import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; import org.springframework.ai.chat.StreamingChatClient; @@ -32,8 +31,6 @@ import org.springframework.ai.openai.OpenAiChatClient; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.api.ApiUtils; import org.springframework.ai.openai.api.OpenAiApi; -import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatClient; -import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatOptions; import java.util.List; From b073c1d37f0c5027f5d2476d8a12836654b01227 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 25 May 2024 22:06:55 +0800 Subject: [PATCH 332/684] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=8E=B7?= =?UTF-8?q?=E5=BE=97=E4=B8=AA=E4=BA=BA=E5=88=86=E9=94=80=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=20NPE=20=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../brokerage/AppBrokerageUserController.java | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java index bb2ba59fe..d82915cde 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.trade.controller.app.brokerage; import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; @@ -10,6 +11,8 @@ import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.*; import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageRecordConvert; import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageUserConvert; import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageEnabledConditionEnum; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum; @@ -17,16 +20,17 @@ import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService; import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService; import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageWithdrawService; import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageWithdrawSummaryRespBO; +import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; import java.time.LocalDateTime; import java.util.Collections; import java.util.Map; @@ -50,7 +54,8 @@ public class AppBrokerageUserController { private BrokerageRecordService brokerageRecordService; @Resource private BrokerageWithdrawService brokerageWithdrawService; - + @Resource + private TradeConfigService tradeConfigService; @Resource private MemberUserApi memberUserApi; @@ -59,9 +64,13 @@ public class AppBrokerageUserController { @PreAuthenticated public CommonResult getBrokerageUser() { Optional user = Optional.ofNullable(brokerageUserService.getBrokerageUser(getLoginUserId())); + // 获得交易中心配置 + TradeConfigDO tradeConfig = tradeConfigService.getTradeConfig(); + // 如果是人人分佣 BrokerageUserDO 为 null 时,也有分销资格 + boolean brokerageEnabled = ObjUtil.equal(BrokerageEnabledConditionEnum.ALL.getCondition(), tradeConfig.getBrokerageEnabledCondition()); // 返回数据 AppBrokerageUserRespVO respVO = new AppBrokerageUserRespVO() - .setBrokerageEnabled(user.map(BrokerageUserDO::getBrokerageEnabled).orElse(false)) + .setBrokerageEnabled(user.map(BrokerageUserDO::getBrokerageEnabled).orElse(brokerageEnabled)) .setBrokeragePrice(user.map(BrokerageUserDO::getBrokeragePrice).orElse(0)) .setFrozenPrice(user.map(BrokerageUserDO::getFrozenPrice).orElse(0)); return success(respVO); @@ -79,21 +88,22 @@ public class AppBrokerageUserController { @PreAuthenticated public CommonResult getBrokerageUserSummary() { // 查询当前登录用户信息 - BrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(getLoginUserId()); + Long userId = getLoginUserId(); + BrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(userId); // 统计用户昨日的佣金 LocalDateTime yesterday = LocalDateTime.now().minusDays(1); LocalDateTime beginTime = LocalDateTimeUtil.beginOfDay(yesterday); LocalDateTime endTime = LocalDateTimeUtil.endOfDay(yesterday); - Integer yesterdayPrice = brokerageRecordService.getSummaryPriceByUserId(brokerageUser.getId(), + Integer yesterdayPrice = brokerageRecordService.getSummaryPriceByUserId(userId, BrokerageRecordBizTypeEnum.ORDER, BrokerageRecordStatusEnum.SETTLEMENT, beginTime, endTime); // 统计用户提现的佣金 - Integer withdrawPrice = brokerageWithdrawService.getWithdrawSummaryListByUserId(Collections.singleton(brokerageUser.getId()), + Integer withdrawPrice = brokerageWithdrawService.getWithdrawSummaryListByUserId(Collections.singleton(userId), BrokerageWithdrawStatusEnum.AUDIT_SUCCESS).stream() .findFirst().map(BrokerageWithdrawSummaryRespBO::getPrice).orElse(0); // 统计分销用户数量(一级) - Long firstBrokerageUserCount = brokerageUserService.getBrokerageUserCountByBindUserId(brokerageUser.getId(), 1); + Long firstBrokerageUserCount = brokerageUserService.getBrokerageUserCountByBindUserId(userId, 1); // 统计分销用户数量(二级) - Long secondBrokerageUserCount = brokerageUserService.getBrokerageUserCountByBindUserId(brokerageUser.getId(), 2); + Long secondBrokerageUserCount = brokerageUserService.getBrokerageUserCountByBindUserId(userId, 2); // 拼接返回 return success(BrokerageUserConvert.INSTANCE.convert(yesterdayPrice, withdrawPrice, firstBrokerageUserCount, secondBrokerageUserCount, brokerageUser)); From 3025bff63111108a60a3999f5e8a041e86756232 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 26 May 2024 09:47:41 +0800 Subject: [PATCH 333/684] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91SYSTEM=EF=BC=9A=E5=AE=8C=E5=96=84=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E5=B0=8F=E7=A8=8B=E5=BA=8F=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/social/AppSocialUserController.java | 15 +--------- .../api/social/dto/SocialWxQrcodeReqDTO.java | 29 +++++++++++++++++++ .../social/SocialClientServiceImpl.java | 12 ++++++-- 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java index 722da6dab..038b225f2 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.member.controller.app.social; import cn.hutool.core.codec.Base64; -import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -33,13 +32,6 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti @Validated public class AppSocialUserController { - public static final String ENV_VERSION = "release"; // 小程序版本。正式版为 "release",体验版为 "trial",开发版为 "develop" - private static final String SCENE = ""; // 页面路径不能携带参数(参数请放在scene字段里) - private static final Integer WIDTH = 430; // 二维码宽度 - private static final Boolean AUTO_COLOR = true; // 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 - private static final Boolean CHECK_PATH = true; // 默认true 检查 page 是否存在 - private static final Boolean HYALINE = true; // 是否需要透明底色, hyaline 为true时,生成透明底色的小程序码 - @Resource private SocialUserApi socialUserApi; @Resource @@ -76,12 +68,7 @@ public class AppSocialUserController { @PostMapping("/wxa-qrcode") @Operation(summary = "获得微信小程序码(base64 image)") public CommonResult getWxQrcode(@RequestBody @Valid AppSocialWxQrcodeReqVO reqVO) { - byte[] wxQrcode = socialClientApi.getWxaQrcode(new SocialWxQrcodeReqDTO().setPath(reqVO.getPath()) - .setEnvVersion(ENV_VERSION).setWidth(ObjUtil.defaultIfNull(reqVO.getWidth(), WIDTH)) - .setScene(ObjUtil.defaultIfNull(reqVO.getScene(), SCENE)) - .setAutoColor(ObjUtil.defaultIfNull(reqVO.getAutoColor(), AUTO_COLOR)) - .setHyaline(ObjUtil.defaultIfNull(reqVO.getHyaline(), HYALINE)) - .setCheckPath(ObjUtil.defaultIfNull(reqVO.getCheckPath(), CHECK_PATH))); + byte[] wxQrcode = socialClientApi.getWxaQrcode(new SocialWxQrcodeReqDTO().setPath(reqVO.getPath())); return success(Base64.encode(wxQrcode)); } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialWxQrcodeReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialWxQrcodeReqDTO.java index efda43e81..4b964af4f 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialWxQrcodeReqDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialWxQrcodeReqDTO.java @@ -12,6 +12,35 @@ import lombok.Data; @Data public class SocialWxQrcodeReqDTO { + /** + * 小程序版本 + * + * 正式版为 "release";体验版为 "trial";开发版为 "develop" + */ + public static final String ENV_VERSION = "release"; + /** + * 页面路径不能携带参数(参数请放在scene字段里) + */ + public static final String SCENE = ""; + /** + * 二维码宽度 + */ + public static final Integer WIDTH = 430; + /** + * 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 + */ + public static final Boolean AUTO_COLOR = true; + /** + * 检查 page 是否存在 + */ + public static final Boolean CHECK_PATH = true; + /** + * 是否需要透明底色 + * + * hyaline 为 true 时,生成透明底色的小程序码 + */ + public static final Boolean HYALINE = true; + /** * 场景 */ diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java index 41b27b171..25d6d99d2 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java @@ -233,9 +233,15 @@ public class SocialClientServiceImpl implements SocialClientService { public byte[] getWxaQrcode(SocialWxQrcodeReqDTO reqVO) { WxMaService service = getWxMaService(UserTypeEnum.MEMBER.getValue()); try { - return service.getQrcodeService().createWxaCodeUnlimitBytes(reqVO.getScene(), reqVO.getPath(), - reqVO.getCheckPath(), reqVO.getEnvVersion(), reqVO.getWidth(), reqVO.getAutoColor(), - null, reqVO.getHyaline()); + return service.getQrcodeService().createWxaCodeUnlimitBytes( + ObjUtil.defaultIfEmpty(reqVO.getScene(), SocialWxQrcodeReqDTO.SCENE), + reqVO.getPath(), + ObjUtil.defaultIfNull(reqVO.getCheckPath(), SocialWxQrcodeReqDTO.CHECK_PATH), + ObjUtil.defaultIfBlank(reqVO.getEnvVersion(), SocialWxQrcodeReqDTO.ENV_VERSION), + ObjUtil.defaultIfNull(reqVO.getWidth(), SocialWxQrcodeReqDTO.WIDTH), + ObjUtil.defaultIfNull(reqVO.getAutoColor(), SocialWxQrcodeReqDTO.AUTO_COLOR), + null, + ObjUtil.defaultIfNull(reqVO.getHyaline(), SocialWxQrcodeReqDTO.HYALINE)); } catch (WxErrorException e) { log.error("[getWxQrcode][reqVO({})) 获得小程序码失败]", reqVO, e); throw exception(SOCIAL_CLIENT_WEIXIN_MINI_APP_QRCODE_ERROR); From 0cdd3423e5050f2745aeb99a9a65d048bc62dd51 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 27 May 2024 15:26:44 +0800 Subject: [PATCH 334/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91AI?= =?UTF-8?q?=20Image=20=E8=B0=83=E6=95=B4=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...StatusEnum.java => AiImageStatusEnum.java} | 6 +-- .../admin/image/AiImageController.java | 4 +- ...rawingReqVO.java => AiImageDallReqVO.java} | 7 ++-- ...wingRespVO.java => AiImageDallRespVO.java} | 10 +++-- .../module/ai/convert/AiImageConvert.java | 6 +-- .../ai/dal/dataobject/image/AiImageDO.java | 16 +++++--- .../ai/service/image/AiImageService.java | 4 +- .../ai/service/image/AiImageServiceImpl.java | 40 +++++++++---------- .../YuDaoMidjourneyMessageHandler.java | 18 ++++----- 9 files changed, 58 insertions(+), 53 deletions(-) rename yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/{AiImageDrawingStatusEnum.java => AiImageStatusEnum.java} (76%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/{AiImageDallDrawingReqVO.java => AiImageDallReqVO.java} (85%) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/{AiImageDallDrawingRespVO.java => AiImageDallRespVO.java} (84%) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageDrawingStatusEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageStatusEnum.java similarity index 76% rename from yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageDrawingStatusEnum.java rename to yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageStatusEnum.java index c38b17756..a5231a3bf 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageDrawingStatusEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageStatusEnum.java @@ -12,7 +12,7 @@ import lombok.Getter; */ @AllArgsConstructor @Getter -public enum AiImageDrawingStatusEnum { +public enum AiImageStatusEnum { SUBMIT("submit", "提交任务"), WAITING("waiting", "等待"), @@ -27,8 +27,8 @@ public enum AiImageDrawingStatusEnum { private String name; - public static AiImageDrawingStatusEnum valueOfStatus(String status) { - for (AiImageDrawingStatusEnum itemEnum : AiImageDrawingStatusEnum.values()) { + public static AiImageStatusEnum valueOfStatus(String status) { + for (AiImageStatusEnum itemEnum : AiImageStatusEnum.values()) { if (itemEnum.getStatus().equals(status)) { return itemEnum; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index fd9ea0802..2dbac1a9b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -37,8 +37,8 @@ public class AiImageController { } @Operation(summary = "dall2/dall3绘画", description = "openAi dall3是付费的!") - @PostMapping("/dallDrawing") - public AiImageDallDrawingRespVO dallDrawing(@Validated @RequestBody AiImageDallDrawingReqVO req) { + @PostMapping("/dall") + public AiImageDallRespVO dallDrawing(@Validated @RequestBody AiImageDallReqVO req) { return aiImageService.dallDrawing(req); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallDrawingReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallReqVO.java similarity index 85% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallDrawingReqVO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallReqVO.java index 3973eb2e9..ef9161870 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallDrawingReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallReqVO.java @@ -15,19 +15,18 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class AiImageDallDrawingReqVO { +public class AiImageDallReqVO { @Schema(description = "提示词") @NotNull(message = "提示词不能为空!") @Size(max = 1200, message = "提示词最大1200") private String prompt; - @Schema(description = "模型") + @Schema(description = "模型(dall2、dall3)") @NotNull(message = "模型不能为空") - private String modal; + private String model; @Schema(description = "图像生成的风格。可为vivid(生动)或natural(自然)") - @NotNull(message = "图像生成的风格,不能为空!") private String style; @Schema(description = "生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallDrawingRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallRespVO.java similarity index 84% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallDrawingRespVO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallRespVO.java index 7e480a8f0..18c27a64f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallDrawingRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallRespVO.java @@ -15,8 +15,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class AiImageDallDrawingRespVO { - +public class AiImageDallRespVO { @Schema(description = "提示词") @NotNull(message = "提示词不能为空!") @@ -25,7 +24,7 @@ public class AiImageDallDrawingRespVO { @Schema(description = "模型") @NotNull(message = "模型不能为空") - private String modal; + private String model; @Schema(description = "风格") private String style; @@ -33,8 +32,11 @@ public class AiImageDallDrawingRespVO { @Schema(description = "图片size 1024x1024 ...") private String size; + @Schema(description = "图片地址(自己服务器)") + private String picUrl; + @Schema(description = "可以访问图像的URL。") - private String url; + private String originalPicUrl; @Schema(description = "图片base64。") private String base64; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java index b0f8abc39..f5e6699d7 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.ai.convert; import org.springframework.ai.models.midjourney.MidjourneyMessage; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallDrawingRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallRespVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageListRespVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyOperationsVO; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; @@ -29,7 +29,7 @@ public interface AiImageConvert { * @param req * @return */ - AiImageDallDrawingRespVO convertAiImageDallDrawingRespVO(AiImageDallDrawingReqVO req); + AiImageDallRespVO convertAiImageDallDrawingRespVO(AiImageDallReqVO req); /** * 转换 - AiImageListRespVO diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java index c04fea12f..cb3aedda1 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java @@ -30,22 +30,28 @@ public class AiImageDO extends BaseDO { private String prompt; @Schema(description = "模型 dall2/dall3、MJ、NIJI") - private String modal; + private String model; @Schema(description = "生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。") private String size; + @Schema(description = "风格") + private String style; + @Schema(description = "图片地址(自己服务器)") - private String imageUrl; + private String picUrl; @Schema(description = "绘画状态:提交、排队、绘画中、绘画完成、绘画失败") - private String drawingStatus; + private String status; @Schema(description = "绘画图片地址(绘画好的服务器)") - private String drawingImageUrl; + private String originalPicUrl; @Schema(description = "绘画错误信息") - private String drawingErrorMessage; + private String errorMessage; + + @Schema(description = "是否发布") + private String publicStatus; // ============ mj 需要字段 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java index 836f37dfb..4af34d3bf 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java @@ -3,8 +3,6 @@ package cn.iocoder.yudao.module.ai.service.image; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; -import java.util.List; - /** * ai 作图 * @@ -27,7 +25,7 @@ public interface AiImageService { * * @param req */ - AiImageDallDrawingRespVO dallDrawing(AiImageDallDrawingReqVO req); + AiImageDallRespVO dallDrawing(AiImageDallReqVO req); /** * midjourney 图片生成 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index f4521af84..01476a4a3 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -22,7 +22,7 @@ import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; import cn.iocoder.yudao.module.ai.convert.AiImageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper; -import cn.iocoder.yudao.module.ai.enums.AiImageDrawingStatusEnum; +import cn.iocoder.yudao.module.ai.enums.AiImageStatusEnum; import jakarta.annotation.PostConstruct; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -85,12 +85,12 @@ public class AiImageServiceImpl implements AiImageService { } @Override - public AiImageDallDrawingRespVO dallDrawing(AiImageDallDrawingReqVO req) { + public AiImageDallRespVO dallDrawing(AiImageDallReqVO req) { // 获取 model - OpenAiImageModelEnum openAiImageModelEnum = OpenAiImageModelEnum.valueOfModel(req.getModal()); + OpenAiImageModelEnum openAiImageModelEnum = OpenAiImageModelEnum.valueOfModel(req.getModel()); OpenAiImageStyleEnum openAiImageStyleEnum = OpenAiImageStyleEnum.valueOfStyle(req.getStyle()); // 转换 AiImageDallDrawingRespVO - AiImageDallDrawingRespVO respVO = AiImageConvert.INSTANCE.convertAiImageDallDrawingRespVO(req); + AiImageDallRespVO respVO = AiImageConvert.INSTANCE.convertAiImageDallDrawingRespVO(req); try { // 转换openai 参数 OpenAiImageOptions openAiImageOptions = new OpenAiImageOptions(); @@ -101,17 +101,17 @@ public class AiImageServiceImpl implements AiImageService { // 发送 ImageGeneration imageGeneration = imageResponse.getResult(); // 保存数据库 - doSave(req.getPrompt(), req.getSize(), req.getModal(), - imageGeneration.getOutput().getUrl(), AiImageDrawingStatusEnum.COMPLETE, null, + doSave(req.getPrompt(), req.getSize(), req.getModel(), + imageGeneration.getOutput().getUrl(), AiImageStatusEnum.COMPLETE, null, null, null, null); // 返回 flex - respVO.setUrl(imageGeneration.getOutput().getUrl()); + respVO.setOriginalPicUrl(imageGeneration.getOutput().getUrl()); respVO.setBase64(imageGeneration.getOutput().getB64Json()); return respVO; } catch (AiException aiException) { // 保存数据库 - doSave(req.getPrompt(), req.getSize(), req.getModal(), - null, AiImageDrawingStatusEnum.FAIL, aiException.getMessage(), + doSave(req.getPrompt(), req.getSize(), req.getModel(), + null, AiImageStatusEnum.FAIL, aiException.getMessage(), null, null, null); // 发送错误信息 respVO.setErrorMessage(aiException.getMessage()); @@ -125,7 +125,7 @@ public class AiImageServiceImpl implements AiImageService { // 保存数据库 String messageId = String.valueOf(IdUtil.getSnowflakeNextId()); AiImageDO aiImageDO = doSave(req.getPrompt(), null, "midjoureny", - null, AiImageDrawingStatusEnum.SUBMIT, null, + null, AiImageStatusEnum.SUBMIT, null, messageId, null, null); // 提交 midjourney 任务 Boolean imagine = midjourneyInteractionsApi.imagine(messageId, req.getPrompt()); @@ -148,8 +148,8 @@ public class AiImageServiceImpl implements AiImageService { // 获取 mjOperationName String mjOperationName = midjourneyOperationsVO.getLabel(); // 保存一个 image 任务记录 - doSave(aiImageDO.getPrompt(), aiImageDO.getSize(), aiImageDO.getModal(), - null, AiImageDrawingStatusEnum.SUBMIT, null, + doSave(aiImageDO.getPrompt(), aiImageDO.getSize(), aiImageDO.getModel(), + null, AiImageStatusEnum.SUBMIT, null, req.getMessageId(), req.getOperateId(), mjOperationName); // 提交操作 midjourneyInteractionsApi.reRoll( @@ -201,9 +201,9 @@ public class AiImageServiceImpl implements AiImageService { private AiImageDO doSave(String prompt, String size, String model, - String drawingImageUrl, - AiImageDrawingStatusEnum drawingStatusEnum, - String drawingErrorMessage, + String originalPicUrl, + AiImageStatusEnum statusEnum, + String errorMessage, String mjMessageId, String mjOperationId, String mjOperationName) { @@ -213,13 +213,13 @@ public class AiImageServiceImpl implements AiImageService { aiImageDO.setId(null); aiImageDO.setPrompt(prompt); aiImageDO.setSize(size); - aiImageDO.setModal(model); + aiImageDO.setModel(model); aiImageDO.setUserId(loginUserId); // TODO @芋艿 如何上传到自己服务器 - aiImageDO.setImageUrl(null); - aiImageDO.setDrawingStatus(drawingStatusEnum.getStatus()); - aiImageDO.setDrawingImageUrl(drawingImageUrl); - aiImageDO.setDrawingErrorMessage(drawingErrorMessage); + aiImageDO.setPicUrl(null); + aiImageDO.setStatus(statusEnum.getStatus()); + aiImageDO.setOriginalPicUrl(originalPicUrl); + aiImageDO.setErrorMessage(errorMessage); // aiImageDO.setMjNonceId(mjMessageId); aiImageDO.setMjOperationId(mjOperationId); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/YuDaoMidjourneyMessageHandler.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/YuDaoMidjourneyMessageHandler.java index 5327d65ff..7b95b968e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/YuDaoMidjourneyMessageHandler.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/YuDaoMidjourneyMessageHandler.java @@ -11,7 +11,7 @@ import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyOpe import cn.iocoder.yudao.module.ai.convert.AiImageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper; -import cn.iocoder.yudao.module.ai.enums.AiImageDrawingStatusEnum; +import cn.iocoder.yudao.module.ai.enums.AiImageStatusEnum; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -67,8 +67,8 @@ public class YuDaoMidjourneyMessageHandler implements MidjourneyMessageHandler { String errorMessage = getErrorMessage(midjourneyMessage); aiImageMapper.updateByMjNonce(nonceId, new AiImageDO() - .setDrawingErrorMessage(errorMessage) - .setDrawingStatus(AiImageDrawingStatusEnum.FAIL.getStatus()) + .setErrorMessage(errorMessage) + .setStatus(AiImageStatusEnum.FAIL.getStatus()) ); } @@ -90,22 +90,22 @@ public class YuDaoMidjourneyMessageHandler implements MidjourneyMessageHandler { imageUrl = midjourneyMessage.getAttachments().get(0).getUrl(); } // 转换状态 - AiImageDrawingStatusEnum drawingStatusEnum = null; + AiImageStatusEnum drawingStatusEnum = null; String generateStatus = midjourneyMessage.getGenerateStatus(); if (MidjourneyGennerateStatusEnum.COMPLETED.getStatus().equals(generateStatus)) { - drawingStatusEnum = AiImageDrawingStatusEnum.COMPLETE; + drawingStatusEnum = AiImageStatusEnum.COMPLETE; } else if (MidjourneyGennerateStatusEnum.IN_PROGRESS.getStatus().equals(generateStatus)) { - drawingStatusEnum = AiImageDrawingStatusEnum.IN_PROGRESS; + drawingStatusEnum = AiImageStatusEnum.IN_PROGRESS; } else if (MidjourneyGennerateStatusEnum.WAITING.getStatus().equals(generateStatus)) { - drawingStatusEnum = AiImageDrawingStatusEnum.WAITING; + drawingStatusEnum = AiImageStatusEnum.WAITING; } // 获取 midjourneyOperations List midjourneyOperations = getMidjourneyOperationsList(midjourneyMessage); // 更新数据库 aiImageMapper.updateByMjNonce(nonceId, new AiImageDO() - .setDrawingImageUrl(imageUrl) - .setDrawingStatus(drawingStatusEnum == null ? null : drawingStatusEnum.getStatus()) + .setOriginalPicUrl(imageUrl) + .setStatus(drawingStatusEnum == null ? null : drawingStatusEnum.getStatus()) .setMjNonceId(midjourneyMessage.getId()) .setMjOperations(JsonUtils.toJsonString(midjourneyOperations)) ); From 447526a6d9c31cce93a27da4176a345f881baf6f Mon Sep 17 00:00:00 2001 From: xiaoxin <718949661@qq.com> Date: Mon, 27 May 2024 15:44:55 +0800 Subject: [PATCH 335/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9Asuno?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ai/core/model/suno/SunoApi.java | 175 ++++++++++++++++++ .../yudao/framework/ai/suno/SunoTests.java | 24 +++ 2 files changed, 199 insertions(+) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/SunoApi.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/SunoApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/SunoApi.java new file mode 100644 index 000000000..0198197f1 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/SunoApi.java @@ -0,0 +1,175 @@ +package cn.iocoder.yudao.framework.ai.core.model.suno; + + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.Data; +import lombok.experimental.Accessors; +import lombok.extern.slf4j.Slf4j; +import okhttp3.*; + +import java.io.IOException; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * @Author xiaoxin + * @Date 2024/5/27 + */ +@Slf4j +public class SunoApi { + + public static final String APPLICATION_JSON = "application/json"; + public static final String TOKEN_PREFIX = "Bearer "; + public static final String API_URL = "https://api.acedata.cloud/suno/audios"; + public static final String TEST_TOKEN = "13f13540dd3f4ae9885f63ac9f5d0b9f"; + private static final int READ_TIMEOUT = 160; // 连接超时时间(秒),音乐生成时间较长,设置为 160s,后续可做callback + private final OkHttpClient client; + private final ObjectMapper objectMapper; + + public SunoApi() { + this.client = new OkHttpClient().newBuilder().readTimeout(READ_TIMEOUT, TimeUnit.SECONDS).build(); + this.objectMapper = new ObjectMapper(); + } + + public SunoResponse generateMusic(SunoRequest sunoRequest) throws IOException { + Request request = new Request.Builder() + .url(API_URL) + .header("Authorization", TOKEN_PREFIX + TEST_TOKEN) + .post(RequestBody.create(MediaType.parse(APPLICATION_JSON), objectMapper.writeValueAsString(sunoRequest))) + .build(); + + try (Response response = client.newCall(request).execute()) { + if (!response.isSuccessful()) { + log.error("suno调用失败! response: {}", response); + throw new IllegalStateException("suno调用失败!" + response); + } + return objectMapper.readValue(response.body().string(), SunoResponse.class); + } + } + + + /** + * 请求数据对象,用于生成音乐音频 + */ + @Data + @Accessors(chain = true) + @JsonInclude(value = JsonInclude.Include.NON_NULL) + public static class SunoRequest { + /** + * 用于生成音乐音频的提示 + */ + private String prompt; + + /** + * 用于生成音乐音频的歌词 + */ + private String lyric; + + /** + * 指示音乐音频是否为定制,如果为 true,则从歌词生成,否则从提示生成 + */ + private boolean custom; + + /** + * 音乐音频的标题 + */ + private String title; + + /** + * 音乐音频的风格 + */ + private String style; + + /** + * 音乐音频生成后回调的 URL + */ + private String callbackUrl; + } + + + /** + * API 响应的数据 + */ + @Data + public static class SunoResponse { + /** + * 表示请求是否成功 + */ + private boolean success; + + /** + * 任务 ID + */ + @JsonProperty("task_id") + private String taskId; + + /** + * 音乐数据列表 + */ + private List data; + + /** + * 表示单个音乐数据的类 + */ + @Data + static class MusicData { + /** + * 音乐数据的 ID + */ + private String id; + + /** + * 音乐音频的标题 + */ + private String title; + + /** + * 音乐音频的图片 URL + */ + @JsonProperty("image_url") + private String imageUrl; + + /** + * 音乐音频的歌词 + */ + private String lyric; + + /** + * 音乐音频的 URL + */ + @JsonProperty("audio_url") + private String audioUrl; + + /** + * 音乐视频的 URL + */ + @JsonProperty("video_url") + private String videoUrl; + + /** + * 音乐音频的创建时间 + */ + @JsonProperty("created_at") + private String createdAt; + + /** + * 使用的模型名称 + */ + private String model; + + /** + * 生成音乐音频的提示 + */ + private String prompt; + + /** + * 音乐音频的风格 + */ + private String style; + } + } + + +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java new file mode 100644 index 000000000..30883a6e1 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.framework.ai.suno; + +import cn.iocoder.yudao.framework.ai.core.model.suno.SunoApi; +import org.junit.Test; + +import java.io.IOException; + +/** + * @Author xiaoxin + * @Date 2024/5/27 + */ +public class SunoTests { + + + @Test + public void generateMusic() throws IOException { + SunoApi sunoApi = new SunoApi(); + SunoApi.SunoRequest sunoRequest = new SunoApi + .SunoRequest() + .setPrompt("创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。"); + SunoApi.SunoResponse sunoResponse = sunoApi.generateMusic(sunoRequest); + System.out.println(sunoResponse); + } +} From ea7f923072bc1879fa1b825f270d7cfb204eaa9f Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 27 May 2024 16:18:52 +0800 Subject: [PATCH 336/684] =?UTF-8?q?SYSTEM=EF=BC=9A=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E5=B0=8F=E7=A8=8B=E5=BA=8F=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/app/social/AppSocialUserController.java | 4 ++-- .../system/api/social/dto/SocialWxQrcodeReqDTO.java | 10 ---------- .../system/service/social/SocialClientServiceImpl.java | 9 ++++++++- yudao-server/src/main/resources/application-dev.yaml | 2 ++ yudao-server/src/main/resources/application-local.yaml | 2 ++ yudao-server/src/main/resources/application.yaml | 2 ++ 6 files changed, 16 insertions(+), 13 deletions(-) diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java index 038b225f2..de76856c3 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java @@ -67,8 +67,8 @@ public class AppSocialUserController { @PostMapping("/wxa-qrcode") @Operation(summary = "获得微信小程序码(base64 image)") - public CommonResult getWxQrcode(@RequestBody @Valid AppSocialWxQrcodeReqVO reqVO) { - byte[] wxQrcode = socialClientApi.getWxaQrcode(new SocialWxQrcodeReqDTO().setPath(reqVO.getPath())); + public CommonResult getWxaQrcode(@RequestBody @Valid AppSocialWxQrcodeReqVO reqVO) { + byte[] wxQrcode = socialClientApi.getWxaQrcode(BeanUtils.toBean(reqVO, SocialWxQrcodeReqDTO.class)); return success(Base64.encode(wxQrcode)); } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialWxQrcodeReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialWxQrcodeReqDTO.java index 4b964af4f..6f4b96f4e 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialWxQrcodeReqDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialWxQrcodeReqDTO.java @@ -12,12 +12,6 @@ import lombok.Data; @Data public class SocialWxQrcodeReqDTO { - /** - * 小程序版本 - * - * 正式版为 "release";体验版为 "trial";开发版为 "develop" - */ - public static final String ENV_VERSION = "release"; /** * 页面路径不能携带参数(参数请放在scene字段里) */ @@ -51,10 +45,6 @@ public class SocialWxQrcodeReqDTO { */ @NotEmpty(message = "页面路径不能为空") private String path; - /** - * 要打开的小程序版本 - */ - private String envVersion; /** * 二维码宽度 */ diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java index 25d6d99d2..b9a339223 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java @@ -41,6 +41,7 @@ import me.chanjar.weixin.common.redis.RedisTemplateWxRedisOps; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; import me.chanjar.weixin.mp.config.impl.WxMpRedisConfigImpl; +import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; @@ -60,6 +61,12 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; @Slf4j public class SocialClientServiceImpl implements SocialClientService { + /** + * 小程序版本 + */ + @Value("${yudao.wxa-code.env-version}") + public String envVersion; + @Resource private AuthRequestFactory authRequestFactory; @@ -237,7 +244,7 @@ public class SocialClientServiceImpl implements SocialClientService { ObjUtil.defaultIfEmpty(reqVO.getScene(), SocialWxQrcodeReqDTO.SCENE), reqVO.getPath(), ObjUtil.defaultIfNull(reqVO.getCheckPath(), SocialWxQrcodeReqDTO.CHECK_PATH), - ObjUtil.defaultIfBlank(reqVO.getEnvVersion(), SocialWxQrcodeReqDTO.ENV_VERSION), + envVersion, ObjUtil.defaultIfNull(reqVO.getWidth(), SocialWxQrcodeReqDTO.WIDTH), ObjUtil.defaultIfNull(reqVO.getAutoColor(), SocialWxQrcodeReqDTO.AUTO_COLOR), null, diff --git a/yudao-server/src/main/resources/application-dev.yaml b/yudao-server/src/main/resources/application-dev.yaml index 936aaae69..cc105790d 100644 --- a/yudao-server/src/main/resources/application-dev.yaml +++ b/yudao-server/src/main/resources/application-dev.yaml @@ -171,6 +171,8 @@ yudao: order-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/order # 支付渠道的【支付】回调地址 refund-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/refund # 支付渠道的【退款】回调地址 demo: true # 开启演示模式 + wxa-code: + env-version: release # 小程序版本: 正式版为 "release";体验版为 "trial";开发版为 "develop" tencent-lbs-key: TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E # QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc justauth: diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index f5912f690..d494593ab 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -220,6 +220,8 @@ yudao: access-log: # 访问日志的配置项 enable: false demo: false # 关闭演示模式 + wxa-code: + env-version: develop # 小程序版本: 正式版为 "release";体验版为 "trial";开发版为 "develop" tencent-lbs-key: TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E # QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc justauth: diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 6cb5386e3..561db7a93 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -177,6 +177,8 @@ yudao: license-url: https://gitee.com/zhijiantianya/ruoyi-vue-pro/blob/master/LICENSE captcha: enable: true # 验证码的开关,默认为 true + wxa-code: + env-version: release # 小程序版本: 正式版为 "release";体验版为 "trial";开发版为 "develop"。默认为 release codegen: base-package: ${yudao.info.base-package} db-schemas: ${spring.datasource.dynamic.datasource.master.name} From ae493e66dface723e8b08f1b93f72a1ff90feebb Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 27 May 2024 16:24:07 +0800 Subject: [PATCH 337/684] =?UTF-8?q?MALL-TRADE=EF=BC=9A=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=20BrokerageUserService#getOrCreateBrokerageUser=20=E8=8E=B7?= =?UTF-8?q?=E5=BE=97=E6=88=96=E5=88=9B=E5=BB=BA=E5=88=86=E9=94=80=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E6=96=B9=E6=B3=95=EF=BC=8C=E8=A7=A3=E5=86=B3=E7=88=B6?= =?UTF-8?q?=E7=BA=A7=E6=8E=A8=E5=B9=BF=E4=BA=BA=E4=B8=8D=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../brokerage/AppBrokerageUserController.java | 14 ++------- .../vo/user/AppBrokerageUserBindReqVO.java | 2 +- .../brokerage/BrokerageUserService.java | 15 ++++++++-- .../brokerage/BrokerageUserServiceImpl.java | 29 +++++++++++++++---- 4 files changed, 38 insertions(+), 22 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java index d82915cde..202ed3c42 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.trade.controller.app.brokerage; import cn.hutool.core.date.LocalDateTimeUtil; -import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; @@ -11,8 +10,6 @@ import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.*; import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageRecordConvert; import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageUserConvert; import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; -import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageEnabledConditionEnum; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum; @@ -20,7 +17,6 @@ import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService; import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService; import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageWithdrawService; import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageWithdrawSummaryRespBO; -import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -55,22 +51,16 @@ public class AppBrokerageUserController { @Resource private BrokerageWithdrawService brokerageWithdrawService; @Resource - private TradeConfigService tradeConfigService; - @Resource private MemberUserApi memberUserApi; @GetMapping("/get") @Operation(summary = "获得个人分销信息") @PreAuthenticated public CommonResult getBrokerageUser() { - Optional user = Optional.ofNullable(brokerageUserService.getBrokerageUser(getLoginUserId())); - // 获得交易中心配置 - TradeConfigDO tradeConfig = tradeConfigService.getTradeConfig(); - // 如果是人人分佣 BrokerageUserDO 为 null 时,也有分销资格 - boolean brokerageEnabled = ObjUtil.equal(BrokerageEnabledConditionEnum.ALL.getCondition(), tradeConfig.getBrokerageEnabledCondition()); + Optional user = Optional.ofNullable(brokerageUserService.getOrCreateBrokerageUser(getLoginUserId())); // 返回数据 AppBrokerageUserRespVO respVO = new AppBrokerageUserRespVO() - .setBrokerageEnabled(user.map(BrokerageUserDO::getBrokerageEnabled).orElse(brokerageEnabled)) + .setBrokerageEnabled(user.map(BrokerageUserDO::getBrokerageEnabled).orElse(false)) .setBrokeragePrice(user.map(BrokerageUserDO::getBrokeragePrice).orElse(0)) .setFrozenPrice(user.map(BrokerageUserDO::getFrozenPrice).orElse(0)); return success(respVO); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserBindReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserBindReqVO.java index e6f2982eb..db23d8e20 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserBindReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserBindReqVO.java @@ -8,7 +8,7 @@ import jakarta.validation.constraints.NotNull; @Schema(description = "应用 App - 绑定推广员 Request VO") @Data -public class AppBrokerageUserBindReqVO extends PageParam { +public class AppBrokerageUserBindReqVO { @Schema(description = "推广员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @NotNull(message = "推广员编号不能为空") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageUserService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageUserService.java index a50eedda1..7b6e4b110 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageUserService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageUserService.java @@ -7,8 +7,8 @@ import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokera import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankByUserCountRespVO; import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankPageReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO; - import jakarta.validation.constraints.NotNull; + import java.util.Collection; import java.util.List; @@ -67,6 +67,14 @@ public interface BrokerageUserService { */ BrokerageUserDO getBindBrokerageUser(Long id); + /** + * 获得或创建分销用户 + * + * @param id 用户编号 + * @return 分销用户 + */ + BrokerageUserDO getOrCreateBrokerageUser(Long id); + /** * 更新用户佣金 * @@ -104,8 +112,8 @@ public interface BrokerageUserService { /** * 【会员】绑定推广员 * - * @param userId 用户编号 - * @param bindUserId 推广员编号 + * @param userId 用户编号 + * @param bindUserId 推广员编号 * @return 是否绑定 */ boolean bindBrokerageUser(@NotNull Long userId, @NotNull Long bindUserId); @@ -134,4 +142,5 @@ public interface BrokerageUserService { * @return 下级分销统计分页 */ PageResult getBrokerageUserChildSummaryPage(AppBrokerageUserChildSummaryPageReqVO pageReqVO, Long userId); + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageUserServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageUserServiceImpl.java index 355e1ee8b..08e42c9a0 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageUserServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageUserServiceImpl.java @@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.BooleanUtil; +import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; @@ -25,10 +26,10 @@ import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; import com.baomidou.mybatisplus.core.metadata.IPage; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; import java.time.LocalDateTime; import java.util.*; @@ -127,6 +128,18 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { .orElse(null); } + @Override + public BrokerageUserDO getOrCreateBrokerageUser(Long id) { + BrokerageUserDO brokerageUser = brokerageUserMapper.selectById(id); + if (brokerageUser == null && ObjUtil.equal(BrokerageEnabledConditionEnum.ALL.getCondition(), + tradeConfigService.getTradeConfig().getBrokerageEnabledCondition())) { // 人人分销的情况下,如果分销人为空则创建分销人 + brokerageUser = new BrokerageUserDO().setId(id).setBrokerageEnabled(true).setBrokeragePrice(0) + .setBrokerageTime(LocalDateTime.now()).setFrozenPrice(0); + brokerageUserMapper.insert(brokerageUser); + } + return brokerageUser; + } + @Override public boolean updateUserPrice(Long id, Integer price) { if (price > 0) { @@ -184,7 +197,6 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { if (BrokerageEnabledConditionEnum.ALL.getCondition().equals(enabledCondition)) { // 人人分销:用户默认就有分销资格 brokerageUser.setBrokerageEnabled(true).setBrokerageTime(LocalDateTime.now()); } - brokerageUser.setBindUserId(bindUserId).setBindUserTime(LocalDateTime.now()); brokerageUserMapper.insert(fillBindUserData(bindUserId, brokerageUser)); } else { brokerageUserMapper.updateById(fillBindUserData(bindUserId, new BrokerageUserDO().setId(userId))); @@ -294,18 +306,23 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { } private void validateCanBindUser(BrokerageUserDO user, Long bindUserId) { - // 校验要绑定的用户有无推广资格 - BrokerageUserDO bindUser = brokerageUserMapper.selectById(bindUserId); + // 1.1 校验推广人是否存在 + MemberUserRespDTO bindUserInfo = memberUserApi.getUser(bindUserId); + if (bindUserInfo == null) { + throw exception(BROKERAGE_USER_NOT_EXISTS); + } + // 1.2 校验要绑定的用户有无推广资格 + BrokerageUserDO bindUser = getOrCreateBrokerageUser(bindUserId); if (bindUser == null || BooleanUtil.isFalse(bindUser.getBrokerageEnabled())) { throw exception(BROKERAGE_BIND_USER_NOT_ENABLED); } - // 校验绑定自己 + // 2. 校验绑定自己 if (Objects.equals(user.getId(), bindUserId)) { throw exception(BROKERAGE_BIND_SELF); } - // 下级不能绑定自己的上级 + // 3. 下级不能绑定自己的上级 for (int i = 0; i <= Short.MAX_VALUE; i++) { if (Objects.equals(bindUser.getBindUserId(), user.getId())) { throw exception(BROKERAGE_BIND_LOOP); From 63a8cc244d054040ad227a9b5651e0382a65d7e9 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 27 May 2024 18:16:44 +0800 Subject: [PATCH 338/684] =?UTF-8?q?=E3=80=90=E4=BF=AE=E6=94=B9=E3=80=91AI?= =?UTF-8?q?=20Image=20dall=20=E8=AF=B7=E6=B1=82=E8=BF=94=E5=9B=9E=E7=BB=93?= =?UTF-8?q?=E6=9E=84=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/image/AiImageController.java | 4 +- .../admin/image/vo/AiImageListRespVO.java | 49 +++++++++++++++++++ .../module/ai/convert/AiImageConvert.java | 8 +++ .../ai/service/image/AiImageServiceImpl.java | 46 ++++++++--------- 4 files changed, 83 insertions(+), 24 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index 2dbac1a9b..d072822eb 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -32,8 +32,8 @@ public class AiImageController { @Operation(summary = "获取image列表", description = "dall3、midjourney") @GetMapping("/list") - public PageResult list(@Validated @RequestBody AiImageListReqVO req) { - return aiImageService.list(req); + public CommonResult> list(@Validated @ModelAttribute AiImageListReqVO req) { + return CommonResult.success(aiImageService.list(req)); } @Operation(summary = "dall2/dall3绘画", description = "openAi dall3是付费的!") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java index 9222a4ec4..1ddec8d7b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java @@ -1,6 +1,9 @@ package cn.iocoder.yudao.module.ai.controller.admin.image.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; @@ -15,4 +18,50 @@ import lombok.experimental.Accessors; @Accessors(chain = true) public class AiImageListRespVO extends PageParam { + private Long id; + + @Schema(description = "用户id") + private Long userId; + + @Schema(description = "提示词") + private String prompt; + + @Schema(description = "模型 dall2/dall3、MJ、NIJI") + private String model; + + @Schema(description = "生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。") + private String size; + + @Schema(description = "风格") + private String style; + + @Schema(description = "图片地址(自己服务器)") + private String picUrl; + + @Schema(description = "绘画状态:提交、排队、绘画中、绘画完成、绘画失败") + private String status; + + @Schema(description = "绘画图片地址(绘画好的服务器)") + private String originalPicUrl; + + @Schema(description = "绘画错误信息") + private String errorMessage; + + @Schema(description = "是否发布") + private String publicStatus; + + // ============ mj 需要字段 + + @Schema(description = "用户操作的Nonce编号(MJ返回)") + private String mjNonceId; + + @Schema(description = "用户操作的操作编号(MJ返回)") + private String mjOperationId; + + @Schema(description = "用户操作的操作名字(MJ返回)") + private String mjOperationName; + + @Schema(description = "mj图片生产成功保存的 components json 数组") + private String mjOperations; + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java index f5e6699d7..df8647a5b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java @@ -23,6 +23,14 @@ public interface AiImageConvert { AiImageConvert INSTANCE = Mappers.getMapper(AiImageConvert.class); + /** + * 转换 - AiImageDallDrawingRespVO + * + * @param req + * @return + */ + AiImageDallRespVO convertAiImageDallDrawingRespVO(AiImageDO req); + /** * 转换 - AiImageDallDrawingRespVO * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index 01476a4a3..18659377c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -2,16 +2,10 @@ package cn.iocoder.yudao.module.ai.service.image; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.ai.core.exception.AiException; -import org.springframework.ai.image.ImageGeneration; -import org.springframework.ai.image.ImagePrompt; -import org.springframework.ai.image.ImageResponse; +import cn.hutool.http.HttpUtil; import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageModelEnum; import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageStyleEnum; -import org.springframework.ai.models.midjourney.api.MidjourneyInteractionsApi; -import org.springframework.ai.models.midjourney.api.req.ReRollReq; -import org.springframework.ai.models.midjourney.webSocket.MidjourneyWebSocketStarter; -import org.springframework.ai.models.midjourney.webSocket.WssNotify; +import cn.iocoder.yudao.framework.ai.core.exception.AiException; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; @@ -23,9 +17,17 @@ import cn.iocoder.yudao.module.ai.convert.AiImageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper; import cn.iocoder.yudao.module.ai.enums.AiImageStatusEnum; +import cn.iocoder.yudao.module.infra.api.file.FileApi; import jakarta.annotation.PostConstruct; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.ai.image.ImageGeneration; +import org.springframework.ai.image.ImagePrompt; +import org.springframework.ai.image.ImageResponse; +import org.springframework.ai.models.midjourney.api.MidjourneyInteractionsApi; +import org.springframework.ai.models.midjourney.api.req.ReRollReq; +import org.springframework.ai.models.midjourney.webSocket.MidjourneyWebSocketStarter; +import org.springframework.ai.models.midjourney.webSocket.WssNotify; import org.springframework.ai.openai.OpenAiImageClient; import org.springframework.ai.openai.OpenAiImageOptions; import org.springframework.stereotype.Service; @@ -47,6 +49,7 @@ import java.util.List; public class AiImageServiceImpl implements AiImageService { private final AiImageMapper aiImageMapper; + private final FileApi fileApi; private final OpenAiImageClient openAiImageClient; private final MidjourneyWebSocketStarter midjourneyWebSocketStarter; private final MidjourneyInteractionsApi midjourneyInteractionsApi; @@ -89,8 +92,6 @@ public class AiImageServiceImpl implements AiImageService { // 获取 model OpenAiImageModelEnum openAiImageModelEnum = OpenAiImageModelEnum.valueOfModel(req.getModel()); OpenAiImageStyleEnum openAiImageStyleEnum = OpenAiImageStyleEnum.valueOfStyle(req.getStyle()); - // 转换 AiImageDallDrawingRespVO - AiImageDallRespVO respVO = AiImageConvert.INSTANCE.convertAiImageDallDrawingRespVO(req); try { // 转换openai 参数 OpenAiImageOptions openAiImageOptions = new OpenAiImageOptions(); @@ -100,22 +101,21 @@ public class AiImageServiceImpl implements AiImageService { ImageResponse imageResponse = openAiImageClient.call(new ImagePrompt(req.getPrompt(), openAiImageOptions)); // 发送 ImageGeneration imageGeneration = imageResponse.getResult(); + // 图片保存到服务器 + String filePath = fileApi.createFile(HttpUtil.downloadBytes(imageGeneration.getOutput().getUrl())); // 保存数据库 - doSave(req.getPrompt(), req.getSize(), req.getModel(), - imageGeneration.getOutput().getUrl(), AiImageStatusEnum.COMPLETE, null, + AiImageDO aiImageDO = doSave(req.getPrompt(), req.getSize(), req.getModel(), + filePath, imageGeneration.getOutput().getUrl(), AiImageStatusEnum.COMPLETE, null, null, null, null); - // 返回 flex - respVO.setOriginalPicUrl(imageGeneration.getOutput().getUrl()); - respVO.setBase64(imageGeneration.getOutput().getB64Json()); - return respVO; + // 转换 AiImageDallDrawingRespVO + return AiImageConvert.INSTANCE.convertAiImageDallDrawingRespVO(aiImageDO); } catch (AiException aiException) { // 保存数据库 - doSave(req.getPrompt(), req.getSize(), req.getModel(), - null, AiImageStatusEnum.FAIL, aiException.getMessage(), + AiImageDO aiImageDO = doSave(req.getPrompt(), req.getSize(), req.getModel(), + null, null, AiImageStatusEnum.FAIL, aiException.getMessage(), null, null, null); // 发送错误信息 - respVO.setErrorMessage(aiException.getMessage()); - return respVO; + return AiImageConvert.INSTANCE.convertAiImageDallDrawingRespVO(aiImageDO); } } @@ -125,7 +125,7 @@ public class AiImageServiceImpl implements AiImageService { // 保存数据库 String messageId = String.valueOf(IdUtil.getSnowflakeNextId()); AiImageDO aiImageDO = doSave(req.getPrompt(), null, "midjoureny", - null, AiImageStatusEnum.SUBMIT, null, + null, null, AiImageStatusEnum.SUBMIT, null, messageId, null, null); // 提交 midjourney 任务 Boolean imagine = midjourneyInteractionsApi.imagine(messageId, req.getPrompt()); @@ -149,7 +149,7 @@ public class AiImageServiceImpl implements AiImageService { String mjOperationName = midjourneyOperationsVO.getLabel(); // 保存一个 image 任务记录 doSave(aiImageDO.getPrompt(), aiImageDO.getSize(), aiImageDO.getModel(), - null, AiImageStatusEnum.SUBMIT, null, + null, null, AiImageStatusEnum.SUBMIT, null, req.getMessageId(), req.getOperateId(), mjOperationName); // 提交操作 midjourneyInteractionsApi.reRoll( @@ -201,6 +201,7 @@ public class AiImageServiceImpl implements AiImageService { private AiImageDO doSave(String prompt, String size, String model, + String picUrl, String originalPicUrl, AiImageStatusEnum statusEnum, String errorMessage, @@ -218,6 +219,7 @@ public class AiImageServiceImpl implements AiImageService { // TODO @芋艿 如何上传到自己服务器 aiImageDO.setPicUrl(null); aiImageDO.setStatus(statusEnum.getStatus()); + aiImageDO.setPicUrl(picUrl); aiImageDO.setOriginalPicUrl(originalPicUrl); aiImageDO.setErrorMessage(errorMessage); // From e97408b3ac1d2c05c96855e622b362db6e33aca3 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 28 May 2024 11:39:29 +0800 Subject: [PATCH 339/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91dal?= =?UTF-8?q?l=20=E7=BB=98=E7=94=BB=EF=BC=8C=E6=94=B9=E4=B8=BA=E5=BC=82?= =?UTF-8?q?=E6=AD=A5=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/service/image/AiImageServiceImpl.java | 75 ++++++++++++------- 1 file changed, 47 insertions(+), 28 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index 18659377c..5d01483ec 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -35,6 +35,9 @@ import org.springframework.transaction.annotation.Transactional; import java.util.Collections; import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; /** * ai 作图 @@ -53,6 +56,8 @@ public class AiImageServiceImpl implements AiImageService { 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)); @PostConstruct public void startMidjourney() { @@ -89,34 +94,48 @@ public class AiImageServiceImpl implements AiImageService { @Override public AiImageDallRespVO dallDrawing(AiImageDallReqVO req) { - // 获取 model - OpenAiImageModelEnum openAiImageModelEnum = OpenAiImageModelEnum.valueOfModel(req.getModel()); - OpenAiImageStyleEnum openAiImageStyleEnum = OpenAiImageStyleEnum.valueOfStyle(req.getStyle()); - try { - // 转换openai 参数 - OpenAiImageOptions openAiImageOptions = new OpenAiImageOptions(); - openAiImageOptions.setModel(openAiImageModelEnum.getModel()); - openAiImageOptions.setStyle(openAiImageStyleEnum.getStyle()); - openAiImageOptions.setSize(req.getSize()); - ImageResponse imageResponse = openAiImageClient.call(new ImagePrompt(req.getPrompt(), openAiImageOptions)); - // 发送 - ImageGeneration imageGeneration = imageResponse.getResult(); - // 图片保存到服务器 - String filePath = fileApi.createFile(HttpUtil.downloadBytes(imageGeneration.getOutput().getUrl())); - // 保存数据库 - AiImageDO aiImageDO = doSave(req.getPrompt(), req.getSize(), req.getModel(), - filePath, imageGeneration.getOutput().getUrl(), AiImageStatusEnum.COMPLETE, null, - null, null, null); - // 转换 AiImageDallDrawingRespVO - return AiImageConvert.INSTANCE.convertAiImageDallDrawingRespVO(aiImageDO); - } catch (AiException aiException) { - // 保存数据库 - AiImageDO aiImageDO = doSave(req.getPrompt(), req.getSize(), req.getModel(), - null, null, AiImageStatusEnum.FAIL, aiException.getMessage(), - null, null, null); - // 发送错误信息 - return AiImageConvert.INSTANCE.convertAiImageDallDrawingRespVO(aiImageDO); - } + // 保存数据库 + AiImageDO aiImageDO = doSave(req.getPrompt(), req.getSize(), req.getModel(), + null, null, AiImageStatusEnum.IN_PROGRESS, null, + null, null, null); + // 异步执行 + EXECUTOR.execute(() -> { + try { + + // 获取 model + OpenAiImageModelEnum openAiImageModelEnum = OpenAiImageModelEnum.valueOfModel(req.getModel()); + OpenAiImageStyleEnum openAiImageStyleEnum = OpenAiImageStyleEnum.valueOfStyle(req.getStyle()); + + // 转换openai 参数 + OpenAiImageOptions openAiImageOptions = new OpenAiImageOptions(); + openAiImageOptions.setModel(openAiImageModelEnum.getModel()); + openAiImageOptions.setStyle(openAiImageStyleEnum.getStyle()); + openAiImageOptions.setSize(req.getSize()); + ImageResponse imageResponse = openAiImageClient.call(new ImagePrompt(req.getPrompt(), openAiImageOptions)); + // 发送 + ImageGeneration imageGeneration = imageResponse.getResult(); + // 图片保存到服务器 + 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()) + ); + } catch (AiException aiException) { + // 更新错误信息 + aiImageMapper.updateById( + new AiImageDO() + .setId(aiImageDO.getId()) + .setStatus(AiImageStatusEnum.FAIL.getStatus()) + .setErrorMessage(aiException.getMessage()) + ); + } + }); + // 转换 AiImageDallDrawingRespVO + return AiImageConvert.INSTANCE.convertAiImageDallDrawingRespVO(aiImageDO); } @Override From 9878abb03c7ebee3e234ee0a1f12491d9a6cb348 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 28 May 2024 14:05:44 +0800 Subject: [PATCH 340/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=8D=95=E4=B8=AA=20image=20=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/admin/image/AiImageController.java | 6 ++++++ .../iocoder/yudao/module/ai/convert/AiImageConvert.java | 8 ++++++++ .../yudao/module/ai/service/image/AiImageService.java | 8 ++++++++ .../yudao/module/ai/service/image/AiImageServiceImpl.java | 6 ++++++ 4 files changed, 28 insertions(+) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index d072822eb..e64edec2c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -36,6 +36,12 @@ public class AiImageController { return CommonResult.success(aiImageService.list(req)); } + @Operation(summary = "获取image信息", description = "获取image信息") + @GetMapping("/get") + public CommonResult get(@RequestParam("id") Long id) { + return CommonResult.success(aiImageService.get(id)); + } + @Operation(summary = "dall2/dall3绘画", description = "openAi dall3是付费的!") @PostMapping("/dall") public AiImageDallRespVO dallDrawing(@Validated @RequestBody AiImageDallReqVO req) { diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java index df8647a5b..c09614739 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java @@ -47,6 +47,14 @@ public interface AiImageConvert { */ List convertAiImageListRespVO(List list); + /** + * 转换 - AiImageListRespVO + * + * @param aiImageDO + * @return + */ + AiImageListRespVO convertAiImageListRespVO(AiImageDO aiImageDO); + /** * 转换 - AiImageMidjourneyOperationsVO * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java index 4af34d3bf..1d4e24764 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java @@ -20,6 +20,14 @@ public interface AiImageService { */ PageResult list(AiImageListReqVO req); + /** + * 获取 - image 信息 + * + * @param id + * @return + */ + AiImageListRespVO get(Long id); + /** * ai绘画 - dall2/dall3 绘画 * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index 5d01483ec..f635fb70e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -92,6 +92,12 @@ public class AiImageServiceImpl implements AiImageService { return result; } + @Override + public AiImageListRespVO get(Long id) { + AiImageDO aiImageDO = aiImageMapper.selectById(id); + return AiImageConvert.INSTANCE.convertAiImageListRespVO(aiImageDO); + } + @Override public AiImageDallRespVO dallDrawing(AiImageDallReqVO req) { // 保存数据库 From 7268f002d830c09fb93b040374a826cc4d7a4acb Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 28 May 2024 14:47:56 +0800 Subject: [PATCH 341/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91dal?= =?UTF-8?q?l=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/image/vo/AiImageListRespVO.java | 10 ++++ .../module/ai/convert/AiImageConvert.java | 8 +++ .../ai/service/image/AiImageServiceImpl.java | 54 +++++-------------- 3 files changed, 31 insertions(+), 41 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java index 1ddec8d7b..8e41f5a87 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java @@ -1,12 +1,16 @@ package cn.iocoder.yudao.module.ai.controller.admin.image.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; +import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; +import java.time.LocalDateTime; + /** * midjourney req * @@ -50,6 +54,12 @@ public class AiImageListRespVO extends PageParam { @Schema(description = "是否发布") private String publicStatus; + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; + // ============ mj 需要字段 @Schema(description = "用户操作的Nonce编号(MJ返回)") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java index c09614739..0f9271061 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java @@ -62,4 +62,12 @@ public interface AiImageConvert { * @return */ AiImageMidjourneyOperationsVO convertAiImageMidjourneyOperationsVO(MidjourneyMessage.Component component); + + /** + * 转换 - AiImageDO + * + * @param req + * @return + */ + AiImageDO convertAiImageDO(AiImageDallReqVO req); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index f635fb70e..6a0aea299 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -100,10 +100,12 @@ public class AiImageServiceImpl implements AiImageService { @Override public AiImageDallRespVO dallDrawing(AiImageDallReqVO req) { + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 保存数据库 - AiImageDO aiImageDO = doSave(req.getPrompt(), req.getSize(), req.getModel(), - null, null, AiImageStatusEnum.IN_PROGRESS, null, - null, null, null); + AiImageDO aiImageDO = AiImageConvert.INSTANCE.convertAiImageDO(req); + aiImageDO.setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus()); + aiImageDO.setUserId(loginUserId); + aiImageMapper.insert(aiImageDO); // 异步执行 EXECUTOR.execute(() -> { try { @@ -149,9 +151,10 @@ public class AiImageServiceImpl implements AiImageService { public void midjourney(AiImageMidjourneyReqVO req) { // 保存数据库 String messageId = String.valueOf(IdUtil.getSnowflakeNextId()); - AiImageDO aiImageDO = doSave(req.getPrompt(), null, "midjoureny", - null, null, AiImageStatusEnum.SUBMIT, null, - messageId, null, null); + // todo +// AiImageDO aiImageDO = doSave(req.getPrompt(), null, "midjoureny", +// null, null, AiImageStatusEnum.SUBMIT, null, +// messageId, null, null); // 提交 midjourney 任务 Boolean imagine = midjourneyInteractionsApi.imagine(messageId, req.getPrompt()); if (!imagine) { @@ -173,9 +176,10 @@ public class AiImageServiceImpl implements AiImageService { // 获取 mjOperationName String mjOperationName = midjourneyOperationsVO.getLabel(); // 保存一个 image 任务记录 - doSave(aiImageDO.getPrompt(), aiImageDO.getSize(), aiImageDO.getModel(), - null, null, AiImageStatusEnum.SUBMIT, null, - req.getMessageId(), req.getOperateId(), mjOperationName); + // todo +// doSave(aiImageDO.getPrompt(), aiImageDO.getSize(), aiImageDO.getModel(), +// null, null, AiImageStatusEnum.SUBMIT, null, +// req.getMessageId(), req.getOperateId(), mjOperationName); // 提交操作 midjourneyInteractionsApi.reRoll( new ReRollReq() @@ -222,36 +226,4 @@ public class AiImageServiceImpl implements AiImageService { } return aiImageDO; } - - private AiImageDO doSave(String prompt, - String size, - String model, - String picUrl, - String originalPicUrl, - AiImageStatusEnum statusEnum, - String errorMessage, - String mjMessageId, - String mjOperationId, - String mjOperationName) { - // 保存数据库 - Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); - AiImageDO aiImageDO = new AiImageDO(); - aiImageDO.setId(null); - aiImageDO.setPrompt(prompt); - aiImageDO.setSize(size); - aiImageDO.setModel(model); - aiImageDO.setUserId(loginUserId); - // TODO @芋艿 如何上传到自己服务器 - aiImageDO.setPicUrl(null); - aiImageDO.setStatus(statusEnum.getStatus()); - aiImageDO.setPicUrl(picUrl); - aiImageDO.setOriginalPicUrl(originalPicUrl); - aiImageDO.setErrorMessage(errorMessage); - // - aiImageDO.setMjNonceId(mjMessageId); - aiImageDO.setMjOperationId(mjOperationId); - aiImageDO.setMjOperationName(mjOperationName); - aiImageMapper.insert(aiImageDO); - return aiImageDO; - } } From 5f278ac23b392d6ecd9452cc50fdfc9e77af97e8 Mon Sep 17 00:00:00 2001 From: zhougang Date: Tue, 28 May 2024 15:09:01 +0800 Subject: [PATCH 342/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=83=A8=E5=88=86=E4=BB=A3=E7=A0=81=E9=A3=8E?= =?UTF-8?q?=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{Signature.java => ApiSignature.java} | 16 ++++--- .../signature/core/aop/SignatureAspect.java | 43 ++++++------------- .../core/redis/SignatureRedisDAO.java | 3 +- ...ot.autoconfigure.AutoConfiguration.imports | 3 +- .../core/filter/CacheRequestBodyWrapper.java | 4 -- 5 files changed, 26 insertions(+), 43 deletions(-) rename yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/annotation/{Signature.java => ApiSignature.java} (75%) diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/annotation/Signature.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/annotation/ApiSignature.java similarity index 75% rename from yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/annotation/Signature.java rename to yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/annotation/ApiSignature.java index 1b7e12786..e338ae709 100644 --- a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/annotation/Signature.java +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/annotation/ApiSignature.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.signature.core.annotation; import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; import java.lang.annotation.*; +import java.util.concurrent.TimeUnit; /** @@ -14,12 +15,17 @@ import java.lang.annotation.*; @Documented @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) -public @interface Signature { +public @interface ApiSignature { /** - * 同一个请求多长时间内有效 默认 10分钟 + * 同一个请求多长时间内有效 默认 60 秒 */ - long expireTime() default 600000L; + int timeout() default 60; + + /** + * 时间单位,默认为 SECONDS 秒 + */ + TimeUnit timeUnit() default TimeUnit.SECONDS; // ========================== 签名参数 ========================== @@ -50,8 +56,4 @@ public @interface Signature { */ String sign() default "sign"; - /** - * url 客户端不需要传递,但是可以用来加签(如: /{id} 带有动态参数的 url ,如果没有动态参数可设置为 false 不进行加签) - */ - boolean urlEnable() default true; } diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/aop/SignatureAspect.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/aop/SignatureAspect.java index dc1510465..a001419f8 100644 --- a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/aop/SignatureAspect.java +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/aop/SignatureAspect.java @@ -1,12 +1,13 @@ package cn.iocoder.yudao.framework.signature.core.aop; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.SignUtil; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; -import cn.iocoder.yudao.framework.signature.core.annotation.Signature; +import cn.iocoder.yudao.framework.signature.core.annotation.ApiSignature; import cn.iocoder.yudao.framework.signature.core.redis.SignatureRedisDAO; import cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyWrapper; import jakarta.servlet.http.HttpServletRequest; @@ -15,7 +16,6 @@ import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; -import org.springframework.util.Assert; import java.nio.charset.StandardCharsets; import java.util.Map; @@ -25,7 +25,7 @@ import java.util.TreeMap; import java.util.concurrent.TimeUnit; /** - * 拦截声明了 {@link Signature} 注解的方法,实现签名 + * 拦截声明了 {@link ApiSignature} 注解的方法,实现签名 * * @author Zhougang */ @@ -37,9 +37,9 @@ public class SignatureAspect { private final SignatureRedisDAO signatureRedisDAO; @Before("@annotation(signature)") - public void beforePointCut(JoinPoint joinPoint, Signature signature) { + public void beforePointCut(JoinPoint joinPoint, ApiSignature signature) { if (!verifySignature(signature, Objects.requireNonNull(ServletUtils.getRequest()))) { - log.info("[beforePointCut][方法{} 参数({}) 签名失败]", joinPoint.getSignature().toString(), + log.error("[beforePointCut][方法{} 参数({}) 签名失败]", joinPoint.getSignature().toString(), joinPoint.getArgs()); String message = StrUtil.blankToDefault(signature.message(), GlobalErrorCodeConstants.BAD_REQUEST.getMsg()); @@ -47,25 +47,22 @@ public class SignatureAspect { } } - private boolean verifySignature(Signature signature, HttpServletRequest request) { + private boolean verifySignature(ApiSignature signature, HttpServletRequest request) { if (!verifyHeaders(signature, request)) { return false; } // 校验 appId 是否能获取到对应的 appSecret String appId = request.getHeader(signature.appId()); String appSecret = signatureRedisDAO.getAppSecret(appId); - Assert.notNull(appSecret, "找不到对应的 appSecret"); + Assert.notNull(appSecret, "[appId({})] 找不到对应的 appSecret", appId); // 请求头 SortedMap headersMap = getRequestHeaders(signature, request); - // 如:/user/{id} url 带有动态参数的情况 - String urlParams = signature.urlEnable() ? request.getServletPath() : ""; // 请求参数 String requestParams = getRequestParams(request); // 请求体 - String requestBody = getRequestBody(request); + String requestBody = ServletUtils.isJsonRequest(request) ? ServletUtils.getBody(request) : ""; // 生成服务端签名 - String serverSignature = SignUtil.signParamsSha256(headersMap, - urlParams + requestParams + requestBody + appSecret); + String serverSignature = SignUtil.signParamsSha256(headersMap, requestParams + requestBody + appSecret); // 客户端签名 String clientSignature = request.getHeader(signature.sign()); if (!StrUtil.equals(clientSignature, serverSignature)) { @@ -73,7 +70,7 @@ public class SignatureAspect { } String nonce = headersMap.get(signature.nonce()); // 将 nonce 记入缓存,防止重复使用(重点二:此处需要将 ttl 设定为允许 timestamp 时间差的值 x 2 ) - signatureRedisDAO.setNonce(nonce, signature.expireTime(), TimeUnit.MILLISECONDS); + signatureRedisDAO.setNonce(nonce, signature.timeout() * 2L, signature.timeUnit()); return true; } @@ -87,7 +84,7 @@ public class SignatureAspect { * @param signature signature * @param request request */ - private boolean verifyHeaders(Signature signature, HttpServletRequest request) { + private boolean verifyHeaders(ApiSignature signature, HttpServletRequest request) { String appId = request.getHeader(signature.appId()); if (StrUtil.isBlank(appId)) { return false; @@ -97,7 +94,7 @@ public class SignatureAspect { return false; } String nonce = request.getHeader(signature.nonce()); - if (StrUtil.isBlank(nonce) || nonce.length() < 10) { + if (StrUtil.isBlank(nonce) || StrUtil.length(nonce) < 10) { return false; } String sign = request.getHeader(signature.sign()); @@ -105,7 +102,7 @@ public class SignatureAspect { return false; } // 其他合法性校验 - long expireTime = signature.expireTime(); + long expireTime = signature.timeUnit().toMillis(signature.timeout()); long requestTimestamp = Long.parseLong(timestamp); // 检查 timestamp 是否超出允许的范围 (重点一:此处需要取绝对值) long timestampDisparity = Math.abs(System.currentTimeMillis() - requestTimestamp); @@ -122,7 +119,7 @@ public class SignatureAspect { * @param request request * @return signature params */ - private SortedMap getRequestHeaders(Signature signature, HttpServletRequest request) { + private SortedMap getRequestHeaders(ApiSignature signature, HttpServletRequest request) { SortedMap sortedMap = new TreeMap<>(); sortedMap.put(signature.appId(), request.getHeader(signature.appId())); sortedMap.put(signature.timestamp(), request.getHeader(signature.timestamp())); @@ -154,17 +151,5 @@ public class SignatureAspect { return queryString.substring(1); } - /** - * 获取请求体参数 - * - * @param request request - * @return body - */ - private String getRequestBody(HttpServletRequest request) { - CacheRequestBodyWrapper requestWrapper = new CacheRequestBodyWrapper(request); - // 获取 body - return new String(requestWrapper.getBody(), StandardCharsets.UTF_8); - } - } diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/redis/SignatureRedisDAO.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/redis/SignatureRedisDAO.java index d00fe7f8d..326e238ee 100644 --- a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/redis/SignatureRedisDAO.java +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/redis/SignatureRedisDAO.java @@ -42,8 +42,7 @@ public class SignatureRedisDAO { } public void setNonce(String nonce, long time, TimeUnit timeUnit) { - // 将 nonce 记入缓存,防止重复使用(重点二:此处需要将 ttl 设定为允许 timestamp 时间差的值 x 2 ) - stringRedisTemplate.opsForValue().set(formatNonceKey(nonce), nonce, time * 2, timeUnit); + stringRedisTemplate.opsForValue().set(formatNonceKey(nonce), nonce, time, timeUnit); } private static String formatAppIdKey(String key) { diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-protection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index d7cd3a883..6cab74e75 100644 --- a/yudao-framework/yudao-spring-boot-starter-protection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,3 +1,4 @@ cn.iocoder.yudao.framework.idempotent.config.YudaoIdempotentConfiguration cn.iocoder.yudao.framework.lock4j.config.YudaoLock4jConfiguration -cn.iocoder.yudao.framework.ratelimiter.config.YudaoRateLimiterConfiguration \ No newline at end of file +cn.iocoder.yudao.framework.ratelimiter.config.YudaoRateLimiterConfiguration +cn.iocoder.yudao.framework.signature.config.YudaoSignatureAutoConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java index e181edeb4..8e80fa591 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java @@ -23,10 +23,6 @@ public class CacheRequestBodyWrapper extends HttpServletRequestWrapper { */ private final byte[] body; - public byte[] getBody() { - return body; - } - public CacheRequestBodyWrapper(HttpServletRequest request) { super(request); body = ServletUtils.getBodyBytes(request); From cfeb4bdca47f1ae807c86633ab82de83a8f95db2 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 28 May 2024 17:59:33 +0800 Subject: [PATCH 343/684] =?UTF-8?q?=E3=80=90=E6=B7=BB=E5=8A=A0=E3=80=91mid?= =?UTF-8?q?journey=20job(=E5=90=8C=E6=AD=A5=20mj=20=E7=BB=93=E6=9E=9C)=20?= =?UTF-8?q?=E6=9C=AA=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-module-ai/yudao-module-ai-biz/pom.xml | 4 ++++ .../yudao/module/ai/job/MidjourneyJob.java | 21 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/job/MidjourneyJob.java diff --git a/yudao-module-ai/yudao-module-ai-biz/pom.xml b/yudao-module-ai/yudao-module-ai-biz/pom.xml index d87818569..3eb23d57f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/pom.xml +++ b/yudao-module-ai/yudao-module-ai-biz/pom.xml @@ -47,6 +47,10 @@ cn.iocoder.boot yudao-spring-boot-starter-test + + cn.iocoder.boot + yudao-spring-boot-starter-job + diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/job/MidjourneyJob.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/job/MidjourneyJob.java new file mode 100644 index 000000000..71b3e7731 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/job/MidjourneyJob.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.ai.job; + +import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; +import org.springframework.stereotype.Component; + +/** + * midjourney job(同步 mj 结果) + * + * @author fansili + * @time 2024/5/28 17:57 + * @since 1.0 + */ +@Component +public class MidjourneyJob implements JobHandler { + + @Override + public String execute(String param) throws Exception { + // todo @范 同步 midjourney proxy 结果 + return ""; + } +} From 4932ce60d24e0b9615df4314927a2f14ecd5861a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 28 May 2024 22:09:35 +0800 Subject: [PATCH 344/684] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91AI=EF=BC=9AAI=20=E7=BB=98=E5=9B=BE=E7=9A=84?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/enums/AiImageStatusEnum.java | 2 + .../admin/image/AiImageController.java | 12 ++++++ .../module/ai/convert/AiImageConvert.java | 1 + .../ai/dal/dataobject/image/AiImageDO.java | 2 + .../ai/service/image/AiImageServiceImpl.java | 37 ++++++++++++------- 5 files changed, 40 insertions(+), 14 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageStatusEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageStatusEnum.java index a5231a3bf..534ad7e3f 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageStatusEnum.java +++ b/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; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index e64edec2c..038b02454 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/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> 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 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 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 delete(@RequestParam("id") Long id) { aiImageService.delete(id); return success(null); } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java index 0f9271061..d094f489d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java +++ b/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 * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java index cb3aedda1..eb901e23f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java +++ b/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; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index 6a0aea299..77299fceb 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/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 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) { // 校验记录是否存在 From c7ee3dc2cd623148c0e56c5db5a9e76dbe138d00 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 29 May 2024 08:34:40 +0800 Subject: [PATCH 345/684] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91AI=EF=BC=9AAI=20=E7=BB=98=E5=9B=BE=E7=9A=84?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/dal/dataobject/image/AiImageDO.java | 16 +++++++++++----- .../ai/service/image/AiImageServiceImpl.java | 3 +-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java index eb901e23f..2a21acd13 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java @@ -8,16 +8,17 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; +// TODO @fan:@time、@sine 注解可以不加哈 /** - * ai 绘画 + * AI 绘画 DO * * @author fansili * @time 2024/4/25 15:53 * @since 1.0 */ @Data -@Accessors(chain = true) -@TableName("ai_image") +@Accessors(chain = true) // TODO @fan:这个不用添加哈,全局的 lombok.config 搞啦 +@TableName("ai_image") // TODO @fan:建议放在 @Data 前面,因为它是关键注解,@Data 本质可悲替代 public class AiImageDO extends BaseDO { @TableId(type = IdType.AUTO) @@ -31,12 +32,14 @@ public class AiImageDO extends BaseDO { // TODO @fan:要加一个平台字段;platform;因为一个平台,会有多种 model 模型; - @Schema(description = "模型 dall2/dall3、MJ、NIJI") + @Schema(description = "模型") private String model; - @Schema(description = "生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。") + // TODO @fan:这个记录到 db,要不改成 width、height?更明确的尺寸 + @Schema(description = "尺寸大小") private String size; + // TODO @fan:style 是所有模型都有么?如果不是,是不是靠 drawRequest 记录下就好了; @Schema(description = "风格") private String style; @@ -55,6 +58,9 @@ public class AiImageDO extends BaseDO { @Schema(description = "是否发布") private String publicStatus; + // TODO @fan:增加一个 Map 字段,drawRequest;用于记录请求模型的字段;对应的就是 ImageOptions + // TODO @fan:增加一个 Map 字段,记录 ImageResponseMetadata?这样 mjNonceId、mjOperationId、mjOperationName、mjOperations 这些字段,貌似可以收掉 + // ============ mj 需要字段 @Schema(description = "用户操作的Nonce编号(MJ返回)") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index 77299fceb..18b1ef0ea 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -141,8 +141,7 @@ 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()) - ); + .setPicUrl(filePath).setOriginalPicUrl(imageGeneration.getOutput().getUrl())); } catch (AiException aiException) { // TODO @fan:错误日志,也打印下哈;因为 aiException.getMessage() 比较精简; aiImageMapper.updateById(new AiImageDO().setId(aiImageDO.getId()).setStatus(AiImageStatusEnum.FAIL.getStatus()) From 1b725fd517d729f34544f6330f6898d25efabab0 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 29 May 2024 10:19:22 +0800 Subject: [PATCH 346/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E8=B0=83=E6=95=B4=20AI=20Image=20=E5=A2=9E=E8=82=8C=20draw=20r?= =?UTF-8?q?quest=20=E5=92=8C=20response?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/dal/dataobject/image/AiImageDO.java | 62 +++++++++---------- 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java index 2a21acd13..d18d03d38 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java @@ -6,19 +6,16 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.experimental.Accessors; -// TODO @fan:@time、@sine 注解可以不加哈 +import java.util.Map; + /** * AI 绘画 DO * * @author fansili - * @time 2024/4/25 15:53 - * @since 1.0 */ +@TableName("ai_image") @Data -@Accessors(chain = true) // TODO @fan:这个不用添加哈,全局的 lombok.config 搞啦 -@TableName("ai_image") // TODO @fan:建议放在 @Data 前面,因为它是关键注解,@Data 本质可悲替代 public class AiImageDO extends BaseDO { @TableId(type = IdType.AUTO) @@ -30,50 +27,49 @@ public class AiImageDO extends BaseDO { @Schema(description = "提示词") private String prompt; - // TODO @fan:要加一个平台字段;platform;因为一个平台,会有多种 model 模型; + @Schema(description = "平台") + private String platform; @Schema(description = "模型") private String model; - // TODO @fan:这个记录到 db,要不改成 width、height?更明确的尺寸 - @Schema(description = "尺寸大小") - private String size; + @Schema(description = "图片宽度") + private String width; - // TODO @fan:style 是所有模型都有么?如果不是,是不是靠 drawRequest 记录下就好了; - @Schema(description = "风格") - private String style; - - @Schema(description = "图片地址(自己服务器)") - private String picUrl; + @Schema(description = "图片高度") + private String height; @Schema(description = "绘画状态:提交、排队、绘画中、绘画完成、绘画失败") private String status; + @Schema(description = "是否发布") + private String publicStatus; + + @Schema(description = "图片地址(自己服务器)") + private String picUrl; + @Schema(description = "绘画图片地址(绘画好的服务器)") private String originalPicUrl; @Schema(description = "绘画错误信息") private String errorMessage; - @Schema(description = "是否发布") - private String publicStatus; + // ============ 绘画请求参数 - // TODO @fan:增加一个 Map 字段,drawRequest;用于记录请求模型的字段;对应的就是 ImageOptions - // TODO @fan:增加一个 Map 字段,记录 ImageResponseMetadata?这样 mjNonceId、mjOperationId、mjOperationName、mjOperations 这些字段,貌似可以收掉 + /** + * - style + */ + @Schema(description = "绘画请求参数") + private Map drawRequest; - // ============ mj 需要字段 - - @Schema(description = "用户操作的Nonce编号(MJ返回)") - private String mjNonceId; - - @Schema(description = "用户操作的操作编号(MJ返回)") - private String mjOperationId; - - @Schema(description = "用户操作的操作名字(MJ返回)") - private String mjOperationName; - - @Schema(description = "mj图片生产成功保存的 components json 数组") - private String mjOperations; + /** + * - mjNonceId + * - mjOperationId + * - mjOperationName + * - mjOperations + */ + @Schema(description = "绘画请求响应参数") + private Map drawResponse; } From 54b60cd564e25040b6996f7e0ada536ce0c7b194 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 29 May 2024 10:29:32 +0800 Subject: [PATCH 347/684] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91=E4=BF=AE=E6=94=B9=20image=20controller=20=E5=91=BD?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/image/AiImageController.java | 49 +++++++------------ 1 file changed, 17 insertions(+), 32 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index 038b02454..f1decdc86 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -6,48 +6,33 @@ import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; import cn.iocoder.yudao.module.ai.service.image.AiImageService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.AllArgsConstructor; +import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -// TODO @芋艿:整理接口定义 -// TODO @fan:参考 AiChatMessageController 改下 swagger 注解、注释 -/** - * ai作图 - * - * @author fansili - * @time 2024/4/25 15:49 - * @since 1.0 - */ -@Tag(name = "A10-ai作图") +@Tag(name = "管理后台 - Ai 绘画") @RestController @RequestMapping("/ai/image") @Slf4j -@AllArgsConstructor public class AiImageController { - // TODO @fan:使用 @Resource 注入哈;然后 aiImageService => imageService; - private final AiImageService aiImageService; + @Resource + private AiImageService aiImageService; - // TODO @fan:分页列表,建议是 getImagePage,包括接口 path 也建议改下哈; - // TODO @fan:@ModelAttribute 不需要哈; - // TODO @fan:这个要不搞成 my-page?因为是我的哈 - @Operation(summary = "获取image列表", description = "dall3、midjourney") - @GetMapping("/list") - public CommonResult> list(@Validated @ModelAttribute AiImageListReqVO req) { - // TODO @fan:import static,这样只要 success() 就行啦 - return CommonResult.success(aiImageService.list(req)); + @Operation(summary = "获取 - 我的分页列表", description = "dall3、midjourney") + @GetMapping("/my-page") + public CommonResult> myPage(@Validated AiImageListReqVO req) { + return success(aiImageService.list(req)); } - // TODO @fan:搞成 get-my? - // TODO @fan:方法名改下哈。 - @Operation(summary = "获取image信息", description = "获取image信息") - @GetMapping("/get") - public CommonResult get(@RequestParam("id") Long id) { - return CommonResult.success(aiImageService.get(id)); + @Operation(summary = "获取 - 我的 image 信息", description = "...") + @GetMapping("/get-my") + public CommonResult getMy(@RequestParam("id") Long id) { + return CommonResult.success(aiImageService.getMy(id)); } // TODO @fan:建议把 dallDrawing、midjourney 融合成一个 draw 接口,异步绘制;然后返回一个 id 给前端;前端通过 get 接口轮询,直到获取到生成成功 @@ -79,11 +64,11 @@ public class AiImageController { return success(null); } - // TODO @fan:delete-my?需要校验是不是当前人哈 @Operation(summary = "删除绘画记录", description = "") - @DeleteMapping("/delete") - public CommonResult delete(@RequestParam("id") Long id) { - aiImageService.delete(id); + @DeleteMapping("/delete-my") + public CommonResult deleteMy(@RequestParam("id") Long id) { + Long loginUserId = getLoginUserId(); + aiImageService.deleteMy(id, loginUserId); return success(null); } From 1d538239829145b3ed25ae68e53350b472b631bc Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 29 May 2024 10:30:22 +0800 Subject: [PATCH 348/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91ai?= =?UTF-8?q?=20image=20=E5=88=A0=E9=99=A4=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=9D=83=E9=99=90=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index ca0af92f4..da48c61e5 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -40,4 +40,7 @@ public interface ErrorCodeConstants { ErrorCode AI_MIDJOURNEY_OPERATION_NOT_EXISTS = new ErrorCode(1_022_000_040, "midjourney 操作不存在!"); ErrorCode AI_MIDJOURNEY_MESSAGE_ID_INCORRECT = new ErrorCode(1_022_000_040, "midjourney message id 不正确!"); + // ========== API 绘画 1-040-005-000 ========== + + ErrorCode AI_IMAGE_NOT_CREATE_USER = new ErrorCode(1_022_005_000, "不是创建用户,不能删除 image!"); } From ed372cffc789a3fa5961f4deaa1bc2fee703f599 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 29 May 2024 10:30:40 +0800 Subject: [PATCH 349/684] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91=E4=BF=AE=E6=94=B9=20ai=20image=20status?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/enums/AiImageStatusEnum.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageStatusEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageStatusEnum.java index 534ad7e3f..ad4ab4590 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageStatusEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageStatusEnum.java @@ -14,19 +14,16 @@ import lombok.Getter; @Getter public enum AiImageStatusEnum { - // TODO @fan:改成 10 生成中;20 成功;30 失败;其它可以去掉噢 - SUBMIT("submit", "提交任务"), - WAITING("waiting", "等待"), - IN_PROGRESS("in_progress", "进行中"), - COMPLETE("complete", "完成"), - FAIL("fail", "失败"), + IN_PROGRESS("10", "进行中"), + COMPLETE("20", "完成"), + FAIL("30", "失败"), ; // TODO @fan:final 一下 - private String status; + private final String status; - private String name; + private final String name; public static AiImageStatusEnum valueOfStatus(String status) { From f347b15a1e5a98118e535b5e92340a1e292bb001 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 29 May 2024 10:32:00 +0800 Subject: [PATCH 350/684] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91=E5=88=A0=E9=99=A4=20mj=20=E7=9B=B8=E5=85=B3=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=EF=BC=8C=E6=8A=BD=E7=A6=BB=E5=88=B0=20drawRequest=20?= =?UTF-8?q?=E5=92=8C=20drwaResponse?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/dal/mysql/image/AiImageMapper.java | 3 +- .../ai/service/image/AiImageService.java | 5 +- .../ai/service/image/AiImageServiceImpl.java | 61 +++++++++++-------- .../YuDaoMidjourneyMessageHandler.java | 9 +-- 4 files changed, 44 insertions(+), 34 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java index 9e75cb436..6cf8a80e7 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java @@ -24,7 +24,8 @@ public interface AiImageMapper extends BaseMapperX { * @param aiImageDO */ default void updateByMjNonce(Long mjNonceId, AiImageDO aiImageDO) { - this.update(aiImageDO, new LambdaQueryWrapperX().eq(AiImageDO::getMjNonceId, mjNonceId)); +// this.update(aiImageDO, new LambdaQueryWrapperX().eq(AiImageDO::getMjNonceId, mjNonceId)); + return; } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java index 1d4e24764..68543e50b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java @@ -26,7 +26,7 @@ public interface AiImageService { * @param id * @return */ - AiImageListRespVO get(Long id); + AiImageListRespVO getMy(Long id); /** * ai绘画 - dall2/dall3 绘画 @@ -54,7 +54,8 @@ public interface AiImageService { * 删除 - image 记录 * * @param id + * @param loginUserId */ - void delete(Long id); + void deleteMy(Long id, Long loginUserId); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index 18b1ef0ea..87e0fa2ff 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -39,6 +39,9 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; + + // TODO @fan:注释优化下哈 /** * ai 作图 @@ -105,7 +108,7 @@ public class AiImageServiceImpl implements AiImageService { // TODO @fan:1)返回 DO;VO 的翻译,交给 Controller;2)还有,使用 BeanUtils 替代哈 @Override - public AiImageListRespVO get(Long id) { + public AiImageListRespVO getMy(Long id) { AiImageDO aiImageDO = aiImageMapper.selectById(id); return AiImageConvert.INSTANCE.convertAiImageListRespVO(aiImageDO); } @@ -172,34 +175,37 @@ public class AiImageServiceImpl implements AiImageService { @Transactional(rollbackFor = Exception.class) @Override public void midjourneyOperate(AiImageMidjourneyOperateReqVO req) { - // 校验是否存在 - AiImageDO aiImageDO = validateExists(req.getId()); - // 获取 midjourneyOperations - List midjourneyOperations = getMidjourneyOperations(aiImageDO); - // 校验 OperateId 是否存在 - AiImageMidjourneyOperationsVO midjourneyOperationsVO = validateMidjourneyOperationsExists(midjourneyOperations, req.getOperateId()); - // 校验 messageId - validateMessageId(aiImageDO.getMjNonceId(), req.getMessageId()); - // 获取 mjOperationName - String mjOperationName = midjourneyOperationsVO.getLabel(); - // 保存一个 image 任务记录 - // todo -// doSave(aiImageDO.getPrompt(), aiImageDO.getSize(), aiImageDO.getModel(), -// null, null, AiImageStatusEnum.SUBMIT, null, -// req.getMessageId(), req.getOperateId(), mjOperationName); - // 提交操作 - midjourneyInteractionsApi.reRoll( - new ReRollReq() - .setCustomId(req.getOperateId()) - .setMessageId(req.getMessageId()) - ); +// // 校验是否存在 +// AiImageDO aiImageDO = validateExists(req.getId()); +// // 获取 midjourneyOperations +// List midjourneyOperations = getMidjourneyOperations(aiImageDO); +// // 校验 OperateId 是否存在 +// AiImageMidjourneyOperationsVO midjourneyOperationsVO = validateMidjourneyOperationsExists(midjourneyOperations, req.getOperateId()); +// // 校验 messageId +// validateMessageId(aiImageDO.getMjNonceId(), req.getMessageId()); +// // 获取 mjOperationName +// String mjOperationName = midjourneyOperationsVO.getLabel(); +// // 保存一个 image 任务记录 +// // todo +//// doSave(aiImageDO.getPrompt(), aiImageDO.getSize(), aiImageDO.getModel(), +//// null, null, AiImageStatusEnum.SUBMIT, null, +//// req.getMessageId(), req.getOperateId(), mjOperationName); +// // 提交操作 +// midjourneyInteractionsApi.reRoll( +// new ReRollReq() +// .setCustomId(req.getOperateId()) +// .setMessageId(req.getMessageId()) +// ); } // TODO @fan:1)需要校验存在;2)需要校验属于我; @Override - public void delete(Long id) { + public void deleteMy(Long id, Long loginUserId) { // 校验记录是否存在 AiImageDO aiImageDO = validateExists(id); + if (!aiImageDO.getUserId().equals(loginUserId)) { + throw exception(ErrorCodeConstants.AI_IMAGE_NOT_CREATE_USER); + } // 删除记录 aiImageMapper.deleteById(id); } @@ -221,10 +227,11 @@ public class AiImageServiceImpl implements AiImageService { private List getMidjourneyOperations(AiImageDO aiImageDO) { - if (StrUtil.isBlank(aiImageDO.getMjOperations())) { - return Collections.emptyList(); - } - return JsonUtils.parseArray(aiImageDO.getMjOperations(), AiImageMidjourneyOperationsVO.class); +// if (StrUtil.isBlank(aiImageDO.getMjOperations())) { +// return Collections.emptyList(); +// } +// return JsonUtils.parseArray(aiImageDO.getMjOperations(), AiImageMidjourneyOperationsVO.class); + return null; } private AiImageDO validateExists(Long id) { diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/YuDaoMidjourneyMessageHandler.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/YuDaoMidjourneyMessageHandler.java index 7b95b968e..6235a9bd7 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/YuDaoMidjourneyMessageHandler.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/YuDaoMidjourneyMessageHandler.java @@ -96,9 +96,10 @@ public class YuDaoMidjourneyMessageHandler implements MidjourneyMessageHandler { drawingStatusEnum = AiImageStatusEnum.COMPLETE; } else if (MidjourneyGennerateStatusEnum.IN_PROGRESS.getStatus().equals(generateStatus)) { drawingStatusEnum = AiImageStatusEnum.IN_PROGRESS; - } else if (MidjourneyGennerateStatusEnum.WAITING.getStatus().equals(generateStatus)) { - drawingStatusEnum = AiImageStatusEnum.WAITING; } +// else if (MidjourneyGennerateStatusEnum.WAITING.getStatus().equals(generateStatus)) { +// drawingStatusEnum = AiImageStatusEnum.WAITING; +// } // 获取 midjourneyOperations List midjourneyOperations = getMidjourneyOperationsList(midjourneyMessage); // 更新数据库 @@ -106,8 +107,8 @@ public class YuDaoMidjourneyMessageHandler implements MidjourneyMessageHandler { new AiImageDO() .setOriginalPicUrl(imageUrl) .setStatus(drawingStatusEnum == null ? null : drawingStatusEnum.getStatus()) - .setMjNonceId(midjourneyMessage.getId()) - .setMjOperations(JsonUtils.toJsonString(midjourneyOperations)) +// .setMjNonceId(midjourneyMessage.getId()) +// .setMjOperations(JsonUtils.toJsonString(midjourneyOperations)) ); } From e4a0512b5185f99cb88576d0f062a61c477eef0b Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 29 May 2024 10:53:37 +0800 Subject: [PATCH 351/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91AI?= =?UTF-8?q?=20Image=20=E5=88=86=E9=A1=B5=E5=88=97=E8=A1=A8=E3=80=81get-my?= =?UTF-8?q?=20=E8=BF=94=E5=9B=9E=20resp=20=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/image/AiImageController.java | 4 +- .../admin/image/vo/AiImageDallRespVO.java | 60 ++++++++++++----- .../admin/image/vo/AiImageListReqVO.java | 2 +- .../admin/image/vo/AiImageListRespVO.java | 66 ++++++++++--------- .../ai/dal/dataobject/image/AiImageDO.java | 4 ++ .../ai/service/image/AiImageService.java | 2 +- .../ai/service/image/AiImageServiceImpl.java | 2 +- 7 files changed, 86 insertions(+), 54 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index f1decdc86..6d15798e4 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -38,8 +38,8 @@ public class AiImageController { // TODO @fan:建议把 dallDrawing、midjourney 融合成一个 draw 接口,异步绘制;然后返回一个 id 给前端;前端通过 get 接口轮询,直到获取到生成成功 @Operation(summary = "dall2/dall3绘画", description = "openAi dall3是付费的!") @PostMapping("/dall") - public AiImageDallRespVO dallDrawing(@Validated @RequestBody AiImageDallReqVO req) { - return aiImageService.dallDrawing(req); + public AiImageDallRespVO dall(@Validated @RequestBody AiImageDallReqVO req) { + return aiImageService.dall(req); } @Operation(summary = "midjourney绘画", description = "midjourney图片绘画流程:1、提交任务 2、获取完成的任务 3、选择对应功能 4、获取最终结果") diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallRespVO.java index 18c27a64f..934141339 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallRespVO.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.ai.controller.admin.image.vo; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; import lombok.Data; import lombok.experimental.Accessors; +import java.util.Map; + /** * dall2/dall2 绘画 * @@ -17,31 +17,57 @@ import lombok.experimental.Accessors; @Accessors(chain = true) public class AiImageDallRespVO { - @Schema(description = "提示词") - @NotNull(message = "提示词不能为空!") - @Size(max = 1200, message = "提示词最大1200") + @Schema(description = "id编号", example = "1") + private Long id; + + @Schema(description = "用户id", example = "1") + private Long userId; + + @Schema(description = "提示词", example = "南极的小企鹅") private String prompt; - @Schema(description = "模型") - @NotNull(message = "模型不能为空") + @Schema(description = "平台", example = "openai") + private String platform; + + @Schema(description = "模型", example = "dall2") private String model; - @Schema(description = "风格") - private String style; + @Schema(description = "图片宽度", example = "1024") + private String width; - @Schema(description = "图片size 1024x1024 ...") - private String size; + @Schema(description = "图片高度", example = "1024") + private String height; - @Schema(description = "图片地址(自己服务器)") + @Schema(description = "绘画状态:10 进行中、20 绘画完成、30 绘画失败", example = "10") + private String status; + + @Schema(description = "是否发布", example = "public") + private String publicStatus; + + @Schema(description = "图片地址(自己服务器)", example = "http://") private String picUrl; - @Schema(description = "可以访问图像的URL。") + @Schema(description = "绘画图片地址(绘画好的服务器)", example = "http://") private String originalPicUrl; - @Schema(description = "图片base64。") - private String base64; - - @Schema(description = "错误信息。") + @Schema(description = "绘画错误信息", example = "图片错误信息") private String errorMessage; + // ============ 绘画请求参数 + + /** + * - style + */ + @Schema(description = "绘画请求参数") + private Map drawRequest; + + /** + * - mjNonceId + * - mjOperationId + * - mjOperationName + * - mjOperations + */ + @Schema(description = "绘画请求响应参数") + private Map drawResponse; + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListReqVO.java index e75ebb4b3..6af980363 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListReqVO.java @@ -5,7 +5,7 @@ import lombok.Data; import lombok.experimental.Accessors; /** - * midjourney req + * AI Image 我的图片列表 req * * @author fansili * @time 2024/4/28 17:42 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java index 8e41f5a87..c0bb20773 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java @@ -10,6 +10,7 @@ import lombok.Data; import lombok.experimental.Accessors; import java.time.LocalDateTime; +import java.util.Map; /** * midjourney req @@ -22,56 +23,57 @@ import java.time.LocalDateTime; @Accessors(chain = true) public class AiImageListRespVO extends PageParam { + @Schema(description = "id编号", example = "1") private Long id; - @Schema(description = "用户id") + @Schema(description = "用户id", example = "1") private Long userId; - @Schema(description = "提示词") + @Schema(description = "提示词", example = "南极的小企鹅") private String prompt; - @Schema(description = "模型 dall2/dall3、MJ、NIJI") + @Schema(description = "平台", example = "openai") + private String platform; + + @Schema(description = "模型", example = "dall2") private String model; - @Schema(description = "生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。") - private String size; + @Schema(description = "图片宽度", example = "1024") + private String width; - @Schema(description = "风格") - private String style; + @Schema(description = "图片高度", example = "1024") + private String height; - @Schema(description = "图片地址(自己服务器)") - private String picUrl; - - @Schema(description = "绘画状态:提交、排队、绘画中、绘画完成、绘画失败") + @Schema(description = "绘画状态:10 进行中、20 绘画完成、30 绘画失败", example = "10") private String status; - @Schema(description = "绘画图片地址(绘画好的服务器)") - private String originalPicUrl; - - @Schema(description = "绘画错误信息") - private String errorMessage; - - @Schema(description = "是否发布") + @Schema(description = "是否发布", example = "public") private String publicStatus; - @Schema(description = "创建时间") - private LocalDateTime createTime; + @Schema(description = "图片地址(自己服务器)", example = "http://") + private String picUrl; - @Schema(description = "更新时间") - private LocalDateTime updateTime; + @Schema(description = "绘画图片地址(绘画好的服务器)", example = "http://") + private String originalPicUrl; - // ============ mj 需要字段 + @Schema(description = "绘画错误信息", example = "图片错误信息") + private String errorMessage; - @Schema(description = "用户操作的Nonce编号(MJ返回)") - private String mjNonceId; + // ============ 绘画请求参数 - @Schema(description = "用户操作的操作编号(MJ返回)") - private String mjOperationId; + /** + * - style + */ + @Schema(description = "绘画请求参数") + private Map drawRequest; - @Schema(description = "用户操作的操作名字(MJ返回)") - private String mjOperationName; - - @Schema(description = "mj图片生产成功保存的 components json 数组") - private String mjOperations; + /** + * - mjNonceId + * - mjOperationId + * - mjOperationName + * - mjOperations + */ + @Schema(description = "绘画请求响应参数") + private Map drawResponse; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java index d18d03d38..1474fc683 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java @@ -2,8 +2,10 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.image; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -60,6 +62,7 @@ public class AiImageDO extends BaseDO { * - style */ @Schema(description = "绘画请求参数") + @TableField(typeHandler = JacksonTypeHandler.class) private Map drawRequest; /** @@ -69,6 +72,7 @@ public class AiImageDO extends BaseDO { * - mjOperations */ @Schema(description = "绘画请求响应参数") + @TableField(typeHandler = JacksonTypeHandler.class) private Map drawResponse; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java index 68543e50b..2ffd72240 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java @@ -33,7 +33,7 @@ public interface AiImageService { * * @param req */ - AiImageDallRespVO dallDrawing(AiImageDallReqVO req); + AiImageDallRespVO dall(AiImageDallReqVO req); /** * midjourney 图片生成 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index 87e0fa2ff..93c1e51f0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -115,7 +115,7 @@ public class AiImageServiceImpl implements AiImageService { // TODO @fan:1)loginUserId 通过 controller 传入; @Override - public AiImageDallRespVO dallDrawing(AiImageDallReqVO req) { + public AiImageDallRespVO dall(AiImageDallReqVO req) { Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); // 保存数据库 // TODO @fan:1)使用 BeanUtils;2)使用链式调用哈; From e582aaad2eeabe4411eec239b67a83c02ee72325 Mon Sep 17 00:00:00 2001 From: xiaoxin <718949661@qq.com> Date: Wed, 29 May 2024 15:17:15 +0800 Subject: [PATCH 352/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9Asuno=E9=9F=B3=E4=B9=90=E7=94=9F=E6=88=90=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/music/MusicController.java | 31 +++++++++ .../admin/music/vo/MusicDataVO.java | 64 +++++++++++++++++++ .../controller/admin/music/vo/SunoReqVO.java | 40 ++++++++++++ .../controller/admin/music/vo/SunoRespVO.java | 29 +++++++++ .../module/ai/service/music/MusicService.java | 19 ++++++ .../ai/service/music/MusicServiceImpl.java | 25 ++++++++ .../ai/config/YudaoAiAutoConfiguration.java | 17 +++-- .../ai/config/YudaoAiProperties.java | 11 ++++ .../ai/core/model/suno/SunoConfig.java | 21 ++++++ .../ai/core/model/suno/{ => api}/SunoApi.java | 32 ++++++---- .../yudao/framework/ai/suno/SunoTests.java | 19 ++++-- .../src/main/resources/application.yaml | 3 + 12 files changed, 287 insertions(+), 24 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/MusicController.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/MusicDataVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/SunoReqVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/SunoRespVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/MusicService.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/MusicServiceImpl.java create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/SunoConfig.java rename yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/{ => api}/SunoApi.java (79%) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/MusicController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/MusicController.java new file mode 100644 index 000000000..ae66d71aa --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/MusicController.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.ai.controller.admin.music; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.ai.controller.admin.music.vo.SunoReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.music.vo.SunoRespVO; +import cn.iocoder.yudao.module.ai.service.music.MusicService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - AI 音乐生成") +@RestController +@RequestMapping("/ai/music") +@RequiredArgsConstructor +public class MusicController { + + private final MusicService musicService; + + @PostMapping("/suno-gen") + @Operation(summary = "音乐生成") + public CommonResult musicGen(@RequestBody @Valid SunoReqVO sunoReqVO) { + return success(musicService.musicGen(sunoReqVO)); + } +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/MusicDataVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/MusicDataVO.java new file mode 100644 index 000000000..ce372aff9 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/MusicDataVO.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.ai.controller.admin.music.vo; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +/** + * 表示单个音乐数据的类 + */ +@Data +public class MusicDataVO { + /** + * 音乐数据的 ID + */ + private String id; + + /** + * 音乐音频的标题 + */ + private String title; + + /** + * 音乐音频的图片 URL + */ + @JsonProperty("image_url") + private String imageUrl; + + /** + * 音乐音频的歌词 + */ + private String lyric; + + /** + * 音乐音频的 URL + */ + @JsonProperty("audio_url") + private String audioUrl; + + /** + * 音乐视频的 URL + */ + @JsonProperty("video_url") + private String videoUrl; + + /** + * 音乐音频的创建时间 + */ + @JsonProperty("created_at") + private String createdAt; + + /** + * 使用的模型名称 + */ + private String model; + + /** + * 生成音乐音频的提示 + */ + private String prompt; + + /** + * 音乐音频的风格 + */ + private String style; +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/SunoReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/SunoReqVO.java new file mode 100644 index 000000000..ae40cf540 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/SunoReqVO.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.ai.controller.admin.music.vo; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Data; +import lombok.experimental.Accessors; + +@Data +@Accessors(chain = true) +@JsonInclude(value = JsonInclude.Include.NON_NULL) +public class SunoReqVO { + /** + * 用于生成音乐音频的提示 + */ + private String prompt; + + /** + * 用于生成音乐音频的歌词 + */ + private String lyric; + + /** + * 指示音乐音频是否为定制,如果为 true,则从歌词生成,否则从提示生成 + */ + private boolean custom; + + /** + * 音乐音频的标题 + */ + private String title; + + /** + * 音乐音频的风格 + */ + private String style; + + /** + * 音乐音频生成后回调的 URL + */ + private String callbackUrl; +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/SunoRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/SunoRespVO.java new file mode 100644 index 000000000..bbb4264c7 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/SunoRespVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.ai.controller.admin.music.vo; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.util.List; + +/** + * API 响应的数据 + */ +@Data +public class SunoRespVO { + /** + * 表示请求是否成功 + */ + private boolean success; + + /** + * 任务 ID + */ + @JsonProperty("task_id") + private String taskId; + + /** + * 音乐数据列表 + */ + private List data; + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/MusicService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/MusicService.java new file mode 100644 index 000000000..c0e7b34f1 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/MusicService.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.ai.service.music; + +import cn.iocoder.yudao.module.ai.controller.admin.music.vo.SunoReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.music.vo.SunoRespVO; + +/** + * @Author xiaoxin + * @Date 2024/5/29 + */ +public interface MusicService { + + /** + * 音乐生成 + * + * @param sunoReqVO 请求实体 + * @return 响应实体 + */ + SunoRespVO musicGen(SunoReqVO sunoReqVO); +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/MusicServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/MusicServiceImpl.java new file mode 100644 index 000000000..64173d2dc --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/MusicServiceImpl.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.ai.service.music; + +import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.ai.controller.admin.music.vo.SunoReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.music.vo.SunoRespVO; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + * @Author xiaoxin + * @Date 2024/5/29 + */ +@Service +@RequiredArgsConstructor +public class MusicServiceImpl implements MusicService { + + private final SunoApi sunoApi; + + @Override + public SunoRespVO musicGen(SunoReqVO sunoReqVO) { + SunoApi.SunoRequest req = BeanUtils.toBean(sunoReqVO, SunoApi.SunoRequest.class); + return BeanUtils.toBean(sunoApi.musicGen(req), SunoRespVO.class); + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index 55705c40f..5472e2faf 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -3,6 +3,8 @@ package cn.iocoder.yudao.framework.ai.config; import cn.hutool.core.io.IoUtil; import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactory; import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactoryImpl; +import cn.iocoder.yudao.framework.ai.core.model.suno.SunoConfig; +import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatClient; import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatModal; import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenOptions; @@ -13,18 +15,14 @@ import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoApi; import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatClient; import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatOptions; import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanApi; +import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; import org.springframework.ai.models.midjourney.MidjourneyConfig; import org.springframework.ai.models.midjourney.MidjourneyMessage; import org.springframework.ai.models.midjourney.api.MidjourneyInteractionsApi; import org.springframework.ai.models.midjourney.webSocket.MidjourneyMessageHandler; import org.springframework.ai.models.midjourney.webSocket.MidjourneyWebSocketStarter; import org.springframework.ai.models.midjourney.webSocket.listener.MidjourneyMessageListener; -import lombok.extern.slf4j.Slf4j; -import org.jetbrains.annotations.NotNull; -import org.springframework.ai.openai.OpenAiImageClient; -import org.springframework.ai.openai.OpenAiImageOptions; -import org.springframework.ai.openai.api.OpenAiImageApi; -import org.springframework.ai.retry.RetryUtils; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -150,6 +148,13 @@ public class YudaoAiAutoConfiguration { return new MidjourneyInteractionsApi(midjourneyConfig); } + @Bean + @ConditionalOnProperty(value = "yudao.ai.suno.enable", havingValue = "true") + public SunoApi sunoApi(YudaoAiProperties yudaoAiProperties) { + // 创建 sunoApi + return new SunoApi(new SunoConfig(yudaoAiProperties.getSuno().getToken())); + } + private static @NotNull MidjourneyConfig getMidjourneyConfig(ApplicationContext applicationContext, YudaoAiProperties.MidjourneyProperties midjourneyProperties) { Map requestTemplates = new HashMap<>(); diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java index 16a6bc40e..4a7dd69de 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java @@ -26,6 +26,7 @@ public class YudaoAiProperties { private YiYanProperties yiyan; private OpenAiImageProperties openAiImage; private MidjourneyProperties midjourney; + private SunoProperties suno; @Data @Accessors(chain = true) @@ -134,4 +135,14 @@ public class YudaoAiProperties { */ private String channelId; } + + @Data + @Accessors(chain = true) + public static class SunoProperties { + private boolean enable = false; + /** + * token + */ + private String token; + } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/SunoConfig.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/SunoConfig.java new file mode 100644 index 000000000..0d717f6cd --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/SunoConfig.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.framework.ai.core.model.suno; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +/** + * @Author xiaoxin + * @Date 2024/5/29 + */ +@Data +@Accessors(chain = true) +@NoArgsConstructor +@AllArgsConstructor +public class SunoConfig { + /** + * token信息 + */ + private String token; +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/SunoApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/SunoApi.java similarity index 79% rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/SunoApi.java rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/SunoApi.java index 0198197f1..5da45fced 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/SunoApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/SunoApi.java @@ -1,9 +1,10 @@ -package cn.iocoder.yudao.framework.ai.core.model.suno; +package cn.iocoder.yudao.framework.ai.core.model.suno.api; +import cn.iocoder.yudao.framework.ai.core.model.suno.SunoConfig; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Data; import lombok.experimental.Accessors; import lombok.extern.slf4j.Slf4j; @@ -23,21 +24,26 @@ public class SunoApi { public static final String APPLICATION_JSON = "application/json"; public static final String TOKEN_PREFIX = "Bearer "; public static final String API_URL = "https://api.acedata.cloud/suno/audios"; - public static final String TEST_TOKEN = "13f13540dd3f4ae9885f63ac9f5d0b9f"; private static final int READ_TIMEOUT = 160; // 连接超时时间(秒),音乐生成时间较长,设置为 160s,后续可做callback private final OkHttpClient client; - private final ObjectMapper objectMapper; - public SunoApi() { - this.client = new OkHttpClient().newBuilder().readTimeout(READ_TIMEOUT, TimeUnit.SECONDS).build(); - this.objectMapper = new ObjectMapper(); + + public SunoApi(SunoConfig sunoConfig) { + this.client = new OkHttpClient().newBuilder().readTimeout(READ_TIMEOUT, TimeUnit.SECONDS) + .addInterceptor(chain -> { + Request originalRequest = chain.request(); + Request requestWithUserAgent = originalRequest.newBuilder() + .header("Authorization", TOKEN_PREFIX + sunoConfig.getToken()) + .build(); + return chain.proceed(requestWithUserAgent); + }) + .build(); } - public SunoResponse generateMusic(SunoRequest sunoRequest) throws IOException { + public SunoResponse musicGen(SunoRequest sunoRequest) { Request request = new Request.Builder() .url(API_URL) - .header("Authorization", TOKEN_PREFIX + TEST_TOKEN) - .post(RequestBody.create(MediaType.parse(APPLICATION_JSON), objectMapper.writeValueAsString(sunoRequest))) + .post(RequestBody.create(MediaType.parse(APPLICATION_JSON), JsonUtils.toJsonString(sunoRequest))) .build(); try (Response response = client.newCall(request).execute()) { @@ -45,7 +51,9 @@ public class SunoApi { log.error("suno调用失败! response: {}", response); throw new IllegalStateException("suno调用失败!" + response); } - return objectMapper.readValue(response.body().string(), SunoResponse.class); + return JsonUtils.parseObject(response.body().string(), SunoResponse.class); + } catch (IOException ioException) { + throw new RuntimeException(ioException); } } @@ -90,7 +98,7 @@ public class SunoApi { /** - * API 响应的数据 + * SunoAPI 响应的数据 */ @Data public static class SunoResponse { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java index 30883a6e1..58d1609f7 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java @@ -1,24 +1,31 @@ package cn.iocoder.yudao.framework.ai.suno; -import cn.iocoder.yudao.framework.ai.core.model.suno.SunoApi; +import cn.iocoder.yudao.framework.ai.core.model.suno.SunoConfig; +import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; +import org.junit.Before; import org.junit.Test; -import java.io.IOException; - /** * @Author xiaoxin * @Date 2024/5/27 */ public class SunoTests { + private SunoConfig sunoConfig; + + @Before + public void setup() { + String token = "13f13540dd3f4ae9885f63ac9f5d0b9f"; + this.sunoConfig = new SunoConfig(token); + } @Test - public void generateMusic() throws IOException { - SunoApi sunoApi = new SunoApi(); + public void generateMusic() { + SunoApi sunoApi = new SunoApi(sunoConfig); SunoApi.SunoRequest sunoRequest = new SunoApi .SunoRequest() .setPrompt("创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。"); - SunoApi.SunoResponse sunoResponse = sunoApi.generateMusic(sunoRequest); + SunoApi.SunoResponse sunoResponse = sunoApi.musicGen(sunoRequest); System.out.println(sunoResponse); } } diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 37e0f5b59..417787ba4 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -199,6 +199,9 @@ yudao.ai: token: MTE4MjE3MjY2MjkxNTY3ODIzOA.GEV1SG.c49F8lZoGCUHwsj8O0UdodmM6nyQHvuD2fXflw guild-id: 1237948819677904956 channel-id: 1237948819677904960 + suno: + enable: true + token: 13f13540dd3f4ae9885f63ac9f5d0b9f --- #################### 芋道相关配置 #################### From 342f603964aae28373f2cc830d4c164238e2fc39 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 30 May 2024 09:35:23 +0800 Subject: [PATCH 353/684] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91AI=EF=BC=9AAI=20=E7=BB=98=E5=9B=BE=E7=9A=84?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/ErrorCodeConstants.java | 2 ++ .../module/ai/enums/AiImageStatusEnum.java | 26 +++++++++---------- .../admin/image/AiImageController.java | 13 +++++++--- .../admin/image/vo/AiImageDallRespVO.java | 7 ++--- .../admin/image/vo/AiImageListRespVO.java | 3 +++ .../ai/dal/dataobject/image/AiImageDO.java | 13 ++++++---- .../ai/dal/mysql/image/AiImageMapper.java | 6 ++--- .../ai/service/image/AiImageServiceImpl.java | 6 +++-- 8 files changed, 46 insertions(+), 30 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index da48c61e5..5ec26f7ed 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -42,5 +42,7 @@ public interface ErrorCodeConstants { // ========== API 绘画 1-040-005-000 ========== + // TODO @fan:这个直接返回找不到图片就好了 ErrorCode AI_IMAGE_NOT_CREATE_USER = new ErrorCode(1_022_005_000, "不是创建用户,不能删除 image!"); + } diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageStatusEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageStatusEnum.java index ad4ab4590..39df7b1a8 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageStatusEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageStatusEnum.java @@ -4,11 +4,9 @@ import lombok.AllArgsConstructor; import lombok.Getter; /** - * ai绘画状态 + * AI 绘画状态的枚举 * * @author fansili - * @time 2024/4/28 17:05 - * @since 1.0 */ @AllArgsConstructor @Getter @@ -16,22 +14,24 @@ public enum AiImageStatusEnum { IN_PROGRESS("10", "进行中"), COMPLETE("20", "完成"), - FAIL("30", "失败"), + FAIL("30", "失败"); - ; - - // TODO @fan:final 一下 + /** + * 状态 + */ private final String status; - + /** + * 状态名 + */ private final String name; - public static AiImageStatusEnum valueOfStatus(String status) { - for (AiImageStatusEnum itemEnum : AiImageStatusEnum.values()) { - if (itemEnum.getStatus().equals(status)) { - return itemEnum; + for (AiImageStatusEnum statusEnum : AiImageStatusEnum.values()) { + if (statusEnum.getStatus().equals(status)) { + return statusEnum; } } - throw new IllegalArgumentException("Invalid MessageType value: " + status); + throw new IllegalArgumentException("未知会话状态: " + status); } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index 6d15798e4..cee0954ce 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; import cn.iocoder.yudao.module.ai.service.image.AiImageService; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -23,13 +24,15 @@ public class AiImageController { @Resource private AiImageService aiImageService; - @Operation(summary = "获取 - 我的分页列表", description = "dall3、midjourney") + // TODO @fan:方法名叫做,getImagePageMy ;我们的命名,还是以动名词哈。不考虑省略名词的原因,是担心一个 Service 扩多个模块,纯粹动词无法表达 + @Operation(summary = "获取【我的】绘图分页") @GetMapping("/my-page") public CommonResult> myPage(@Validated AiImageListReqVO req) { return success(aiImageService.list(req)); } - @Operation(summary = "获取 - 我的 image 信息", description = "...") + // TODO @fan:类似 /my-page 的建议 + @Operation(summary = "获取【我的】绘图记录", description = "...") @GetMapping("/get-my") public CommonResult getMy(@RequestParam("id") Long id) { return CommonResult.success(aiImageService.getMy(id)); @@ -64,9 +67,13 @@ public class AiImageController { return success(null); } - @Operation(summary = "删除绘画记录", description = "") + // TODO @fan:类似 /my-page 的建议 + // TODO @fan:目前如果没结果,返回 Boolean 哈 + @Operation(summary = "删除【我的】绘画记录") @DeleteMapping("/delete-my") + @Parameter(name = "id", required = true, description = "绘画编号", example = "1024") public CommonResult deleteMy(@RequestParam("id") Long id) { + // TODO @fan:这种一次性的 loginUserId,可以不用定义变量,直接当参数传递 Long loginUserId = getLoginUserId(); aiImageService.deleteMy(id, loginUserId); return success(null); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallRespVO.java index 934141339..a687192e6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallRespVO.java @@ -44,17 +44,18 @@ public class AiImageDallRespVO { @Schema(description = "是否发布", example = "public") private String publicStatus; - @Schema(description = "图片地址(自己服务器)", example = "http://") + @Schema(description = "图片地址(自己服务器)", example = "https://") private String picUrl; - @Schema(description = "绘画图片地址(绘画好的服务器)", example = "http://") + @Schema(description = "绘画图片地址(绘画好的服务器)", example = "https://") private String originalPicUrl; @Schema(description = "绘画错误信息", example = "图片错误信息") private String errorMessage; - // ============ 绘画请求参数 + // ============ 绘画请求参数 ============ + // todo @fan:下面的 style、mjNonceId 直接就不用注释啦,直接去看 DO 完事哈 /** * - style */ diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java index c0bb20773..1ee14cb89 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java @@ -12,6 +12,7 @@ import lombok.experimental.Accessors; import java.time.LocalDateTime; import java.util.Map; +// TODO @fan:可以考虑,复用 AiImageDallRespVO,统一成 AIImageRespVO /** * midjourney req * @@ -61,6 +62,8 @@ public class AiImageListRespVO extends PageParam { // ============ 绘画请求参数 + // todo @fan:下面的 style、mjNonceId 直接就不用注释啦,直接去看 DO 完事哈 + /** * - style */ diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java index 1474fc683..259215cdc 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java @@ -20,10 +20,12 @@ import java.util.Map; @Data public class AiImageDO extends BaseDO { + // TODO @fan:1)使用 java 注释哈,不要注解。2)关联、枚举字段,要关联到对应类,参考 AiChatMessageDO 的注释 + @TableId(type = IdType.AUTO) private Long id; - @Schema(description = "用户id") + @Schema(description = "用户编号") private Long userId; @Schema(description = "提示词") @@ -41,6 +43,7 @@ public class AiImageDO extends BaseDO { @Schema(description = "图片高度") private String height; + // TODO @fan:这种就注释绘画状态,然后枚举类关联下就好啦 @Schema(description = "绘画状态:提交、排队、绘画中、绘画完成、绘画失败") private String status; @@ -53,10 +56,7 @@ public class AiImageDO extends BaseDO { @Schema(description = "绘画图片地址(绘画好的服务器)") private String originalPicUrl; - @Schema(description = "绘画错误信息") - private String errorMessage; - - // ============ 绘画请求参数 + // ============ 绘画请求参数 ============ /** * - style @@ -75,5 +75,8 @@ public class AiImageDO extends BaseDO { @TableField(typeHandler = JacksonTypeHandler.class) private Map drawResponse; + @Schema(description = "绘画错误信息") + private String errorMessage; + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java index 6cf8a80e7..f60668d21 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java @@ -7,16 +7,14 @@ import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; /** - * ai image + * AI 绘图 Mapper * * @author fansili - * @time 2024/4/28 14:01 - * @since 1.0 */ @Mapper public interface AiImageMapper extends BaseMapperX { - + // TODO @fan:这个建议,直接使用 update,service 拼接要改的状态哈 /** * 更新 - 根据 messageId * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index 93c1e51f0..1cce11642 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -200,10 +200,12 @@ public class AiImageServiceImpl implements AiImageService { // TODO @fan:1)需要校验存在;2)需要校验属于我; @Override - public void deleteMy(Long id, Long loginUserId) { + public void deleteMy(Long id, Long userId) { // 校验记录是否存在 + // TODO @fan:aiImageDO 这种命名 image 就 ok 拉,更简洁 + // TODO @fan:下面这个,可以返回图片不存在 AiImageDO aiImageDO = validateExists(id); - if (!aiImageDO.getUserId().equals(loginUserId)) { + if (!aiImageDO.getUserId().equals(userId)) { throw exception(ErrorCodeConstants.AI_IMAGE_NOT_CREATE_USER); } // 删除记录 From aea4f465ee73f8e1f5bc1f8d52be6b65dbcd08e0 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 30 May 2024 10:12:25 +0800 Subject: [PATCH 354/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91Ai?= =?UTF-8?q?=20Image=20=E5=A2=9E=E5=8A=A0=20PublicStatus=20=E6=9E=9A?= =?UTF-8?q?=E4=B8=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/enums/AiImagePublicStatusEnum.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImagePublicStatusEnum.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImagePublicStatusEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImagePublicStatusEnum.java new file mode 100644 index 000000000..3a7762bb7 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImagePublicStatusEnum.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.ai.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * ai绘画 public 状态 + * + * @author fansili + * @time 2024/4/28 17:05 + * @since 1.0 + */ +@AllArgsConstructor +@Getter +public enum AiImagePublicStatusEnum { + + PRIVATE("private", "私有"), + PUBLIC("public", "公开"), + + ; + + // TODO @fan:final 一下 + private final String status; + + private final String name; + + + public static AiImagePublicStatusEnum valueOfStatus(String status) { + for (AiImagePublicStatusEnum itemEnum : AiImagePublicStatusEnum.values()) { + if (itemEnum.getStatus().equals(status)) { + return itemEnum; + } + } + throw new IllegalArgumentException("Invalid MessageType value: " + status); + } +} From 92ee6659961d0ff65eb247a0b6f66a13e17e6b59 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 30 May 2024 10:14:00 +0800 Subject: [PATCH 355/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91AI?= =?UTF-8?q?=20Image=20=E5=B8=B8=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/AiCommonConstants.java | 9 ++- .../admin/image/vo/AiImageDallRespVO.java | 74 ------------------- 2 files changed, 7 insertions(+), 76 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallRespVO.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/AiCommonConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/AiCommonConstants.java index 2bd71376b..01b57733e 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/AiCommonConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/AiCommonConstants.java @@ -10,7 +10,12 @@ package cn.iocoder.yudao.module.ai; public class AiCommonConstants { /** - * 对话 - 默认 title + * 绘画 request - style */ - public static final String CONVERSATION_DEFAULT_TITLE = "新增对话"; + public static final String DRAW_REQ_KEY_STYLE = "style"; + /** + * dall size - 模板(1024x1024) + */ + public static final String DALL_SIZE_TEMPLATE = "%sx%s"; + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallRespVO.java deleted file mode 100644 index a687192e6..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallRespVO.java +++ /dev/null @@ -1,74 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.image.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.experimental.Accessors; - -import java.util.Map; - -/** - * dall2/dall2 绘画 - * - * @author fansili - * @time 2024/4/25 16:24 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiImageDallRespVO { - - @Schema(description = "id编号", example = "1") - private Long id; - - @Schema(description = "用户id", example = "1") - private Long userId; - - @Schema(description = "提示词", example = "南极的小企鹅") - private String prompt; - - @Schema(description = "平台", example = "openai") - private String platform; - - @Schema(description = "模型", example = "dall2") - private String model; - - @Schema(description = "图片宽度", example = "1024") - private String width; - - @Schema(description = "图片高度", example = "1024") - private String height; - - @Schema(description = "绘画状态:10 进行中、20 绘画完成、30 绘画失败", example = "10") - private String status; - - @Schema(description = "是否发布", example = "public") - private String publicStatus; - - @Schema(description = "图片地址(自己服务器)", example = "https://") - private String picUrl; - - @Schema(description = "绘画图片地址(绘画好的服务器)", example = "https://") - private String originalPicUrl; - - @Schema(description = "绘画错误信息", example = "图片错误信息") - private String errorMessage; - - // ============ 绘画请求参数 ============ - - // todo @fan:下面的 style、mjNonceId 直接就不用注释啦,直接去看 DO 完事哈 - /** - * - style - */ - @Schema(description = "绘画请求参数") - private Map drawRequest; - - /** - * - mjNonceId - * - mjOperationId - * - mjOperationName - * - mjOperations - */ - @Schema(description = "绘画请求响应参数") - private Map drawResponse; - -} From 8b1e1c047bf6c6334b3bd6ed17c1dc20d7677b83 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 30 May 2024 10:14:34 +0800 Subject: [PATCH 356/684] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91=20=E5=A4=84=E7=90=86=20dall=20=E5=BC=82=E6=AD=A5?= =?UTF-8?q?=E8=B0=83=E7=94=A8=EF=BC=8C=E9=87=87=E7=94=A8=20@Async?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/service/image/AiImageServiceImpl.java | 181 ++++++++---------- 1 file changed, 82 insertions(+), 99 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index 1cce11642..a3494fb20 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -1,56 +1,51 @@ package cn.iocoder.yudao.module.ai.service.image; import cn.hutool.core.util.IdUtil; -import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageModelEnum; import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageStyleEnum; import cn.iocoder.yudao.framework.ai.core.exception.AiException; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.module.ai.AiCommonConstants; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; -import cn.iocoder.yudao.module.ai.convert.AiImageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper; +import cn.iocoder.yudao.module.ai.enums.AiImagePublicStatusEnum; import cn.iocoder.yudao.module.ai.enums.AiImageStatusEnum; import cn.iocoder.yudao.module.infra.api.file.FileApi; +import com.google.common.collect.ImmutableMap; import jakarta.annotation.PostConstruct; -import lombok.AllArgsConstructor; +import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.image.ImageGeneration; import org.springframework.ai.image.ImagePrompt; import org.springframework.ai.image.ImageResponse; import org.springframework.ai.models.midjourney.api.MidjourneyInteractionsApi; -import org.springframework.ai.models.midjourney.api.req.ReRollReq; import org.springframework.ai.models.midjourney.webSocket.MidjourneyWebSocketStarter; -import org.springframework.ai.models.midjourney.webSocket.WssNotify; import org.springframework.ai.openai.OpenAiImageClient; import org.springframework.ai.openai.OpenAiImageOptions; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.Collections; import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; // TODO @fan:注释优化下哈 + /** - * ai 作图 + * AI 绘画(接入 dall2/dall3、midjourney) * * @author fansili * @time 2024/4/25 15:51 * @since 1.0 */ -@AllArgsConstructor @Service @Slf4j public class AiImageServiceImpl implements AiImageService { @@ -58,102 +53,92 @@ 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)); + @Resource + private AiImageMapper imageMapper; + @Resource + private FileApi fileApi; + @Resource + private OpenAiImageClient openAiImageClient; + @Resource + private MidjourneyWebSocketStarter midjourneyWebSocketStarter; + @Resource + private MidjourneyInteractionsApi midjourneyInteractionsApi; // TODO @fan:接 mj proxy @PostConstruct public void startMidjourney() { - log.info("midjourney web socket starter..."); - midjourneyWebSocketStarter.start(new WssNotify() { - @Override - public void notify(int code, String message) { - log.info("code: {}, message: {}", code, message); - if (message.contains("Authentication failed")) { - // TODO 芋艿,这里看怎么处理,token无效的时候会认证失败! - // 认证失败 - log.error("midjourney socket 认证失败,检查token是否失效!"); - } - } - }); + // todo @fan 暂时注释掉 +// log.info("midjourney web socket starter..."); +// midjourneyWebSocketStarter.start(new WssNotify() { +// @Override +// public void notify(int code, String message) { +// log.info("code: {}, message: {}", code, message); +// if (message.contains("Authentication failed")) { +// // TODO 芋艿,这里看怎么处理,token无效的时候会认证失败! +// // 认证失败 +// log.error("midjourney socket 认证失败,检查token是否失效!"); +// } +// } +// }); } - // TODO @fan:1)分页,然后 loginUser 通过参数传入,这样 Service 无状态;2)另外,返回 DO;VO 的翻译,交给 Controller;3:还有,使用 BeanUtils 替代哈 @Override - public PageResult list(AiImageListReqVO req) { - // 获取登录用户 - Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + public PageResult getImagePageMy(Long loginUserId, AiImageListReqVO req) { // 查询当前用户下所有的绘画记录 - PageResult pageResult = aiImageMapper.selectPage(req, + return imageMapper.selectPage(req, new LambdaQueryWrapperX() .eq(AiImageDO::getUserId, loginUserId) - .orderByDesc(AiImageDO::getId) - ); - // 转换 PageResult 返回 - PageResult result = new PageResult<>(); - result.setTotal(pageResult.getTotal()); - result.setList(AiImageConvert.INSTANCE.convertAiImageListRespVO(pageResult.getList())); - return result; + .orderByDesc(AiImageDO::getId)); } - // TODO @fan:1)返回 DO;VO 的翻译,交给 Controller;2)还有,使用 BeanUtils 替代哈 @Override - public AiImageListRespVO getMy(Long id) { - AiImageDO aiImageDO = aiImageMapper.selectById(id); - return AiImageConvert.INSTANCE.convertAiImageListRespVO(aiImageDO); + public AiImageDO getMy(Long id) { + return imageMapper.selectById(id); } - // TODO @fan:1)loginUserId 通过 controller 传入; @Override - public AiImageDallRespVO dall(AiImageDallReqVO req) { - Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + public Long dall(Long loginUserId, AiImageDallReqVO req) { // 保存数据库 - // TODO @fan:1)使用 BeanUtils;2)使用链式调用哈; - AiImageDO aiImageDO = AiImageConvert.INSTANCE.convertAiImageDO(req); - aiImageDO.setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus()); - aiImageDO.setUserId(loginUserId); - aiImageMapper.insert(aiImageDO); + AiImageDO aiImageDO = BeanUtils.toBean(req, AiImageDO.class) + .setUserId(loginUserId) + .setWidth(req.getWidth()) + .setHeight(req.getHeight()) + .setDrawRequest(ImmutableMap.of(AiCommonConstants.DRAW_REQ_KEY_STYLE, req.getStyle())) + .setPublicStatus(AiImagePublicStatusEnum.PRIVATE.getStatus()) + .setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus()); + imageMapper.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()); - openAiImageOptions.setSize(req.getSize()); - ImageResponse imageResponse = openAiImageClient.call(new ImagePrompt(req.getPrompt(), openAiImageOptions)); - // 发送 - ImageGeneration imageGeneration = imageResponse.getResult(); - // 图片保存到服务器 - 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())); - } catch (AiException aiException) { - // TODO @fan:错误日志,也打印下哈;因为 aiException.getMessage() 比较精简; - aiImageMapper.updateById(new AiImageDO().setId(aiImageDO.getId()).setStatus(AiImageStatusEnum.FAIL.getStatus()) - .setErrorMessage(aiException.getMessage())); - } - }); - // TODO @fan:返回 id 就可以啦 + doDall(aiImageDO, req); // 转换 AiImageDallDrawingRespVO - return AiImageConvert.INSTANCE.convertAiImageDallDrawingRespVO(aiImageDO); + return aiImageDO.getId(); + } + + @Async + public void doDall(AiImageDO aiImageDO, AiImageDallReqVO req) { + 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()); + openAiImageOptions.setSize(String.format(AiCommonConstants.DALL_SIZE_TEMPLATE, req.getWidth(), req.getHeight())); + ImageResponse imageResponse = openAiImageClient.call(new ImagePrompt(req.getPrompt(), openAiImageOptions)); + // 发送 + ImageGeneration imageGeneration = imageResponse.getResult(); + // 图片保存到服务器 + String filePath = fileApi.createFile(HttpUtil.downloadBytes(imageGeneration.getOutput().getUrl())); + // 更新数据库 + imageMapper.updateById(new AiImageDO().setId(aiImageDO.getId()).setStatus(AiImageStatusEnum.COMPLETE.getStatus()) + .setPicUrl(filePath).setOriginalPicUrl(imageGeneration.getOutput().getUrl())); + } catch (AiException aiException) { + // TODO @fan:错误日志,也打印下哈;因为 aiException.getMessage() 比较精简; + imageMapper.updateById(new AiImageDO().setId(aiImageDO.getId()).setStatus(AiImageStatusEnum.FAIL.getStatus()) + .setErrorMessage(aiException.getMessage())); + } } @Override @@ -198,18 +183,16 @@ public class AiImageServiceImpl implements AiImageService { // ); } - // TODO @fan:1)需要校验存在;2)需要校验属于我; @Override public void deleteMy(Long id, Long userId) { - // 校验记录是否存在 - // TODO @fan:aiImageDO 这种命名 image 就 ok 拉,更简洁 - // TODO @fan:下面这个,可以返回图片不存在 - AiImageDO aiImageDO = validateExists(id); - if (!aiImageDO.getUserId().equals(userId)) { - throw exception(ErrorCodeConstants.AI_IMAGE_NOT_CREATE_USER); + // 校验是否存在,并获取 image + AiImageDO image = validateExists(id); + // 是否属于当前用户 + if (!image.getUserId().equals(userId)) { + throw exception(ErrorCodeConstants.AI_IMAGE_NOT_EXISTS); } // 删除记录 - aiImageMapper.deleteById(id); + imageMapper.deleteById(id); } private void validateMessageId(String mjMessageId, String messageId) { @@ -237,7 +220,7 @@ public class AiImageServiceImpl implements AiImageService { } private AiImageDO validateExists(Long id) { - AiImageDO aiImageDO = aiImageMapper.selectById(id); + AiImageDO aiImageDO = imageMapper.selectById(id); if (aiImageDO == null) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MIDJOURNEY_IMAGINE_FAIL); } From 26616ea7a7deca95dafceaed6a246ffebf6d686b Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 30 May 2024 10:15:02 +0800 Subject: [PATCH 357/684] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91=E5=B0=86=20login=20user=20=E9=80=9A=E8=BF=87=20contro?= =?UTF-8?q?ller=20=E4=BC=A0=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/image/AiImageController.java | 28 ++++++++++++------- .../ai/service/image/AiImageService.java | 14 +++++++--- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index cee0954ce..e847cc193 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -2,7 +2,9 @@ package cn.iocoder.yudao.module.ai.controller.admin.image; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; +import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.service.image.AiImageService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -24,25 +26,33 @@ public class AiImageController { @Resource private AiImageService aiImageService; - // TODO @fan:方法名叫做,getImagePageMy ;我们的命名,还是以动名词哈。不考虑省略名词的原因,是担心一个 Service 扩多个模块,纯粹动词无法表达 @Operation(summary = "获取【我的】绘图分页") @GetMapping("/my-page") - public CommonResult> myPage(@Validated AiImageListReqVO req) { - return success(aiImageService.list(req)); + public CommonResult> getImagePageMy(@Validated AiImageListReqVO req) { + // 转换 resp + PageResult pageResult = aiImageService.getImagePageMy(getLoginUserId(), req); + // 转换 PageResult 返回 + PageResult result = new PageResult<>(); + result.setTotal(pageResult.getTotal()); + result.setList(BeanUtils.toBean(pageResult.getList(), AiImagePageMyRespVO.class)); + return success(result); } // TODO @fan:类似 /my-page 的建议 @Operation(summary = "获取【我的】绘图记录", description = "...") @GetMapping("/get-my") - public CommonResult getMy(@RequestParam("id") Long id) { - return CommonResult.success(aiImageService.getMy(id)); + public CommonResult getMy(@RequestParam("id") Long id) { + // 获取 image 信息 + AiImageDO imageDO = aiImageService.getMy(id); + // 转 resp 并返回 + return CommonResult.success(BeanUtils.toBean(imageDO, AiImagePageMyRespVO.class)); } // TODO @fan:建议把 dallDrawing、midjourney 融合成一个 draw 接口,异步绘制;然后返回一个 id 给前端;前端通过 get 接口轮询,直到获取到生成成功 @Operation(summary = "dall2/dall3绘画", description = "openAi dall3是付费的!") @PostMapping("/dall") - public AiImageDallRespVO dall(@Validated @RequestBody AiImageDallReqVO req) { - return aiImageService.dall(req); + public CommonResult dall(@Validated @RequestBody AiImageDallReqVO req) { + return success(aiImageService.dall(getLoginUserId(), req)); } @Operation(summary = "midjourney绘画", description = "midjourney图片绘画流程:1、提交任务 2、获取完成的任务 3、选择对应功能 4、获取最终结果") @@ -73,9 +83,7 @@ public class AiImageController { @DeleteMapping("/delete-my") @Parameter(name = "id", required = true, description = "绘画编号", example = "1024") public CommonResult deleteMy(@RequestParam("id") Long id) { - // TODO @fan:这种一次性的 loginUserId,可以不用定义变量,直接当参数传递 - Long loginUserId = getLoginUserId(); - aiImageService.deleteMy(id, loginUserId); + aiImageService.deleteMy(id, getLoginUserId()); return success(null); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java index 2ffd72240..7cb44fa5b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java @@ -1,7 +1,11 @@ package cn.iocoder.yudao.module.ai.service.image; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageListReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyOperateReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReqVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; /** * ai 作图 @@ -15,10 +19,11 @@ public interface AiImageService { /** * ai绘画 - 列表 * + * @param loginUserId * @param req * @return */ - PageResult list(AiImageListReqVO req); + PageResult getImagePageMy(Long loginUserId, AiImageListReqVO req); /** * 获取 - image 信息 @@ -26,14 +31,15 @@ public interface AiImageService { * @param id * @return */ - AiImageListRespVO getMy(Long id); + AiImageDO getMy(Long id); /** * ai绘画 - dall2/dall3 绘画 * + * @param loginUserId * @param req */ - AiImageDallRespVO dall(AiImageDallReqVO req); + Long dall(Long loginUserId, AiImageDallReqVO req); /** * midjourney 图片生成 From c808453c1dc7213e4b94113f7f21c3fcc735c4ca Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 30 May 2024 10:16:40 +0800 Subject: [PATCH 358/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91ima?= =?UTF-8?q?ge=20=E8=BF=94=E5=9B=9E=E7=9A=84size=20=E6=94=B9=E4=B8=BA=20wid?= =?UTF-8?q?th=20=E5=92=8C=20height?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/admin/image/vo/AiImageDallReqVO.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallReqVO.java index ef9161870..ad4512832 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallReqVO.java @@ -29,8 +29,12 @@ public class AiImageDallReqVO { @Schema(description = "图像生成的风格。可为vivid(生动)或natural(自然)") private String style; - @Schema(description = "生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。") - @NotNull(message = "size不能为空!") - private String size; + @Schema(description = "图片高度。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。") + @NotNull(message = "图片高度不能为空!") + private String height; + + @Schema(description = "图片宽度。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。") + @NotNull(message = "图片宽度不能为空!") + private String width; } From 2eade5ad5bcbacfd0f23fb0b4272866c5883284d Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 30 May 2024 10:17:14 +0800 Subject: [PATCH 359/684] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91=E4=BF=AE=E6=94=B9=E5=BC=82=E5=B8=B8=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=20image=20=E4=B8=8D=E5=AD=98=E5=9C=A8=EF=BC=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java index 5ec26f7ed..f0833b71f 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java @@ -42,7 +42,6 @@ public interface ErrorCodeConstants { // ========== API 绘画 1-040-005-000 ========== - // TODO @fan:这个直接返回找不到图片就好了 - ErrorCode AI_IMAGE_NOT_CREATE_USER = new ErrorCode(1_022_005_000, "不是创建用户,不能删除 image!"); + ErrorCode AI_IMAGE_NOT_EXISTS = new ErrorCode(1_022_005_000, "image 不存在!"); } From 1c0cf4b860596de08a88602b2e3b8725b6f46502 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 30 May 2024 10:18:55 +0800 Subject: [PATCH 360/684] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91=E6=89=80=E6=9C=89=E8=BD=AC=E6=8D=A2=E9=83=BD=E4=B8=8D?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=20convert=20=E9=87=87=E7=94=A8=20BeanUtils?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...stRespVO.java => AiImagePageMyRespVO.java} | 7 +- .../module/ai/convert/AiImageConvert.java | 74 ------------------- .../YuDaoMidjourneyMessageHandler.java | 33 ++++----- 3 files changed, 16 insertions(+), 98 deletions(-) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/{AiImageListRespVO.java => AiImagePageMyRespVO.java} (87%) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePageMyRespVO.java similarity index 87% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePageMyRespVO.java index 1ee14cb89..e542879ca 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePageMyRespVO.java @@ -1,15 +1,10 @@ package cn.iocoder.yudao.module.ai.controller.admin.image.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; -import java.time.LocalDateTime; import java.util.Map; // TODO @fan:可以考虑,复用 AiImageDallRespVO,统一成 AIImageRespVO @@ -22,7 +17,7 @@ import java.util.Map; */ @Data @Accessors(chain = true) -public class AiImageListRespVO extends PageParam { +public class AiImagePageMyRespVO extends PageParam { @Schema(description = "id编号", example = "1") private Long id; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java deleted file mode 100644 index d094f489d..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/convert/AiImageConvert.java +++ /dev/null @@ -1,74 +0,0 @@ -package cn.iocoder.yudao.module.ai.convert; - -import org.springframework.ai.models.midjourney.MidjourneyMessage; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageListRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyOperationsVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -// TODO @fan:convert 可以考虑去掉,使用 BeanUtils.copy 替代 -/** - * ai image convert - * - * @author fansili - * @time 2024/4/18 16:39 - * @since 1.0 - */ -@Mapper -public interface AiImageConvert { - - AiImageConvert INSTANCE = Mappers.getMapper(AiImageConvert.class); - - /** - * 转换 - AiImageDallDrawingRespVO - * - * @param req - * @return - */ - AiImageDallRespVO convertAiImageDallDrawingRespVO(AiImageDO req); - - /** - * 转换 - AiImageDallDrawingRespVO - * - * @param req - * @return - */ - AiImageDallRespVO convertAiImageDallDrawingRespVO(AiImageDallReqVO req); - - /** - * 转换 - AiImageListRespVO - * - * @param list - * @return - */ - List convertAiImageListRespVO(List list); - - /** - * 转换 - AiImageListRespVO - * - * @param aiImageDO - * @return - */ - AiImageListRespVO convertAiImageListRespVO(AiImageDO aiImageDO); - - /** - * 转换 - AiImageMidjourneyOperationsVO - * - * @param component - * @return - */ - AiImageMidjourneyOperationsVO convertAiImageMidjourneyOperationsVO(MidjourneyMessage.Component component); - - /** - * 转换 - AiImageDO - * - * @param req - * @return - */ - AiImageDO convertAiImageDO(AiImageDallReqVO req); -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/YuDaoMidjourneyMessageHandler.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/YuDaoMidjourneyMessageHandler.java index 6235a9bd7..0568bbec6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/YuDaoMidjourneyMessageHandler.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/YuDaoMidjourneyMessageHandler.java @@ -2,23 +2,19 @@ package cn.iocoder.yudao.module.ai.service.image.midjourneyHandler; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; -import com.alibaba.fastjson.JSON; -import org.springframework.ai.models.midjourney.MidjourneyMessage; -import org.springframework.ai.models.midjourney.constants.MidjourneyGennerateStatusEnum; -import org.springframework.ai.models.midjourney.webSocket.MidjourneyMessageHandler; -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyOperationsVO; -import cn.iocoder.yudao.module.ai.convert.AiImageConvert; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper; import cn.iocoder.yudao.module.ai.enums.AiImageStatusEnum; +import com.alibaba.fastjson.JSON; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.ai.models.midjourney.MidjourneyMessage; +import org.springframework.ai.models.midjourney.constants.MidjourneyGennerateStatusEnum; +import org.springframework.ai.models.midjourney.webSocket.MidjourneyMessageHandler; import org.springframework.stereotype.Component; -import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; /** * yudao message handler @@ -113,15 +109,16 @@ public class YuDaoMidjourneyMessageHandler implements MidjourneyMessageHandler { } private List getMidjourneyOperationsList(MidjourneyMessage midjourneyMessage) { - // 为空直接返回 - if (CollUtil.isEmpty(midjourneyMessage.getComponents())) { - return Collections.emptyList(); - } - // 将 component 转成 AiImageMidjourneyOperationsVO - return midjourneyMessage.getComponents().stream() - .map(componentType -> componentType.getComponents().stream() - .map(AiImageConvert.INSTANCE::convertAiImageMidjourneyOperationsVO) - .collect(Collectors.toList())) - .toList().stream().flatMap(List::stream).toList(); +// // 为空直接返回 +// if (CollUtil.isEmpty(midjourneyMessage.getComponents())) { +// return Collections.emptyList(); +// } +// // 将 component 转成 AiImageMidjourneyOperationsVO +// return midjourneyMessage.getComponents().stream() +// .map(componentType -> componentType.getComponents().stream() +// .map(AiImageConvert.INSTANCE::convertAiImageMidjourneyOperationsVO) +// .collect(Collectors.toList())) +// .toList().stream().flatMap(List::stream).toList(); + return null; } } From bde1eede2a863f0a0bce8e7954f1cefd65e271ed Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 30 May 2024 10:22:06 +0800 Subject: [PATCH 361/684] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91image=20delete-my=20=E5=88=A0=E9=99=A4=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=20boolean?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/controller/admin/image/AiImageController.java | 6 ++---- .../yudao/module/ai/service/image/AiImageService.java | 2 +- .../yudao/module/ai/service/image/AiImageServiceImpl.java | 4 ++-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index e847cc193..8b279e484 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -78,13 +78,11 @@ public class AiImageController { } // TODO @fan:类似 /my-page 的建议 - // TODO @fan:目前如果没结果,返回 Boolean 哈 @Operation(summary = "删除【我的】绘画记录") @DeleteMapping("/delete-my") @Parameter(name = "id", required = true, description = "绘画编号", example = "1024") - public CommonResult deleteMy(@RequestParam("id") Long id) { - aiImageService.deleteMy(id, getLoginUserId()); - return success(null); + public CommonResult deleteMy(@RequestParam("id") Long id) { + return success(aiImageService.deleteMy(id, getLoginUserId())); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java index 7cb44fa5b..6a374178a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java @@ -62,6 +62,6 @@ public interface AiImageService { * @param id * @param loginUserId */ - void deleteMy(Long id, Long loginUserId); + Boolean deleteMy(Long id, Long loginUserId); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index a3494fb20..fc23ed6fb 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -184,7 +184,7 @@ public class AiImageServiceImpl implements AiImageService { } @Override - public void deleteMy(Long id, Long userId) { + public Boolean deleteMy(Long id, Long userId) { // 校验是否存在,并获取 image AiImageDO image = validateExists(id); // 是否属于当前用户 @@ -192,7 +192,7 @@ public class AiImageServiceImpl implements AiImageService { throw exception(ErrorCodeConstants.AI_IMAGE_NOT_EXISTS); } // 删除记录 - imageMapper.deleteById(id); + return imageMapper.deleteById(id) > 0; } private void validateMessageId(String mjMessageId, String messageId) { From 0d4b67a9c458d26a6450348eba9bd75b1200e548 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 30 May 2024 10:23:26 +0800 Subject: [PATCH 362/684] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91image=20=E5=88=A0=E9=99=A4=E9=87=8D=E5=91=BD=E5=90=8D?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=20my=20delete?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/admin/image/AiImageController.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index 8b279e484..e9e35352e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -77,12 +77,11 @@ public class AiImageController { return success(null); } - // TODO @fan:类似 /my-page 的建议 @Operation(summary = "删除【我的】绘画记录") - @DeleteMapping("/delete-my") + @DeleteMapping("/my-delete") @Parameter(name = "id", required = true, description = "绘画编号", example = "1024") - public CommonResult deleteMy(@RequestParam("id") Long id) { - return success(aiImageService.deleteMy(id, getLoginUserId())); + public CommonResult myDelete(@RequestParam("id") Long id) { + return success(aiImageService.myDelete(id, getLoginUserId())); } } From 610badf503e0fbebb0e9a7a6bd7830429058c2d0 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 30 May 2024 10:23:32 +0800 Subject: [PATCH 363/684] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91image=20=E5=88=A0=E9=99=A4=E9=87=8D=E5=91=BD=E5=90=8D?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=20my=20delete?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iocoder/yudao/module/ai/service/image/AiImageService.java | 2 +- .../yudao/module/ai/service/image/AiImageServiceImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java index 6a374178a..3d8c30d49 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java @@ -62,6 +62,6 @@ public interface AiImageService { * @param id * @param loginUserId */ - Boolean deleteMy(Long id, Long loginUserId); + Boolean myDelete(Long id, Long loginUserId); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index fc23ed6fb..6e0ede470 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -184,7 +184,7 @@ public class AiImageServiceImpl implements AiImageService { } @Override - public Boolean deleteMy(Long id, Long userId) { + public Boolean myDelete(Long id, Long userId) { // 校验是否存在,并获取 image AiImageDO image = validateExists(id); // 是否属于当前用户 From 5d8aedbe9bbdfc15c25f89eebf4552566e77baf4 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 30 May 2024 10:26:23 +0800 Subject: [PATCH 364/684] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91image=20=E5=88=A0=E9=99=A4=E9=87=8D=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/controller/admin/image/AiImageController.java | 6 +++--- .../yudao/module/ai/service/image/AiImageService.java | 2 +- .../yudao/module/ai/service/image/AiImageServiceImpl.java | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index e9e35352e..dc7d80c2b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -78,10 +78,10 @@ public class AiImageController { } @Operation(summary = "删除【我的】绘画记录") - @DeleteMapping("/my-delete") + @DeleteMapping("/delete-my") @Parameter(name = "id", required = true, description = "绘画编号", example = "1024") - public CommonResult myDelete(@RequestParam("id") Long id) { - return success(aiImageService.myDelete(id, getLoginUserId())); + public CommonResult deleteMyById(@RequestParam("id") Long id) { + return success(aiImageService.deleteMyById(id, getLoginUserId())); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java index 3d8c30d49..1569ce05d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java @@ -62,6 +62,6 @@ public interface AiImageService { * @param id * @param loginUserId */ - Boolean myDelete(Long id, Long loginUserId); + Boolean deleteMyById(Long id, Long loginUserId); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index 6e0ede470..337d9fa4b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -184,7 +184,7 @@ public class AiImageServiceImpl implements AiImageService { } @Override - public Boolean myDelete(Long id, Long userId) { + public Boolean deleteMyById(Long id, Long userId) { // 校验是否存在,并获取 image AiImageDO image = validateExists(id); // 是否属于当前用户 From 347824c985a3b53d7a91bfa2fb25c465682187db Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 30 May 2024 11:05:44 +0800 Subject: [PATCH 365/684] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91image=20=E5=88=A0=E9=99=A4=E9=87=8D=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/controller/admin/image/AiImageController.java | 7 +++---- .../yudao/module/ai/service/image/AiImageService.java | 2 +- .../yudao/module/ai/service/image/AiImageServiceImpl.java | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index dc7d80c2b..4dc66a644 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -78,10 +78,9 @@ public class AiImageController { } @Operation(summary = "删除【我的】绘画记录") - @DeleteMapping("/delete-my") + @DeleteMapping("/delete-id-my") @Parameter(name = "id", required = true, description = "绘画编号", example = "1024") - public CommonResult deleteMyById(@RequestParam("id") Long id) { - return success(aiImageService.deleteMyById(id, getLoginUserId())); + public CommonResult deleteIdMy(@RequestParam("id") Long id) { + return success(aiImageService.deleteIdMy(id, getLoginUserId())); } - } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java index 1569ce05d..6a342a804 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java @@ -62,6 +62,6 @@ public interface AiImageService { * @param id * @param loginUserId */ - Boolean deleteMyById(Long id, Long loginUserId); + Boolean deleteIdMy(Long id, Long loginUserId); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index 337d9fa4b..25467c9af 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -184,7 +184,7 @@ public class AiImageServiceImpl implements AiImageService { } @Override - public Boolean deleteMyById(Long id, Long userId) { + public Boolean deleteIdMy(Long id, Long userId) { // 校验是否存在,并获取 image AiImageDO image = validateExists(id); // 是否属于当前用户 From 0faba44acf890d1f66851845de03db1bfded28fc Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 30 May 2024 13:19:33 +0800 Subject: [PATCH 366/684] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91AI=EF=BC=9ASuno=20=E9=9F=B3=E4=B9=90=E7=9A=84?= =?UTF-8?q?=20review?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ai/config/YudaoAiAutoConfiguration.java | 1 - .../yudao/framework/ai/config/YudaoAiProperties.java | 5 ++++- .../framework/ai/core/model/suno/api/SunoApi.java | 11 +++++++++-- .../cn/iocoder/yudao/framework/ai/suno/SunoTests.java | 1 + 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index 5472e2faf..7285448a3 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -151,7 +151,6 @@ public class YudaoAiAutoConfiguration { @Bean @ConditionalOnProperty(value = "yudao.ai.suno.enable", havingValue = "true") public SunoApi sunoApi(YudaoAiProperties yudaoAiProperties) { - // 创建 sunoApi return new SunoApi(new SunoConfig(yudaoAiProperties.getSuno().getToken())); } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java index 4a7dd69de..209407e80 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java @@ -137,12 +137,15 @@ public class YudaoAiProperties { } @Data - @Accessors(chain = true) + @Accessors(chain = true) // TODO @xiaoxin:可以去掉这个,默认全局已经开启 public static class SunoProperties { + private boolean enable = false; /** * token */ private String token; + } + } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/SunoApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/SunoApi.java index 5da45fced..b8496a094 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/SunoApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/SunoApi.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.framework.ai.core.model.suno.api; - import cn.iocoder.yudao.framework.ai.core.model.suno.SunoConfig; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import com.fasterxml.jackson.annotation.JsonInclude; @@ -14,6 +13,7 @@ import java.io.IOException; import java.util.List; import java.util.concurrent.TimeUnit; +// TODO @xiaoxin:类注释 /** * @Author xiaoxin * @Date 2024/5/27 @@ -21,13 +21,17 @@ import java.util.concurrent.TimeUnit; @Slf4j public class SunoApi { + // TODO @xiaoxin:APPLICATION_JSON、TOKEN_PREFIX 看看 spring 有没自带的这 2 个枚举哈。变量越少越好 public static final String APPLICATION_JSON = "application/json"; public static final String TOKEN_PREFIX = "Bearer "; public static final String API_URL = "https://api.acedata.cloud/suno/audios"; + private static final int READ_TIMEOUT = 160; // 连接超时时间(秒),音乐生成时间较长,设置为 160s,后续可做callback + + // TODO @xiaoxin:建议使用 webClient 对接。参考 https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiApi.java private final OkHttpClient client; - + // TODO @xiaoxin:sunoConfig => config,简洁一点 public SunoApi(SunoConfig sunoConfig) { this.client = new OkHttpClient().newBuilder().readTimeout(READ_TIMEOUT, TimeUnit.SECONDS) .addInterceptor(chain -> { @@ -40,6 +44,7 @@ public class SunoApi { .build(); } + // TODO @芋艿:方法名,要考虑下; public SunoResponse musicGen(SunoRequest sunoRequest) { Request request = new Request.Builder() .url(API_URL) @@ -57,6 +62,7 @@ public class SunoApi { } } + // TODO @xiaoxin:看看是不是使用 record 特性,简化下; /** * 请求数据对象,用于生成音乐音频 @@ -96,6 +102,7 @@ public class SunoApi { private String callbackUrl; } + // TODO @xiaoxin:看看是不是使用 record 特性,简化下; /** * SunoAPI 响应的数据 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java index 58d1609f7..1bbac41e2 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java @@ -28,4 +28,5 @@ public class SunoTests { SunoApi.SunoResponse sunoResponse = sunoApi.musicGen(sunoRequest); System.out.println(sunoResponse); } + } From b9d823f0ed5ab08a4639fc25614caa755cf33a14 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 30 May 2024 13:58:19 +0800 Subject: [PATCH 367/684] =?UTF-8?q?=E3=80=90=E5=88=A0=E9=99=A4=E3=80=91?= =?UTF-8?q?=E5=88=A0=E9=99=A4=20MidjourneyJob=20=E6=8F=90=E4=BE=9B=20?= =?UTF-8?q?=E9=80=9A=E7=9F=A5=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/job/MidjourneyJob.java | 21 ------------------- 1 file changed, 21 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/job/MidjourneyJob.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/job/MidjourneyJob.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/job/MidjourneyJob.java deleted file mode 100644 index 71b3e7731..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/job/MidjourneyJob.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.ai.job; - -import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; -import org.springframework.stereotype.Component; - -/** - * midjourney job(同步 mj 结果) - * - * @author fansili - * @time 2024/5/28 17:57 - * @since 1.0 - */ -@Component -public class MidjourneyJob implements JobHandler { - - @Override - public String execute(String param) throws Exception { - // todo @范 同步 midjourney proxy 结果 - return ""; - } -} From 20addff45edc33ea44d2ca013c666cca80027603 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 30 May 2024 14:21:13 +0800 Subject: [PATCH 368/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91Mid?= =?UTF-8?q?journey=20client=EF=BC=8C=E5=A2=9E=E5=8A=A0=20imagine=20?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/client/MidjourneyProxyClient.java | 40 +++++++++++++++++++ .../ai/client/vo/MidjourneyImagineReqVO.java | 32 +++++++++++++++ .../ai/client/vo/MidjourneySubmitRespVO.java | 27 +++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/MidjourneyProxyClient.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyImagineReqVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitRespVO.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/MidjourneyProxyClient.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/MidjourneyProxyClient.java new file mode 100644 index 000000000..79db06e5c --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/MidjourneyProxyClient.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.ai.client; + +import cn.iocoder.yudao.module.ai.client.vo.MidjourneyImagineReqVO; +import cn.iocoder.yudao.module.ai.client.vo.MidjourneySubmitRespVO; +import jakarta.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.client.RestTemplate; + +/** + * Midjourney Proxy 客户端 + * + * @author fansili + * @time 2024/5/30 13:58 + * @since 1.0 + */ +@Component +public class MidjourneyProxyClient { + + private static final String URI_IMAGINE = "/submit/imagine"; + + @Value("${ai.midjourney-proxy.url:http://127.0.0.1:8080/mj}") + private String url; + + @Autowired + private RestTemplate restTemplate; + + /** + * imagine - 根据提示词提交绘画任务 + * + * @param imagineReqVO + * @return + */ + public MidjourneySubmitRespVO imagine(@Validated @NotNull MidjourneyImagineReqVO imagineReqVO) { + return restTemplate.postForObject(url.concat(URI_IMAGINE), imagineReqVO, MidjourneySubmitRespVO.class); + } + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyImagineReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyImagineReqVO.java new file mode 100644 index 000000000..ce3b33c4a --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyImagineReqVO.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.ai.client.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.util.List; + +/** + * Midjourney:Imagine 请求 + * + * @author fansili + * @time 2024/5/30 14:02 + * @since 1.0 + */ +@Data +public class MidjourneyImagineReqVO { + + @Schema(description = "垫图(参考图)base64数组", required = false) + private List base64Array; + + @Schema(description = "通知地址", required = false) + @NotNull(message = "回调地址不能为空!") + private String notifyHook; + + @Schema(description = "提示词", required = true) + @NotNull(message = "提示词不能为空!") + private String prompt; + + @Schema(description = "自定义参数", required = false) + private String state; +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitRespVO.java new file mode 100644 index 000000000..c9a430d50 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitRespVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.ai.client.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * Midjourney:Imagine 请求 + * + * @author fansili + * @time 2024/5/30 14:02 + * @since 1.0 + */ +@Data +public class MidjourneySubmitRespVO { + + @Schema(description = "状态码: 1(提交成功), 21(已存在), 22(排队中), other(错误)") + private String code; + + @Schema(description = "描述") + private String description; + + @Schema(description = "扩展字段") + private String properties; + + @Schema(description = "任务ID") + private String result; +} From a858eb84e5ade81a7b142e1c68fef153094134a5 Mon Sep 17 00:00:00 2001 From: xiaoxin <718949661@qq.com> Date: Thu, 30 May 2024 15:34:36 +0800 Subject: [PATCH 369/684] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91Suno=E8=B0=83=E7=94=A8=E6=94=B9=E4=B8=BAWebClient?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/service/music/MusicServiceImpl.java | 2 +- .../ai/config/YudaoAiProperties.java | 1 - .../ai/core/model/suno/SunoConfig.java | 2 - .../ai/core/model/suno/api/SunoApi.java | 71 ++++++++----------- .../yudao/framework/ai/suno/SunoTests.java | 9 ++- 5 files changed, 33 insertions(+), 52 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/MusicServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/MusicServiceImpl.java index 64173d2dc..cbc4f9429 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/MusicServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/MusicServiceImpl.java @@ -19,7 +19,7 @@ public class MusicServiceImpl implements MusicService { @Override public SunoRespVO musicGen(SunoReqVO sunoReqVO) { - SunoApi.SunoRequest req = BeanUtils.toBean(sunoReqVO, SunoApi.SunoRequest.class); + SunoApi.SunoReq req = BeanUtils.toBean(sunoReqVO, SunoApi.SunoReq.class); return BeanUtils.toBean(sunoApi.musicGen(req), SunoRespVO.class); } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java index 209407e80..e0cfa05f9 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java @@ -137,7 +137,6 @@ public class YudaoAiProperties { } @Data - @Accessors(chain = true) // TODO @xiaoxin:可以去掉这个,默认全局已经开启 public static class SunoProperties { private boolean enable = false; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/SunoConfig.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/SunoConfig.java index 0d717f6cd..b0526e665 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/SunoConfig.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/SunoConfig.java @@ -3,14 +3,12 @@ package cn.iocoder.yudao.framework.ai.core.model.suno; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import lombok.experimental.Accessors; /** * @Author xiaoxin * @Date 2024/5/29 */ @Data -@Accessors(chain = true) @NoArgsConstructor @AllArgsConstructor public class SunoConfig { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/SunoApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/SunoApi.java index b8496a094..1b1a500ad 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/SunoApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/SunoApi.java @@ -1,65 +1,51 @@ package cn.iocoder.yudao.framework.ai.core.model.suno.api; import cn.iocoder.yudao.framework.ai.core.model.suno.SunoConfig; -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; -import lombok.experimental.Accessors; import lombok.extern.slf4j.Slf4j; -import okhttp3.*; +import org.springframework.ai.openai.api.ApiUtils; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; -import java.io.IOException; import java.util.List; -import java.util.concurrent.TimeUnit; -// TODO @xiaoxin:类注释 /** + * Suno API + *
+ * 文档地址:https://platform.acedata.cloud/documents/d016ee3f-421b-4b6e-989a-8beba8701701 + * * @Author xiaoxin * @Date 2024/5/27 */ @Slf4j public class SunoApi { - // TODO @xiaoxin:APPLICATION_JSON、TOKEN_PREFIX 看看 spring 有没自带的这 2 个枚举哈。变量越少越好 - public static final String APPLICATION_JSON = "application/json"; - public static final String TOKEN_PREFIX = "Bearer "; - public static final String API_URL = "https://api.acedata.cloud/suno/audios"; + public static final String DEFAULT_BASE_URL = "https://api.acedata.cloud/suno"; + private final WebClient webClient; - private static final int READ_TIMEOUT = 160; // 连接超时时间(秒),音乐生成时间较长,设置为 160s,后续可做callback - - // TODO @xiaoxin:建议使用 webClient 对接。参考 https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiApi.java - private final OkHttpClient client; - - // TODO @xiaoxin:sunoConfig => config,简洁一点 - public SunoApi(SunoConfig sunoConfig) { - this.client = new OkHttpClient().newBuilder().readTimeout(READ_TIMEOUT, TimeUnit.SECONDS) - .addInterceptor(chain -> { - Request originalRequest = chain.request(); - Request requestWithUserAgent = originalRequest.newBuilder() - .header("Authorization", TOKEN_PREFIX + sunoConfig.getToken()) - .build(); - return chain.proceed(requestWithUserAgent); - }) + public SunoApi(SunoConfig config) { + this.webClient = WebClient.builder() + .baseUrl(DEFAULT_BASE_URL) + .defaultHeaders(ApiUtils.getJsonContentHeaders(config.getToken())) .build(); } // TODO @芋艿:方法名,要考虑下; - public SunoResponse musicGen(SunoRequest sunoRequest) { - Request request = new Request.Builder() - .url(API_URL) - .post(RequestBody.create(MediaType.parse(APPLICATION_JSON), JsonUtils.toJsonString(sunoRequest))) - .build(); - - try (Response response = client.newCall(request).execute()) { - if (!response.isSuccessful()) { - log.error("suno调用失败! response: {}", response); - throw new IllegalStateException("suno调用失败!" + response); - } - return JsonUtils.parseObject(response.body().string(), SunoResponse.class); - } catch (IOException ioException) { - throw new RuntimeException(ioException); - } + public SunoResp musicGen(SunoReq sunReq) { + return this.webClient.post() + .uri("/audios") + .body(Mono.just(sunReq), SunoReq.class) + .retrieve() + .onStatus(status -> !status.is2xxSuccessful(), + response -> response.bodyToMono(String.class) + .handle((respBody, sink) -> { + log.error("【Suno】调用失败!resp: 【{}】", respBody); + sink.error(new IllegalStateException("【Suno】调用失败!")); + })) + .bodyToMono(SunoResp.class) + .block(); } // TODO @xiaoxin:看看是不是使用 record 特性,简化下; @@ -68,9 +54,8 @@ public class SunoApi { * 请求数据对象,用于生成音乐音频 */ @Data - @Accessors(chain = true) @JsonInclude(value = JsonInclude.Include.NON_NULL) - public static class SunoRequest { + public static class SunoReq { /** * 用于生成音乐音频的提示 */ @@ -108,7 +93,7 @@ public class SunoApi { * SunoAPI 响应的数据 */ @Data - public static class SunoResponse { + public static class SunoResp { /** * 表示请求是否成功 */ diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java index 1bbac41e2..02e9243d2 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java @@ -15,18 +15,17 @@ public class SunoTests { @Before public void setup() { - String token = "13f13540dd3f4ae9885f63ac9f5d0b9f"; + String token = "16b4356581984d538652354b60d69ff0"; this.sunoConfig = new SunoConfig(token); } @Test public void generateMusic() { SunoApi sunoApi = new SunoApi(sunoConfig); - SunoApi.SunoRequest sunoRequest = new SunoApi - .SunoRequest() + SunoApi.SunoReq sunoReq = new SunoApi.SunoReq() .setPrompt("创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。"); - SunoApi.SunoResponse sunoResponse = sunoApi.musicGen(sunoRequest); - System.out.println(sunoResponse); + SunoApi.SunoResp sunoResp = sunoApi.musicGen(sunoReq); + System.out.println(sunoResp); } } From 020f3a9a12b715c8d648ae620160c67bdc113600 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Thu, 30 May 2024 16:09:36 +0800 Subject: [PATCH 370/684] =?UTF-8?q?MALL-KEHU:=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=AE=A2=E6=9C=8D=E7=9B=B8=E5=85=B3=E5=AE=9E=E4=BD=93=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../promotion/enums/kehu/MessageTypeEnum.java | 42 +++++++ .../dal/dataobject/kefu/KehuMessageDO.java | 72 ++++++++++++ .../dal/dataobject/kefu/KehuTalkDO.java | 104 ++++++++++++++++++ 3 files changed, 218 insertions(+) create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/kehu/MessageTypeEnum.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KehuMessageDO.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KehuTalkDO.java diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/kehu/MessageTypeEnum.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/kehu/MessageTypeEnum.java new file mode 100644 index 000000000..f866414c6 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/kehu/MessageTypeEnum.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.promotion.enums.kehu; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 消息类型枚举 + * + * @author HUIHUI + */ +@AllArgsConstructor +@Getter +public enum MessageTypeEnum implements IntArrayValuable { + + MESSAGE(1, "普通消息"), + PICTURE(2, "图片消息"), + VOICE(3, "语音消息"), + GOODS(4, "商品消息"), + ORDER(5, "订单消息"), + VIDEO(6, "视频消息"); + + private static final int[] ARRAYS = Arrays.stream(values()).mapToInt(MessageTypeEnum::getType).toArray(); + + /** + * 类型 + */ + private final Integer type; + + /** + * 名称 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KehuMessageDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KehuMessageDO.java new file mode 100644 index 000000000..e949daf0b --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KehuMessageDO.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.promotion.dal.dataobject.kefu; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.promotion.enums.kehu.MessageTypeEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 客户消息 DO + * + * @author HUIHUI + */ +@TableName("kehu_message") +@KeySequence("kehu_message_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class KehuMessageDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 会话编号 + * + * 关联 {@link KehuTalkDO#getId()} + */ + private Long talkId; + + /** + * 发送者 + */ + private Long fromUserId; + /** + * 发送者用户类型 + */ + private String fromUserType; + /** + * 接收者 + */ + private Long toUserId; + /** + * 接收着用户类型 + */ + private String toUserType; + + /** + * 消息类型 + * + * 枚举 {@link MessageTypeEnum} + */ + private Integer messageType; + /** + * 消息 + */ + private String message; + + //======================= 消息相关状态 ======================= + + /** + * 是/否已读 + */ + private Boolean isRead; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KehuTalkDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KehuTalkDO.java new file mode 100644 index 000000000..303281438 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KehuTalkDO.java @@ -0,0 +1,104 @@ +package cn.iocoder.yudao.module.promotion.dal.dataobject.kefu; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.promotion.enums.kehu.MessageTypeEnum; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.time.LocalDateTime; + +/** + * 客户会话 DO + * + * @author HUIHUI + */ +@TableName("kehu_talk") +@KeySequence("kehu_talk_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class KehuTalkDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 会话所属用户 + * + * 关联 {@link MemberUserRespDTO#getId()} + */ + private Long userId; + /** + * 用户名称 + * + * 关联 {@link MemberUserRespDTO#getNickname()} + */ + private String userName; + /** + * 用户头像 + * + * 关联 {@link MemberUserRespDTO#getAvatar()} + */ + private String userFace; + /** + * 管理员名称 + * + * 关联 {@link AdminUserRespDTO#getNickname()} + */ + private String adminName; + /** + * 管理员头像, 管理员搞个默认头像 + */ + private String adminFace; + + /** + * 最后聊天时间 + */ + private LocalDateTime lastTalkTime; + /** + * 最后聊天内容 + */ + private String lastTalkMessage; + /** + * 最后发送的消息类型 + * + * 枚举 {@link MessageTypeEnum} + */ + private Integer lastMessageType; + + //======================= 会话操作相关 ======================= + + /** + * 管理端置顶 + */ + private Boolean adminPinned; + /** + * 用户端不可见,默认为 true + * + * 用户删除此会话时设置为 false + */ + private Boolean userDisable; + /** + * 管理员端不可见,默认为 true + * + * 管理员删除此会话时设置为 false + */ + private Boolean adminDisable; + + /** + * 管理员未读消息数 + * + * 用户发送消息时增加,管理员查看后扣减 + */ + private Integer adminUnreadMessageCount; + +} From a1f738dd81dac8149a0004cc1003c76bb3236297 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 30 May 2024 16:29:28 +0800 Subject: [PATCH 371/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20midjourney=20=E6=8F=90=E4=BA=A4=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/vo/MidjourneySubmitCodeEnum.java | 36 +++++++ .../ai/client/vo/MidjourneySubmitRespVO.java | 4 +- .../admin/image/AiImageController.java | 37 ++++---- ...ava => AiImageMidjourneyImagineReqVO.java} | 17 ++-- .../ai/service/image/AiImageService.java | 5 +- .../ai/service/image/AiImageServiceImpl.java | 95 ++++++++++++------- 6 files changed, 126 insertions(+), 68 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitCodeEnum.java rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/{AiImageMidjourneyReqVO.java => AiImageMidjourneyImagineReqVO.java} (51%) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitCodeEnum.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitCodeEnum.java new file mode 100644 index 000000000..5bf571929 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitCodeEnum.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.ai.client.vo; + +import com.google.common.collect.Lists; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; + +/** + * Midjourney 提交任务 code 枚举 + * + * @author fansili + * @time 2024/5/30 14:33 + * @since 1.0 + */ +@Getter +@AllArgsConstructor +public enum MidjourneySubmitCodeEnum { + + // 状态码: 1(提交成功), 21(已存在), 22(排队中), other(错误) + SUBMIT_SUCCESS("1", "提交成功"), + ALREADY_EXISTS("1", "已存在"), + QUEUING("22", "排队中"), + + ; + + public static final List SUCCESS_CODES = Lists.newArrayList( + SUBMIT_SUCCESS.code, + ALREADY_EXISTS.code, + QUEUING.code + ); + + private String code; + private String name; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitRespVO.java index c9a430d50..d689b2bd7 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitRespVO.java @@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.ai.client.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.util.Map; + /** * Midjourney:Imagine 请求 * @@ -20,7 +22,7 @@ public class MidjourneySubmitRespVO { private String description; @Schema(description = "扩展字段") - private String properties; + private Map properties; @Schema(description = "任务ID") private String result; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index 4dc66a644..6841b1c9c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -3,13 +3,17 @@ package cn.iocoder.yudao.module.ai.controller.admin.image; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageListReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyImagineReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImagePageMyRespVO; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.service.image.AiImageService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -49,32 +53,17 @@ public class AiImageController { } // TODO @fan:建议把 dallDrawing、midjourney 融合成一个 draw 接口,异步绘制;然后返回一个 id 给前端;前端通过 get 接口轮询,直到获取到生成成功 + // TODO @芋艿: 参数差异较大 @Operation(summary = "dall2/dall3绘画", description = "openAi dall3是付费的!") @PostMapping("/dall") public CommonResult dall(@Validated @RequestBody AiImageDallReqVO req) { return success(aiImageService.dall(getLoginUserId(), req)); } - @Operation(summary = "midjourney绘画", description = "midjourney图片绘画流程:1、提交任务 2、获取完成的任务 3、选择对应功能 4、获取最终结果") - @PostMapping("/midjourney") - public CommonResult midjourney(@Validated @RequestBody AiImageMidjourneyReqVO req) { - aiImageService.midjourney(req); - return success(null); - } - - @Operation(summary = "midjourney绘画操作", description = "一般有选择图片、放大、换一批...") - @PostMapping("/midjourney-operate") - public CommonResult midjourneyOperate(@Validated @RequestBody AiImageMidjourneyOperateReqVO req) { - aiImageService.midjourneyOperate(req); - return success(null); - } - - // TODO @fan:要不先不要 midjourneyOperate、cancelMidjourney 接口哈 - @Operation(summary = "取消 midjourney 绘画", description = "取消 midjourney 绘画") - @PostMapping("/cancel-midjourney") - public CommonResult cancelMidjourney(@RequestParam("id") Long id) { - // @范 这里实现mj取消逻辑 - return success(null); + @Operation(summary = "midjourney-imagine 绘画", description = "...") + @PostMapping("/midjourney/imagine") + public CommonResult midjourneyImagine(@Validated @RequestBody AiImageMidjourneyImagineReqVO req) { + return success(aiImageService.midjourneyImagine(getLoginUserId(), req)); } @Operation(summary = "删除【我的】绘画记录") @@ -83,4 +72,10 @@ public class AiImageController { public CommonResult deleteIdMy(@RequestParam("id") Long id) { return success(aiImageService.deleteIdMy(id, getLoginUserId())); } + + @Operation(summary = "删除【我的】绘画记录") + @RequestMapping("/midjourney-notify") + public CommonResult midjourneyNotify(HttpServletRequest request) { + return success(true); + } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyImagineReqVO.java similarity index 51% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyReqVO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyImagineReqVO.java index e6cb0dcec..07cd10ab6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyImagineReqVO.java @@ -1,9 +1,12 @@ package cn.iocoder.yudao.module.ai.controller.admin.image.vo; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; import lombok.Data; import lombok.experimental.Accessors; +import java.util.List; + /** * midjourney req * @@ -13,17 +16,15 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class AiImageMidjourneyReqVO { +public class AiImageMidjourneyImagineReqVO { @Schema(description = "提示词") + @NotNull(message = "提示词不能为空!") private String prompt; - @Schema(description = "绘画比例 1:1、3:4、4:3、9:16、16:9") - private String size; + @Schema(description = "模型(midjourney、niji)") + private String model; - @Schema(description = "风格") - private String style; - - @Schema(description = "参考图") - private String referImage; + @Schema(description = "垫图(参考图)base64数组") + private List base64Array; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java index 6a342a804..b07ba7dd8 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.ai.service.image; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageListReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyImagineReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyOperateReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; /** @@ -44,10 +44,11 @@ public interface AiImageService { /** * midjourney 图片生成 * + * @param loginUserId * @param req * @return */ - void midjourney(AiImageMidjourneyReqVO req); + Long midjourneyImagine(Long loginUserId, AiImageMidjourneyImagineReqVO req); /** * midjourney 操作(u1、u2、放大、换一批...) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index 25467c9af..d6da654f5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.ai.service.image; -import cn.hutool.core.util.IdUtil; import cn.hutool.http.HttpUtil; +import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageModelEnum; import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageStyleEnum; import cn.iocoder.yudao.framework.ai.core.exception.AiException; @@ -11,6 +11,10 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.AiCommonConstants; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; +import cn.iocoder.yudao.module.ai.client.MidjourneyProxyClient; +import cn.iocoder.yudao.module.ai.client.vo.MidjourneyImagineReqVO; +import cn.iocoder.yudao.module.ai.client.vo.MidjourneySubmitCodeEnum; +import cn.iocoder.yudao.module.ai.client.vo.MidjourneySubmitRespVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper; @@ -18,21 +22,22 @@ import cn.iocoder.yudao.module.ai.enums.AiImagePublicStatusEnum; import cn.iocoder.yudao.module.ai.enums.AiImageStatusEnum; import cn.iocoder.yudao.module.infra.api.file.FileApi; import com.google.common.collect.ImmutableMap; -import jakarta.annotation.PostConstruct; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.image.ImageGeneration; import org.springframework.ai.image.ImagePrompt; import org.springframework.ai.image.ImageResponse; -import org.springframework.ai.models.midjourney.api.MidjourneyInteractionsApi; -import org.springframework.ai.models.midjourney.webSocket.MidjourneyWebSocketStarter; import org.springframework.ai.openai.OpenAiImageClient; import org.springframework.ai.openai.OpenAiImageOptions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.HashMap; import java.util.List; +import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -59,28 +64,11 @@ public class AiImageServiceImpl implements AiImageService { private FileApi fileApi; @Resource private OpenAiImageClient openAiImageClient; - @Resource - private MidjourneyWebSocketStarter midjourneyWebSocketStarter; - @Resource - private MidjourneyInteractionsApi midjourneyInteractionsApi; + @Autowired + private MidjourneyProxyClient midjourneyProxyClient; - // TODO @fan:接 mj proxy - @PostConstruct - public void startMidjourney() { - // todo @fan 暂时注释掉 -// log.info("midjourney web socket starter..."); -// midjourneyWebSocketStarter.start(new WssNotify() { -// @Override -// public void notify(int code, String message) { -// log.info("code: {}, message: {}", code, message); -// if (message.contains("Authentication failed")) { -// // TODO 芋艿,这里看怎么处理,token无效的时候会认证失败! -// // 认证失败 -// log.error("midjourney socket 认证失败,检查token是否失效!"); -// } -// } -// }); - } + @Value("${ai.midjourney-proxy.notifyUrl:http://127.0.0.1:48080/admin-api/ai/image/midjourney-notify}") + private String midjourneyNotifyUrl; @Override public PageResult getImagePageMy(Long loginUserId, AiImageListReqVO req) { @@ -143,18 +131,53 @@ public class AiImageServiceImpl implements AiImageService { @Override @Transactional(rollbackFor = Exception.class) - public void midjourney(AiImageMidjourneyReqVO req) { - // 保存数据库 - String messageId = String.valueOf(IdUtil.getSnowflakeNextId()); - // todo -// AiImageDO aiImageDO = doSave(req.getPrompt(), null, "midjoureny", -// null, null, AiImageStatusEnum.SUBMIT, null, -// messageId, null, null); - // 提交 midjourney 任务 - Boolean imagine = midjourneyInteractionsApi.imagine(messageId, req.getPrompt()); - if (!imagine) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MIDJOURNEY_IMAGINE_FAIL); + public Long midjourneyImagine(Long loginUserId, AiImageMidjourneyImagineReqVO req) { + + // 1、构建 AiImageDO + AiImageDO aiImageDO = new AiImageDO(); + aiImageDO.setId(null); + aiImageDO.setUserId(loginUserId); + aiImageDO.setPrompt(req.getPrompt()); + aiImageDO.setPlatform(AiPlatformEnum.MIDJOURNEY.getPlatform()); + // todo @范 平台需要转换(mj 模型一般分版本) + aiImageDO.setModel(null); + aiImageDO.setWidth(null); + aiImageDO.setHeight(null); + aiImageDO.setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus()); + aiImageDO.setPublicStatus(AiImagePublicStatusEnum.PRIVATE.getStatus()); + aiImageDO.setPicUrl(null); + aiImageDO.setOriginalPicUrl(null); + aiImageDO.setDrawRequest(null); + aiImageDO.setDrawResponse(null); + aiImageDO.setErrorMessage(null); + + // 2、保存 image + imageMapper.insert(aiImageDO); + + // 3、调用 MidjourneyProxy 提交任务 + MidjourneyImagineReqVO imagineReqVO = BeanUtils.toBean(req, MidjourneyImagineReqVO.class); + imagineReqVO.setNotifyHook(midjourneyNotifyUrl); + imagineReqVO.setState(String.valueOf(aiImageDO.getId())); + MidjourneySubmitRespVO submitRespVO = midjourneyProxyClient.imagine(imagineReqVO); + + // 4、保存任务 id (状态码: 1(提交成功), 21(已存在), 22(排队中), other(错误)) + String updateStatus = null; + String errorMessage = null; + Map drawResponse = new HashMap<>(); + + if (!MidjourneySubmitCodeEnum.SUCCESS_CODES.contains(submitRespVO.getCode())) { + updateStatus = AiImageStatusEnum.FAIL.getStatus(); + errorMessage = submitRespVO.getDescription(); + } else { + drawResponse.put("jobId", submitRespVO.getResult()); } + imageMapper.updateById(new AiImageDO() + .setId(aiImageDO.getId()) + .setStatus(updateStatus) + .setErrorMessage(errorMessage) + .setDrawResponse(drawResponse) + ); + return aiImageDO.getId(); } @Transactional(rollbackFor = Exception.class) From c0de6cc508a0be28ede39bb9ac627246897e3844 Mon Sep 17 00:00:00 2001 From: xiaoxin <718949661@qq.com> Date: Thu, 30 May 2024 16:56:49 +0800 Subject: [PATCH 372/684] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91SunoResp=E3=80=81SunoReq=E6=94=B9=E4=B8=BArecord?= =?UTF-8?q?=E7=AE=80=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/music/vo/MusicDataVO.java | 23 ++- .../controller/admin/music/vo/SunoRespVO.java | 11 ++ .../ai/service/music/MusicServiceImpl.java | 12 +- .../ai/core/model/suno/api/SunoApi.java | 166 ++++++------------ .../yudao/framework/ai/suno/SunoTests.java | 4 +- .../src/main/resources/application.yaml | 2 +- 6 files changed, 98 insertions(+), 120 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/MusicDataVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/MusicDataVO.java index ce372aff9..d4c4afa22 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/MusicDataVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/MusicDataVO.java @@ -1,13 +1,17 @@ package cn.iocoder.yudao.module.ai.controller.admin.music.vo; +import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; +import java.util.List; +import java.util.stream.Collectors; + /** * 表示单个音乐数据的类 */ @Data -public class MusicDataVO { +public class MusicDataVO { /** * 音乐数据的 ID */ @@ -61,4 +65,21 @@ public class MusicDataVO { * 音乐音频的风格 */ private String style; + + public static List convertFrom(List musicDataList) { + return musicDataList.stream().map(musicData -> { + MusicDataVO musicDataVO = new MusicDataVO(); + musicDataVO.setId(musicData.id()); + musicDataVO.setTitle(musicData.title()); + musicDataVO.setImageUrl(musicData.imageUrl()); + musicDataVO.setLyric(musicData.lyric()); + musicDataVO.setAudioUrl(musicData.audioUrl()); + musicDataVO.setVideoUrl(musicData.videoUrl()); + musicDataVO.setCreatedAt(musicData.createdAt()); + musicDataVO.setModel(musicData.model()); + musicDataVO.setPrompt(musicData.prompt()); + musicDataVO.setStyle(musicData.style()); + return musicDataVO; + }).collect(Collectors.toList()); + } } \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/SunoRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/SunoRespVO.java index bbb4264c7..b3d66363f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/SunoRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/SunoRespVO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.ai.controller.admin.music.vo; +import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; @@ -26,4 +27,14 @@ public class SunoRespVO { */ private List data; + + //把 SunoResp转为本vo类 + public static SunoRespVO convertFrom(SunoApi.SunoResp sunoResp) { + SunoRespVO sunoRespVO = new SunoRespVO(); + sunoRespVO.setSuccess(sunoResp.success()); + sunoRespVO.setTaskId(sunoResp.taskId()); + sunoRespVO.setData(MusicDataVO.convertFrom(sunoResp.data())); + return sunoRespVO; + } + } \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/MusicServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/MusicServiceImpl.java index cbc4f9429..0673e59ac 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/MusicServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/MusicServiceImpl.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.ai.service.music; import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.ai.controller.admin.music.vo.SunoReqVO; import cn.iocoder.yudao.module.ai.controller.admin.music.vo.SunoRespVO; import lombok.RequiredArgsConstructor; @@ -19,7 +18,14 @@ public class MusicServiceImpl implements MusicService { @Override public SunoRespVO musicGen(SunoReqVO sunoReqVO) { - SunoApi.SunoReq req = BeanUtils.toBean(sunoReqVO, SunoApi.SunoReq.class); - return BeanUtils.toBean(sunoApi.musicGen(req), SunoRespVO.class); + SunoApi.SunoResp sunoResp = sunoApi.musicGen(new SunoApi.SunoReq( + sunoReqVO.getPrompt(), + sunoReqVO.getLyric(), + sunoReqVO.isCustom(), + sunoReqVO.getTitle(), + sunoReqVO.getStyle(), + sunoReqVO.getCallbackUrl() + )); + return SunoRespVO.convertFrom(sunoResp); } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/SunoApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/SunoApi.java index 1b1a500ad..22435affd 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/SunoApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/SunoApi.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.framework.ai.core.model.suno.api; import cn.iocoder.yudao.framework.ai.core.model.suno.SunoConfig; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.openai.api.ApiUtils; import org.springframework.web.reactive.function.client.WebClient; @@ -48,128 +47,69 @@ public class SunoApi { .block(); } - // TODO @xiaoxin:看看是不是使用 record 特性,简化下; - /** - * 请求数据对象,用于生成音乐音频 + * 请求数据对象,用于生成音乐音频。 + * + * @param prompt 用于生成音乐音频的提示 + * @param lyric 用于生成音乐音频的歌词 + * @param custom 指示音乐音频是否为定制,如果为 true,则从歌词生成,否则从提示生成 + * @param title 音乐音频的标题 + * @param style 音乐音频的风格 + * @param callbackUrl 音乐音频生成后回调的 URL */ - @Data @JsonInclude(value = JsonInclude.Include.NON_NULL) - public static class SunoReq { - /** - * 用于生成音乐音频的提示 - */ - private String prompt; + public record SunoReq( + String prompt, + String lyric, + boolean custom, + String title, + String style, + String callbackUrl + ) { + public SunoReq(String prompt) { + this(prompt, null, false, null, null, null); + } - /** - * 用于生成音乐音频的歌词 - */ - private String lyric; - - /** - * 指示音乐音频是否为定制,如果为 true,则从歌词生成,否则从提示生成 - */ - private boolean custom; - - /** - * 音乐音频的标题 - */ - private String title; - - /** - * 音乐音频的风格 - */ - private String style; - - /** - * 音乐音频生成后回调的 URL - */ - private String callbackUrl; } - // TODO @xiaoxin:看看是不是使用 record 特性,简化下; - /** - * SunoAPI 响应的数据 + * SunoAPI 响应的数据。 + * + * @param success 表示请求是否成功 + * @param taskId 任务 ID + * @param data 音乐数据列表 */ - @Data - public static class SunoResp { + public record SunoResp( + boolean success, + @JsonProperty("task_id") String taskId, + List data + ) { /** - * 表示请求是否成功 + * 单个音乐数据。 + * + * @param id 音乐数据的 ID + * @param title 音乐音频的标题 + * @param imageUrl 音乐音频的图片 URL + * @param lyric 音乐音频的歌词 + * @param audioUrl 音乐音频的 URL + * @param videoUrl 音乐视频的 URL + * @param createdAt 音乐音频的创建时间 + * @param model 使用的模型名称 + * @param prompt 生成音乐音频的提示 + * @param style 音乐音频的风格 */ - private boolean success; - - /** - * 任务 ID - */ - @JsonProperty("task_id") - private String taskId; - - /** - * 音乐数据列表 - */ - private List data; - - /** - * 表示单个音乐数据的类 - */ - @Data - static class MusicData { - /** - * 音乐数据的 ID - */ - private String id; - - /** - * 音乐音频的标题 - */ - private String title; - - /** - * 音乐音频的图片 URL - */ - @JsonProperty("image_url") - private String imageUrl; - - /** - * 音乐音频的歌词 - */ - private String lyric; - - /** - * 音乐音频的 URL - */ - @JsonProperty("audio_url") - private String audioUrl; - - /** - * 音乐视频的 URL - */ - @JsonProperty("video_url") - private String videoUrl; - - /** - * 音乐音频的创建时间 - */ - @JsonProperty("created_at") - private String createdAt; - - /** - * 使用的模型名称 - */ - private String model; - - /** - * 生成音乐音频的提示 - */ - private String prompt; - - /** - * 音乐音频的风格 - */ - private String style; + public record MusicData( + String id, + String title, + @JsonProperty("image_url") String imageUrl, + String lyric, + @JsonProperty("audio_url") String audioUrl, + @JsonProperty("video_url") String videoUrl, + @JsonProperty("created_at") String createdAt, + String model, + String prompt, + String style + ) { } } - - } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java index 02e9243d2..36fc40b17 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java @@ -22,8 +22,8 @@ public class SunoTests { @Test public void generateMusic() { SunoApi sunoApi = new SunoApi(sunoConfig); - SunoApi.SunoReq sunoReq = new SunoApi.SunoReq() - .setPrompt("创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。"); + SunoApi.SunoReq sunoReq = new SunoApi.SunoReq("创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。"); + SunoApi.SunoResp sunoResp = sunoApi.musicGen(sunoReq); System.out.println(sunoResp); } diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 417787ba4..f1b8f56f7 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -201,7 +201,7 @@ yudao.ai: channel-id: 1237948819677904960 suno: enable: true - token: 13f13540dd3f4ae9885f63ac9f5d0b9f + token: 16b4356581984d538652354b60d69ff0 --- #################### 芋道相关配置 #################### From 74620ebc349393249b65116561bd7c28623c8a43 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 30 May 2024 17:21:22 +0800 Subject: [PATCH 373/684] =?UTF-8?q?=E3=80=90sql=E3=80=91=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E6=9C=80=E6=96=B0=E7=89=88=20image=20sql?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/ai_image.sql | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/resources/ai_image.sql diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/ai_image.sql b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/ai_image.sql new file mode 100644 index 000000000..4de719235 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/ai_image.sql @@ -0,0 +1,61 @@ +/* + Navicat Premium Data Transfer + + Source Server : localhost + Source Server Type : MySQL + Source Server Version : 80034 (8.0.34) + Source Host : localhost:3306 + Source Schema : ruoyi-vue-pro + + Target Server Type : MySQL + Target Server Version : 80034 (8.0.34) + File Encoding : 65001 + + Date: 30/05/2024 17:20:37 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for ai_image +-- ---------------------------- +DROP TABLE IF EXISTS `ai_image`; +CREATE TABLE `ai_image` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `user_id` bigint DEFAULT NULL, + `prompt` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '提示词\n', + `platform` varchar(32) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '平台', + `model` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '模型 dall2/dall3、MJ、NIJI', + `width` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '图片宽度', + `height` varchar(32) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '图片高度', + `status` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '绘画状态:提交、排队、绘画中、绘画完成、绘画失败\n', + `public_status` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '是否发布', + `pic_url` varchar(512) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '图片地址', + `original_pic_url` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '绘画图片地址\n', + `error_message` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '错误信息', + `draw_request` json DEFAULT NULL COMMENT '绘画request', + `draw_response` json DEFAULT NULL COMMENT '绘画response', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `creator` bigint DEFAULT NULL COMMENT '创建用户', + `updater` bigint DEFAULT NULL COMMENT '更新用户', + `deleted` bit(1) DEFAULT b'0' COMMENT '删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=107 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; + +-- ---------------------------- +-- Records of ai_image +-- ---------------------------- +BEGIN; +INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `platform`, `model`, `width`, `height`, `status`, `public_status`, `pic_url`, `original_pic_url`, `error_message`, `draw_request`, `draw_response`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (91, 1, '北极企鹅', NULL, 'dall-e-2', '1024', '1024', '20', NULL, 'http://test.yudao.iocoder.cn/75b4d733222b60aafdbdcd0475562ff88149eaaff93a25c4e4c66a95bd07f01f.png', 'https://oaidalleapiprodscus.blob.core.windows.net/private/org-FttVrm20iQRlsxxFE7BLEgkT/user-5p7zykU5aS1sYXCjczkTXn8I/img-z4KBxbWtUpLBYmgaYPvWXjBh.png?st=2024-05-29T04%3A50%3A54Z&se=2024-05-29T06%3A50%3A54Z&sp=r&sv=2023-11-03&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2024-05-28T23%3A21%3A22Z&ske=2024-05-29T23%3A21%3A22Z&sks=b&skv=2023-11-03&sig=jSw/hJfuPWJqQgjSoINtVrt4w61FsaQ6ed4pRCM8UUA%3D', NULL, '{\"style\": \"vivid\"}', NULL, '2024-05-29 13:50:43', '2024-05-29 13:51:05', 1, 1, b'0'); +INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `platform`, `model`, `width`, `height`, `status`, `public_status`, `pic_url`, `original_pic_url`, `error_message`, `draw_request`, `draw_response`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (93, 1, '北极企鹅', NULL, 'dall-e-2', '1024', '1024', '20', 'private', 'http://test.yudao.iocoder.cn/ab326bbf3fae9a940770a5c36bbf39467ae539a5b94a030b6c6cc2f179d7dd31.png', 'https://oaidalleapiprodscus.blob.core.windows.net/private/org-FttVrm20iQRlsxxFE7BLEgkT/user-5p7zykU5aS1sYXCjczkTXn8I/img-CsJtCgLT9lTigTuBDJtPyO8X.png?st=2024-05-29T09%3A02%3A12Z&se=2024-05-29T11%3A02%3A12Z&sp=r&sv=2023-11-03&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2024-05-28T23%3A21%3A54Z&ske=2024-05-29T23%3A21%3A54Z&sks=b&skv=2023-11-03&sig=tH6yFzHtcp3Dxwaua2crFYurCdE7B7%2BAXhyPNVVep1c%3D', NULL, '{\"style\": \"vivid\"}', NULL, '2024-05-29 18:02:03', '2024-05-29 18:02:17', 1, 1, b'0'); +INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `platform`, `model`, `width`, `height`, `status`, `public_status`, `pic_url`, `original_pic_url`, `error_message`, `draw_request`, `draw_response`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (94, 1, '北极大熊猫', NULL, 'dall-e-2', '1024', '1024', '20', 'private', 'http://test.yudao.iocoder.cn/ed9d43a6c841c4a967700e211c998778994eeea60cff2dfeb1c3a88b0542ebdd.png', 'https://oaidalleapiprodscus.blob.core.windows.net/private/org-FttVrm20iQRlsxxFE7BLEgkT/user-5p7zykU5aS1sYXCjczkTXn8I/img-GAwShv01C2408VY5lXvLTP4Q.png?st=2024-05-30T01%3A31%3A28Z&se=2024-05-30T03%3A31%3A28Z&sp=r&sv=2023-11-03&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2024-05-29T23%3A39%3A20Z&ske=2024-05-30T23%3A39%3A20Z&sks=b&skv=2023-11-03&sig=n/rqAnD0qJDkhbh/Qm12lz1Se70PQSdXetarmwCKoMY%3D', NULL, '{\"style\": \"vivid\"}', NULL, '2024-05-30 10:31:18', '2024-05-30 10:31:34', 1, 1, b'1'); +INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `platform`, `model`, `width`, `height`, `status`, `public_status`, `pic_url`, `original_pic_url`, `error_message`, `draw_request`, `draw_response`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (102, 1, '女少侠', 'midjourney', NULL, NULL, NULL, '30', 'private', NULL, NULL, '无可用的账号实例', NULL, '{}', '2024-05-30 16:11:13', '2024-05-30 16:11:13', 1, 1, b'1'); +INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `platform`, `model`, `width`, `height`, `status`, `public_status`, `pic_url`, `original_pic_url`, `error_message`, `draw_request`, `draw_response`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (103, 1, '123123', 'midjourney', NULL, NULL, NULL, '30', 'private', NULL, NULL, '无可用的账号实例', NULL, '{}', '2024-05-30 16:27:34', '2024-05-30 16:27:34', 1, 1, b'1'); +INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `platform`, `model`, `width`, `height`, `status`, `public_status`, `pic_url`, `original_pic_url`, `error_message`, `draw_request`, `draw_response`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (104, 1, '123123', 'midjourney', NULL, NULL, NULL, '30', 'private', NULL, NULL, '无可用的账号实例', NULL, '{}', '2024-05-30 16:28:23', '2024-05-30 16:28:24', 1, 1, b'1'); +INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `platform`, `model`, `width`, `height`, `status`, `public_status`, `pic_url`, `original_pic_url`, `error_message`, `draw_request`, `draw_response`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (105, 1, '123123', 'midjourney', NULL, NULL, NULL, '30', 'private', NULL, NULL, '无可用的账号实例', NULL, '{}', '2024-05-30 16:28:25', '2024-05-30 16:28:25', 1, 1, b'1'); +INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `platform`, `model`, `width`, `height`, `status`, `public_status`, `pic_url`, `original_pic_url`, `error_message`, `draw_request`, `draw_response`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (106, 1, '123123', 'midjourney', NULL, NULL, NULL, '30', 'private', NULL, NULL, '无可用的账号实例', NULL, '{}', '2024-05-30 16:28:34', '2024-05-30 16:28:34', 1, 1, b'1'); +COMMIT; + +SET FOREIGN_KEY_CHECKS = 1; From c53633a286aefc8e0fbc06020c904602e3a7f06d Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 30 May 2024 19:21:12 +0800 Subject: [PATCH 374/684] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91AI=EF=BC=9ASuno=20=E9=9F=B3=E4=B9=90=E7=9A=84?= =?UTF-8?q?=20review?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/iocoder/yudao/module/ai/client/MidjourneyProxyClient.java | 1 + .../yudao/module/ai/client/vo/MidjourneyImagineReqVO.java | 1 + .../yudao/module/ai/client/vo/MidjourneySubmitCodeEnum.java | 1 + .../yudao/module/ai/client/vo/MidjourneySubmitRespVO.java | 1 + .../module/ai/controller/admin/image/AiImageController.java | 1 + .../controller/admin/image/vo/AiImageMidjourneyImagineReqVO.java | 1 + 6 files changed, 6 insertions(+) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/MidjourneyProxyClient.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/MidjourneyProxyClient.java index 79db06e5c..efba5234b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/MidjourneyProxyClient.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/MidjourneyProxyClient.java @@ -9,6 +9,7 @@ import org.springframework.stereotype.Component; import org.springframework.validation.annotation.Validated; import org.springframework.web.client.RestTemplate; +// TODO @fan:这个写到 starter-ai 里哈。搞个 MidjourneyApi,参考 https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiApi.java 的风格写哈 /** * Midjourney Proxy 客户端 * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyImagineReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyImagineReqVO.java index ce3b33c4a..5f48747b6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyImagineReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyImagineReqVO.java @@ -6,6 +6,7 @@ import lombok.Data; import java.util.List; +// TODO @fan:待定 /** * Midjourney:Imagine 请求 * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitCodeEnum.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitCodeEnum.java index 5bf571929..13bf09814 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitCodeEnum.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitCodeEnum.java @@ -6,6 +6,7 @@ import lombok.Getter; import java.util.List; +// TODO @fan:待定 /** * Midjourney 提交任务 code 枚举 * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitRespVO.java index d689b2bd7..9aa9e97f1 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitRespVO.java @@ -5,6 +5,7 @@ import lombok.Data; import java.util.Map; +// TODO @fan:待定 /** * Midjourney:Imagine 请求 * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index 6841b1c9c..bef20fe14 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -54,6 +54,7 @@ public class AiImageController { // TODO @fan:建议把 dallDrawing、midjourney 融合成一个 draw 接口,异步绘制;然后返回一个 id 给前端;前端通过 get 接口轮询,直到获取到生成成功 // TODO @芋艿: 参数差异较大 + // TODO @fan:直接参数平铺?写好注释,要么? @Operation(summary = "dall2/dall3绘画", description = "openAi dall3是付费的!") @PostMapping("/dall") public CommonResult dall(@Validated @RequestBody AiImageDallReqVO req) { diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyImagineReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyImagineReqVO.java index 07cd10ab6..df43efa36 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyImagineReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyImagineReqVO.java @@ -7,6 +7,7 @@ import lombok.experimental.Accessors; import java.util.List; +// TODO @fan:待定 /** * midjourney req * From 0be9c67aa6b534e872b25b9e82e4a32e7fc7e331 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Fri, 31 May 2024 09:58:23 +0800 Subject: [PATCH 375/684] =?UTF-8?q?MALL-KEFU:=20=E6=A0=B9=E6=8D=AE?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E8=AF=84=E5=AE=A1=E4=BF=AE=E6=94=B9=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...m.java => KeFuMessageContentTypeEnum.java} | 15 +-- .../dataobject/kefu/KeFuConversationDO.java | 83 ++++++++++++++ .../dal/dataobject/kefu/KeFuMessageDO.java | 81 ++++++++++++++ .../dal/dataobject/kefu/KehuMessageDO.java | 72 ------------ .../dal/dataobject/kefu/KehuTalkDO.java | 104 ------------------ 5 files changed, 172 insertions(+), 183 deletions(-) rename yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/kehu/{MessageTypeEnum.java => KeFuMessageContentTypeEnum.java} (64%) create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KeFuConversationDO.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KeFuMessageDO.java delete mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KehuMessageDO.java delete mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KehuTalkDO.java diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/kehu/MessageTypeEnum.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/kehu/KeFuMessageContentTypeEnum.java similarity index 64% rename from yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/kehu/MessageTypeEnum.java rename to yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/kehu/KeFuMessageContentTypeEnum.java index f866414c6..29c3b34c4 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/kehu/MessageTypeEnum.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/kehu/KeFuMessageContentTypeEnum.java @@ -13,16 +13,17 @@ import java.util.Arrays; */ @AllArgsConstructor @Getter -public enum MessageTypeEnum implements IntArrayValuable { +public enum KeFuMessageContentTypeEnum implements IntArrayValuable { - MESSAGE(1, "普通消息"), - PICTURE(2, "图片消息"), + TEXT(1, "文本消息"), + IMAGE(2, "图片消息"), VOICE(3, "语音消息"), - GOODS(4, "商品消息"), - ORDER(5, "订单消息"), - VIDEO(6, "视频消息"); + VIDEO(4, "视频消息"), + // 和正常消息隔离下 + PRODUCT(10, "商品消息"), + ORDER(11, "订单消息"); - private static final int[] ARRAYS = Arrays.stream(values()).mapToInt(MessageTypeEnum::getType).toArray(); + private static final int[] ARRAYS = Arrays.stream(values()).mapToInt(KeFuMessageContentTypeEnum::getType).toArray(); /** * 类型 diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KeFuConversationDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KeFuConversationDO.java new file mode 100644 index 000000000..04432eebe --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KeFuConversationDO.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.module.promotion.dal.dataobject.kefu; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.promotion.enums.kehu.KeFuMessageContentTypeEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.time.LocalDateTime; + +/** + * 客服会话 DO + * + * @author HUIHUI + */ +@TableName("promotion_kefu_conversation") +@KeySequence("promotion_kefu_conversation_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class KeFuConversationDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 会话所属用户 + * + * 关联 {@link MemberUserRespDTO#getId()} + */ + private Long userId; + + /** + * 最后聊天时间 + */ + private LocalDateTime lastMessageTime; + /** + * 最后聊天内容 + */ + private String lastMessageContent; + /** + * 最后发送的消息类型 + * + * 枚举 {@link KeFuMessageContentTypeEnum} + */ + private Integer lastMessageContentType; + + //======================= 会话操作相关 ======================= + + /** + * 管理端置顶 + */ + private Boolean adminPinned; + /** + * 用户是否可见 + * + * true - 可见,默认值 + * false - 不可见,用户删除时设置为 false + */ + private Boolean userDeleted; + /** + * 管理员是否可见 + * + * true - 可见,默认值 + * false - 不可见,管理员删除时设置为 false + */ + private Boolean adminDeleted; + + /** + * 管理员未读消息数 + * + * 用户发送消息时增加,管理员查看后扣减 + */ + private Integer adminUnreadMessageCount; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KeFuMessageDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KeFuMessageDO.java new file mode 100644 index 000000000..bd542f890 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KeFuMessageDO.java @@ -0,0 +1,81 @@ +package cn.iocoder.yudao.module.promotion.dal.dataobject.kefu; + +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.promotion.enums.kehu.KeFuMessageContentTypeEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 客服消息 DO + * + * @author HUIHUI + */ +@TableName("promotion_kefu_message") +@KeySequence("promotion_kefu_message_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class KeFuMessageDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 会话编号 + * + * 关联 {@link KeFuConversationDO#getId()} + */ + private Long conversationId; + + /** + * 发送人编号 + * + * 存储的是用户编号 + */ + private Long senderId; + /** + * 发送人类型 + * + * 枚举,{@link UserTypeEnum} + */ + private Integer senderType; + /** + * 接收人编号 + * + * 存储的是用户编号 + */ + private Long receiverId; + /** + * 接收人类型 + * + * 枚举,{@link UserTypeEnum} + */ + private Integer receiverType; + + /** + * 消息类型 + * + * 枚举 {@link KeFuMessageContentTypeEnum} + */ + private Integer contentType; + /** + * 消息 + */ + private String content; + + //======================= 消息相关状态 ======================= + + /** + * 是/否已读 + */ + private Boolean readStatus; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KehuMessageDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KehuMessageDO.java deleted file mode 100644 index e949daf0b..000000000 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KehuMessageDO.java +++ /dev/null @@ -1,72 +0,0 @@ -package cn.iocoder.yudao.module.promotion.dal.dataobject.kefu; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.promotion.enums.kehu.MessageTypeEnum; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -/** - * 客户消息 DO - * - * @author HUIHUI - */ -@TableName("kehu_message") -@KeySequence("kehu_message_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class KehuMessageDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - /** - * 会话编号 - * - * 关联 {@link KehuTalkDO#getId()} - */ - private Long talkId; - - /** - * 发送者 - */ - private Long fromUserId; - /** - * 发送者用户类型 - */ - private String fromUserType; - /** - * 接收者 - */ - private Long toUserId; - /** - * 接收着用户类型 - */ - private String toUserType; - - /** - * 消息类型 - * - * 枚举 {@link MessageTypeEnum} - */ - private Integer messageType; - /** - * 消息 - */ - private String message; - - //======================= 消息相关状态 ======================= - - /** - * 是/否已读 - */ - private Boolean isRead; - -} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KehuTalkDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KehuTalkDO.java deleted file mode 100644 index 303281438..000000000 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KehuTalkDO.java +++ /dev/null @@ -1,104 +0,0 @@ -package cn.iocoder.yudao.module.promotion.dal.dataobject.kefu; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; -import cn.iocoder.yudao.module.promotion.enums.kehu.MessageTypeEnum; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -import java.time.LocalDateTime; - -/** - * 客户会话 DO - * - * @author HUIHUI - */ -@TableName("kehu_talk") -@KeySequence("kehu_talk_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class KehuTalkDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - /** - * 会话所属用户 - * - * 关联 {@link MemberUserRespDTO#getId()} - */ - private Long userId; - /** - * 用户名称 - * - * 关联 {@link MemberUserRespDTO#getNickname()} - */ - private String userName; - /** - * 用户头像 - * - * 关联 {@link MemberUserRespDTO#getAvatar()} - */ - private String userFace; - /** - * 管理员名称 - * - * 关联 {@link AdminUserRespDTO#getNickname()} - */ - private String adminName; - /** - * 管理员头像, 管理员搞个默认头像 - */ - private String adminFace; - - /** - * 最后聊天时间 - */ - private LocalDateTime lastTalkTime; - /** - * 最后聊天内容 - */ - private String lastTalkMessage; - /** - * 最后发送的消息类型 - * - * 枚举 {@link MessageTypeEnum} - */ - private Integer lastMessageType; - - //======================= 会话操作相关 ======================= - - /** - * 管理端置顶 - */ - private Boolean adminPinned; - /** - * 用户端不可见,默认为 true - * - * 用户删除此会话时设置为 false - */ - private Boolean userDisable; - /** - * 管理员端不可见,默认为 true - * - * 管理员删除此会话时设置为 false - */ - private Boolean adminDisable; - - /** - * 管理员未读消息数 - * - * 用户发送消息时增加,管理员查看后扣减 - */ - private Integer adminUnreadMessageCount; - -} From 27f052de0a7bf9f61d17eea59427aee8fcf79c47 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 31 May 2024 14:05:16 +0800 Subject: [PATCH 376/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91mid?= =?UTF-8?q?journey=20=E5=A2=9E=E5=8A=A0=20--ar=20=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/image/vo/AiImageMidjourneyImagineReqVO.java | 6 ++++++ .../yudao/module/ai/service/image/AiImageServiceImpl.java | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyImagineReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyImagineReqVO.java index 07cd10ab6..ee17f1065 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyImagineReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyImagineReqVO.java @@ -25,6 +25,12 @@ public class AiImageMidjourneyImagineReqVO { @Schema(description = "模型(midjourney、niji)") private String model; + @Schema(description = "图片宽度") + private String width; + + @Schema(description = "图片高度") + private String height; + @Schema(description = "垫图(参考图)base64数组") private List base64Array; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index d6da654f5..ee45eee73 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -12,8 +12,8 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.AiCommonConstants; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.client.MidjourneyProxyClient; +import cn.iocoder.yudao.module.ai.client.enums.MidjourneySubmitCodeEnum; import cn.iocoder.yudao.module.ai.client.vo.MidjourneyImagineReqVO; -import cn.iocoder.yudao.module.ai.client.vo.MidjourneySubmitCodeEnum; import cn.iocoder.yudao.module.ai.client.vo.MidjourneySubmitRespVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; @@ -157,7 +157,8 @@ public class AiImageServiceImpl implements AiImageService { // 3、调用 MidjourneyProxy 提交任务 MidjourneyImagineReqVO imagineReqVO = BeanUtils.toBean(req, MidjourneyImagineReqVO.class); imagineReqVO.setNotifyHook(midjourneyNotifyUrl); - imagineReqVO.setState(String.valueOf(aiImageDO.getId())); + // 设置 midjourney 扩展参数,通过 --ar 来设置尺寸 + imagineReqVO.setState(String.format("--ar %s:%s", req.getWidth(), req.getHeight())); MidjourneySubmitRespVO submitRespVO = midjourneyProxyClient.imagine(imagineReqVO); // 4、保存任务 id (状态码: 1(提交成功), 21(已存在), 22(排队中), other(错误)) From 47ff5bf814490791317f654e9515364fca05aedd Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 31 May 2024 14:25:03 +0800 Subject: [PATCH 377/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91mid?= =?UTF-8?q?journey=20=E5=A2=9E=E5=8A=A0=E7=89=88=E6=9C=AC=E5=8F=B7?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/image/vo/AiImageMidjourneyImagineReqVO.java | 7 +++++-- .../yudao/module/ai/service/image/AiImageServiceImpl.java | 4 +++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyImagineReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyImagineReqVO.java index b4398ad73..e83dd2c87 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyImagineReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyImagineReqVO.java @@ -26,12 +26,15 @@ public class AiImageMidjourneyImagineReqVO { @Schema(description = "模型(midjourney、niji)") private String model; - @Schema(description = "图片宽度") + @Schema(description = "图片宽度 --ar 设置") private String width; - @Schema(description = "图片高度") + @Schema(description = "图片高度 --ar 设置") private String height; + @Schema(description = "版本号 --v 设置") + private String version; + @Schema(description = "垫图(参考图)base64数组") private List base64Array; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index ee45eee73..67884e264 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -158,7 +158,9 @@ public class AiImageServiceImpl implements AiImageService { MidjourneyImagineReqVO imagineReqVO = BeanUtils.toBean(req, MidjourneyImagineReqVO.class); imagineReqVO.setNotifyHook(midjourneyNotifyUrl); // 设置 midjourney 扩展参数,通过 --ar 来设置尺寸 - imagineReqVO.setState(String.format("--ar %s:%s", req.getWidth(), req.getHeight())); + String midjourneySizeParam = String.format("--ar %s:%s", req.getWidth(), req.getHeight()); + String midjourneyVersionParam = String.format("--v %s", req.getVersion()); + imagineReqVO.setState(midjourneySizeParam.concat(" ").concat(midjourneyVersionParam)); MidjourneySubmitRespVO submitRespVO = midjourneyProxyClient.imagine(imagineReqVO); // 4、保存任务 id (状态码: 1(提交成功), 21(已存在), 22(排队中), other(错误)) From 8f3076b2ea6ad9e803f7ebc998f54868bafc0181 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 31 May 2024 14:36:07 +0800 Subject: [PATCH 378/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91nij?= =?UTF-8?q?i=20=E6=A8=A1=E5=9E=8B=E5=8F=82=E6=95=B0=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/client/enums/MidjourneyModelEnum.java | 30 +++++++++++++++++++ .../ai/service/image/AiImageServiceImpl.java | 15 +++++++--- 2 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/enums/MidjourneyModelEnum.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/enums/MidjourneyModelEnum.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/enums/MidjourneyModelEnum.java new file mode 100644 index 000000000..6c53b9294 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/enums/MidjourneyModelEnum.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.ai.client.enums; + + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 来源于 midjourney-proxy + */ +@Getter +@AllArgsConstructor +public enum MidjourneyModelEnum { + + MIDJOURNEY("midjourney", "midjourney"), + NIJI("Niji", "Niji"), + + ; + + private String model; + private String name; + + public static MidjourneyModelEnum valueOfModel(String model) { + for (MidjourneyModelEnum itemEnum : MidjourneyModelEnum.values()) { + if (itemEnum.getModel().equals(model)) { + return itemEnum; + } + } + throw new IllegalArgumentException("Invalid MessageType value: " + model); + } +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index 67884e264..bef3b600b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -12,6 +12,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.AiCommonConstants; import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.client.MidjourneyProxyClient; +import cn.iocoder.yudao.module.ai.client.enums.MidjourneyModelEnum; import cn.iocoder.yudao.module.ai.client.enums.MidjourneySubmitCodeEnum; import cn.iocoder.yudao.module.ai.client.vo.MidjourneyImagineReqVO; import cn.iocoder.yudao.module.ai.client.vo.MidjourneySubmitRespVO; @@ -157,10 +158,16 @@ public class AiImageServiceImpl implements AiImageService { // 3、调用 MidjourneyProxy 提交任务 MidjourneyImagineReqVO imagineReqVO = BeanUtils.toBean(req, MidjourneyImagineReqVO.class); imagineReqVO.setNotifyHook(midjourneyNotifyUrl); - // 设置 midjourney 扩展参数,通过 --ar 来设置尺寸 - String midjourneySizeParam = String.format("--ar %s:%s", req.getWidth(), req.getHeight()); - String midjourneyVersionParam = String.format("--v %s", req.getVersion()); - imagineReqVO.setState(midjourneySizeParam.concat(" ").concat(midjourneyVersionParam)); + // 设置 midjourney 扩展参数 + // --ar 来设置尺寸 + String midjourneySizeParam = String.format(" --ar %s:%s ", req.getWidth(), req.getHeight()); + // --v 版本 + String midjourneyVersionParam = String.format(" --v %s ", req.getVersion()); + // --niji 模型 + MidjourneyModelEnum midjourneyModelEnum = MidjourneyModelEnum.valueOfModel(req.getModel()); + String midjourneyNijiParam = MidjourneyModelEnum.NIJI == midjourneyModelEnum ? " --niji " : ""; + // 设置参数 + imagineReqVO.setState(midjourneySizeParam.concat(midjourneyVersionParam).concat(midjourneyNijiParam)); MidjourneySubmitRespVO submitRespVO = midjourneyProxyClient.imagine(imagineReqVO); // 4、保存任务 id (状态码: 1(提交成功), 21(已存在), 22(排队中), other(错误)) From 3c7fccfcf315d001cbb19b710e8a550e7e1dbeda Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 31 May 2024 14:37:47 +0800 Subject: [PATCH 379/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91mid?= =?UTF-8?q?journey=20proxy=20=E9=80=9A=E7=9F=A5=E5=9B=9E=E8=B0=83=20vo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/client/vo/MidjourneyNotifyVO.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyVO.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyVO.java new file mode 100644 index 000000000..c2a934331 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyVO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.ai.client.vo; + +import cn.iocoder.yudao.module.ai.client.enums.MidjourneyTaskActionEnum; +import cn.iocoder.yudao.module.ai.client.enums.MidjourneyTaskStatusEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * @author fansili + * @time 2024/5/31 10:37 + * @since 1.0 + */ +@Data +public class MidjourneyNotifyVO { + + @Schema(description = "任务类型") + private MidjourneyTaskActionEnum action; + @Schema(description = "任务状态") + private MidjourneyTaskStatusEnum status = MidjourneyTaskStatusEnum.NOT_START; + + @Schema(description = "提示词") + private String prompt; + @Schema(description = "提示词-英文") + private String promptEn; + + @Schema(description = "任务描述") + private String description; + @Schema(description = "自定义参数") + private String state; + + @Schema(description = "提交时间") + private Long submitTime; + @Schema(description = "开始执行时间") + private Long startTime; + @Schema(description = "结束时间") + private Long finishTime; + + @Schema(description = "图片url") + private String imageUrl; + + @Schema(description = "任务进度") + private String progress; + @Schema(description = "失败原因") + private String failReason; + +} From 3c6fb95917c22a263628dd0e70e29d13f2c95112 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 31 May 2024 14:38:04 +0800 Subject: [PATCH 380/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91mid?= =?UTF-8?q?journey=20proxy=20=E6=9E=9A=E4=B8=BE=20action=20=E5=92=8C=20sta?= =?UTF-8?q?tus?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../enums/MidjourneyTaskActionEnum.java | 35 +++++++++++++++++ .../enums/MidjourneyTaskStatusEnum.java | 38 +++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/enums/MidjourneyTaskActionEnum.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/enums/MidjourneyTaskStatusEnum.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/enums/MidjourneyTaskActionEnum.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/enums/MidjourneyTaskActionEnum.java new file mode 100644 index 000000000..a845a47f8 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/enums/MidjourneyTaskActionEnum.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.ai.client.enums; + +import lombok.Getter; + +/** + * 来源于 midjourney-proxy + */ +@Getter +public enum MidjourneyTaskActionEnum { + /** + * 生成图片. + */ + IMAGINE, + /** + * 选中放大. + */ + UPSCALE, + /** + * 选中其中的一张图,生成四张相似的. + */ + VARIATION, + /** + * 重新执行. + */ + REROLL, + /** + * 图转prompt. + */ + DESCRIBE, + /** + * 多图混合. + */ + BLEND + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/enums/MidjourneyTaskStatusEnum.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/enums/MidjourneyTaskStatusEnum.java new file mode 100644 index 000000000..b3af66e2e --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/enums/MidjourneyTaskStatusEnum.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.ai.client.enums; + + +import lombok.Getter; + +/** + * 来源于 midjourney-proxy + */ +public enum MidjourneyTaskStatusEnum { + /** + * 未启动. + */ + NOT_START(0), + /** + * 已提交. + */ + SUBMITTED(1), + /** + * 执行中. + */ + IN_PROGRESS(3), + /** + * 失败. + */ + FAILURE(4), + /** + * 成功. + */ + SUCCESS(4); + + @Getter + private final int order; + + MidjourneyTaskStatusEnum(int order) { + this.order = order; + } + +} From 36b6fee0ec86d407af1c67585c3927606fddc8f6 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 31 May 2024 14:38:15 +0800 Subject: [PATCH 381/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=20package?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/client/{vo => enums}/MidjourneySubmitCodeEnum.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/{vo => enums}/MidjourneySubmitCodeEnum.java (93%) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitCodeEnum.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/enums/MidjourneySubmitCodeEnum.java similarity index 93% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitCodeEnum.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/enums/MidjourneySubmitCodeEnum.java index 13bf09814..3f432ce36 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneySubmitCodeEnum.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/enums/MidjourneySubmitCodeEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.client.vo; +package cn.iocoder.yudao.module.ai.client.enums; import com.google.common.collect.Lists; import lombok.AllArgsConstructor; From 127a98a93478abbaa0e54a49052b0793c6334d8e Mon Sep 17 00:00:00 2001 From: puhui999 Date: Fri, 31 May 2024 16:59:06 +0800 Subject: [PATCH 382/684] =?UTF-8?q?MALL-KEFU:=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=AE=A2=E6=9C=8D=E7=9B=B8=E5=85=B3=E6=93=8D=E4=BD=9C=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/mysql/mall-promotion-kefu.sql | 37 +++++ .../promotion/enums/ErrorCodeConstants.java | 6 + .../kefu/KeFuConversationController.java | 54 ++++++++ .../admin/kefu/KeFuMessageController.java | 58 ++++++++ .../conversation/KeFuConversationRespVO.java | 42 ++++++ .../KeFuConversationUpdatePinnedReqVO.java | 19 +++ .../kefu/vo/message/KeFuMessagePageReqVO.java | 16 +++ .../kefu/vo/message/KeFuMessageRespVO.java | 43 ++++++ .../kefu/vo/message/KeFuMessageSendReqVO.java | 43 ++++++ .../kefu/AppKeFuConversationController.java | 35 +++++ .../app/kefu/AppKeFuMessageController.java | 58 ++++++++ .../AppKeFuConversationRespVO.java | 42 ++++++ .../vo/message/AppKeFuMessagePageReqVO.java | 18 +++ .../kefu/vo/message/AppKeFuMessageRespVO.java | 42 ++++++ .../vo/message/AppKeFuMessageSendReqVO.java | 43 ++++++ .../dataobject/kefu/KeFuConversationDO.java | 8 +- .../mysql/kefu/KeFuConversationMapper.java | 38 ++++++ .../dal/mysql/kefu/KeFuMessageMapper.java | 42 ++++++ .../service/kefu/KeFuConversationService.java | 78 +++++++++++ .../kefu/KeFuConversationServiceImpl.java | 88 ++++++++++++ .../service/kefu/KeFuMessageService.java | 40 ++++++ .../service/kefu/KeFuMessageServiceImpl.java | 128 ++++++++++++++++++ .../module/member/api/user/MemberUserApi.java | 8 ++ .../member/api/user/MemberUserApiImpl.java | 11 ++ 24 files changed, 993 insertions(+), 4 deletions(-) create mode 100644 sql/mysql/mall-promotion-kefu.sql create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/KeFuConversationController.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/KeFuMessageController.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/conversation/KeFuConversationRespVO.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/conversation/KeFuConversationUpdatePinnedReqVO.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessagePageReqVO.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessageRespVO.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessageSendReqVO.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/AppKeFuConversationController.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/AppKeFuMessageController.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/conversation/AppKeFuConversationRespVO.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/message/AppKeFuMessagePageReqVO.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/message/AppKeFuMessageRespVO.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/message/AppKeFuMessageSendReqVO.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/kefu/KeFuConversationMapper.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/kefu/KeFuMessageMapper.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuConversationService.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuConversationServiceImpl.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuMessageService.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuMessageServiceImpl.java diff --git a/sql/mysql/mall-promotion-kefu.sql b/sql/mysql/mall-promotion-kefu.sql new file mode 100644 index 000000000..e0b478f57 --- /dev/null +++ b/sql/mysql/mall-promotion-kefu.sql @@ -0,0 +1,37 @@ +DROP TABLE IF EXISTS `promotion_kefu_conversation`; +CREATE TABLE `promotion_kefu_conversation` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '编号', + `user_id` BIGINT NOT NULL COMMENT '会话所属用户', + `last_message_time` DATETIME NOT NULL COMMENT '最后聊天时间', + `last_message_content` VARCHAR(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '最后聊天内容', + `last_message_content_type` INT NOT NULL COMMENT '最后发送的消息类型', + `admin_pinned` BIT(1) NOT NULL DEFAULT b'0' COMMENT '管理端置顶', + `user_deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '用户是否可见', + `admin_deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '管理员是否可见', + `admin_unread_message_count` INT NOT NULL COMMENT '管理员未读消息数', + `creator` VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '客服会话' ROW_FORMAT = Dynamic; + +DROP TABLE IF EXISTS `promotion_kefu_message`; +CREATE TABLE `promotion_kefu_message` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '编号', + `conversation_id` BIGINT NOT NULL COMMENT '会话编号', + `sender_id` BIGINT NOT NULL COMMENT '发送人编号', + `sender_type` INT NOT NULL COMMENT '发送人类型', + `receiver_id` BIGINT NOT NULL COMMENT '接收人编号', + `receiver_type` INT NOT NULL COMMENT '接收人类型', + `content_type` INT NOT NULL COMMENT '消息类型', + `content` VARCHAR(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '消息', + `read_status` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否已读', + `creator` VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '客服消息' ROW_FORMAT = Dynamic; diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java index 3b19d616a..8cebd6e13 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java @@ -125,4 +125,10 @@ public interface ErrorCodeConstants { ErrorCode DIY_PAGE_NOT_EXISTS = new ErrorCode(1_013_018_000, "装修页面不存在"); ErrorCode DIY_PAGE_NAME_USED = new ErrorCode(1_013_018_001, "装修页面名称({})已经被使用"); + // ========== 客服会话 1-013-019-000 ========== + ErrorCode KEFU_CONVERSATION_NOT_EXISTS = new ErrorCode(1_013_019_000, "客服会话不存在"); + + // ========== 客服消息 1-013-020-000 ========== + ErrorCode KEFU_MESSAGE_NOT_EXISTS = new ErrorCode(1_013_020_000, "客服消息不存在"); + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/KeFuConversationController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/KeFuConversationController.java new file mode 100644 index 000000000..099cc264c --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/KeFuConversationController.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.kefu; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.conversation.KeFuConversationRespVO; +import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.conversation.KeFuConversationUpdatePinnedReqVO; +import cn.iocoder.yudao.module.promotion.service.kefu.KeFuConversationService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 客服会话") +@RestController +@RequestMapping("/promotion/kefu-conversation") +@Validated +public class KeFuConversationController { + + @Resource + private KeFuConversationService conversationService; + + @PostMapping("/update-pinned") + @Operation(summary = "置顶客服会话") + @PreAuthorize("@ss.hasPermission('promotion:kefu-conversation:update')") + public CommonResult updatePinned(@Valid @RequestBody KeFuConversationUpdatePinnedReqVO updateReqVO) { + conversationService.updatePinned(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除客服会话") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('promotion:kefu-conversation:delete')") + public CommonResult deleteKefuConversation(@RequestParam("id") Long id) { + conversationService.deleteKefuConversation(id); + return success(true); + } + + @GetMapping("/list") + @Operation(summary = "获得客服会话列表") + @PreAuthorize("@ss.hasPermission('promotion:kefu-conversation:query')") + public CommonResult> getKefuConversationPage() { + return success(BeanUtils.toBean(conversationService.getKefuConversationList(), KeFuConversationRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/KeFuMessageController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/KeFuMessageController.java new file mode 100644 index 000000000..b8adada3a --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/KeFuMessageController.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.kefu; + +import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessagePageReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageRespVO; +import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageSendReqVO; +import org.springframework.web.bind.annotation.*; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import jakarta.validation.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO; +import cn.iocoder.yudao.module.promotion.service.kefu.KeFuMessageService; + +@Tag(name = "管理后台 - 客服消息") +@RestController +@RequestMapping("/promotion/kefu-message") +@Validated +public class KeFuMessageController { + + @Resource + private KeFuMessageService messageService; + + @PostMapping("/send") + @Operation(summary = "发送客服消息") + @PreAuthorize("@ss.hasPermission('promotion:kefu-message:send')") + public CommonResult createKefuMessage(@Valid @RequestBody KeFuMessageSendReqVO sendReqVO) { + return success(messageService.sendKefuMessage(sendReqVO)); + } + + @PutMapping("/update-read-status") + @Operation(summary = "更新客服消息已读状态") + @Parameter(name = "conversationId", description = "会话编号", required = true) + @PreAuthorize("@ss.hasPermission('promotion:kefu-message:update')") + public CommonResult updateKefuMessageReadStatus(@RequestParam("conversationId") Long conversationId) { + messageService.updateKefuMessageReadStatus(conversationId, getLoginUserId()); + return success(true); + } + + @GetMapping("/page") + @Operation(summary = "获得客服消息分页") + @PreAuthorize("@ss.hasPermission('promotion:kefu-message:query')") + public CommonResult> getKefuMessagePage(@Valid KeFuMessagePageReqVO pageReqVO) { + PageResult pageResult = messageService.getKefuMessagePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, KeFuMessageRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/conversation/KeFuConversationRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/conversation/KeFuConversationRespVO.java new file mode 100644 index 000000000..b3748e147 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/conversation/KeFuConversationRespVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.conversation; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 客服会话 Response VO") +@Data +public class KeFuConversationRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24988") + private Long id; + + @Schema(description = "会话所属用户", requiredMode = Schema.RequiredMode.REQUIRED, example = "8300") + private Long userId; + + @Schema(description = "最后聊天时间", requiredMode = Schema.RequiredMode.REQUIRED,example = "2024-01-01 00:00:00") + private LocalDateTime lastMessageTime; + + @Schema(description = "最后聊天内容", requiredMode = Schema.RequiredMode.REQUIRED,example = "嗨,您好啊") + private String lastMessageContent; + + @Schema(description = "最后发送的消息类型", requiredMode = Schema.RequiredMode.REQUIRED,example = "1") + private Integer lastMessageContentType; + + @Schema(description = "管理端置顶", requiredMode = Schema.RequiredMode.REQUIRED,example = "false") + private Boolean adminPinned; + + @Schema(description = "用户是否可见", requiredMode = Schema.RequiredMode.REQUIRED,example = "true") + private Boolean userDeleted; + + @Schema(description = "管理员是否可见", requiredMode = Schema.RequiredMode.REQUIRED,example = "true") + private Boolean adminDeleted; + + @Schema(description = "管理员未读消息数", requiredMode = Schema.RequiredMode.REQUIRED,example = "6") + private Integer adminUnreadMessageCount; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED,example = "2024-01-01 00:00:00") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/conversation/KeFuConversationUpdatePinnedReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/conversation/KeFuConversationUpdatePinnedReqVO.java new file mode 100644 index 000000000..235f78227 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/conversation/KeFuConversationUpdatePinnedReqVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.conversation; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - 客服会话置顶 Request VO") +@Data +public class KeFuConversationUpdatePinnedReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23202") + @NotNull(message = "会话编号,不能为空") + private Long id; + + @Schema(description = "管理端置顶", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + @NotNull(message = "管理端置顶,不能为空") + private Boolean adminPinned; + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessagePageReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessagePageReqVO.java new file mode 100644 index 000000000..ec5e7261c --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessagePageReqVO.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message; + +import lombok.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +@Schema(description = "管理后台 - 客服消息分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class KeFuMessagePageReqVO extends PageParam { + + @Schema(description = "会话编号", example = "12580") + private Long conversationId; + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessageRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessageRespVO.java new file mode 100644 index 000000000..41f9c52f6 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessageRespVO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; + +@Schema(description = "管理后台 - 客服消息 Response VO") +@Data +public class KeFuMessageRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23202") + private Long id; + + @Schema(description = "会话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "12580") + private Long conversationId; + + @Schema(description = "发送人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24571") + private Long senderId; + + @Schema(description = "发送人类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer senderType; + + @Schema(description = "接收人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29124") + private Long receiverId; + + @Schema(description = "接收人类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Integer receiverType; + + @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer contentType; + + @Schema(description = "消息", requiredMode = Schema.RequiredMode.REQUIRED) + private String content; + + @Schema(description = "是否已读", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Boolean readStatus; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessageSendReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessageSendReqVO.java new file mode 100644 index 000000000..5ac8f04c4 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessageSendReqVO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - 发送客服消息 Request VO") +@Data +public class KeFuMessageSendReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23202") + private Long id; + + @Schema(description = "会话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "12580") + @NotNull(message = "会话编号不能为空") + private Long conversationId; + + @Schema(description = "发送人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24571") + @NotNull(message = "发送人编号不能为空") + private Long senderId; + + @Schema(description = "发送人类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "发送人类型不能为空") + private Integer senderType; + + @Schema(description = "接收人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29124") + @NotNull(message = "接收人编号不能为空") + private Long receiverId; + + @Schema(description = "接收人类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "接收人类型不能为空") + private Integer receiverType; + + @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "消息类型不能为空") + private Integer contentType; + + @Schema(description = "消息", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "消息不能为空") + private String content; + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/AppKeFuConversationController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/AppKeFuConversationController.java new file mode 100644 index 000000000..15c0e2892 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/AppKeFuConversationController.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.promotion.controller.app.kefu; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; +import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.conversation.AppKeFuConversationRespVO; +import cn.iocoder.yudao.module.promotion.service.kefu.KeFuConversationService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "用户 APP - 客户会话") +@RestController +@RequestMapping("/promotion/kefu-conversation") +@Validated +public class AppKeFuConversationController { + + @Resource + private KeFuConversationService conversationService; + + @GetMapping("/get") + @Operation(summary = "获得客服会话") + @PreAuthenticated + public CommonResult getDiyPage() { + return success(BeanUtils.toBean(conversationService.getOrCreateConversation(getLoginUserId()), AppKeFuConversationRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/AppKeFuMessageController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/AppKeFuMessageController.java new file mode 100644 index 000000000..1af72dba7 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/AppKeFuMessageController.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.promotion.controller.app.kefu; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; +import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessagePageReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageRespVO; +import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageSendReqVO; +import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessageSendReqVO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO; +import cn.iocoder.yudao.module.promotion.service.kefu.KeFuMessageService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "管理后台 - 客服消息") +@RestController +@RequestMapping("/promotion/kefu-message") +@Validated +public class AppKeFuMessageController { + + @Resource + private KeFuMessageService kefuMessageService; + + @PostMapping("/send") + @Operation(summary = "发送客服消息") + @PreAuthenticated + public CommonResult createKefuMessage(@Valid @RequestBody AppKeFuMessageSendReqVO sendReqVO) { + return success(kefuMessageService.sendKefuMessage(BeanUtils.toBean(sendReqVO, KeFuMessageSendReqVO.class))); + } + + @PutMapping("/update-read-status") + @Operation(summary = "更新客服消息已读状态") + @Parameter(name = "conversationId", description = "会话编号", required = true) + @PreAuthenticated + public CommonResult updateKefuMessageReadStatus(@RequestParam("conversationId") Long conversationId) { + kefuMessageService.updateKefuMessageReadStatus(conversationId, getLoginUserId()); + return success(true); + } + + @GetMapping("/page") + @Operation(summary = "获得客服消息分页") + @PreAuthenticated + public CommonResult> getKefuMessagePage(@Valid KeFuMessagePageReqVO pageReqVO) { + PageResult pageResult = kefuMessageService.getKefuMessagePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, KeFuMessageRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/conversation/AppKeFuConversationRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/conversation/AppKeFuConversationRespVO.java new file mode 100644 index 000000000..39a295dc1 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/conversation/AppKeFuConversationRespVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.conversation; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +import java.time.LocalDateTime; + +@Schema(description = "用户 App - 客服会话 Response VO") +@Data +public class AppKeFuConversationRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24988") + private Long id; + + @Schema(description = "会话所属用户", requiredMode = Schema.RequiredMode.REQUIRED, example = "8300") + private Long userId; + + @Schema(description = "最后聊天时间", requiredMode = Schema.RequiredMode.REQUIRED,example = "2024-01-01 00:00:00") + private LocalDateTime lastMessageTime; + + @Schema(description = "最后聊天内容", requiredMode = Schema.RequiredMode.REQUIRED,example = "嗨,您好啊") + private String lastMessageContent; + + @Schema(description = "最后发送的消息类型", requiredMode = Schema.RequiredMode.REQUIRED,example = "1") + private Integer lastMessageContentType; + + @Schema(description = "管理端置顶", requiredMode = Schema.RequiredMode.REQUIRED,example = "false") + private Boolean adminPinned; + + @Schema(description = "用户是否可见", requiredMode = Schema.RequiredMode.REQUIRED,example = "true") + private Boolean userDeleted; + + @Schema(description = "管理员是否可见", requiredMode = Schema.RequiredMode.REQUIRED,example = "true") + private Boolean adminDeleted; + + @Schema(description = "管理员未读消息数", requiredMode = Schema.RequiredMode.REQUIRED,example = "6") + private Integer adminUnreadMessageCount; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED,example = "2024-01-01 00:00:00") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/message/AppKeFuMessagePageReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/message/AppKeFuMessagePageReqVO.java new file mode 100644 index 000000000..a332d34ad --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/message/AppKeFuMessagePageReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "用户 App - 客服消息分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class AppKeFuMessagePageReqVO extends PageParam { + + @Schema(description = "会话编号", example = "12580") + private Long conversationId; + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/message/AppKeFuMessageRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/message/AppKeFuMessageRespVO.java new file mode 100644 index 000000000..fb7331afc --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/message/AppKeFuMessageRespVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "用户 App - 客服消息 Response VO") +@Data +public class AppKeFuMessageRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23202") + private Long id; + + @Schema(description = "会话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "12580") + private Long conversationId; + + @Schema(description = "发送人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24571") + private Long senderId; + + @Schema(description = "发送人类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer senderType; + + @Schema(description = "接收人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29124") + private Long receiverId; + + @Schema(description = "接收人类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Integer receiverType; + + @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer contentType; + + @Schema(description = "消息", requiredMode = Schema.RequiredMode.REQUIRED) + private String content; + + @Schema(description = "是否已读", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Boolean readStatus; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/message/AppKeFuMessageSendReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/message/AppKeFuMessageSendReqVO.java new file mode 100644 index 000000000..f2de632da --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/message/AppKeFuMessageSendReqVO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "用户 App - 发送客服消息 Request VO") +@Data +public class AppKeFuMessageSendReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23202") + private Long id; + + @Schema(description = "会话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "12580") + @NotNull(message = "会话编号不能为空") + private Long conversationId; + + @Schema(description = "发送人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24571") + @NotNull(message = "发送人编号不能为空") + private Long senderId; + + @Schema(description = "发送人类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "发送人类型不能为空") + private Integer senderType; + + @Schema(description = "接收人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29124") + @NotNull(message = "接收人编号不能为空") + private Long receiverId; + + @Schema(description = "接收人类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "接收人类型不能为空") + private Integer receiverType; + + @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "消息类型不能为空") + private Integer contentType; + + @Schema(description = "消息", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "消息不能为空") + private String content; + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KeFuConversationDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KeFuConversationDO.java index 04432eebe..e9a73284f 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KeFuConversationDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/kefu/KeFuConversationDO.java @@ -61,15 +61,15 @@ public class KeFuConversationDO extends BaseDO { /** * 用户是否可见 * - * true - 可见,默认值 - * false - 不可见,用户删除时设置为 false + * false - 可见,默认值 + * true - 不可见,用户删除时设置为 true */ private Boolean userDeleted; /** * 管理员是否可见 * - * true - 可见,默认值 - * false - 不可见,管理员删除时设置为 false + * false - 可见,默认值 + * true - 不可见,管理员删除时设置为 true */ private Boolean adminDeleted; diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/kefu/KeFuConversationMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/kefu/KeFuConversationMapper.java new file mode 100644 index 000000000..eae9b7401 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/kefu/KeFuConversationMapper.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.promotion.dal.mysql.kefu; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuConversationDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 客服会话 Mapper + * + * @author HUIHUI + */ +@Mapper +public interface KeFuConversationMapper extends BaseMapperX { + + default List selectListWithSort() { + return selectList(new LambdaQueryWrapperX() + .eq(KeFuConversationDO::getAdminDeleted, Boolean.FALSE) + .orderByDesc(KeFuConversationDO::getAdminPinned) // 置顶优先 + .orderByDesc(KeFuConversationDO::getCreateTime)); + } + + default void updateAdminUnreadMessageCountByConversationId(Long id, Integer count) { + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(KeFuConversationDO::getId, id); + if (count != null && count > 0) { // 情况一:会员发送消息时增加管理员的未读消息数 + updateWrapper.setSql("admin_unread_message_count = admin_unread_message_count + 1"); + } else { // 情况二:管理员已读后重置 + updateWrapper.set(KeFuConversationDO::getAdminUnreadMessageCount, 0); + } + + update(updateWrapper); + } + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/kefu/KeFuMessageMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/kefu/KeFuMessageMapper.java new file mode 100644 index 000000000..5ec0a6cd9 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/kefu/KeFuMessageMapper.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.promotion.dal.mysql.kefu; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessagePageReqVO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * 客服消息 Mapper + * + * @author HUIHUI + */ +@Mapper +public interface KeFuMessageMapper extends BaseMapperX { + + default PageResult selectPage(KeFuMessagePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(KeFuMessageDO::getConversationId, reqVO.getConversationId()) + .orderByDesc(KeFuMessageDO::getId)); + } + + default List selectListByConversationIdAndReceiverIdAndReadStatus(Long conversationId, Long receiverId, Boolean readStatus) { + return selectList(new LambdaQueryWrapper() + .eq(KeFuMessageDO::getConversationId, conversationId) + .eq(KeFuMessageDO::getReceiverId, receiverId) + .eq(KeFuMessageDO::getReadStatus, readStatus)); + } + + default void updateReadStstusBatchByIds(Collection ids, Boolean readStatus) { + update(new LambdaUpdateWrapper() + .in(KeFuMessageDO::getId, ids) + .set(KeFuMessageDO::getReadStatus, readStatus)); + } + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuConversationService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuConversationService.java new file mode 100644 index 000000000..828626310 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuConversationService.java @@ -0,0 +1,78 @@ +package cn.iocoder.yudao.module.promotion.service.kefu; + +import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.conversation.KeFuConversationUpdatePinnedReqVO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuConversationDO; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 客服会话 Service 接口 + * + * @author HUIHUI + */ +public interface KeFuConversationService { + + /** + * 删除客服会话 + * + * @param id 编号 + */ + void deleteKefuConversation(Long id); + + /** + * 客服会话置顶 + * + * @param updateReqVO 请求 + */ + void updatePinned(KeFuConversationUpdatePinnedReqVO updateReqVO); + + /** + * 更新会话客服消息冗余信息 + * + * @param id 编号 + * @param lastMessageTime 最后聊天时间 + * @param lastMessageContent 最后聊天内容 + * @param lastMessageContentType 最后聊天内容类型 + */ + void updateConversationMessage(Long id, LocalDateTime lastMessageTime, String lastMessageContent, Integer lastMessageContentType); + + /** + * 更新管理员未读消息数 + * + * @param id 编号 + * @param count 数量:0 则重置 1 则消息数加一 + */ + void updateAdminUnreadMessageCountByConversationId(Long id, Integer count); + + /** + * 更新会话对于管理员是否可见 + * + * @param adminDeleted 管理员是否可见 + */ + void updateConversationAdminDeleted(Long id, Boolean adminDeleted); + + /** + * 获得客服会话列表 + * + * @return 会话列表 + */ + List getKefuConversationList(); + + /** + * 获得或创建会话 + * + * @param userId 用户编号 + * @return 客服会话 + */ + KeFuConversationDO getOrCreateConversation(Long userId); + + /** + * 校验客服会话是否存在 + * + * @param id 编号 + * @return 客服会话 + */ + KeFuConversationDO validateKefuConversationExists(Long id); + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuConversationServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuConversationServiceImpl.java new file mode 100644 index 000000000..416e613ff --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuConversationServiceImpl.java @@ -0,0 +1,88 @@ +package cn.iocoder.yudao.module.promotion.service.kefu; + +import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.conversation.KeFuConversationUpdatePinnedReqVO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuConversationDO; +import cn.iocoder.yudao.module.promotion.dal.mysql.kefu.KeFuConversationMapper; +import cn.iocoder.yudao.module.promotion.enums.kehu.KeFuMessageContentTypeEnum; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.KEFU_CONVERSATION_NOT_EXISTS; + +/** + * 客服会话 Service 实现类 + * + * @author HUIHUI + */ +@Service +@Validated +public class KeFuConversationServiceImpl implements KeFuConversationService { + + @Resource + private KeFuConversationMapper conversationMapper; + + @Override + public void deleteKefuConversation(Long id) { + // 校验存在 + validateKefuConversationExists(id); + + // 只有管理员端可以删除会话,也不真的删,只是管理员端看不到啦 + conversationMapper.updateById(new KeFuConversationDO().setId(id).setAdminDeleted(Boolean.TRUE)); + } + + @Override + public void updatePinned(KeFuConversationUpdatePinnedReqVO updateReqVO) { + // 只有管理员端可以置顶会话 + conversationMapper.updateById(new KeFuConversationDO().setId(updateReqVO.getId()).setAdminPinned(updateReqVO.getAdminPinned())); + } + + @Override + public void updateConversationMessage(Long id, LocalDateTime lastMessageTime, String lastMessageContent, Integer lastMessageContentType) { + conversationMapper.updateById(new KeFuConversationDO().setId(id).setLastMessageTime(lastMessageTime) + .setLastMessageContent(lastMessageContent).setLastMessageContentType(lastMessageContentType)); + } + + @Override + public void updateAdminUnreadMessageCountByConversationId(Long id, Integer count) { + conversationMapper.updateAdminUnreadMessageCountByConversationId(id, count); + } + + @Override + public void updateConversationAdminDeleted(Long id, Boolean adminDeleted) { + conversationMapper.updateById(new KeFuConversationDO().setId(id).setAdminDeleted(adminDeleted)); + } + + @Override + public List getKefuConversationList() { + return conversationMapper.selectListWithSort(); + } + + @Override + public KeFuConversationDO getOrCreateConversation(Long userId) { + KeFuConversationDO conversation = conversationMapper.selectOne(KeFuConversationDO::getUserId, userId); + if (conversation == null) { // 没有历史会话则初始化一个新会话 + conversation = new KeFuConversationDO().setUserId(userId).setLastMessageTime(LocalDateTime.now()) + .setLastMessageContent("").setLastMessageContentType(KeFuMessageContentTypeEnum.TEXT.getType()) + .setAdminPinned(Boolean.FALSE).setUserDeleted(Boolean.FALSE).setAdminDeleted(Boolean.FALSE) + .setAdminUnreadMessageCount(0); + conversationMapper.insert(conversation); + } + return conversation; + } + + @Override + public KeFuConversationDO validateKefuConversationExists(Long id) { + KeFuConversationDO conversationDO = conversationMapper.selectById(id); + if (conversationDO == null) { + throw exception(KEFU_CONVERSATION_NOT_EXISTS); + } + + return conversationDO; + } + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuMessageService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuMessageService.java new file mode 100644 index 000000000..10d5aca32 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuMessageService.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.promotion.service.kefu; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessagePageReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageSendReqVO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO; +import jakarta.validation.Valid; + +/** + * 客服消息 Service 接口 + * + * @author HUIHUI + */ +public interface KeFuMessageService { + + /** + * 发送客服消息 + * + * @param sendReqVO 信息 + * @return 编号 + */ + Long sendKefuMessage(@Valid KeFuMessageSendReqVO sendReqVO); + + /** + * 更新消息已读状态 + * + * @param conversationId 会话编号 + * @param receiverId 用户编号 + */ + void updateKefuMessageReadStatus(Long conversationId, Long receiverId); + + /** + * 获得客服消息分页 + * + * @param pageReqVO 分页查询 + * @return 客服消息分页 + */ + PageResult getKefuMessagePage(KeFuMessagePageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuMessageServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuMessageServiceImpl.java new file mode 100644 index 000000000..ff6224407 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuMessageServiceImpl.java @@ -0,0 +1,128 @@ +package cn.iocoder.yudao.module.promotion.service.kefu; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.extra.spring.SpringUtil; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi; +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; +import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessagePageReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageSendReqVO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuConversationDO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO; +import cn.iocoder.yudao.module.promotion.dal.mysql.kefu.KeFuMessageMapper; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import jakarta.annotation.Resource; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getFirst; + +/** + * 客服消息 Service 实现类 + * + * @author HUIHUI + */ +@Service +@Validated +public class KeFuMessageServiceImpl implements KeFuMessageService { + + private static final String KEFU_MESSAGE_TYPE = "kefu_message_type"; // 客服消息类型 + + @Resource + private KeFuMessageMapper messageMapper; + @Resource + private KeFuConversationService conversationService; + @Resource + private AdminUserApi adminUserApi; + @Resource + private MemberUserApi memberUserApi; + @Resource + private WebSocketSenderApi webSocketSenderApi; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long sendKefuMessage(KeFuMessageSendReqVO sendReqVO) { + // 1.1 校验会话是否存在 + KeFuConversationDO conversation = conversationService.validateKefuConversationExists(sendReqVO.getConversationId()); + // 1.2 校验接收人是否存在 + validateReceiverExist(sendReqVO.getReceiverId(), sendReqVO.getReceiverType()); + + // 2.1 保存消息 + KeFuMessageDO kefuMessage = BeanUtils.toBean(sendReqVO, KeFuMessageDO.class); + messageMapper.insert(kefuMessage); + // 2.2 更新会话消息冗余 + conversationService.updateConversationMessage(kefuMessage.getConversationId(), LocalDateTime.now(), + kefuMessage.getContent(), kefuMessage.getContentType()); + // 2.3 更新管理员未读消息数 + if (UserTypeEnum.ADMIN.getValue().equals(kefuMessage.getReceiverType())) { + conversationService.updateAdminUnreadMessageCountByConversationId(kefuMessage.getConversationId(), 1); + } + // 2.4 会员用户发送消息时,如果管理员删除过会话则进行恢复 + if (UserTypeEnum.MEMBER.getValue().equals(kefuMessage.getSenderType()) && Boolean.TRUE.equals(conversation.getAdminDeleted())) { + conversationService.updateConversationAdminDeleted(kefuMessage.getConversationId(), Boolean.FALSE); + } + + // 3. 发送消息 + getSelf().sendAsyncMessage(sendReqVO.getReceiverType(), sendReqVO.getReceiverId(), kefuMessage); + + // 返回 + return kefuMessage.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateKefuMessageReadStatus(Long conversationId, Long receiverId) { + // 1.1 校验会话是否存在 + conversationService.validateKefuConversationExists(conversationId); + // 1.2 查询接收人所有的未读消息 + List messageList = messageMapper.selectListByConversationIdAndReceiverIdAndReadStatus( + conversationId, receiverId, Boolean.FALSE); + // 1.3 情况一:没有未读消息 + if (CollUtil.isEmpty(messageList)) { + return; + } + + // 2.1 情况二:更新未读消息状态为已读 + messageMapper.updateReadStstusBatchByIds(convertSet(messageList, KeFuMessageDO::getId), Boolean.TRUE); + // 2.2 更新管理员未读消息数 + KeFuMessageDO message = getFirst(messageList); + assert message != null; + if (UserTypeEnum.ADMIN.getValue().equals(message.getReceiverType())) { + conversationService.updateAdminUnreadMessageCountByConversationId(conversationId, 0); + } + // 2.3 发送消息通知发送者,接收者已读 -> 发送者更新发送的消息状态 + getSelf().sendAsyncMessage(message.getSenderType(), message.getSenderId(), "keFuMessageReadStatusChange"); + } + + private void validateReceiverExist(Long receiverId, Integer receiverType) { + if (UserTypeEnum.ADMIN.getValue().equals(receiverType)) { + adminUserApi.validateUser(receiverId); + } + if (UserTypeEnum.MEMBER.getValue().equals(receiverType)) { + memberUserApi.validateUser(receiverId); + } + } + + @Async + public void sendAsyncMessage(Integer userType, Long userId, Object content) { + webSocketSenderApi.sendObject(userType, userId, KEFU_MESSAGE_TYPE, content); + } + + @Override + public PageResult getKefuMessagePage(KeFuMessagePageReqVO pageReqVO) { + return messageMapper.selectPage(pageReqVO); + } + + private KeFuMessageServiceImpl getSelf() { + return SpringUtil.getBean(getClass()); + } + +} \ No newline at end of file diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApi.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApi.java index c9fb80100..da74aaa92 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApi.java +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApi.java @@ -57,4 +57,12 @@ public interface MemberUserApi { * @return 用户信息 */ MemberUserRespDTO getUserByMobile(String mobile); + + /** + * 校验用户是否存在 + * + * @param id 用户编号 + */ + void validateUser(Long id); + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApiImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApiImpl.java index 659c39b57..960930ddc 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApiImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApiImpl.java @@ -11,6 +11,9 @@ import jakarta.annotation.Resource; import java.util.Collection; import java.util.List; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.USER_MOBILE_NOT_EXISTS; + /** * 会员用户的 API 实现类 * @@ -44,4 +47,12 @@ public class MemberUserApiImpl implements MemberUserApi { return MemberUserConvert.INSTANCE.convert2(userService.getUserByMobile(mobile)); } + @Override + public void validateUser(Long id) { + MemberUserDO user = userService.getUser(id); + if (user == null) { + throw exception(USER_MOBILE_NOT_EXISTS); + } + } + } From 56e8707e387736294cf431425e978fdc2575bd3a Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 31 May 2024 17:05:28 +0800 Subject: [PATCH 383/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91Mid?= =?UTF-8?q?journey=20Proxy=20=E5=9B=9E=E8=B0=83=E9=80=9A=E7=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...tifyVO.java => MidjourneyNotifyReqVO.java} | 5 +- .../admin/image/AiImageController.java | 8 +-- .../ai/dal/dataobject/image/AiImageDO.java | 3 + .../ai/dal/mysql/image/AiImageMapper.java | 11 ++- .../ai/service/image/AiImageService.java | 9 +++ .../ai/service/image/AiImageServiceImpl.java | 71 ++++++++++--------- 6 files changed, 67 insertions(+), 40 deletions(-) rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/{MidjourneyNotifyVO.java => MidjourneyNotifyReqVO.java} (92%) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyReqVO.java similarity index 92% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyVO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyReqVO.java index c2a934331..3cc92c719 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyReqVO.java @@ -11,7 +11,10 @@ import lombok.Data; * @since 1.0 */ @Data -public class MidjourneyNotifyVO { +public class MidjourneyNotifyReqVO { + + @Schema(description = "job id") + private String id; @Schema(description = "任务类型") private MidjourneyTaskActionEnum action; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index bef20fe14..1ffe4f1c8 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.ai.controller.admin.image; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.ai.client.vo.MidjourneyNotifyReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageListReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyImagineReqVO; @@ -13,7 +14,6 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -74,9 +74,9 @@ public class AiImageController { return success(aiImageService.deleteIdMy(id, getLoginUserId())); } - @Operation(summary = "删除【我的】绘画记录") + @Operation(summary = "midjourney proxy - 回调通知") @RequestMapping("/midjourney-notify") - public CommonResult midjourneyNotify(HttpServletRequest request) { - return success(true); + public CommonResult midjourneyNotify(MidjourneyNotifyReqVO notifyReqVO) { + return success(aiImageService.midjourneyNotify(getLoginUserId(), notifyReqVO)); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java index 259215cdc..0f6282a27 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java @@ -28,6 +28,9 @@ public class AiImageDO extends BaseDO { @Schema(description = "用户编号") private Long userId; + @Schema(description = "midjourney proxy 关联的 job id") + private String jobId; + @Schema(description = "提示词") private String prompt; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java index f60668d21..af37a2937 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java @@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import org.apache.ibatis.annotations.Mapper; -import org.springframework.stereotype.Repository; /** * AI 绘图 Mapper @@ -26,4 +25,14 @@ public interface AiImageMapper extends BaseMapperX { return; } + /** + * 查询 - 根据 job id + * + * @param id + * @return + */ + default AiImageDO selectByJobId(String id) { + return this.selectOne(new LambdaQueryWrapperX().eq(AiImageDO::getJobId, id)); + } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java index b07ba7dd8..05ad0ed28 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.ai.service.image; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.ai.client.vo.MidjourneyNotifyReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageListReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyImagineReqVO; @@ -65,4 +66,12 @@ public interface AiImageService { */ Boolean deleteIdMy(Long id, Long loginUserId); + /** + * midjourney proxy - 回调通知 + * + * @param loginUserId + * @param notifyReqVO + * @return + */ + Boolean midjourneyNotify(Long loginUserId, MidjourneyNotifyReqVO notifyReqVO); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index bef3b600b..16887045f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.ai.service.image; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageModelEnum; @@ -14,9 +16,14 @@ import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.client.MidjourneyProxyClient; import cn.iocoder.yudao.module.ai.client.enums.MidjourneyModelEnum; import cn.iocoder.yudao.module.ai.client.enums.MidjourneySubmitCodeEnum; +import cn.iocoder.yudao.module.ai.client.enums.MidjourneyTaskStatusEnum; import cn.iocoder.yudao.module.ai.client.vo.MidjourneyImagineReqVO; +import cn.iocoder.yudao.module.ai.client.vo.MidjourneyNotifyReqVO; import cn.iocoder.yudao.module.ai.client.vo.MidjourneySubmitRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageListReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyImagineReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyOperateReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper; import cn.iocoder.yudao.module.ai.enums.AiImagePublicStatusEnum; @@ -36,15 +43,9 @@ import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -// TODO @fan:注释优化下哈 - /** * AI 绘画(接入 dall2/dall3、midjourney) * @@ -56,9 +57,6 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU @Slf4j public class AiImageServiceImpl implements AiImageService { - // TODO @fan:使用 @Resource 注入 - - // TODO @fan:imageMapper @Resource private AiImageMapper imageMapper; @Resource @@ -173,19 +171,16 @@ public class AiImageServiceImpl implements AiImageService { // 4、保存任务 id (状态码: 1(提交成功), 21(已存在), 22(排队中), other(错误)) String updateStatus = null; String errorMessage = null; - Map drawResponse = new HashMap<>(); if (!MidjourneySubmitCodeEnum.SUCCESS_CODES.contains(submitRespVO.getCode())) { updateStatus = AiImageStatusEnum.FAIL.getStatus(); errorMessage = submitRespVO.getDescription(); - } else { - drawResponse.put("jobId", submitRespVO.getResult()); } imageMapper.updateById(new AiImageDO() .setId(aiImageDO.getId()) .setStatus(updateStatus) .setErrorMessage(errorMessage) - .setDrawResponse(drawResponse) + .setJobId(submitRespVO.getResult()) ); return aiImageDO.getId(); } @@ -228,28 +223,36 @@ public class AiImageServiceImpl implements AiImageService { return imageMapper.deleteById(id) > 0; } - private void validateMessageId(String mjMessageId, String messageId) { - if (!mjMessageId.equals(messageId)) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MIDJOURNEY_MESSAGE_ID_INCORRECT); + @Override + public Boolean midjourneyNotify(Long loginUserId, MidjourneyNotifyReqVO notifyReqVO) { + // 1、根据 job id 查询关联的 image + AiImageDO image = imageMapper.selectByJobId(notifyReqVO.getId()); + if (image == null) { + log.warn("midjourneyNotify 回调的 jobId 不存在! jobId: {}", notifyReqVO.getId()); + return false; } - } - - private AiImageMidjourneyOperationsVO validateMidjourneyOperationsExists(List midjourneyOperations, String operateId) { - for (AiImageMidjourneyOperationsVO midjourneyOperation : midjourneyOperations) { - if (midjourneyOperation.getCustom_id().equals(operateId)) { - return midjourneyOperation; - } + // + String imageStatus = null; + if (MidjourneyTaskStatusEnum.SUCCESS == notifyReqVO.getStatus()) { + imageStatus = AiImageStatusEnum.COMPLETE.getStatus(); + } else if (MidjourneyTaskStatusEnum.FAILURE == notifyReqVO.getStatus()) { + imageStatus = AiImageStatusEnum.FAIL.getStatus(); } - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MIDJOURNEY_OPERATION_NOT_EXISTS); - } - - - private List getMidjourneyOperations(AiImageDO aiImageDO) { -// if (StrUtil.isBlank(aiImageDO.getMjOperations())) { -// return Collections.emptyList(); -// } -// return JsonUtils.parseArray(aiImageDO.getMjOperations(), AiImageMidjourneyOperationsVO.class); - return null; + // 2、上传图片 + String filePath = null; + if (!StrUtil.isBlank(notifyReqVO.getImageUrl())) { + filePath = fileApi.createFile(HttpUtil.downloadBytes(notifyReqVO.getImageUrl())); + } + // 2、更新 image 状态 + imageMapper.updateById( + new AiImageDO() + .setId(image.getId()) + .setStatus(imageStatus) + .setPicUrl(filePath) + .setOriginalPicUrl(notifyReqVO.getImageUrl()) + .setDrawResponse(BeanUtil.beanToMap(notifyReqVO)) + ); + return true; } private AiImageDO validateExists(Long id) { From c1f2e490663a337fe87eeaa6d3fc870003acb21d Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 31 May 2024 17:06:41 +0800 Subject: [PATCH 384/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E4=BC=98=E5=8C=96=20=20midjourney=20=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/admin/image/AiImageController.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index 1ffe4f1c8..1c5b40fc5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -61,12 +61,6 @@ public class AiImageController { return success(aiImageService.dall(getLoginUserId(), req)); } - @Operation(summary = "midjourney-imagine 绘画", description = "...") - @PostMapping("/midjourney/imagine") - public CommonResult midjourneyImagine(@Validated @RequestBody AiImageMidjourneyImagineReqVO req) { - return success(aiImageService.midjourneyImagine(getLoginUserId(), req)); - } - @Operation(summary = "删除【我的】绘画记录") @DeleteMapping("/delete-id-my") @Parameter(name = "id", required = true, description = "绘画编号", example = "1024") @@ -74,6 +68,14 @@ public class AiImageController { return success(aiImageService.deleteIdMy(id, getLoginUserId())); } + // ================ midjourney 接口 + + @Operation(summary = "midjourney-imagine 绘画", description = "...") + @PostMapping("/midjourney/imagine") + public CommonResult midjourneyImagine(@Validated @RequestBody AiImageMidjourneyImagineReqVO req) { + return success(aiImageService.midjourneyImagine(getLoginUserId(), req)); + } + @Operation(summary = "midjourney proxy - 回调通知") @RequestMapping("/midjourney-notify") public CommonResult midjourneyNotify(MidjourneyNotifyReqVO notifyReqVO) { From 458f5acdf0c0929fc942bda031338237913ecad1 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 31 May 2024 21:47:48 +0800 Subject: [PATCH 385/684] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91AI=EF=BC=9AImage=20=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E7=9A=84=E5=88=97=E8=A1=A8=E3=80=81=E8=AF=A6=E6=83=85=E7=AD=89?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/image/AiImageController.java | 49 +++++------ .../admin/image/vo/AiImageListReqVO.java | 18 ---- .../admin/image/vo/AiImageMidjourneyRes.java | 16 ---- ...gePageMyRespVO.java => AiImageRespVO.java} | 14 +-- .../ai/dal/mysql/image/AiImageMapper.java | 8 ++ .../ai/service/image/AiImageService.java | 40 ++++----- .../ai/service/image/AiImageServiceImpl.java | 88 +++++++------------ 7 files changed, 83 insertions(+), 150 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListReqVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyRes.java rename yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/{AiImagePageMyRespVO.java => AiImageRespVO.java} (84%) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index 1c5b40fc5..15e4304e6 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -1,13 +1,14 @@ package cn.iocoder.yudao.module.ai.controller.admin.image; +import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.ai.client.vo.MidjourneyNotifyReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageListReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyImagineReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImagePageMyRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageRespVO; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.service.image.AiImageService; import io.swagger.v3.oas.annotations.Operation; @@ -21,35 +22,30 @@ import org.springframework.web.bind.annotation.*; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -@Tag(name = "管理后台 - Ai 绘画") +@Tag(name = "管理后台 - AI 绘画") @RestController @RequestMapping("/ai/image") @Slf4j public class AiImageController { @Resource - private AiImageService aiImageService; + private AiImageService imageService; @Operation(summary = "获取【我的】绘图分页") @GetMapping("/my-page") - public CommonResult> getImagePageMy(@Validated AiImageListReqVO req) { - // 转换 resp - PageResult pageResult = aiImageService.getImagePageMy(getLoginUserId(), req); - // 转换 PageResult 返回 - PageResult result = new PageResult<>(); - result.setTotal(pageResult.getTotal()); - result.setList(BeanUtils.toBean(pageResult.getList(), AiImagePageMyRespVO.class)); - return success(result); + public CommonResult> getImagePageMy(@Validated PageParam pageReqVO) { + PageResult pageResult = imageService.getImagePageMy(getLoginUserId(), pageReqVO); + return success(BeanUtils.toBean(pageResult, AiImageRespVO.class)); } - // TODO @fan:类似 /my-page 的建议 - @Operation(summary = "获取【我的】绘图记录", description = "...") + @Operation(summary = "获取【我的】绘图记录") @GetMapping("/get-my") - public CommonResult getMy(@RequestParam("id") Long id) { - // 获取 image 信息 - AiImageDO imageDO = aiImageService.getMy(id); - // 转 resp 并返回 - return CommonResult.success(BeanUtils.toBean(imageDO, AiImagePageMyRespVO.class)); + public CommonResult getImageMy(@RequestParam("id") Long id) { + AiImageDO image = imageService.getImage(id); + if (image == null || ObjUtil.notEqual(getLoginUserId(), image.getUserId())) { + return success(null); + } + return success(BeanUtils.toBean(image, AiImageRespVO.class)); } // TODO @fan:建议把 dallDrawing、midjourney 融合成一个 draw 接口,异步绘制;然后返回一个 id 给前端;前端通过 get 接口轮询,直到获取到生成成功 @@ -58,14 +54,15 @@ public class AiImageController { @Operation(summary = "dall2/dall3绘画", description = "openAi dall3是付费的!") @PostMapping("/dall") public CommonResult dall(@Validated @RequestBody AiImageDallReqVO req) { - return success(aiImageService.dall(getLoginUserId(), req)); + return success(imageService.dall(getLoginUserId(), req)); } @Operation(summary = "删除【我的】绘画记录") - @DeleteMapping("/delete-id-my") + @DeleteMapping("/delete-my") @Parameter(name = "id", required = true, description = "绘画编号", example = "1024") - public CommonResult deleteIdMy(@RequestParam("id") Long id) { - return success(aiImageService.deleteIdMy(id, getLoginUserId())); + public CommonResult deleteImageMy(@RequestParam("id") Long id) { + imageService.deleteImageMy(id, getLoginUserId()); + return success(true); } // ================ midjourney 接口 @@ -73,12 +70,14 @@ public class AiImageController { @Operation(summary = "midjourney-imagine 绘画", description = "...") @PostMapping("/midjourney/imagine") public CommonResult midjourneyImagine(@Validated @RequestBody AiImageMidjourneyImagineReqVO req) { - return success(aiImageService.midjourneyImagine(getLoginUserId(), req)); + return success(imageService.midjourneyImagine(getLoginUserId(), req)); } + // TODO @fan:可以考虑,复用 AiImageDallRespVO,统一成 AIImageRespVO @Operation(summary = "midjourney proxy - 回调通知") @RequestMapping("/midjourney-notify") public CommonResult midjourneyNotify(MidjourneyNotifyReqVO notifyReqVO) { - return success(aiImageService.midjourneyNotify(getLoginUserId(), notifyReqVO)); + return success(imageService.midjourneyNotify(getLoginUserId(), notifyReqVO)); } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListReqVO.java deleted file mode 100644 index 6af980363..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageListReqVO.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.image.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * AI Image 我的图片列表 req - * - * @author fansili - * @time 2024/4/28 17:42 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiImageListReqVO extends PageParam { - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyRes.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyRes.java deleted file mode 100644 index 8d1a52e8c..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyRes.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.image.vo; - -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * midjourney - * - * @author fansili - * @time 2024/4/28 17:42 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiImageMidjourneyRes { -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePageMyRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageRespVO.java similarity index 84% rename from yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePageMyRespVO.java rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageRespVO.java index e542879ca..4d12f7f4b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePageMyRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageRespVO.java @@ -1,23 +1,13 @@ package cn.iocoder.yudao.module.ai.controller.admin.image.vo; -import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.experimental.Accessors; import java.util.Map; -// TODO @fan:可以考虑,复用 AiImageDallRespVO,统一成 AIImageRespVO -/** - * midjourney req - * - * @author fansili - * @time 2024/4/28 17:42 - * @since 1.0 - */ +// TODO @芋艿:完善 swagger 注解 @Data -@Accessors(chain = true) -public class AiImagePageMyRespVO extends PageParam { +public class AiImageRespVO { @Schema(description = "id编号", example = "1") private Long id; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java index af37a2937..aada8a661 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.ai.dal.mysql.image; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; @@ -35,4 +37,10 @@ public interface AiImageMapper extends BaseMapperX { return this.selectOne(new LambdaQueryWrapperX().eq(AiImageDO::getJobId, id)); } + default PageResult selectPage(Long userId, PageParam pageReqVO) { + return selectPage(pageReqVO, new LambdaQueryWrapperX() + .eq(AiImageDO::getUserId, userId) + .orderByDesc(AiImageDO::getId)); + } + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java index 05ad0ed28..2442e79a9 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java @@ -1,38 +1,35 @@ package cn.iocoder.yudao.module.ai.service.image; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.client.vo.MidjourneyNotifyReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageListReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyImagineReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyOperateReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; /** - * ai 作图 + * AI 绘图 Service 接口 * * @author fansili - * @time 2024/4/25 15:50 - * @since 1.0 */ public interface AiImageService { /** - * ai绘画 - 列表 + * 获取【我的】绘图分页 * - * @param loginUserId - * @param req - * @return + * @param userId 用户编号 + * @param pageReqVO 分页条件 + * @return 绘图分页 */ - PageResult getImagePageMy(Long loginUserId, AiImageListReqVO req); + PageResult getImagePageMy(Long userId, PageParam pageReqVO); /** - * 获取 - image 信息 + * 获得绘图记录 * - * @param id - * @return + * @param id 绘图编号 + * @return 绘图记录 */ - AiImageDO getMy(Long id); + AiImageDO getImage(Long id); /** * ai绘画 - dall2/dall3 绘画 @@ -52,19 +49,12 @@ public interface AiImageService { Long midjourneyImagine(Long loginUserId, AiImageMidjourneyImagineReqVO req); /** - * midjourney 操作(u1、u2、放大、换一批...) + * 删除【我的】绘画记录 * - * @param req + * @param id 绘画编号 + * @param userId 用户编号 */ - void midjourneyOperate(AiImageMidjourneyOperateReqVO req); - - /** - * 删除 - image 记录 - * - * @param id - * @param loginUserId - */ - Boolean deleteIdMy(Long id, Long loginUserId); + void deleteImageMy(Long id, Long userId); /** * midjourney proxy - 回调通知 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index 16887045f..2b4f7e617 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -2,17 +2,17 @@ package cn.iocoder.yudao.module.ai.service.image; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.extra.spring.SpringUtil; import cn.hutool.http.HttpUtil; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageModelEnum; import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageStyleEnum; import cn.iocoder.yudao.framework.ai.core.exception.AiException; -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.ai.AiCommonConstants; -import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.client.MidjourneyProxyClient; import cn.iocoder.yudao.module.ai.client.enums.MidjourneyModelEnum; import cn.iocoder.yudao.module.ai.client.enums.MidjourneySubmitCodeEnum; @@ -21,9 +21,7 @@ import cn.iocoder.yudao.module.ai.client.vo.MidjourneyImagineReqVO; import cn.iocoder.yudao.module.ai.client.vo.MidjourneyNotifyReqVO; import cn.iocoder.yudao.module.ai.client.vo.MidjourneySubmitRespVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageListReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyImagineReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyOperateReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper; import cn.iocoder.yudao.module.ai.enums.AiImagePublicStatusEnum; @@ -46,12 +44,12 @@ import org.springframework.transaction.annotation.Transactional; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.AI_IMAGE_NOT_EXISTS; + /** - * AI 绘画(接入 dall2/dall3、midjourney) + * AI 绘画 Service 实现类 * * @author fansili - * @time 2024/4/25 15:51 - * @since 1.0 */ @Service @Slf4j @@ -59,10 +57,13 @@ public class AiImageServiceImpl implements AiImageService { @Resource private AiImageMapper imageMapper; + @Resource private FileApi fileApi; + @Resource private OpenAiImageClient openAiImageClient; + @Autowired private MidjourneyProxyClient midjourneyProxyClient; @@ -70,16 +71,12 @@ public class AiImageServiceImpl implements AiImageService { private String midjourneyNotifyUrl; @Override - public PageResult getImagePageMy(Long loginUserId, AiImageListReqVO req) { - // 查询当前用户下所有的绘画记录 - return imageMapper.selectPage(req, - new LambdaQueryWrapperX() - .eq(AiImageDO::getUserId, loginUserId) - .orderByDesc(AiImageDO::getId)); + public PageResult getImagePageMy(Long userId, PageParam pageReqVO) { + return imageMapper.selectPage(userId, pageReqVO); } @Override - public AiImageDO getMy(Long id) { + public AiImageDO getImage(Long id) { return imageMapper.selectById(id); } @@ -95,7 +92,7 @@ public class AiImageServiceImpl implements AiImageService { .setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus()); imageMapper.insert(aiImageDO); // 异步执行 - doDall(aiImageDO, req); + getSelf().doDall(aiImageDO, req); // 转换 AiImageDallDrawingRespVO return aiImageDO.getId(); } @@ -185,42 +182,15 @@ public class AiImageServiceImpl implements AiImageService { return aiImageDO.getId(); } - @Transactional(rollbackFor = Exception.class) @Override - public void midjourneyOperate(AiImageMidjourneyOperateReqVO req) { -// // 校验是否存在 -// AiImageDO aiImageDO = validateExists(req.getId()); -// // 获取 midjourneyOperations -// List midjourneyOperations = getMidjourneyOperations(aiImageDO); -// // 校验 OperateId 是否存在 -// AiImageMidjourneyOperationsVO midjourneyOperationsVO = validateMidjourneyOperationsExists(midjourneyOperations, req.getOperateId()); -// // 校验 messageId -// validateMessageId(aiImageDO.getMjNonceId(), req.getMessageId()); -// // 获取 mjOperationName -// String mjOperationName = midjourneyOperationsVO.getLabel(); -// // 保存一个 image 任务记录 -// // todo -//// doSave(aiImageDO.getPrompt(), aiImageDO.getSize(), aiImageDO.getModel(), -//// null, null, AiImageStatusEnum.SUBMIT, null, -//// req.getMessageId(), req.getOperateId(), mjOperationName); -// // 提交操作 -// midjourneyInteractionsApi.reRoll( -// new ReRollReq() -// .setCustomId(req.getOperateId()) -// .setMessageId(req.getMessageId()) -// ); - } - - @Override - public Boolean deleteIdMy(Long id, Long userId) { - // 校验是否存在,并获取 image - AiImageDO image = validateExists(id); - // 是否属于当前用户 - if (!image.getUserId().equals(userId)) { - throw exception(ErrorCodeConstants.AI_IMAGE_NOT_EXISTS); + public void deleteImageMy(Long id, Long userId) { + // 1. 校验是否存在 + AiImageDO image = validateImageExists(id); + if (ObjUtil.notEqual(image.getUserId(), userId)) { + throw exception(AI_IMAGE_NOT_EXISTS); } // 删除记录 - return imageMapper.deleteById(id) > 0; + imageMapper.deleteById(id); } @Override @@ -255,11 +225,21 @@ public class AiImageServiceImpl implements AiImageService { return true; } - private AiImageDO validateExists(Long id) { - AiImageDO aiImageDO = imageMapper.selectById(id); - if (aiImageDO == null) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MIDJOURNEY_IMAGINE_FAIL); + private AiImageDO validateImageExists(Long id) { + AiImageDO image = imageMapper.selectById(id); + if (image == null) { + throw exception(AI_IMAGE_NOT_EXISTS); } - return aiImageDO; + return image; } + + /** + * 获得自身的代理对象,解决 AOP 生效问题 + * + * @return 自己 + */ + private AiImageServiceImpl getSelf() { + return SpringUtil.getBean(getClass()); + } + } From a6bee12fbc07ed2114c9389355e868bfaae5559b Mon Sep 17 00:00:00 2001 From: dhb52 Date: Fri, 31 May 2024 22:55:09 +0800 Subject: [PATCH 386/684] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E4=BA=BA?= =?UTF-8?q?=E5=A4=A7=E9=87=91=E4=BB=93=E6=95=B0KingbaseES?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/kingbase/ruoyi-vue-pro.sql | 4723 +++++++++++++++++ sql/tools/README.md | 31 +- sql/tools/convertor.py | 40 +- sql/tools/docker-compose.yaml | 17 + .../src/main/resources/application-local.yaml | 1 + 5 files changed, 4807 insertions(+), 5 deletions(-) create mode 100644 sql/kingbase/ruoyi-vue-pro.sql diff --git a/sql/kingbase/ruoyi-vue-pro.sql b/sql/kingbase/ruoyi-vue-pro.sql new file mode 100644 index 000000000..37f3b9b66 --- /dev/null +++ b/sql/kingbase/ruoyi-vue-pro.sql @@ -0,0 +1,4723 @@ +/* + Yudao Database Transfer Tool + + Source Server Type : MySQL + + Target Server Type : Kingbase + + Date: 2024-05-31 22:42:53 +*/ + + +-- ---------------------------- +-- Table structure for dual +-- ---------------------------- +DROP TABLE IF EXISTS dual; +CREATE TABLE dual +( + id int2 +); + +COMMENT ON TABLE dual IS '数据库连接的表'; + +-- ---------------------------- +-- Records of dual +-- ---------------------------- +-- @formatter:off +INSERT INTO dual VALUES (1); +-- @formatter:on + +-- ---------------------------- +-- Table structure for infra_api_access_log +-- ---------------------------- +DROP TABLE IF EXISTS infra_api_access_log; +CREATE TABLE infra_api_access_log +( + id int8 NOT NULL, + trace_id varchar(64) NULL DEFAULT '', + user_id int8 NOT NULL DEFAULT 0, + user_type int2 NOT NULL DEFAULT 0, + application_name varchar(50) NOT NULL, + request_method varchar(16) NULL DEFAULT '', + request_url varchar(255) NULL DEFAULT '', + request_params text NULL, + response_body text NULL, + user_ip varchar(50) NOT NULL, + user_agent varchar(512) NOT NULL, + operate_module varchar(50) NULL DEFAULT NULL, + operate_name varchar(50) NULL DEFAULT NULL, + operate_type int2 NULL DEFAULT 0, + begin_time timestamp NOT NULL, + end_time timestamp NOT NULL, + duration int4 NOT NULL, + result_code int4 NOT NULL DEFAULT 0, + result_msg varchar(512) NULL DEFAULT '', + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE infra_api_access_log + ADD CONSTRAINT pk_infra_api_access_log PRIMARY KEY (id); + +CREATE INDEX idx_infra_api_access_log_01 ON infra_api_access_log (create_time); + +COMMENT ON COLUMN infra_api_access_log.id IS '日志主键'; +COMMENT ON COLUMN infra_api_access_log.trace_id IS '链路追踪编号'; +COMMENT ON COLUMN infra_api_access_log.user_id IS '用户编号'; +COMMENT ON COLUMN infra_api_access_log.user_type IS '用户类型'; +COMMENT ON COLUMN infra_api_access_log.application_name IS '应用名'; +COMMENT ON COLUMN infra_api_access_log.request_method IS '请求方法名'; +COMMENT ON COLUMN infra_api_access_log.request_url IS '请求地址'; +COMMENT ON COLUMN infra_api_access_log.request_params IS '请求参数'; +COMMENT ON COLUMN infra_api_access_log.response_body IS '响应结果'; +COMMENT ON COLUMN infra_api_access_log.user_ip IS '用户 IP'; +COMMENT ON COLUMN infra_api_access_log.user_agent IS '浏览器 UA'; +COMMENT ON COLUMN infra_api_access_log.operate_module IS '操作模块'; +COMMENT ON COLUMN infra_api_access_log.operate_name IS '操作名'; +COMMENT ON COLUMN infra_api_access_log.operate_type IS '操作分类'; +COMMENT ON COLUMN infra_api_access_log.begin_time IS '开始请求时间'; +COMMENT ON COLUMN infra_api_access_log.end_time IS '结束请求时间'; +COMMENT ON COLUMN infra_api_access_log.duration IS '执行时长'; +COMMENT ON COLUMN infra_api_access_log.result_code IS '结果码'; +COMMENT ON COLUMN infra_api_access_log.result_msg IS '结果提示'; +COMMENT ON COLUMN infra_api_access_log.creator IS '创建者'; +COMMENT ON COLUMN infra_api_access_log.create_time IS '创建时间'; +COMMENT ON COLUMN infra_api_access_log.updater IS '更新者'; +COMMENT ON COLUMN infra_api_access_log.update_time IS '更新时间'; +COMMENT ON COLUMN infra_api_access_log.deleted IS '是否删除'; +COMMENT ON COLUMN infra_api_access_log.tenant_id IS '租户编号'; +COMMENT ON TABLE infra_api_access_log IS 'API 访问日志表'; + +DROP SEQUENCE IF EXISTS infra_api_access_log_seq; +CREATE SEQUENCE infra_api_access_log_seq + START 1; + +-- ---------------------------- +-- Table structure for infra_api_error_log +-- ---------------------------- +DROP TABLE IF EXISTS infra_api_error_log; +CREATE TABLE infra_api_error_log +( + id int4 NOT NULL, + trace_id varchar(64) NOT NULL, + user_id int4 NOT NULL DEFAULT 0, + user_type int2 NOT NULL DEFAULT 0, + application_name varchar(50) NOT NULL, + request_method varchar(16) NOT NULL, + request_url varchar(255) NOT NULL, + request_params varchar(8000) NOT NULL, + user_ip varchar(50) NOT NULL, + user_agent varchar(512) NOT NULL, + exception_time timestamp NOT NULL, + exception_name varchar(128) NULL DEFAULT '', + exception_message text NOT NULL, + exception_root_cause_message text NOT NULL, + exception_stack_trace text NOT NULL, + exception_class_name varchar(512) NOT NULL, + exception_file_name varchar(512) NOT NULL, + exception_method_name varchar(512) NOT NULL, + exception_line_number int4 NOT NULL, + process_status int2 NOT NULL, + process_time timestamp NULL DEFAULT NULL, + process_user_id int4 NULL DEFAULT 0, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE infra_api_error_log + ADD CONSTRAINT pk_infra_api_error_log PRIMARY KEY (id); + +COMMENT ON COLUMN infra_api_error_log.id IS '编号'; +COMMENT ON COLUMN infra_api_error_log.trace_id IS '链路追踪编号 + * + * 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。'; +COMMENT ON COLUMN infra_api_error_log.user_id IS '用户编号'; +COMMENT ON COLUMN infra_api_error_log.user_type IS '用户类型'; +COMMENT ON COLUMN infra_api_error_log.application_name IS '应用名 + * + * 目前读取 spring.application.name'; +COMMENT ON COLUMN infra_api_error_log.request_method IS '请求方法名'; +COMMENT ON COLUMN infra_api_error_log.request_url IS '请求地址'; +COMMENT ON COLUMN infra_api_error_log.request_params IS '请求参数'; +COMMENT ON COLUMN infra_api_error_log.user_ip IS '用户 IP'; +COMMENT ON COLUMN infra_api_error_log.user_agent IS '浏览器 UA'; +COMMENT ON COLUMN infra_api_error_log.exception_time IS '异常发生时间'; +COMMENT ON COLUMN infra_api_error_log.exception_name IS '异常名 + * + * {@link Throwable#getClass()} 的类全名'; +COMMENT ON COLUMN infra_api_error_log.exception_message IS '异常导致的消息 + * + * {@link cn.iocoder.common.framework.util.ExceptionUtil#getMessage(Throwable)}'; +COMMENT ON COLUMN infra_api_error_log.exception_root_cause_message IS '异常导致的根消息 + * + * {@link cn.iocoder.common.framework.util.ExceptionUtil#getRootCauseMessage(Throwable)}'; +COMMENT ON COLUMN infra_api_error_log.exception_stack_trace IS '异常的栈轨迹 + * + * {@link cn.iocoder.common.framework.util.ExceptionUtil#getServiceException(Exception)}'; +COMMENT ON COLUMN infra_api_error_log.exception_class_name IS '异常发生的类全名 + * + * {@link StackTraceElement#getClassName()}'; +COMMENT ON COLUMN infra_api_error_log.exception_file_name IS '异常发生的类文件 + * + * {@link StackTraceElement#getFileName()}'; +COMMENT ON COLUMN infra_api_error_log.exception_method_name IS '异常发生的方法名 + * + * {@link StackTraceElement#getMethodName()}'; +COMMENT ON COLUMN infra_api_error_log.exception_line_number IS '异常发生的方法所在行 + * + * {@link StackTraceElement#getLineNumber()}'; +COMMENT ON COLUMN infra_api_error_log.process_status IS '处理状态'; +COMMENT ON COLUMN infra_api_error_log.process_time IS '处理时间'; +COMMENT ON COLUMN infra_api_error_log.process_user_id IS '处理用户编号'; +COMMENT ON COLUMN infra_api_error_log.creator IS '创建者'; +COMMENT ON COLUMN infra_api_error_log.create_time IS '创建时间'; +COMMENT ON COLUMN infra_api_error_log.updater IS '更新者'; +COMMENT ON COLUMN infra_api_error_log.update_time IS '更新时间'; +COMMENT ON COLUMN infra_api_error_log.deleted IS '是否删除'; +COMMENT ON COLUMN infra_api_error_log.tenant_id IS '租户编号'; +COMMENT ON TABLE infra_api_error_log IS '系统异常日志'; + +DROP SEQUENCE IF EXISTS infra_api_error_log_seq; +CREATE SEQUENCE infra_api_error_log_seq + START 1; + +-- ---------------------------- +-- Table structure for infra_codegen_column +-- ---------------------------- +DROP TABLE IF EXISTS infra_codegen_column; +CREATE TABLE infra_codegen_column +( + id int8 NOT NULL, + table_id int8 NOT NULL, + column_name varchar(200) NOT NULL, + data_type varchar(100) NOT NULL, + column_comment varchar(500) NOT NULL, + nullable bool NOT NULL, + primary_key bool NOT NULL, + ordinal_position int4 NOT NULL, + java_type varchar(32) NOT NULL, + java_field varchar(64) NOT NULL, + dict_type varchar(200) NULL DEFAULT '', + example varchar(64) NULL DEFAULT NULL, + create_operation bool NOT NULL, + update_operation bool NOT NULL, + list_operation bool NOT NULL, + list_operation_condition varchar(32) NOT NULL DEFAULT '=', + list_operation_result bool NOT NULL, + html_type varchar(32) NOT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0 +); + +ALTER TABLE infra_codegen_column + ADD CONSTRAINT pk_infra_codegen_column PRIMARY KEY (id); + +COMMENT ON COLUMN infra_codegen_column.id IS '编号'; +COMMENT ON COLUMN infra_codegen_column.table_id IS '表编号'; +COMMENT ON COLUMN infra_codegen_column.column_name IS '字段名'; +COMMENT ON COLUMN infra_codegen_column.data_type IS '字段类型'; +COMMENT ON COLUMN infra_codegen_column.column_comment IS '字段描述'; +COMMENT ON COLUMN infra_codegen_column.nullable IS '是否允许为空'; +COMMENT ON COLUMN infra_codegen_column.primary_key IS '是否主键'; +COMMENT ON COLUMN infra_codegen_column.ordinal_position IS '排序'; +COMMENT ON COLUMN infra_codegen_column.java_type IS 'Java 属性类型'; +COMMENT ON COLUMN infra_codegen_column.java_field IS 'Java 属性名'; +COMMENT ON COLUMN infra_codegen_column.dict_type IS '字典类型'; +COMMENT ON COLUMN infra_codegen_column.example IS '数据示例'; +COMMENT ON COLUMN infra_codegen_column.create_operation IS '是否为 Create 创建操作的字段'; +COMMENT ON COLUMN infra_codegen_column.update_operation IS '是否为 Update 更新操作的字段'; +COMMENT ON COLUMN infra_codegen_column.list_operation IS '是否为 List 查询操作的字段'; +COMMENT ON COLUMN infra_codegen_column.list_operation_condition IS 'List 查询操作的条件类型'; +COMMENT ON COLUMN infra_codegen_column.list_operation_result IS '是否为 List 查询操作的返回字段'; +COMMENT ON COLUMN infra_codegen_column.html_type IS '显示类型'; +COMMENT ON COLUMN infra_codegen_column.creator IS '创建者'; +COMMENT ON COLUMN infra_codegen_column.create_time IS '创建时间'; +COMMENT ON COLUMN infra_codegen_column.updater IS '更新者'; +COMMENT ON COLUMN infra_codegen_column.update_time IS '更新时间'; +COMMENT ON COLUMN infra_codegen_column.deleted IS '是否删除'; +COMMENT ON TABLE infra_codegen_column IS '代码生成表字段定义'; + +DROP SEQUENCE IF EXISTS infra_codegen_column_seq; +CREATE SEQUENCE infra_codegen_column_seq + START 1; + +-- ---------------------------- +-- Table structure for infra_codegen_table +-- ---------------------------- +DROP TABLE IF EXISTS infra_codegen_table; +CREATE TABLE infra_codegen_table +( + id int8 NOT NULL, + data_source_config_id int8 NOT NULL, + scene int2 NOT NULL DEFAULT 1, + table_name varchar(200) NULL DEFAULT '', + table_comment varchar(500) NULL DEFAULT '', + remark varchar(500) NULL DEFAULT NULL, + module_name varchar(30) NOT NULL, + business_name varchar(30) NOT NULL, + class_name varchar(100) NULL DEFAULT '', + class_comment varchar(50) NOT NULL, + author varchar(50) NOT NULL, + template_type int2 NOT NULL DEFAULT 1, + front_type int2 NOT NULL, + parent_menu_id int8 NULL DEFAULT NULL, + master_table_id int8 NULL DEFAULT NULL, + sub_join_column_id int8 NULL DEFAULT NULL, + sub_join_many bool NULL DEFAULT NULL, + tree_parent_column_id int8 NULL DEFAULT NULL, + tree_name_column_id int8 NULL DEFAULT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0 +); + +ALTER TABLE infra_codegen_table + ADD CONSTRAINT pk_infra_codegen_table PRIMARY KEY (id); + +COMMENT ON COLUMN infra_codegen_table.id IS '编号'; +COMMENT ON COLUMN infra_codegen_table.data_source_config_id IS '数据源配置的编号'; +COMMENT ON COLUMN infra_codegen_table.scene IS '生成场景'; +COMMENT ON COLUMN infra_codegen_table.table_name IS '表名称'; +COMMENT ON COLUMN infra_codegen_table.table_comment IS '表描述'; +COMMENT ON COLUMN infra_codegen_table.remark IS '备注'; +COMMENT ON COLUMN infra_codegen_table.module_name IS '模块名'; +COMMENT ON COLUMN infra_codegen_table.business_name IS '业务名'; +COMMENT ON COLUMN infra_codegen_table.class_name IS '类名称'; +COMMENT ON COLUMN infra_codegen_table.class_comment IS '类描述'; +COMMENT ON COLUMN infra_codegen_table.author IS '作者'; +COMMENT ON COLUMN infra_codegen_table.template_type IS '模板类型'; +COMMENT ON COLUMN infra_codegen_table.front_type IS '前端类型'; +COMMENT ON COLUMN infra_codegen_table.parent_menu_id IS '父菜单编号'; +COMMENT ON COLUMN infra_codegen_table.master_table_id IS '主表的编号'; +COMMENT ON COLUMN infra_codegen_table.sub_join_column_id IS '子表关联主表的字段编号'; +COMMENT ON COLUMN infra_codegen_table.sub_join_many IS '主表与子表是否一对多'; +COMMENT ON COLUMN infra_codegen_table.tree_parent_column_id IS '树表的父字段编号'; +COMMENT ON COLUMN infra_codegen_table.tree_name_column_id IS '树表的名字字段编号'; +COMMENT ON COLUMN infra_codegen_table.creator IS '创建者'; +COMMENT ON COLUMN infra_codegen_table.create_time IS '创建时间'; +COMMENT ON COLUMN infra_codegen_table.updater IS '更新者'; +COMMENT ON COLUMN infra_codegen_table.update_time IS '更新时间'; +COMMENT ON COLUMN infra_codegen_table.deleted IS '是否删除'; +COMMENT ON TABLE infra_codegen_table IS '代码生成表定义'; + +DROP SEQUENCE IF EXISTS infra_codegen_table_seq; +CREATE SEQUENCE infra_codegen_table_seq + START 1; + +-- ---------------------------- +-- Table structure for infra_config +-- ---------------------------- +DROP TABLE IF EXISTS infra_config; +CREATE TABLE infra_config +( + id int4 NOT NULL, + category varchar(50) NOT NULL, + type int2 NOT NULL, + name varchar(100) NULL DEFAULT '', + config_key varchar(100) NULL DEFAULT '', + value varchar(500) NULL DEFAULT '', + visible bool NOT NULL, + remark varchar(500) NULL DEFAULT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0 +); + +ALTER TABLE infra_config + ADD CONSTRAINT pk_infra_config PRIMARY KEY (id); + +COMMENT ON COLUMN infra_config.id IS '参数主键'; +COMMENT ON COLUMN infra_config.category IS '参数分组'; +COMMENT ON COLUMN infra_config.type IS '参数类型'; +COMMENT ON COLUMN infra_config.name IS '参数名称'; +COMMENT ON COLUMN infra_config.config_key IS '参数键名'; +COMMENT ON COLUMN infra_config.value IS '参数键值'; +COMMENT ON COLUMN infra_config.visible IS '是否可见'; +COMMENT ON COLUMN infra_config.remark IS '备注'; +COMMENT ON COLUMN infra_config.creator IS '创建者'; +COMMENT ON COLUMN infra_config.create_time IS '创建时间'; +COMMENT ON COLUMN infra_config.updater IS '更新者'; +COMMENT ON COLUMN infra_config.update_time IS '更新时间'; +COMMENT ON COLUMN infra_config.deleted IS '是否删除'; +COMMENT ON TABLE infra_config IS '参数配置表'; + +-- ---------------------------- +-- Records of infra_config +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO infra_config (id, category, type, name, config_key, value, visible, remark, creator, create_time, updater, update_time, deleted) VALUES (2, 'biz', 1, '用户管理-账号初始密码', 'sys.user.init-password', '123456', '0', '初始化密码 123456', 'admin', '2021-01-05 17:03:48', '1', '2024-04-03 17:22:28', '0'); +INSERT INTO infra_config (id, category, type, name, config_key, value, visible, remark, creator, create_time, updater, update_time, deleted) VALUES (7, 'url', 2, 'MySQL 监控的地址', 'url.druid', '', '1', '', '1', '2023-04-07 13:41:16', '1', '2023-04-07 14:33:38', '0'); +INSERT INTO infra_config (id, category, type, name, config_key, value, visible, remark, creator, create_time, updater, update_time, deleted) VALUES (8, 'url', 2, 'SkyWalking 监控的地址', 'url.skywalking', '', '1', '', '1', '2023-04-07 13:41:16', '1', '2023-04-07 14:57:03', '0'); +INSERT INTO infra_config (id, category, type, name, config_key, value, visible, remark, creator, create_time, updater, update_time, deleted) VALUES (9, 'url', 2, 'Spring Boot Admin 监控的地址', 'url.spring-boot-admin', '', '1', '', '1', '2023-04-07 13:41:16', '1', '2023-04-07 14:52:07', '0'); +INSERT INTO infra_config (id, category, type, name, config_key, value, visible, remark, creator, create_time, updater, update_time, deleted) VALUES (10, 'url', 2, 'Swagger 接口文档的地址', 'url.swagger', '', '1', '', '1', '2023-04-07 13:41:16', '1', '2023-04-07 14:59:00', '0'); +INSERT INTO infra_config (id, category, type, name, config_key, value, visible, remark, creator, create_time, updater, update_time, deleted) VALUES (11, 'ui', 2, '腾讯地图 key', 'tencent.lbs.key', 'TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E', '1', '腾讯地图 key', '1', '2023-06-03 19:16:27', '1', '2023-06-03 19:16:27', '0'); +INSERT INTO infra_config (id, category, type, name, config_key, value, visible, remark, creator, create_time, updater, update_time, deleted) VALUES (12, 'test2', 2, 'test3', 'test4', 'test5', '1', 'test6', '1', '2023-12-03 09:55:16', '1', '2023-12-03 09:55:27', '0'); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS infra_config_seq; +CREATE SEQUENCE infra_config_seq + START 13; + +-- ---------------------------- +-- Table structure for infra_data_source_config +-- ---------------------------- +DROP TABLE IF EXISTS infra_data_source_config; +CREATE TABLE infra_data_source_config +( + id int8 NOT NULL, + name varchar(100) NULL DEFAULT '', + url varchar(1024) NOT NULL, + username varchar(255) NOT NULL, + password varchar(255) NULL DEFAULT '', + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0 +); + +ALTER TABLE infra_data_source_config + ADD CONSTRAINT pk_infra_data_source_config PRIMARY KEY (id); + +COMMENT ON COLUMN infra_data_source_config.id IS '主键编号'; +COMMENT ON COLUMN infra_data_source_config.name IS '参数名称'; +COMMENT ON COLUMN infra_data_source_config.url IS '数据源连接'; +COMMENT ON COLUMN infra_data_source_config.username IS '用户名'; +COMMENT ON COLUMN infra_data_source_config.password IS '密码'; +COMMENT ON COLUMN infra_data_source_config.creator IS '创建者'; +COMMENT ON COLUMN infra_data_source_config.create_time IS '创建时间'; +COMMENT ON COLUMN infra_data_source_config.updater IS '更新者'; +COMMENT ON COLUMN infra_data_source_config.update_time IS '更新时间'; +COMMENT ON COLUMN infra_data_source_config.deleted IS '是否删除'; +COMMENT ON TABLE infra_data_source_config IS '数据源配置表'; + +DROP SEQUENCE IF EXISTS infra_data_source_config_seq; +CREATE SEQUENCE infra_data_source_config_seq + START 1; + +-- ---------------------------- +-- Table structure for infra_file +-- ---------------------------- +DROP TABLE IF EXISTS infra_file; +CREATE TABLE infra_file +( + id int8 NOT NULL, + config_id int8 NULL DEFAULT NULL, + name varchar(256) NULL DEFAULT NULL, + path varchar(512) NOT NULL, + url varchar(1024) NOT NULL, + type varchar(128) NULL DEFAULT NULL, + size int4 NOT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0 +); + +ALTER TABLE infra_file + ADD CONSTRAINT pk_infra_file PRIMARY KEY (id); + +COMMENT ON COLUMN infra_file.id IS '文件编号'; +COMMENT ON COLUMN infra_file.config_id IS '配置编号'; +COMMENT ON COLUMN infra_file.name IS '文件名'; +COMMENT ON COLUMN infra_file.path IS '文件路径'; +COMMENT ON COLUMN infra_file.url IS '文件 URL'; +COMMENT ON COLUMN infra_file.type IS '文件类型'; +COMMENT ON COLUMN infra_file.size IS '文件大小'; +COMMENT ON COLUMN infra_file.creator IS '创建者'; +COMMENT ON COLUMN infra_file.create_time IS '创建时间'; +COMMENT ON COLUMN infra_file.updater IS '更新者'; +COMMENT ON COLUMN infra_file.update_time IS '更新时间'; +COMMENT ON COLUMN infra_file.deleted IS '是否删除'; +COMMENT ON TABLE infra_file IS '文件表'; + +DROP SEQUENCE IF EXISTS infra_file_seq; +CREATE SEQUENCE infra_file_seq + START 1; + +-- ---------------------------- +-- Table structure for infra_file_config +-- ---------------------------- +DROP TABLE IF EXISTS infra_file_config; +CREATE TABLE infra_file_config +( + id int8 NOT NULL, + name varchar(63) NOT NULL, + storage int2 NOT NULL, + remark varchar(255) NULL DEFAULT NULL, + master bool NOT NULL, + config varchar(4096) NOT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0 +); + +ALTER TABLE infra_file_config + ADD CONSTRAINT pk_infra_file_config PRIMARY KEY (id); + +COMMENT ON COLUMN infra_file_config.id IS '编号'; +COMMENT ON COLUMN infra_file_config.name IS '配置名'; +COMMENT ON COLUMN infra_file_config.storage IS '存储器'; +COMMENT ON COLUMN infra_file_config.remark IS '备注'; +COMMENT ON COLUMN infra_file_config.master IS '是否为主配置'; +COMMENT ON COLUMN infra_file_config.config IS '存储配置'; +COMMENT ON COLUMN infra_file_config.creator IS '创建者'; +COMMENT ON COLUMN infra_file_config.create_time IS '创建时间'; +COMMENT ON COLUMN infra_file_config.updater IS '更新者'; +COMMENT ON COLUMN infra_file_config.update_time IS '更新时间'; +COMMENT ON COLUMN infra_file_config.deleted IS '是否删除'; +COMMENT ON TABLE infra_file_config IS '文件配置表'; + +-- ---------------------------- +-- Records of infra_file_config +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO infra_file_config (id, name, storage, remark, master, config, creator, create_time, updater, update_time, deleted) VALUES (4, '数据库', 1, '我是数据库', '0', '{"@class":"cn.iocoder.yudao.module.infra.framework.file.core.client.db.DBFileClientConfig","domain":"http://127.0.0.1:48080"}', '1', '2022-03-15 23:56:24', '1', '2024-02-28 22:54:07', '0'); +INSERT INTO infra_file_config (id, name, storage, remark, master, config, creator, create_time, updater, update_time, deleted) VALUES (22, '七牛存储器', 20, '', '1', '{"@class":"cn.iocoder.yudao.module.infra.framework.file.core.client.s3.S3FileClientConfig","endpoint":"s3.cn-south-1.qiniucs.com","domain":"http://test.yudao.iocoder.cn","bucket":"ruoyi-vue-pro","accessKey":"3TvrJ70gl2Gt6IBe7_IZT1F6i_k0iMuRtyEv4EyS","accessSecret":"wd0tbVBYlp0S-ihA8Qg2hPLncoP83wyrIq24OZuY"}', '1', '2024-01-13 22:11:12', '1', '2024-04-03 19:38:34', '0'); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS infra_file_config_seq; +CREATE SEQUENCE infra_file_config_seq + START 23; + +-- ---------------------------- +-- Table structure for infra_file_content +-- ---------------------------- +DROP TABLE IF EXISTS infra_file_content; +CREATE TABLE infra_file_content +( + id int8 NOT NULL, + config_id int8 NOT NULL, + path varchar(512) NOT NULL, + content bytea NOT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0 +); + +ALTER TABLE infra_file_content + ADD CONSTRAINT pk_infra_file_content PRIMARY KEY (id); + +COMMENT ON COLUMN infra_file_content.id IS '编号'; +COMMENT ON COLUMN infra_file_content.config_id IS '配置编号'; +COMMENT ON COLUMN infra_file_content.path IS '文件路径'; +COMMENT ON COLUMN infra_file_content.content IS '文件内容'; +COMMENT ON COLUMN infra_file_content.creator IS '创建者'; +COMMENT ON COLUMN infra_file_content.create_time IS '创建时间'; +COMMENT ON COLUMN infra_file_content.updater IS '更新者'; +COMMENT ON COLUMN infra_file_content.update_time IS '更新时间'; +COMMENT ON COLUMN infra_file_content.deleted IS '是否删除'; +COMMENT ON TABLE infra_file_content IS '文件表'; + +DROP SEQUENCE IF EXISTS infra_file_content_seq; +CREATE SEQUENCE infra_file_content_seq + START 1; + +-- ---------------------------- +-- Table structure for infra_job +-- ---------------------------- +DROP TABLE IF EXISTS infra_job; +CREATE TABLE infra_job +( + id int8 NOT NULL, + name varchar(32) NOT NULL, + status int2 NOT NULL, + handler_name varchar(64) NOT NULL, + handler_param varchar(255) NULL DEFAULT NULL, + cron_expression varchar(32) NOT NULL, + retry_count int4 NOT NULL DEFAULT 0, + retry_interval int4 NOT NULL DEFAULT 0, + monitor_timeout int4 NOT NULL DEFAULT 0, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0 +); + +ALTER TABLE infra_job + ADD CONSTRAINT pk_infra_job PRIMARY KEY (id); + +COMMENT ON COLUMN infra_job.id IS '任务编号'; +COMMENT ON COLUMN infra_job.name IS '任务名称'; +COMMENT ON COLUMN infra_job.status IS '任务状态'; +COMMENT ON COLUMN infra_job.handler_name IS '处理器的名字'; +COMMENT ON COLUMN infra_job.handler_param IS '处理器的参数'; +COMMENT ON COLUMN infra_job.cron_expression IS 'CRON 表达式'; +COMMENT ON COLUMN infra_job.retry_count IS '重试次数'; +COMMENT ON COLUMN infra_job.retry_interval IS '重试间隔'; +COMMENT ON COLUMN infra_job.monitor_timeout IS '监控超时时间'; +COMMENT ON COLUMN infra_job.creator IS '创建者'; +COMMENT ON COLUMN infra_job.create_time IS '创建时间'; +COMMENT ON COLUMN infra_job.updater IS '更新者'; +COMMENT ON COLUMN infra_job.update_time IS '更新时间'; +COMMENT ON COLUMN infra_job.deleted IS '是否删除'; +COMMENT ON TABLE infra_job IS '定时任务表'; + +-- ---------------------------- +-- Records of infra_job +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO infra_job (id, name, status, handler_name, handler_param, cron_expression, retry_count, retry_interval, monitor_timeout, creator, create_time, updater, update_time, deleted) VALUES (5, '支付通知 Job', 2, 'payNotifyJob', NULL, '* * * * * ?', 0, 0, 0, '1', '2021-10-27 08:34:42', '1', '2023-07-09 20:51:41', '0'); +INSERT INTO infra_job (id, name, status, handler_name, handler_param, cron_expression, retry_count, retry_interval, monitor_timeout, creator, create_time, updater, update_time, deleted) VALUES (17, '支付订单同步 Job', 2, 'payOrderSyncJob', NULL, '0 0/1 * * * ?', 0, 0, 0, '1', '2023-07-22 14:36:26', '1', '2023-07-22 15:39:08', '0'); +INSERT INTO infra_job (id, name, status, handler_name, handler_param, cron_expression, retry_count, retry_interval, monitor_timeout, creator, create_time, updater, update_time, deleted) VALUES (18, '支付订单过期 Job', 2, 'payOrderExpireJob', NULL, '0 0/1 * * * ?', 0, 0, 0, '1', '2023-07-22 15:36:23', '1', '2023-07-22 15:39:54', '0'); +INSERT INTO infra_job (id, name, status, handler_name, handler_param, cron_expression, retry_count, retry_interval, monitor_timeout, creator, create_time, updater, update_time, deleted) VALUES (19, '退款订单的同步 Job', 2, 'payRefundSyncJob', NULL, '0 0/1 * * * ?', 0, 0, 0, '1', '2023-07-23 21:03:44', '1', '2023-07-23 21:09:00', '0'); +INSERT INTO infra_job (id, name, status, handler_name, handler_param, cron_expression, retry_count, retry_interval, monitor_timeout, creator, create_time, updater, update_time, deleted) VALUES (21, '交易订单的自动过期 Job', 2, 'tradeOrderAutoCancelJob', '', '0 * * * * ?', 3, 0, 0, '1', '2023-09-25 23:43:26', '1', '2023-09-26 19:23:30', '0'); +INSERT INTO infra_job (id, name, status, handler_name, handler_param, cron_expression, retry_count, retry_interval, monitor_timeout, creator, create_time, updater, update_time, deleted) VALUES (22, '交易订单的自动收货 Job', 2, 'tradeOrderAutoReceiveJob', '', '0 * * * * ?', 3, 0, 0, '1', '2023-09-26 19:23:53', '1', '2023-09-26 23:38:08', '0'); +INSERT INTO infra_job (id, name, status, handler_name, handler_param, cron_expression, retry_count, retry_interval, monitor_timeout, creator, create_time, updater, update_time, deleted) VALUES (23, '交易订单的自动评论 Job', 2, 'tradeOrderAutoCommentJob', '', '0 * * * * ?', 3, 0, 0, '1', '2023-09-26 23:38:29', '1', '2023-09-27 11:03:10', '0'); +INSERT INTO infra_job (id, name, status, handler_name, handler_param, cron_expression, retry_count, retry_interval, monitor_timeout, creator, create_time, updater, update_time, deleted) VALUES (24, '佣金解冻 Job', 2, 'brokerageRecordUnfreezeJob', '', '0 * * * * ?', 3, 0, 0, '1', '2023-09-28 22:01:46', '1', '2023-09-28 22:01:56', '0'); +INSERT INTO infra_job (id, name, status, handler_name, handler_param, cron_expression, retry_count, retry_interval, monitor_timeout, creator, create_time, updater, update_time, deleted) VALUES (25, '访问日志清理 Job', 2, 'accessLogCleanJob', '', '0 0 0 * * ?', 3, 0, 0, '1', '2023-10-03 10:59:41', '1', '2023-10-03 11:01:10', '0'); +INSERT INTO infra_job (id, name, status, handler_name, handler_param, cron_expression, retry_count, retry_interval, monitor_timeout, creator, create_time, updater, update_time, deleted) VALUES (26, '错误日志清理 Job', 2, 'errorLogCleanJob', '', '0 0 0 * * ?', 3, 0, 0, '1', '2023-10-03 11:00:43', '1', '2023-10-03 11:01:12', '0'); +INSERT INTO infra_job (id, name, status, handler_name, handler_param, cron_expression, retry_count, retry_interval, monitor_timeout, creator, create_time, updater, update_time, deleted) VALUES (27, '任务日志清理 Job', 2, 'jobLogCleanJob', '', '0 0 0 * * ?', 3, 0, 0, '1', '2023-10-03 11:01:33', '1', '2023-10-03 11:01:42', '0'); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS infra_job_seq; +CREATE SEQUENCE infra_job_seq + START 28; + +-- ---------------------------- +-- Table structure for infra_job_log +-- ---------------------------- +DROP TABLE IF EXISTS infra_job_log; +CREATE TABLE infra_job_log +( + id int8 NOT NULL, + job_id int8 NOT NULL, + handler_name varchar(64) NOT NULL, + handler_param varchar(255) NULL DEFAULT NULL, + execute_index int2 NOT NULL DEFAULT 1, + begin_time timestamp NOT NULL, + end_time timestamp NULL DEFAULT NULL, + duration int4 NULL DEFAULT NULL, + status int2 NOT NULL, + result varchar(4000) NULL DEFAULT '', + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0 +); + +ALTER TABLE infra_job_log + ADD CONSTRAINT pk_infra_job_log PRIMARY KEY (id); + +COMMENT ON COLUMN infra_job_log.id IS '日志编号'; +COMMENT ON COLUMN infra_job_log.job_id IS '任务编号'; +COMMENT ON COLUMN infra_job_log.handler_name IS '处理器的名字'; +COMMENT ON COLUMN infra_job_log.handler_param IS '处理器的参数'; +COMMENT ON COLUMN infra_job_log.execute_index IS '第几次执行'; +COMMENT ON COLUMN infra_job_log.begin_time IS '开始执行时间'; +COMMENT ON COLUMN infra_job_log.end_time IS '结束执行时间'; +COMMENT ON COLUMN infra_job_log.duration IS '执行时长'; +COMMENT ON COLUMN infra_job_log.status IS '任务状态'; +COMMENT ON COLUMN infra_job_log.result IS '结果数据'; +COMMENT ON COLUMN infra_job_log.creator IS '创建者'; +COMMENT ON COLUMN infra_job_log.create_time IS '创建时间'; +COMMENT ON COLUMN infra_job_log.updater IS '更新者'; +COMMENT ON COLUMN infra_job_log.update_time IS '更新时间'; +COMMENT ON COLUMN infra_job_log.deleted IS '是否删除'; +COMMENT ON TABLE infra_job_log IS '定时任务日志表'; + +DROP SEQUENCE IF EXISTS infra_job_log_seq; +CREATE SEQUENCE infra_job_log_seq + START 1; + +-- ---------------------------- +-- Table structure for system_dept +-- ---------------------------- +DROP TABLE IF EXISTS system_dept; +CREATE TABLE system_dept +( + id int8 NOT NULL, + name varchar(30) NULL DEFAULT '', + parent_id int8 NOT NULL DEFAULT 0, + sort int4 NOT NULL DEFAULT 0, + leader_user_id int8 NULL DEFAULT NULL, + phone varchar(11) NULL DEFAULT NULL, + email varchar(50) NULL DEFAULT NULL, + status int2 NOT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_dept + ADD CONSTRAINT pk_system_dept PRIMARY KEY (id); + +COMMENT ON COLUMN system_dept.id IS '部门id'; +COMMENT ON COLUMN system_dept.name IS '部门名称'; +COMMENT ON COLUMN system_dept.parent_id IS '父部门id'; +COMMENT ON COLUMN system_dept.sort IS '显示顺序'; +COMMENT ON COLUMN system_dept.leader_user_id IS '负责人'; +COMMENT ON COLUMN system_dept.phone IS '联系电话'; +COMMENT ON COLUMN system_dept.email IS '邮箱'; +COMMENT ON COLUMN system_dept.status IS '部门状态(0正常 1停用)'; +COMMENT ON COLUMN system_dept.creator IS '创建者'; +COMMENT ON COLUMN system_dept.create_time IS '创建时间'; +COMMENT ON COLUMN system_dept.updater IS '更新者'; +COMMENT ON COLUMN system_dept.update_time IS '更新时间'; +COMMENT ON COLUMN system_dept.deleted IS '是否删除'; +COMMENT ON COLUMN system_dept.tenant_id IS '租户编号'; +COMMENT ON TABLE system_dept IS '部门表'; + +-- ---------------------------- +-- Records of system_dept +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO system_dept (id, name, parent_id, sort, leader_user_id, phone, email, status, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (100, '芋道源码', 0, 0, 1, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '1', '2023-11-14 23:30:36', '0', 1); +INSERT INTO system_dept (id, name, parent_id, sort, leader_user_id, phone, email, status, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (101, '深圳总公司', 100, 1, 104, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '1', '2023-12-02 09:53:35', '0', 1); +INSERT INTO system_dept (id, name, parent_id, sort, leader_user_id, phone, email, status, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (102, '长沙分公司', 100, 2, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-12-15 05:01:40', '0', 1); +INSERT INTO system_dept (id, name, parent_id, sort, leader_user_id, phone, email, status, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (103, '研发部门', 101, 1, 104, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '1', '2024-03-24 20:56:04', '0', 1); +INSERT INTO system_dept (id, name, parent_id, sort, leader_user_id, phone, email, status, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (104, '市场部门', 101, 2, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-12-15 05:01:38', '0', 1); +INSERT INTO system_dept (id, name, parent_id, sort, leader_user_id, phone, email, status, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (105, '测试部门', 101, 3, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '1', '2022-05-16 20:25:15', '0', 1); +INSERT INTO system_dept (id, name, parent_id, sort, leader_user_id, phone, email, status, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (106, '财务部门', 101, 4, 103, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '103', '2022-01-15 21:32:22', '0', 1); +INSERT INTO system_dept (id, name, parent_id, sort, leader_user_id, phone, email, status, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (107, '运维部门', 101, 5, 1, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '1', '2023-12-02 09:28:22', '0', 1); +INSERT INTO system_dept (id, name, parent_id, sort, leader_user_id, phone, email, status, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (108, '市场部门', 102, 1, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '1', '2022-02-16 08:35:45', '0', 1); +INSERT INTO system_dept (id, name, parent_id, sort, leader_user_id, phone, email, status, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (109, '财务部门', 102, 2, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-12-15 05:01:29', '0', 1); +INSERT INTO system_dept (id, name, parent_id, sort, leader_user_id, phone, email, status, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (110, '新部门', 0, 1, NULL, NULL, NULL, 0, '110', '2022-02-23 20:46:30', '110', '2022-02-23 20:46:30', '0', 121); +INSERT INTO system_dept (id, name, parent_id, sort, leader_user_id, phone, email, status, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (111, '顶级部门', 0, 1, NULL, NULL, NULL, 0, '113', '2022-03-07 21:44:50', '113', '2022-03-07 21:44:50', '0', 122); +INSERT INTO system_dept (id, name, parent_id, sort, leader_user_id, phone, email, status, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (112, '产品部门', 101, 100, 1, NULL, NULL, 1, '1', '2023-12-02 09:45:13', '1', '2023-12-02 09:45:31', '0', 1); +INSERT INTO system_dept (id, name, parent_id, sort, leader_user_id, phone, email, status, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (113, '支持部门', 102, 3, 104, NULL, NULL, 1, '1', '2023-12-02 09:47:38', '1', '2023-12-02 09:47:38', '0', 1); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS system_dept_seq; +CREATE SEQUENCE system_dept_seq + START 114; + +-- ---------------------------- +-- Table structure for system_dict_data +-- ---------------------------- +DROP TABLE IF EXISTS system_dict_data; +CREATE TABLE system_dict_data +( + id int8 NOT NULL, + sort int4 NOT NULL DEFAULT 0, + label varchar(100) NULL DEFAULT '', + value varchar(100) NULL DEFAULT '', + dict_type varchar(100) NULL DEFAULT '', + status int2 NOT NULL DEFAULT 0, + color_type varchar(100) NULL DEFAULT '', + css_class varchar(100) NULL DEFAULT '', + remark varchar(500) NULL DEFAULT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_dict_data + ADD CONSTRAINT pk_system_dict_data PRIMARY KEY (id); + +COMMENT ON COLUMN system_dict_data.id IS '字典编码'; +COMMENT ON COLUMN system_dict_data.sort IS '字典排序'; +COMMENT ON COLUMN system_dict_data.label IS '字典标签'; +COMMENT ON COLUMN system_dict_data.value IS '字典键值'; +COMMENT ON COLUMN system_dict_data.dict_type IS '字典类型'; +COMMENT ON COLUMN system_dict_data.status IS '状态(0正常 1停用)'; +COMMENT ON COLUMN system_dict_data.color_type IS '颜色类型'; +COMMENT ON COLUMN system_dict_data.css_class IS 'css 样式'; +COMMENT ON COLUMN system_dict_data.remark IS '备注'; +COMMENT ON COLUMN system_dict_data.creator IS '创建者'; +COMMENT ON COLUMN system_dict_data.create_time IS '创建时间'; +COMMENT ON COLUMN system_dict_data.updater IS '更新者'; +COMMENT ON COLUMN system_dict_data.update_time IS '更新时间'; +COMMENT ON COLUMN system_dict_data.deleted IS '是否删除'; +COMMENT ON TABLE system_dict_data IS '字典数据表'; + +-- ---------------------------- +-- Records of system_dict_data +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1, 1, '男', '1', 'system_user_sex', 0, 'default', 'A', '性别男', 'admin', '2021-01-05 17:03:48', '1', '2022-03-29 00:14:39', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (2, 2, '女', '2', 'system_user_sex', 0, 'success', '', '性别女', 'admin', '2021-01-05 17:03:48', '1', '2023-11-15 23:30:37', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (8, 1, '正常', '1', 'infra_job_status', 0, 'success', '', '正常状态', 'admin', '2021-01-05 17:03:48', '1', '2022-02-16 19:33:38', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (9, 2, '暂停', '2', 'infra_job_status', 0, 'danger', '', '停用状态', 'admin', '2021-01-05 17:03:48', '1', '2022-02-16 19:33:45', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (12, 1, '系统内置', '1', 'infra_config_type', 0, 'danger', '', '参数类型 - 系统内置', 'admin', '2021-01-05 17:03:48', '1', '2022-02-16 19:06:02', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (13, 2, '自定义', '2', 'infra_config_type', 0, 'primary', '', '参数类型 - 自定义', 'admin', '2021-01-05 17:03:48', '1', '2022-02-16 19:06:07', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (14, 1, '通知', '1', 'system_notice_type', 0, 'success', '', '通知', 'admin', '2021-01-05 17:03:48', '1', '2022-02-16 13:05:57', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (15, 2, '公告', '2', 'system_notice_type', 0, 'info', '', '公告', 'admin', '2021-01-05 17:03:48', '1', '2022-02-16 13:06:01', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (16, 0, '其它', '0', 'infra_operate_type', 0, 'default', '', '其它操作', 'admin', '2021-01-05 17:03:48', '1', '2024-03-14 12:44:19', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (17, 1, '查询', '1', 'infra_operate_type', 0, 'info', '', '查询操作', 'admin', '2021-01-05 17:03:48', '1', '2024-03-14 12:44:20', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (18, 2, '新增', '2', 'infra_operate_type', 0, 'primary', '', '新增操作', 'admin', '2021-01-05 17:03:48', '1', '2024-03-14 12:44:21', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (19, 3, '修改', '3', 'infra_operate_type', 0, 'warning', '', '修改操作', 'admin', '2021-01-05 17:03:48', '1', '2024-03-14 12:44:22', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (20, 4, '删除', '4', 'infra_operate_type', 0, 'danger', '', '删除操作', 'admin', '2021-01-05 17:03:48', '1', '2024-03-14 12:44:23', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (22, 5, '导出', '5', 'infra_operate_type', 0, 'default', '', '导出操作', 'admin', '2021-01-05 17:03:48', '1', '2024-03-14 12:44:24', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (23, 6, '导入', '6', 'infra_operate_type', 0, 'default', '', '导入操作', 'admin', '2021-01-05 17:03:48', '1', '2024-03-14 12:44:25', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (27, 1, '开启', '0', 'common_status', 0, 'primary', '', '开启状态', 'admin', '2021-01-05 17:03:48', '1', '2022-02-16 08:00:39', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (28, 2, '关闭', '1', 'common_status', 0, 'info', '', '关闭状态', 'admin', '2021-01-05 17:03:48', '1', '2022-02-16 08:00:44', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (29, 1, '目录', '1', 'system_menu_type', 0, '', '', '目录', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:43:45', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (30, 2, '菜单', '2', 'system_menu_type', 0, '', '', '菜单', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:43:41', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (31, 3, '按钮', '3', 'system_menu_type', 0, '', '', '按钮', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:43:39', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (32, 1, '内置', '1', 'system_role_type', 0, 'danger', '', '内置角色', 'admin', '2021-01-05 17:03:48', '1', '2022-02-16 13:02:08', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (33, 2, '自定义', '2', 'system_role_type', 0, 'primary', '', '自定义角色', 'admin', '2021-01-05 17:03:48', '1', '2022-02-16 13:02:12', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (34, 1, '全部数据权限', '1', 'system_data_scope', 0, '', '', '全部数据权限', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:47:17', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (35, 2, '指定部门数据权限', '2', 'system_data_scope', 0, '', '', '指定部门数据权限', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:47:18', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (36, 3, '本部门数据权限', '3', 'system_data_scope', 0, '', '', '本部门数据权限', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:47:16', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (37, 4, '本部门及以下数据权限', '4', 'system_data_scope', 0, '', '', '本部门及以下数据权限', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:47:21', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (38, 5, '仅本人数据权限', '5', 'system_data_scope', 0, '', '', '仅本人数据权限', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:47:23', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (39, 0, '成功', '0', 'system_login_result', 0, 'success', '', '登陆结果 - 成功', '', '2021-01-18 06:17:36', '1', '2022-02-16 13:23:49', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (40, 10, '账号或密码不正确', '10', 'system_login_result', 0, 'primary', '', '登陆结果 - 账号或密码不正确', '', '2021-01-18 06:17:54', '1', '2022-02-16 13:24:27', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (41, 20, '用户被禁用', '20', 'system_login_result', 0, 'warning', '', '登陆结果 - 用户被禁用', '', '2021-01-18 06:17:54', '1', '2022-02-16 13:23:57', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (42, 30, '验证码不存在', '30', 'system_login_result', 0, 'info', '', '登陆结果 - 验证码不存在', '', '2021-01-18 06:17:54', '1', '2022-02-16 13:24:07', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (43, 31, '验证码不正确', '31', 'system_login_result', 0, 'info', '', '登陆结果 - 验证码不正确', '', '2021-01-18 06:17:54', '1', '2022-02-16 13:24:11', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (44, 100, '未知异常', '100', 'system_login_result', 0, 'danger', '', '登陆结果 - 未知异常', '', '2021-01-18 06:17:54', '1', '2022-02-16 13:24:23', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (45, 1, '是', 'true', 'infra_boolean_string', 0, 'danger', '', 'Boolean 是否类型 - 是', '', '2021-01-19 03:20:55', '1', '2022-03-15 23:01:45', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (46, 1, '否', 'false', 'infra_boolean_string', 0, 'info', '', 'Boolean 是否类型 - 否', '', '2021-01-19 03:20:55', '1', '2022-03-15 23:09:45', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (50, 1, '单表(增删改查)', '1', 'infra_codegen_template_type', 0, '', '', NULL, '', '2021-02-05 07:09:06', '', '2022-03-10 16:33:15', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (51, 2, '树表(增删改查)', '2', 'infra_codegen_template_type', 0, '', '', NULL, '', '2021-02-05 07:14:46', '', '2022-03-10 16:33:19', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (53, 0, '初始化中', '0', 'infra_job_status', 0, 'primary', '', NULL, '', '2021-02-07 07:46:49', '1', '2022-02-16 19:33:29', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (57, 0, '运行中', '0', 'infra_job_log_status', 0, 'primary', '', 'RUNNING', '', '2021-02-08 10:04:24', '1', '2022-02-16 19:07:48', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (58, 1, '成功', '1', 'infra_job_log_status', 0, 'success', '', NULL, '', '2021-02-08 10:06:57', '1', '2022-02-16 19:07:52', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (59, 2, '失败', '2', 'infra_job_log_status', 0, 'warning', '', '失败', '', '2021-02-08 10:07:38', '1', '2022-02-16 19:07:56', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (60, 1, '会员', '1', 'user_type', 0, 'primary', '', NULL, '', '2021-02-26 00:16:27', '1', '2022-02-16 10:22:19', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (61, 2, '管理员', '2', 'user_type', 0, 'success', '', NULL, '', '2021-02-26 00:16:34', '1', '2022-02-16 10:22:22', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (62, 0, '未处理', '0', 'infra_api_error_log_process_status', 0, 'primary', '', NULL, '', '2021-02-26 07:07:19', '1', '2022-02-16 20:14:17', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (63, 1, '已处理', '1', 'infra_api_error_log_process_status', 0, 'success', '', NULL, '', '2021-02-26 07:07:26', '1', '2022-02-16 20:14:08', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (64, 2, '已忽略', '2', 'infra_api_error_log_process_status', 0, 'danger', '', NULL, '', '2021-02-26 07:07:34', '1', '2022-02-16 20:14:14', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (66, 2, '阿里云', 'ALIYUN', 'system_sms_channel_code', 0, 'primary', '', NULL, '1', '2021-04-05 01:05:26', '1', '2022-02-16 10:09:52', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (67, 1, '验证码', '1', 'system_sms_template_type', 0, 'warning', '', NULL, '1', '2021-04-05 21:50:57', '1', '2022-02-16 12:48:30', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (68, 2, '通知', '2', 'system_sms_template_type', 0, 'primary', '', NULL, '1', '2021-04-05 21:51:08', '1', '2022-02-16 12:48:27', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (69, 0, '营销', '3', 'system_sms_template_type', 0, 'danger', '', NULL, '1', '2021-04-05 21:51:15', '1', '2022-02-16 12:48:22', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (70, 0, '初始化', '0', 'system_sms_send_status', 0, 'primary', '', NULL, '1', '2021-04-11 20:18:33', '1', '2022-02-16 10:26:07', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (71, 1, '发送成功', '10', 'system_sms_send_status', 0, 'success', '', NULL, '1', '2021-04-11 20:18:43', '1', '2022-02-16 10:25:56', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (72, 2, '发送失败', '20', 'system_sms_send_status', 0, 'danger', '', NULL, '1', '2021-04-11 20:18:49', '1', '2022-02-16 10:26:03', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (73, 3, '不发送', '30', 'system_sms_send_status', 0, 'info', '', NULL, '1', '2021-04-11 20:19:44', '1', '2022-02-16 10:26:10', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (74, 0, '等待结果', '0', 'system_sms_receive_status', 0, 'primary', '', NULL, '1', '2021-04-11 20:27:43', '1', '2022-02-16 10:28:24', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (75, 1, '接收成功', '10', 'system_sms_receive_status', 0, 'success', '', NULL, '1', '2021-04-11 20:29:25', '1', '2022-02-16 10:28:28', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (76, 2, '接收失败', '20', 'system_sms_receive_status', 0, 'danger', '', NULL, '1', '2021-04-11 20:29:31', '1', '2022-02-16 10:28:32', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (77, 0, '调试(钉钉)', 'DEBUG_DING_TALK', 'system_sms_channel_code', 0, 'info', '', NULL, '1', '2021-04-13 00:20:37', '1', '2022-02-16 10:10:00', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (80, 100, '账号登录', '100', 'system_login_type', 0, 'primary', '', '账号登录', '1', '2021-10-06 00:52:02', '1', '2022-02-16 13:11:34', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (81, 101, '社交登录', '101', 'system_login_type', 0, 'info', '', '社交登录', '1', '2021-10-06 00:52:17', '1', '2022-02-16 13:11:40', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (83, 200, '主动登出', '200', 'system_login_type', 0, 'primary', '', '主动登出', '1', '2021-10-06 00:52:58', '1', '2022-02-16 13:11:49', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (85, 202, '强制登出', '202', 'system_login_type', 0, 'danger', '', '强制退出', '1', '2021-10-06 00:53:41', '1', '2022-02-16 13:11:57', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (86, 0, '病假', '1', 'bpm_oa_leave_type', 0, 'primary', '', NULL, '1', '2021-09-21 22:35:28', '1', '2022-02-16 10:00:41', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (87, 1, '事假', '2', 'bpm_oa_leave_type', 0, 'info', '', NULL, '1', '2021-09-21 22:36:11', '1', '2022-02-16 10:00:49', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (88, 2, '婚假', '3', 'bpm_oa_leave_type', 0, 'warning', '', NULL, '1', '2021-09-21 22:36:38', '1', '2022-02-16 10:00:53', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (113, 1, '微信公众号支付', 'wx_pub', 'pay_channel_code', 0, 'success', '', '微信公众号支付', '1', '2021-12-03 10:40:24', '1', '2023-07-19 20:08:47', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (114, 2, '微信小程序支付', 'wx_lite', 'pay_channel_code', 0, 'success', '', '微信小程序支付', '1', '2021-12-03 10:41:06', '1', '2023-07-19 20:08:50', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (115, 3, '微信 App 支付', 'wx_app', 'pay_channel_code', 0, 'success', '', '微信 App 支付', '1', '2021-12-03 10:41:20', '1', '2023-07-19 20:08:56', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (116, 10, '支付宝 PC 网站支付', 'alipay_pc', 'pay_channel_code', 0, 'primary', '', '支付宝 PC 网站支付', '1', '2021-12-03 10:42:09', '1', '2023-07-19 20:09:12', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (117, 11, '支付宝 Wap 网站支付', 'alipay_wap', 'pay_channel_code', 0, 'primary', '', '支付宝 Wap 网站支付', '1', '2021-12-03 10:42:26', '1', '2023-07-19 20:09:16', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (118, 12, '支付宝 App 支付', 'alipay_app', 'pay_channel_code', 0, 'primary', '', '支付宝 App 支付', '1', '2021-12-03 10:42:55', '1', '2023-07-19 20:09:20', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (119, 14, '支付宝扫码支付', 'alipay_qr', 'pay_channel_code', 0, 'primary', '', '支付宝扫码支付', '1', '2021-12-03 10:43:10', '1', '2023-07-19 20:09:28', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (120, 10, '通知成功', '10', 'pay_notify_status', 0, 'success', '', '通知成功', '1', '2021-12-03 11:02:41', '1', '2023-07-19 10:08:19', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (121, 20, '通知失败', '20', 'pay_notify_status', 0, 'danger', '', '通知失败', '1', '2021-12-03 11:02:59', '1', '2023-07-19 10:08:21', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (122, 0, '等待通知', '0', 'pay_notify_status', 0, 'info', '', '未通知', '1', '2021-12-03 11:03:10', '1', '2023-07-19 10:08:24', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (123, 10, '支付成功', '10', 'pay_order_status', 0, 'success', '', '支付成功', '1', '2021-12-03 11:18:29', '1', '2023-07-19 18:04:28', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (124, 30, '支付关闭', '30', 'pay_order_status', 0, 'info', '', '支付关闭', '1', '2021-12-03 11:18:42', '1', '2023-07-19 18:05:07', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (125, 0, '等待支付', '0', 'pay_order_status', 0, 'info', '', '未支付', '1', '2021-12-03 11:18:18', '1', '2023-07-19 18:04:15', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (600, 5, '首页', '1', 'promotion_banner_position', 0, 'warning', '', '', '1', '2023-10-11 07:45:24', '1', '2023-10-11 07:45:38', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (601, 4, '秒杀活动页', '2', 'promotion_banner_position', 0, 'warning', '', '', '1', '2023-10-11 07:45:24', '1', '2023-10-11 07:45:38', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (602, 3, '砍价活动页', '3', 'promotion_banner_position', 0, 'warning', '', '', '1', '2023-10-11 07:45:24', '1', '2023-10-11 07:45:38', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (603, 2, '限时折扣页', '4', 'promotion_banner_position', 0, 'warning', '', '', '1', '2023-10-11 07:45:24', '1', '2023-10-11 07:45:38', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (604, 1, '满减送页', '5', 'promotion_banner_position', 0, 'warning', '', '', '1', '2023-10-11 07:45:24', '1', '2023-10-11 07:45:38', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1118, 0, '等待退款', '0', 'pay_refund_status', 0, 'info', '', '等待退款', '1', '2021-12-10 16:44:59', '1', '2023-07-19 10:14:39', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1119, 20, '退款失败', '20', 'pay_refund_status', 0, 'danger', '', '退款失败', '1', '2021-12-10 16:45:10', '1', '2023-07-19 10:15:10', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1124, 10, '退款成功', '10', 'pay_refund_status', 0, 'success', '', '退款成功', '1', '2021-12-10 16:46:26', '1', '2023-07-19 10:15:00', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1127, 1, '审批中', '1', 'bpm_process_instance_status', 0, 'default', '', '流程实例的状态 - 进行中', '1', '2022-01-07 23:47:22', '1', '2024-03-16 16:11:45', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1128, 2, '审批通过', '2', 'bpm_process_instance_status', 0, 'success', '', '流程实例的状态 - 已完成', '1', '2022-01-07 23:47:49', '1', '2024-03-16 16:11:54', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1129, 1, '审批中', '1', 'bpm_task_status', 0, 'primary', '', '流程实例的结果 - 处理中', '1', '2022-01-07 23:48:32', '1', '2024-03-08 22:41:37', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1130, 2, '审批通过', '2', 'bpm_task_status', 0, 'success', '', '流程实例的结果 - 通过', '1', '2022-01-07 23:48:45', '1', '2024-03-08 22:41:38', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1131, 3, '审批不通过', '3', 'bpm_task_status', 0, 'danger', '', '流程实例的结果 - 不通过', '1', '2022-01-07 23:48:55', '1', '2024-03-08 22:41:38', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1132, 4, '已取消', '4', 'bpm_task_status', 0, 'info', '', '流程实例的结果 - 撤销', '1', '2022-01-07 23:49:06', '1', '2024-03-08 22:41:39', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1133, 10, '流程表单', '10', 'bpm_model_form_type', 0, '', '', '流程的表单类型 - 流程表单', '103', '2022-01-11 23:51:30', '103', '2022-01-11 23:51:30', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1134, 20, '业务表单', '20', 'bpm_model_form_type', 0, '', '', '流程的表单类型 - 业务表单', '103', '2022-01-11 23:51:47', '103', '2022-01-11 23:51:47', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1135, 10, '角色', '10', 'bpm_task_candidate_strategy', 0, 'info', '', '任务分配规则的类型 - 角色', '103', '2022-01-12 23:21:22', '1', '2024-03-06 02:53:16', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1136, 20, '部门的成员', '20', 'bpm_task_candidate_strategy', 0, 'primary', '', '任务分配规则的类型 - 部门的成员', '103', '2022-01-12 23:21:47', '1', '2024-03-06 02:53:17', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1137, 21, '部门的负责人', '21', 'bpm_task_candidate_strategy', 0, 'primary', '', '任务分配规则的类型 - 部门的负责人', '103', '2022-01-12 23:33:36', '1', '2024-03-06 02:53:18', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1138, 30, '用户', '30', 'bpm_task_candidate_strategy', 0, 'info', '', '任务分配规则的类型 - 用户', '103', '2022-01-12 23:34:02', '1', '2024-03-06 02:53:19', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1139, 40, '用户组', '40', 'bpm_task_candidate_strategy', 0, 'warning', '', '任务分配规则的类型 - 用户组', '103', '2022-01-12 23:34:21', '1', '2024-03-06 02:53:20', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1140, 60, '流程表达式', '60', 'bpm_task_candidate_strategy', 0, 'danger', '', '任务分配规则的类型 - 流程表达式', '103', '2022-01-12 23:34:43', '1', '2024-03-06 02:53:20', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1141, 22, '岗位', '22', 'bpm_task_candidate_strategy', 0, 'success', '', '任务分配规则的类型 - 岗位', '103', '2022-01-14 18:41:55', '1', '2024-03-06 02:53:21', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1145, 1, '管理后台', '1', 'infra_codegen_scene', 0, '', '', '代码生成的场景枚举 - 管理后台', '1', '2022-02-02 13:15:06', '1', '2022-03-10 16:32:59', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1146, 2, '用户 APP', '2', 'infra_codegen_scene', 0, '', '', '代码生成的场景枚举 - 用户 APP', '1', '2022-02-02 13:15:19', '1', '2022-03-10 16:33:03', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1150, 1, '数据库', '1', 'infra_file_storage', 0, 'default', '', NULL, '1', '2022-03-15 00:25:28', '1', '2022-03-15 00:25:28', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1151, 10, '本地磁盘', '10', 'infra_file_storage', 0, 'default', '', NULL, '1', '2022-03-15 00:25:41', '1', '2022-03-15 00:25:56', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1152, 11, 'FTP 服务器', '11', 'infra_file_storage', 0, 'default', '', NULL, '1', '2022-03-15 00:26:06', '1', '2022-03-15 00:26:10', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1153, 12, 'SFTP 服务器', '12', 'infra_file_storage', 0, 'default', '', NULL, '1', '2022-03-15 00:26:22', '1', '2022-03-15 00:26:22', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1154, 20, 'S3 对象存储', '20', 'infra_file_storage', 0, 'default', '', NULL, '1', '2022-03-15 00:26:31', '1', '2022-03-15 00:26:45', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1155, 103, '短信登录', '103', 'system_login_type', 0, 'default', '', NULL, '1', '2022-05-09 23:57:58', '1', '2022-05-09 23:58:09', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1156, 1, 'password', 'password', 'system_oauth2_grant_type', 0, 'default', '', '密码模式', '1', '2022-05-12 00:22:05', '1', '2022-05-11 16:26:01', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1157, 2, 'authorization_code', 'authorization_code', 'system_oauth2_grant_type', 0, 'primary', '', '授权码模式', '1', '2022-05-12 00:22:59', '1', '2022-05-11 16:26:02', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1158, 3, 'implicit', 'implicit', 'system_oauth2_grant_type', 0, 'success', '', '简化模式', '1', '2022-05-12 00:23:40', '1', '2022-05-11 16:26:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1159, 4, 'client_credentials', 'client_credentials', 'system_oauth2_grant_type', 0, 'default', '', '客户端模式', '1', '2022-05-12 00:23:51', '1', '2022-05-11 16:26:08', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1160, 5, 'refresh_token', 'refresh_token', 'system_oauth2_grant_type', 0, 'info', '', '刷新模式', '1', '2022-05-12 00:24:02', '1', '2022-05-11 16:26:11', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1162, 1, '销售中', '1', 'product_spu_status', 0, 'success', '', '商品 SPU 状态 - 销售中', '1', '2022-10-24 21:19:47', '1', '2022-10-24 21:20:38', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1163, 0, '仓库中', '0', 'product_spu_status', 0, 'info', '', '商品 SPU 状态 - 仓库中', '1', '2022-10-24 21:20:54', '1', '2022-10-24 21:21:22', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1164, 0, '回收站', '-1', 'product_spu_status', 0, 'default', '', '商品 SPU 状态 - 回收站', '1', '2022-10-24 21:21:11', '1', '2022-10-24 21:21:11', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1165, 1, '满减', '1', 'promotion_discount_type', 0, 'success', '', '优惠类型 - 满减', '1', '2022-11-01 12:46:41', '1', '2022-11-01 12:50:11', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1166, 2, '折扣', '2', 'promotion_discount_type', 0, 'primary', '', '优惠类型 - 折扣', '1', '2022-11-01 12:46:51', '1', '2022-11-01 12:50:08', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1167, 1, '固定日期', '1', 'promotion_coupon_template_validity_type', 0, 'default', '', '优惠劵模板的有限期类型 - 固定日期', '1', '2022-11-02 00:07:34', '1', '2022-11-04 00:07:49', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1168, 2, '领取之后', '2', 'promotion_coupon_template_validity_type', 0, 'default', '', '优惠劵模板的有限期类型 - 领取之后', '1', '2022-11-02 00:07:54', '1', '2022-11-04 00:07:52', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1169, 1, '通用劵', '1', 'promotion_product_scope', 0, 'default', '', '营销的商品范围 - 全部商品参与', '1', '2022-11-02 00:28:22', '1', '2023-09-28 00:27:42', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1170, 2, '商品劵', '2', 'promotion_product_scope', 0, 'default', '', '营销的商品范围 - 指定商品参与', '1', '2022-11-02 00:28:34', '1', '2023-09-28 00:27:44', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1171, 1, '未使用', '1', 'promotion_coupon_status', 0, 'primary', '', '优惠劵的状态 - 已领取', '1', '2022-11-04 00:15:08', '1', '2023-10-03 12:54:38', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1172, 2, '已使用', '2', 'promotion_coupon_status', 0, 'success', '', '优惠劵的状态 - 已使用', '1', '2022-11-04 00:15:21', '1', '2022-11-04 19:16:08', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1173, 3, '已过期', '3', 'promotion_coupon_status', 0, 'info', '', '优惠劵的状态 - 已过期', '1', '2022-11-04 00:15:43', '1', '2022-11-04 19:16:12', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1174, 1, '直接领取', '1', 'promotion_coupon_take_type', 0, 'primary', '', '优惠劵的领取方式 - 直接领取', '1', '2022-11-04 19:13:00', '1', '2022-11-04 19:13:25', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1175, 2, '指定发放', '2', 'promotion_coupon_take_type', 0, 'success', '', '优惠劵的领取方式 - 指定发放', '1', '2022-11-04 19:13:13', '1', '2022-11-04 19:14:48', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1176, 10, '未开始', '10', 'promotion_activity_status', 0, 'primary', '', '促销活动的状态枚举 - 未开始', '1', '2022-11-04 22:54:49', '1', '2022-11-04 22:55:53', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1177, 20, '进行中', '20', 'promotion_activity_status', 0, 'success', '', '促销活动的状态枚举 - 进行中', '1', '2022-11-04 22:55:06', '1', '2022-11-04 22:55:20', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1178, 30, '已结束', '30', 'promotion_activity_status', 0, 'info', '', '促销活动的状态枚举 - 已结束', '1', '2022-11-04 22:55:41', '1', '2022-11-04 22:55:41', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1179, 40, '已关闭', '40', 'promotion_activity_status', 0, 'warning', '', '促销活动的状态枚举 - 已关闭', '1', '2022-11-04 22:56:10', '1', '2022-11-04 22:56:18', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1180, 10, '满 N 元', '10', 'promotion_condition_type', 0, 'primary', '', '营销的条件类型 - 满 N 元', '1', '2022-11-04 22:59:45', '1', '2022-11-04 22:59:45', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1181, 20, '满 N 件', '20', 'promotion_condition_type', 0, 'success', '', '营销的条件类型 - 满 N 件', '1', '2022-11-04 23:00:02', '1', '2022-11-04 23:00:02', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1182, 10, '申请售后', '10', 'trade_after_sale_status', 0, 'primary', '', '交易售后状态 - 申请售后', '1', '2022-11-19 20:53:33', '1', '2022-11-19 20:54:42', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1183, 20, '商品待退货', '20', 'trade_after_sale_status', 0, 'primary', '', '交易售后状态 - 商品待退货', '1', '2022-11-19 20:54:36', '1', '2022-11-19 20:58:58', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1184, 30, '商家待收货', '30', 'trade_after_sale_status', 0, 'primary', '', '交易售后状态 - 商家待收货', '1', '2022-11-19 20:56:56', '1', '2022-11-19 20:59:20', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1185, 40, '等待退款', '40', 'trade_after_sale_status', 0, 'primary', '', '交易售后状态 - 等待退款', '1', '2022-11-19 20:59:54', '1', '2022-11-19 21:00:01', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1186, 50, '退款成功', '50', 'trade_after_sale_status', 0, 'default', '', '交易售后状态 - 退款成功', '1', '2022-11-19 21:00:33', '1', '2022-11-19 21:00:33', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1187, 61, '买家取消', '61', 'trade_after_sale_status', 0, 'info', '', '交易售后状态 - 买家取消', '1', '2022-11-19 21:01:29', '1', '2022-11-19 21:01:29', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1188, 62, '商家拒绝', '62', 'trade_after_sale_status', 0, 'info', '', '交易售后状态 - 商家拒绝', '1', '2022-11-19 21:02:17', '1', '2022-11-19 21:02:17', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1189, 63, '商家拒收货', '63', 'trade_after_sale_status', 0, 'info', '', '交易售后状态 - 商家拒收货', '1', '2022-11-19 21:02:37', '1', '2022-11-19 21:03:07', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1190, 10, '售中退款', '10', 'trade_after_sale_type', 0, 'success', '', '交易售后的类型 - 售中退款', '1', '2022-11-19 21:05:05', '1', '2022-11-19 21:38:23', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1191, 20, '售后退款', '20', 'trade_after_sale_type', 0, 'primary', '', '交易售后的类型 - 售后退款', '1', '2022-11-19 21:05:32', '1', '2022-11-19 21:38:32', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1192, 10, '仅退款', '10', 'trade_after_sale_way', 0, 'primary', '', '交易售后的方式 - 仅退款', '1', '2022-11-19 21:39:19', '1', '2022-11-19 21:39:19', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1193, 20, '退货退款', '20', 'trade_after_sale_way', 0, 'success', '', '交易售后的方式 - 退货退款', '1', '2022-11-19 21:39:38', '1', '2022-11-19 21:39:49', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1194, 10, '微信小程序', '10', 'terminal', 0, 'default', '', '终端 - 微信小程序', '1', '2022-12-10 10:51:11', '1', '2022-12-10 10:51:57', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1195, 20, 'H5 网页', '20', 'terminal', 0, 'default', '', '终端 - H5 网页', '1', '2022-12-10 10:51:30', '1', '2022-12-10 10:51:59', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1196, 11, '微信公众号', '11', 'terminal', 0, 'default', '', '终端 - 微信公众号', '1', '2022-12-10 10:54:16', '1', '2022-12-10 10:52:01', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1197, 31, '苹果 App', '31', 'terminal', 0, 'default', '', '终端 - 苹果 App', '1', '2022-12-10 10:54:42', '1', '2022-12-10 10:52:18', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1198, 32, '安卓 App', '32', 'terminal', 0, 'default', '', '终端 - 安卓 App', '1', '2022-12-10 10:55:02', '1', '2022-12-10 10:59:17', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1199, 0, '普通订单', '0', 'trade_order_type', 0, 'default', '', '交易订单的类型 - 普通订单', '1', '2022-12-10 16:34:14', '1', '2022-12-10 16:34:14', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1200, 1, '秒杀订单', '1', 'trade_order_type', 0, 'default', '', '交易订单的类型 - 秒杀订单', '1', '2022-12-10 16:34:26', '1', '2022-12-10 16:34:26', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1201, 2, '拼团订单', '2', 'trade_order_type', 0, 'default', '', '交易订单的类型 - 拼团订单', '1', '2022-12-10 16:34:36', '1', '2022-12-10 16:34:36', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1202, 3, '砍价订单', '3', 'trade_order_type', 0, 'default', '', '交易订单的类型 - 砍价订单', '1', '2022-12-10 16:34:48', '1', '2022-12-10 16:34:48', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1203, 0, '待支付', '0', 'trade_order_status', 0, 'default', '', '交易订单状态 - 待支付', '1', '2022-12-10 16:49:29', '1', '2022-12-10 16:49:29', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1204, 10, '待发货', '10', 'trade_order_status', 0, 'primary', '', '交易订单状态 - 待发货', '1', '2022-12-10 16:49:53', '1', '2022-12-10 16:51:17', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1205, 20, '已发货', '20', 'trade_order_status', 0, 'primary', '', '交易订单状态 - 已发货', '1', '2022-12-10 16:50:13', '1', '2022-12-10 16:51:31', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1206, 30, '已完成', '30', 'trade_order_status', 0, 'success', '', '交易订单状态 - 已完成', '1', '2022-12-10 16:50:30', '1', '2022-12-10 16:51:06', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1207, 40, '已取消', '40', 'trade_order_status', 0, 'danger', '', '交易订单状态 - 已取消', '1', '2022-12-10 16:50:50', '1', '2022-12-10 16:51:00', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1208, 0, '未售后', '0', 'trade_order_item_after_sale_status', 0, 'info', '', '交易订单项的售后状态 - 未售后', '1', '2022-12-10 20:58:42', '1', '2022-12-10 20:59:29', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1209, 1, '售后中', '1', 'trade_order_item_after_sale_status', 0, 'primary', '', '交易订单项的售后状态 - 售后中', '1', '2022-12-10 20:59:21', '1', '2022-12-10 20:59:21', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1210, 2, '已退款', '2', 'trade_order_item_after_sale_status', 0, 'success', '', '交易订单项的售后状态 - 已退款', '1', '2022-12-10 20:59:46', '1', '2022-12-10 20:59:46', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1211, 1, '完全匹配', '1', 'mp_auto_reply_request_match', 0, 'primary', '', '公众号自动回复的请求关键字匹配模式 - 完全匹配', '1', '2023-01-16 23:30:39', '1', '2023-01-16 23:31:00', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1212, 2, '半匹配', '2', 'mp_auto_reply_request_match', 0, 'success', '', '公众号自动回复的请求关键字匹配模式 - 半匹配', '1', '2023-01-16 23:30:55', '1', '2023-01-16 23:31:10', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1213, 1, '文本', 'text', 'mp_message_type', 0, 'default', '', '公众号的消息类型 - 文本', '1', '2023-01-17 22:17:32', '1', '2023-01-17 22:17:39', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1214, 2, '图片', 'image', 'mp_message_type', 0, 'default', '', '公众号的消息类型 - 图片', '1', '2023-01-17 22:17:32', '1', '2023-01-17 14:19:47', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1215, 3, '语音', 'voice', 'mp_message_type', 0, 'default', '', '公众号的消息类型 - 语音', '1', '2023-01-17 22:17:32', '1', '2023-01-17 14:20:08', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1216, 4, '视频', 'video', 'mp_message_type', 0, 'default', '', '公众号的消息类型 - 视频', '1', '2023-01-17 22:17:32', '1', '2023-01-17 14:21:08', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1217, 5, '小视频', 'shortvideo', 'mp_message_type', 0, 'default', '', '公众号的消息类型 - 小视频', '1', '2023-01-17 22:17:32', '1', '2023-01-17 14:19:59', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1218, 6, '图文', 'news', 'mp_message_type', 0, 'default', '', '公众号的消息类型 - 图文', '1', '2023-01-17 22:17:32', '1', '2023-01-17 14:22:54', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1219, 7, '音乐', 'music', 'mp_message_type', 0, 'default', '', '公众号的消息类型 - 音乐', '1', '2023-01-17 22:17:32', '1', '2023-01-17 14:22:54', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1220, 8, '地理位置', 'location', 'mp_message_type', 0, 'default', '', '公众号的消息类型 - 地理位置', '1', '2023-01-17 22:17:32', '1', '2023-01-17 14:23:51', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1221, 9, '链接', 'link', 'mp_message_type', 0, 'default', '', '公众号的消息类型 - 链接', '1', '2023-01-17 22:17:32', '1', '2023-01-17 14:24:49', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1222, 10, '事件', 'event', 'mp_message_type', 0, 'default', '', '公众号的消息类型 - 事件', '1', '2023-01-17 22:17:32', '1', '2023-01-17 14:24:49', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1223, 0, '初始化', '0', 'system_mail_send_status', 0, 'primary', '', '邮件发送状态 - 初始化\n', '1', '2023-01-26 09:53:49', '1', '2023-01-26 16:36:14', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1224, 10, '发送成功', '10', 'system_mail_send_status', 0, 'success', '', '邮件发送状态 - 发送成功', '1', '2023-01-26 09:54:28', '1', '2023-01-26 16:36:22', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1225, 20, '发送失败', '20', 'system_mail_send_status', 0, 'danger', '', '邮件发送状态 - 发送失败', '1', '2023-01-26 09:54:50', '1', '2023-01-26 16:36:26', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1226, 30, '不发送', '30', 'system_mail_send_status', 0, 'info', '', '邮件发送状态 - 不发送', '1', '2023-01-26 09:55:06', '1', '2023-01-26 16:36:36', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1227, 1, '通知公告', '1', 'system_notify_template_type', 0, 'primary', '', '站内信模版的类型 - 通知公告', '1', '2023-01-28 10:35:59', '1', '2023-01-28 10:35:59', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1228, 2, '系统消息', '2', 'system_notify_template_type', 0, 'success', '', '站内信模版的类型 - 系统消息', '1', '2023-01-28 10:36:20', '1', '2023-01-28 10:36:25', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1230, 13, '支付宝条码支付', 'alipay_bar', 'pay_channel_code', 0, 'primary', '', '支付宝条码支付', '1', '2023-02-18 23:32:24', '1', '2023-07-19 20:09:23', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1231, 10, 'Vue2 Element UI 标准模版', '10', 'infra_codegen_front_type', 0, '', '', '', '1', '2023-04-13 00:03:55', '1', '2023-04-13 00:03:55', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1232, 20, 'Vue3 Element Plus 标准模版', '20', 'infra_codegen_front_type', 0, '', '', '', '1', '2023-04-13 00:04:08', '1', '2023-04-13 00:04:08', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1233, 21, 'Vue3 Element Plus Schema 模版', '21', 'infra_codegen_front_type', 0, '', '', '', '1', '2023-04-13 00:04:26', '1', '2023-04-13 00:04:26', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1234, 30, 'Vue3 vben 模版', '30', 'infra_codegen_front_type', 0, '', '', '', '1', '2023-04-13 00:04:26', '1', '2023-04-13 00:04:26', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1244, 0, '按件', '1', 'trade_delivery_express_charge_mode', 0, '', '', '', '1', '2023-05-21 22:46:40', '1', '2023-05-21 22:46:40', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1245, 1, '按重量', '2', 'trade_delivery_express_charge_mode', 0, '', '', '', '1', '2023-05-21 22:46:58', '1', '2023-05-21 22:46:58', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1246, 2, '按体积', '3', 'trade_delivery_express_charge_mode', 0, '', '', '', '1', '2023-05-21 22:47:18', '1', '2023-05-21 22:47:18', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1335, 11, '订单积分抵扣', '11', 'member_point_biz_type', 0, '', '', '', '1', '2023-06-10 12:15:27', '1', '2023-10-11 07:41:43', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1336, 1, '签到', '1', 'member_point_biz_type', 0, '', '', '', '1', '2023-06-10 12:15:48', '1', '2023-08-20 11:59:53', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1341, 20, '已退款', '20', 'pay_order_status', 0, 'danger', '', '已退款', '1', '2023-07-19 18:05:37', '1', '2023-07-19 18:05:37', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1342, 21, '请求成功,但是结果失败', '21', 'pay_notify_status', 0, 'warning', '', '请求成功,但是结果失败', '1', '2023-07-19 18:10:47', '1', '2023-07-19 18:11:38', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1343, 22, '请求失败', '22', 'pay_notify_status', 0, 'warning', '', NULL, '1', '2023-07-19 18:11:05', '1', '2023-07-19 18:11:27', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1344, 4, '微信扫码支付', 'wx_native', 'pay_channel_code', 0, 'success', '', '微信扫码支付', '1', '2023-07-19 20:07:47', '1', '2023-07-19 20:09:03', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1345, 5, '微信条码支付', 'wx_bar', 'pay_channel_code', 0, 'success', '', '微信条码支付\n', '1', '2023-07-19 20:08:06', '1', '2023-07-19 20:09:08', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1346, 1, '支付单', '1', 'pay_notify_type', 0, 'primary', '', '支付单', '1', '2023-07-20 12:23:17', '1', '2023-07-20 12:23:17', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1347, 2, '退款单', '2', 'pay_notify_type', 0, 'danger', '', NULL, '1', '2023-07-20 12:23:26', '1', '2023-07-20 12:23:26', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1348, 20, '模拟支付', 'mock', 'pay_channel_code', 0, 'default', '', '模拟支付', '1', '2023-07-29 11:10:51', '1', '2023-07-29 03:14:10', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1349, 12, '订单积分抵扣(整单取消)', '12', 'member_point_biz_type', 0, '', '', '', '1', '2023-08-20 12:00:03', '1', '2023-10-11 07:42:01', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1350, 0, '管理员调整', '0', 'member_experience_biz_type', 0, '', '', NULL, '', '2023-08-22 12:41:01', '', '2023-08-22 12:41:01', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1351, 1, '邀新奖励', '1', 'member_experience_biz_type', 0, '', '', NULL, '', '2023-08-22 12:41:01', '', '2023-08-22 12:41:01', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1352, 11, '下单奖励', '11', 'member_experience_biz_type', 0, 'success', '', NULL, '', '2023-08-22 12:41:01', '1', '2023-10-11 07:45:09', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1353, 12, '下单奖励(整单取消)', '12', 'member_experience_biz_type', 0, 'warning', '', NULL, '', '2023-08-22 12:41:01', '1', '2023-10-11 07:45:01', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1354, 4, '签到奖励', '4', 'member_experience_biz_type', 0, '', '', NULL, '', '2023-08-22 12:41:01', '', '2023-08-22 12:41:01', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1355, 5, '抽奖奖励', '5', 'member_experience_biz_type', 0, '', '', NULL, '', '2023-08-22 12:41:01', '', '2023-08-22 12:41:01', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1356, 1, '快递发货', '1', 'trade_delivery_type', 0, '', '', '', '1', '2023-08-23 00:04:55', '1', '2023-08-23 00:04:55', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1357, 2, '用户自提', '2', 'trade_delivery_type', 0, '', '', '', '1', '2023-08-23 00:05:05', '1', '2023-08-23 00:05:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1358, 3, '品类劵', '3', 'promotion_product_scope', 0, 'default', '', '', '1', '2023-09-01 23:43:07', '1', '2023-09-28 00:27:47', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1359, 1, '人人分销', '1', 'brokerage_enabled_condition', 0, '', '', '所有用户都可以分销', '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1360, 2, '指定分销', '2', 'brokerage_enabled_condition', 0, '', '', '仅可后台手动设置推广员', '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1361, 1, '首次绑定', '1', 'brokerage_bind_mode', 0, '', '', '只要用户没有推广人,随时都可以绑定推广关系', '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1362, 2, '注册绑定', '2', 'brokerage_bind_mode', 0, '', '', '仅新用户注册时才能绑定推广关系', '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1363, 3, '覆盖绑定', '3', 'brokerage_bind_mode', 0, '', '', '如果用户已经有推广人,推广人会被变更', '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1364, 1, '钱包', '1', 'brokerage_withdraw_type', 0, '', '', NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1365, 2, '银行卡', '2', 'brokerage_withdraw_type', 0, '', '', NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1366, 3, '微信', '3', 'brokerage_withdraw_type', 0, '', '', NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1367, 4, '支付宝', '4', 'brokerage_withdraw_type', 0, '', '', NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1368, 1, '订单返佣', '1', 'brokerage_record_biz_type', 0, '', '', NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1369, 2, '申请提现', '2', 'brokerage_record_biz_type', 0, '', '', NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1370, 3, '申请提现驳回', '3', 'brokerage_record_biz_type', 0, '', '', NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1371, 0, '待结算', '0', 'brokerage_record_status', 0, '', '', NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1372, 1, '已结算', '1', 'brokerage_record_status', 0, '', '', NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1373, 2, '已取消', '2', 'brokerage_record_status', 0, '', '', NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1374, 0, '审核中', '0', 'brokerage_withdraw_status', 0, '', '', NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1375, 10, '审核通过', '10', 'brokerage_withdraw_status', 0, 'success', '', NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1376, 11, '提现成功', '11', 'brokerage_withdraw_status', 0, 'success', '', NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1377, 20, '审核不通过', '20', 'brokerage_withdraw_status', 0, 'danger', '', NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1378, 21, '提现失败', '21', 'brokerage_withdraw_status', 0, 'danger', '', NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1379, 0, '工商银行', '0', 'brokerage_bank_name', 0, '', '', NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1380, 1, '建设银行', '1', 'brokerage_bank_name', 0, '', '', NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1381, 2, '农业银行', '2', 'brokerage_bank_name', 0, '', '', NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1382, 3, '中国银行', '3', 'brokerage_bank_name', 0, '', '', NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1383, 4, '交通银行', '4', 'brokerage_bank_name', 0, '', '', NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1384, 5, '招商银行', '5', 'brokerage_bank_name', 0, '', '', NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1385, 21, '钱包', 'wallet', 'pay_channel_code', 0, 'primary', '', '', '1', '2023-10-01 21:46:19', '1', '2023-10-01 21:48:01', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1386, 1, '砍价中', '1', 'promotion_bargain_record_status', 0, 'default', '', '', '1', '2023-10-05 10:41:26', '1', '2023-10-05 10:41:26', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1387, 2, '砍价成功', '2', 'promotion_bargain_record_status', 0, 'success', '', '', '1', '2023-10-05 10:41:39', '1', '2023-10-05 10:41:39', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1388, 3, '砍价失败', '3', 'promotion_bargain_record_status', 0, 'warning', '', '', '1', '2023-10-05 10:41:57', '1', '2023-10-05 10:41:57', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1389, 1, '拼团中', '1', 'promotion_combination_record_status', 0, '', '', '', '1', '2023-10-08 07:24:44', '1', '2023-10-08 07:24:44', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1390, 2, '拼团成功', '2', 'promotion_combination_record_status', 0, 'success', '', '', '1', '2023-10-08 07:24:56', '1', '2023-10-08 07:24:56', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1391, 3, '拼团失败', '3', 'promotion_combination_record_status', 0, 'warning', '', '', '1', '2023-10-08 07:25:11', '1', '2023-10-08 07:25:11', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1392, 2, '管理员修改', '2', 'member_point_biz_type', 0, 'default', '', '', '1', '2023-10-11 07:41:34', '1', '2023-10-11 07:41:34', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1393, 13, '订单积分抵扣(单个退款)', '13', 'member_point_biz_type', 0, '', '', '', '1', '2023-10-11 07:42:29', '1', '2023-10-11 07:42:29', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1394, 21, '订单积分奖励', '21', 'member_point_biz_type', 0, 'default', '', '', '1', '2023-10-11 07:42:44', '1', '2023-10-11 07:42:44', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1395, 22, '订单积分奖励(整单取消)', '22', 'member_point_biz_type', 0, 'default', '', '', '1', '2023-10-11 07:42:55', '1', '2023-10-11 07:43:01', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1396, 23, '订单积分奖励(单个退款)', '23', 'member_point_biz_type', 0, 'default', '', '', '1', '2023-10-11 07:43:16', '1', '2023-10-11 07:43:16', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1397, 13, '下单奖励(单个退款)', '13', 'member_experience_biz_type', 0, 'warning', '', '', '1', '2023-10-11 07:45:24', '1', '2023-10-11 07:45:38', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1398, 5, '网上转账', '5', 'crm_receivable_return_type', 0, 'default', '', '', '1', '2023-10-18 21:55:24', '1', '2023-10-18 21:55:24', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1399, 6, '支付宝', '6', 'crm_receivable_return_type', 0, 'default', '', '', '1', '2023-10-18 21:55:38', '1', '2023-10-18 21:55:38', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1400, 7, '微信支付', '7', 'crm_receivable_return_type', 0, 'default', '', '', '1', '2023-10-18 21:55:53', '1', '2023-10-18 21:55:53', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1401, 8, '其他', '8', 'crm_receivable_return_type', 0, 'default', '', '', '1', '2023-10-18 21:56:06', '1', '2023-10-18 21:56:06', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1402, 1, 'IT', '1', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:02:15', '1', '2024-02-18 23:30:38', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1403, 2, '金融业', '2', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:02:29', '1', '2024-02-18 23:30:43', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1404, 3, '房地产', '3', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:02:41', '1', '2024-02-18 23:30:48', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1405, 4, '商业服务', '4', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:02:54', '1', '2024-02-18 23:30:54', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1406, 5, '运输/物流', '5', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:03:03', '1', '2024-02-18 23:31:00', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1407, 6, '生产', '6', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:03:13', '1', '2024-02-18 23:31:08', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1408, 7, '政府', '7', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:03:27', '1', '2024-02-18 23:31:13', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1409, 8, '文化传媒', '8', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:03:37', '1', '2024-02-18 23:31:20', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1422, 1, 'A (重点客户)', '1', 'crm_customer_level', 0, 'primary', '', '', '1', '2023-10-28 23:07:13', '1', '2023-10-28 23:07:13', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1423, 2, 'B (普通客户)', '2', 'crm_customer_level', 0, 'info', '', '', '1', '2023-10-28 23:07:35', '1', '2023-10-28 23:07:35', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1424, 3, 'C (非优先客户)', '3', 'crm_customer_level', 0, 'default', '', '', '1', '2023-10-28 23:07:53', '1', '2023-10-28 23:07:53', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1425, 1, '促销', '1', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:08:29', '1', '2023-10-28 23:08:29', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1426, 2, '搜索引擎', '2', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:08:39', '1', '2023-10-28 23:08:39', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1427, 3, '广告', '3', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:08:47', '1', '2023-10-28 23:08:47', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1428, 4, '转介绍', '4', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:08:58', '1', '2023-10-28 23:08:58', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1429, 5, '线上注册', '5', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:09:12', '1', '2023-10-28 23:09:12', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1430, 6, '线上咨询', '6', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:09:22', '1', '2023-10-28 23:09:22', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1431, 7, '预约上门', '7', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:09:39', '1', '2023-10-28 23:09:39', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1432, 8, '陌拜', '8', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:10:04', '1', '2023-10-28 23:10:04', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1433, 9, '电话咨询', '9', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:10:18', '1', '2023-10-28 23:10:18', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1434, 10, '邮件咨询', '10', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:10:33', '1', '2023-10-28 23:10:33', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1435, 10, 'Gitee', '10', 'system_social_type', 0, '', '', '', '1', '2023-11-04 13:04:42', '1', '2023-11-04 13:04:42', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1436, 20, '钉钉', '20', 'system_social_type', 0, '', '', '', '1', '2023-11-04 13:04:54', '1', '2023-11-04 13:04:54', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1437, 30, '企业微信', '30', 'system_social_type', 0, '', '', '', '1', '2023-11-04 13:05:09', '1', '2023-11-04 13:05:09', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1438, 31, '微信公众平台', '31', 'system_social_type', 0, '', '', '', '1', '2023-11-04 13:05:18', '1', '2023-11-04 13:05:18', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1439, 32, '微信开放平台', '32', 'system_social_type', 0, '', '', '', '1', '2023-11-04 13:05:30', '1', '2023-11-04 13:05:30', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1440, 34, '微信小程序', '34', 'system_social_type', 0, '', '', '', '1', '2023-11-04 13:05:38', '1', '2023-11-04 13:07:16', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1441, 1, '上架', '1', 'crm_product_status', 0, 'success', '', '', '1', '2023-10-30 21:49:34', '1', '2023-10-30 21:49:34', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1442, 0, '下架', '0', 'crm_product_status', 0, 'success', '', '', '1', '2023-10-30 21:49:13', '1', '2023-10-30 21:49:13', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1443, 15, '子表', '15', 'infra_codegen_template_type', 0, 'default', '', '', '1', '2023-11-13 23:06:16', '1', '2023-11-13 23:06:16', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1444, 10, '主表(标准模式)', '10', 'infra_codegen_template_type', 0, 'default', '', '', '1', '2023-11-14 12:32:49', '1', '2023-11-14 12:32:49', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1445, 11, '主表(ERP 模式)', '11', 'infra_codegen_template_type', 0, 'default', '', '', '1', '2023-11-14 12:33:05', '1', '2023-11-14 12:33:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1446, 12, '主表(内嵌模式)', '12', 'infra_codegen_template_type', 0, '', '', '', '1', '2023-11-14 12:33:31', '1', '2023-11-14 12:33:31', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1447, 1, '负责人', '1', 'crm_permission_level', 0, 'default', '', '', '1', '2023-11-30 09:53:12', '1', '2023-11-30 09:53:12', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1448, 2, '只读', '2', 'crm_permission_level', 0, '', '', '', '1', '2023-11-30 09:53:29', '1', '2023-11-30 09:53:29', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1449, 3, '读写', '3', 'crm_permission_level', 0, '', '', '', '1', '2023-11-30 09:53:36', '1', '2023-11-30 09:53:36', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1450, 0, '未提交', '0', 'crm_audit_status', 0, '', '', '', '1', '2023-11-30 18:56:59', '1', '2023-11-30 18:56:59', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1451, 10, '审批中', '10', 'crm_audit_status', 0, '', '', '', '1', '2023-11-30 18:57:10', '1', '2023-11-30 18:57:10', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1452, 20, '审核通过', '20', 'crm_audit_status', 0, '', '', '', '1', '2023-11-30 18:57:24', '1', '2023-11-30 18:57:24', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1453, 30, '审核不通过', '30', 'crm_audit_status', 0, '', '', '', '1', '2023-11-30 18:57:32', '1', '2023-11-30 18:57:32', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1454, 40, '已取消', '40', 'crm_audit_status', 0, '', '', '', '1', '2023-11-30 18:57:42', '1', '2023-11-30 18:57:42', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1456, 1, '支票', '1', 'crm_receivable_return_type', 0, 'default', '', '', '1', '2023-10-18 21:54:29', '1', '2023-10-18 21:54:29', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1457, 2, '现金', '2', 'crm_receivable_return_type', 0, 'default', '', '', '1', '2023-10-18 21:54:41', '1', '2023-10-18 21:54:41', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1458, 3, '邮政汇款', '3', 'crm_receivable_return_type', 0, 'default', '', '', '1', '2023-10-18 21:54:53', '1', '2023-10-18 21:54:53', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1459, 4, '电汇', '4', 'crm_receivable_return_type', 0, 'default', '', '', '1', '2023-10-18 21:55:07', '1', '2023-10-18 21:55:07', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1460, 5, '网上转账', '5', 'crm_receivable_return_type', 0, 'default', '', '', '1', '2023-10-18 21:55:24', '1', '2023-10-18 21:55:24', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1461, 1, '个', '1', 'crm_product_unit', 0, '', '', '', '1', '2023-12-05 23:02:26', '1', '2023-12-05 23:02:26', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1462, 2, '块', '2', 'crm_product_unit', 0, '', '', '', '1', '2023-12-05 23:02:34', '1', '2023-12-05 23:02:34', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1463, 3, '只', '3', 'crm_product_unit', 0, '', '', '', '1', '2023-12-05 23:02:57', '1', '2023-12-05 23:02:57', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1464, 4, '把', '4', 'crm_product_unit', 0, '', '', '', '1', '2023-12-05 23:03:05', '1', '2023-12-05 23:03:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1465, 5, '枚', '5', 'crm_product_unit', 0, '', '', '', '1', '2023-12-05 23:03:14', '1', '2023-12-05 23:03:14', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1466, 6, '瓶', '6', 'crm_product_unit', 0, '', '', '', '1', '2023-12-05 23:03:20', '1', '2023-12-05 23:03:20', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1467, 7, '盒', '7', 'crm_product_unit', 0, '', '', '', '1', '2023-12-05 23:03:30', '1', '2023-12-05 23:03:30', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1468, 8, '台', '8', 'crm_product_unit', 0, '', '', '', '1', '2023-12-05 23:03:41', '1', '2023-12-05 23:03:41', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1469, 9, '吨', '9', 'crm_product_unit', 0, '', '', '', '1', '2023-12-05 23:03:48', '1', '2023-12-05 23:03:48', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1470, 10, '千克', '10', 'crm_product_unit', 0, '', '', '', '1', '2023-12-05 23:04:03', '1', '2023-12-05 23:04:03', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1471, 11, '米', '11', 'crm_product_unit', 0, '', '', '', '1', '2023-12-05 23:04:12', '1', '2023-12-05 23:04:12', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1472, 12, '箱', '12', 'crm_product_unit', 0, '', '', '', '1', '2023-12-05 23:04:25', '1', '2023-12-05 23:04:25', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1473, 13, '套', '13', 'crm_product_unit', 0, '', '', '', '1', '2023-12-05 23:04:34', '1', '2023-12-05 23:04:34', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1474, 1, '打电话', '1', 'crm_follow_up_type', 0, '', '', '', '1', '2024-01-15 20:48:20', '1', '2024-01-15 20:48:20', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1475, 2, '发短信', '2', 'crm_follow_up_type', 0, '', '', '', '1', '2024-01-15 20:48:31', '1', '2024-01-15 20:48:31', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1476, 3, '上门拜访', '3', 'crm_follow_up_type', 0, '', '', '', '1', '2024-01-15 20:49:07', '1', '2024-01-15 20:49:07', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1477, 4, '微信沟通', '4', 'crm_follow_up_type', 0, '', '', '', '1', '2024-01-15 20:49:15', '1', '2024-01-15 20:49:15', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1478, 4, '钱包余额', '4', 'pay_transfer_type', 0, 'info', '', '', '1', '2023-10-28 16:28:37', '1', '2023-10-28 16:28:37', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1479, 3, '银行卡', '3', 'pay_transfer_type', 0, 'default', '', '', '1', '2023-10-28 16:28:21', '1', '2023-10-28 16:28:21', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1480, 2, '微信余额', '2', 'pay_transfer_type', 0, 'info', '', '', '1', '2023-10-28 16:28:07', '1', '2023-10-28 16:28:07', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1481, 1, '支付宝余额', '1', 'pay_transfer_type', 0, 'default', '', '', '1', '2023-10-28 16:27:44', '1', '2023-10-28 16:27:44', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1482, 4, '转账失败', '30', 'pay_transfer_status', 0, 'warning', '', '', '1', '2023-10-28 16:24:16', '1', '2023-10-28 16:24:16', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1483, 3, '转账成功', '20', 'pay_transfer_status', 0, 'success', '', '', '1', '2023-10-28 16:23:50', '1', '2023-10-28 16:23:50', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1484, 2, '转账进行中', '10', 'pay_transfer_status', 0, 'info', '', '', '1', '2023-10-28 16:23:12', '1', '2023-10-28 16:23:12', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1485, 1, '等待转账', '0', 'pay_transfer_status', 0, 'default', '', '', '1', '2023-10-28 16:21:43', '1', '2023-10-28 16:23:22', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1486, 10, '其它入库', '10', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-05 18:07:25', '1', '2024-02-05 18:07:43', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1487, 11, '其它入库(作废)', '11', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-05 18:08:07', '1', '2024-02-05 19:20:16', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1488, 20, '其它出库', '20', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-05 18:08:51', '1', '2024-02-05 18:08:51', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1489, 21, '其它出库(作废)', '21', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-05 18:09:00', '1', '2024-02-05 19:20:10', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1490, 10, '未审核', '10', 'erp_audit_status', 0, 'default', '', '', '1', '2024-02-06 00:00:21', '1', '2024-02-06 00:00:21', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1491, 20, '已审核', '20', 'erp_audit_status', 0, 'success', '', '', '1', '2024-02-06 00:00:35', '1', '2024-02-06 00:00:35', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1492, 30, '调拨入库', '30', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-07 20:34:19', '1', '2024-02-07 12:36:31', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1493, 31, '调拨入库(作废)', '31', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-07 20:34:29', '1', '2024-02-07 20:37:11', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1494, 32, '调拨出库', '32', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-07 20:34:38', '1', '2024-02-07 12:36:33', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1495, 33, '调拨出库(作废)', '33', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-07 20:34:49', '1', '2024-02-07 20:37:06', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1496, 40, '盘盈入库', '40', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-08 08:53:00', '1', '2024-02-08 08:53:09', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1497, 41, '盘盈入库(作废)', '41', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-08 08:53:39', '1', '2024-02-16 19:40:54', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1498, 42, '盘亏出库', '42', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-08 08:54:16', '1', '2024-02-08 08:54:16', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1499, 43, '盘亏出库(作废)', '43', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-08 08:54:31', '1', '2024-02-16 19:40:46', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1500, 50, '销售出库', '50', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-11 21:47:25', '1', '2024-02-11 21:50:40', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1501, 51, '销售出库(作废)', '51', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-11 21:47:37', '1', '2024-02-11 21:51:12', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1502, 60, '销售退货入库', '60', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-12 06:51:05', '1', '2024-02-12 06:51:05', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1503, 61, '销售退货入库(作废)', '61', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-12 06:51:18', '1', '2024-02-12 06:51:18', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1504, 70, '采购入库', '70', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-16 13:10:02', '1', '2024-02-16 13:10:02', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1505, 71, '采购入库(作废)', '71', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-16 13:10:10', '1', '2024-02-16 19:40:40', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1506, 80, '采购退货出库', '80', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-16 13:10:17', '1', '2024-02-16 13:10:17', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1507, 81, '采购退货出库(作废)', '81', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-16 13:10:26', '1', '2024-02-16 19:40:33', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1509, 3, '审批不通过', '3', 'bpm_process_instance_status', 0, 'danger', '', '', '1', '2024-03-16 16:12:06', '1', '2024-03-16 16:12:06', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1510, 4, '已取消', '4', 'bpm_process_instance_status', 0, 'warning', '', '', '1', '2024-03-16 16:12:22', '1', '2024-03-16 16:12:22', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1511, 5, '已退回', '5', 'bpm_task_status', 0, 'warning', '', '', '1', '2024-03-16 19:10:46', '1', '2024-03-08 22:41:40', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1512, 6, '委派中', '6', 'bpm_task_status', 0, 'primary', '', '', '1', '2024-03-17 10:06:22', '1', '2024-03-08 22:41:40', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1513, 7, '审批通过中', '7', 'bpm_task_status', 0, 'success', '', '', '1', '2024-03-17 10:06:47', '1', '2024-03-08 22:41:41', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1514, 0, '待审批', '0', 'bpm_task_status', 0, 'info', '', '', '1', '2024-03-17 10:07:11', '1', '2024-03-08 22:41:42', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1515, 35, '发起人自选', '35', 'bpm_task_candidate_strategy', 0, '', '', '', '1', '2024-03-22 19:45:16', '1', '2024-03-22 19:45:16', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1516, 1, '执行监听器', 'execution', 'bpm_process_listener_type', 0, 'primary', '', '', '1', '2024-03-23 12:54:03', '1', '2024-03-23 19:14:19', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1517, 1, '任务监听器', 'task', 'bpm_process_listener_type', 0, 'success', '', '', '1', '2024-03-23 12:54:13', '1', '2024-03-23 19:14:24', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1526, 1, 'Java 类', 'class', 'bpm_process_listener_value_type', 0, 'primary', '', '', '1', '2024-03-23 15:08:45', '1', '2024-03-23 19:14:32', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1527, 2, '表达式', 'expression', 'bpm_process_listener_value_type', 0, 'success', '', '', '1', '2024-03-23 15:09:06', '1', '2024-03-23 19:14:38', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1528, 3, '代理表达式', 'delegateExpression', 'bpm_process_listener_value_type', 0, 'info', '', '', '1', '2024-03-23 15:11:23', '1', '2024-03-23 19:14:41', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1529, 1, '天', '1', 'date_interval', 0, '', '', '', '1', '2024-03-29 22:50:26', '1', '2024-03-29 22:50:26', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1530, 2, '周', '2', 'date_interval', 0, '', '', '', '1', '2024-03-29 22:50:36', '1', '2024-03-29 22:50:36', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1531, 3, '月', '3', 'date_interval', 0, '', '', '', '1', '2024-03-29 22:50:46', '1', '2024-03-29 22:50:54', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1532, 4, '季度', '4', 'date_interval', 0, '', '', '', '1', '2024-03-29 22:51:01', '1', '2024-03-29 22:51:01', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1533, 5, '年', '5', 'date_interval', 0, '', '', '', '1', '2024-03-29 22:51:07', '1', '2024-03-29 22:51:07', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1534, 1, '赢单', '1', 'crm_business_end_status_type', 0, 'success', '', '', '1', '2024-04-13 23:26:57', '1', '2024-04-13 23:26:57', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1535, 2, '输单', '2', 'crm_business_end_status_type', 0, 'primary', '', '', '1', '2024-04-13 23:27:31', '1', '2024-04-13 23:27:31', '0'); +INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES (1536, 3, '无效', '3', 'crm_business_end_status_type', 0, 'info', '', '', '1', '2024-04-13 23:27:59', '1', '2024-04-13 23:27:59', '0'); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS system_dict_data_seq; +CREATE SEQUENCE system_dict_data_seq + START 1537; + +-- ---------------------------- +-- Table structure for system_dict_type +-- ---------------------------- +DROP TABLE IF EXISTS system_dict_type; +CREATE TABLE system_dict_type +( + id int8 NOT NULL, + name varchar(100) NULL DEFAULT '', + type varchar(100) NULL DEFAULT '', + status int2 NOT NULL DEFAULT 0, + remark varchar(500) NULL DEFAULT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + deleted_time timestamp NULL DEFAULT NULL +); + +ALTER TABLE system_dict_type + ADD CONSTRAINT pk_system_dict_type PRIMARY KEY (id); + +COMMENT ON COLUMN system_dict_type.id IS '字典主键'; +COMMENT ON COLUMN system_dict_type.name IS '字典名称'; +COMMENT ON COLUMN system_dict_type.type IS '字典类型'; +COMMENT ON COLUMN system_dict_type.status IS '状态(0正常 1停用)'; +COMMENT ON COLUMN system_dict_type.remark IS '备注'; +COMMENT ON COLUMN system_dict_type.creator IS '创建者'; +COMMENT ON COLUMN system_dict_type.create_time IS '创建时间'; +COMMENT ON COLUMN system_dict_type.updater IS '更新者'; +COMMENT ON COLUMN system_dict_type.update_time IS '更新时间'; +COMMENT ON COLUMN system_dict_type.deleted IS '是否删除'; +COMMENT ON COLUMN system_dict_type.deleted_time IS '删除时间'; +COMMENT ON TABLE system_dict_type IS '字典类型表'; + +-- ---------------------------- +-- Records of system_dict_type +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (1, '用户性别', 'system_user_sex', 0, NULL, 'admin', '2021-01-05 17:03:48', '1', '2022-05-16 20:29:32', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (6, '参数类型', 'infra_config_type', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:36:54', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (7, '通知类型', 'system_notice_type', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:35:26', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (9, '操作类型', 'infra_operate_type', 0, NULL, 'admin', '2021-01-05 17:03:48', '1', '2024-03-14 12:44:01', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (10, '系统状态', 'common_status', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:21:28', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (11, 'Boolean 是否类型', 'infra_boolean_string', 0, 'boolean 转是否', '', '2021-01-19 03:20:08', '', '2022-02-01 16:37:10', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (104, '登陆结果', 'system_login_result', 0, '登陆结果', '', '2021-01-18 06:17:11', '', '2022-02-01 16:36:00', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (106, '代码生成模板类型', 'infra_codegen_template_type', 0, NULL, '', '2021-02-05 07:08:06', '1', '2022-05-16 20:26:50', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (107, '定时任务状态', 'infra_job_status', 0, NULL, '', '2021-02-07 07:44:16', '', '2022-02-01 16:51:11', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (108, '定时任务日志状态', 'infra_job_log_status', 0, NULL, '', '2021-02-08 10:03:51', '', '2022-02-01 16:50:43', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (109, '用户类型', 'user_type', 0, NULL, '', '2021-02-26 00:15:51', '', '2021-02-26 00:15:51', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (110, 'API 异常数据的处理状态', 'infra_api_error_log_process_status', 0, NULL, '', '2021-02-26 07:07:01', '', '2022-02-01 16:50:53', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (111, '短信渠道编码', 'system_sms_channel_code', 0, NULL, '1', '2021-04-05 01:04:50', '1', '2022-02-16 02:09:08', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (112, '短信模板的类型', 'system_sms_template_type', 0, NULL, '1', '2021-04-05 21:50:43', '1', '2022-02-01 16:35:06', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (113, '短信发送状态', 'system_sms_send_status', 0, NULL, '1', '2021-04-11 20:18:03', '1', '2022-02-01 16:35:09', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (114, '短信接收状态', 'system_sms_receive_status', 0, NULL, '1', '2021-04-11 20:27:14', '1', '2022-02-01 16:35:14', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (116, '登陆日志的类型', 'system_login_type', 0, '登陆日志的类型', '1', '2021-10-06 00:50:46', '1', '2022-02-01 16:35:56', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (117, 'OA 请假类型', 'bpm_oa_leave_type', 0, NULL, '1', '2021-09-21 22:34:33', '1', '2022-01-22 10:41:37', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (130, '支付渠道编码类型', 'pay_channel_code', 0, '支付渠道的编码', '1', '2021-12-03 10:35:08', '1', '2023-07-10 10:11:39', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (131, '支付回调状态', 'pay_notify_status', 0, '支付回调状态(包括退款回调)', '1', '2021-12-03 10:53:29', '1', '2023-07-19 18:09:43', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (132, '支付订单状态', 'pay_order_status', 0, '支付订单状态', '1', '2021-12-03 11:17:50', '1', '2021-12-03 11:17:50', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (134, '退款订单状态', 'pay_refund_status', 0, '退款订单状态', '1', '2021-12-10 16:42:50', '1', '2023-07-19 10:13:17', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (139, '流程实例的状态', 'bpm_process_instance_status', 0, '流程实例的状态', '1', '2022-01-07 23:46:42', '1', '2022-01-07 23:46:42', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (140, '流程实例的结果', 'bpm_task_status', 0, '流程实例的结果', '1', '2022-01-07 23:48:10', '1', '2024-03-08 22:42:03', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (141, '流程的表单类型', 'bpm_model_form_type', 0, '流程的表单类型', '103', '2022-01-11 23:50:45', '103', '2022-01-11 23:50:45', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (142, '任务分配规则的类型', 'bpm_task_candidate_strategy', 0, 'BPM 任务的候选人的策略', '103', '2022-01-12 23:21:04', '103', '2024-03-06 02:53:59', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (144, '代码生成的场景枚举', 'infra_codegen_scene', 0, '代码生成的场景枚举', '1', '2022-02-02 13:14:45', '1', '2022-03-10 16:33:46', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (145, '角色类型', 'system_role_type', 0, '角色类型', '1', '2022-02-16 13:01:46', '1', '2022-02-16 13:01:46', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (146, '文件存储器', 'infra_file_storage', 0, '文件存储器', '1', '2022-03-15 00:24:38', '1', '2022-03-15 00:24:38', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (147, 'OAuth 2.0 授权类型', 'system_oauth2_grant_type', 0, 'OAuth 2.0 授权类型(模式)', '1', '2022-05-12 00:20:52', '1', '2022-05-11 16:25:49', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (149, '商品 SPU 状态', 'product_spu_status', 0, '商品 SPU 状态', '1', '2022-10-24 21:19:04', '1', '2022-10-24 21:19:08', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (150, '优惠类型', 'promotion_discount_type', 0, '优惠类型', '1', '2022-11-01 12:46:06', '1', '2022-11-01 12:46:06', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (151, '优惠劵模板的有限期类型', 'promotion_coupon_template_validity_type', 0, '优惠劵模板的有限期类型', '1', '2022-11-02 00:06:20', '1', '2022-11-04 00:08:26', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (152, '营销的商品范围', 'promotion_product_scope', 0, '营销的商品范围', '1', '2022-11-02 00:28:01', '1', '2022-11-02 00:28:01', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (153, '优惠劵的状态', 'promotion_coupon_status', 0, '优惠劵的状态', '1', '2022-11-04 00:14:49', '1', '2022-11-04 00:14:49', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (154, '优惠劵的领取方式', 'promotion_coupon_take_type', 0, '优惠劵的领取方式', '1', '2022-11-04 19:12:27', '1', '2022-11-04 19:12:27', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (155, '促销活动的状态', 'promotion_activity_status', 0, '促销活动的状态', '1', '2022-11-04 22:54:23', '1', '2022-11-04 22:54:23', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (156, '营销的条件类型', 'promotion_condition_type', 0, '营销的条件类型', '1', '2022-11-04 22:59:23', '1', '2022-11-04 22:59:23', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (157, '交易售后状态', 'trade_after_sale_status', 0, '交易售后状态', '1', '2022-11-19 20:52:56', '1', '2022-11-19 20:52:56', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (158, '交易售后的类型', 'trade_after_sale_type', 0, '交易售后的类型', '1', '2022-11-19 21:04:09', '1', '2022-11-19 21:04:09', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (159, '交易售后的方式', 'trade_after_sale_way', 0, '交易售后的方式', '1', '2022-11-19 21:39:04', '1', '2022-11-19 21:39:04', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (160, '终端', 'terminal', 0, '终端', '1', '2022-12-10 10:50:50', '1', '2022-12-10 10:53:11', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (161, '交易订单的类型', 'trade_order_type', 0, '交易订单的类型', '1', '2022-12-10 16:33:54', '1', '2022-12-10 16:33:54', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (162, '交易订单的状态', 'trade_order_status', 0, '交易订单的状态', '1', '2022-12-10 16:48:44', '1', '2022-12-10 16:48:44', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (163, '交易订单项的售后状态', 'trade_order_item_after_sale_status', 0, '交易订单项的售后状态', '1', '2022-12-10 20:58:08', '1', '2022-12-10 20:58:08', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (164, '公众号自动回复的请求关键字匹配模式', 'mp_auto_reply_request_match', 0, '公众号自动回复的请求关键字匹配模式', '1', '2023-01-16 23:29:56', '1', '2023-01-16 23:29:56', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (165, '公众号的消息类型', 'mp_message_type', 0, '公众号的消息类型', '1', '2023-01-17 22:17:09', '1', '2023-01-17 22:17:09', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (166, '邮件发送状态', 'system_mail_send_status', 0, '邮件发送状态', '1', '2023-01-26 09:53:13', '1', '2023-01-26 09:53:13', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (167, '站内信模版的类型', 'system_notify_template_type', 0, '站内信模版的类型', '1', '2023-01-28 10:35:10', '1', '2023-01-28 10:35:10', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (168, '代码生成的前端类型', 'infra_codegen_front_type', 0, '', '1', '2023-04-12 23:57:52', '1', '2023-04-12 23:57:52', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (170, '快递计费方式', 'trade_delivery_express_charge_mode', 0, '用于商城交易模块配送管理', '1', '2023-05-21 22:45:03', '1', '2023-05-21 22:45:03', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (171, '积分业务类型', 'member_point_biz_type', 0, '', '1', '2023-06-10 12:15:00', '1', '2023-06-28 13:48:20', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (173, '支付通知类型', 'pay_notify_type', 0, NULL, '1', '2023-07-20 12:23:03', '1', '2023-07-20 12:23:03', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (174, '会员经验业务类型', 'member_experience_biz_type', 0, NULL, '', '2023-08-22 12:41:01', '', '2023-08-22 12:41:01', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (175, '交易配送类型', 'trade_delivery_type', 0, '', '1', '2023-08-23 00:03:14', '1', '2023-08-23 00:03:14', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (176, '分佣模式', 'brokerage_enabled_condition', 0, NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (177, '分销关系绑定模式', 'brokerage_bind_mode', 0, NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (178, '佣金提现类型', 'brokerage_withdraw_type', 0, NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (179, '佣金记录业务类型', 'brokerage_record_biz_type', 0, NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (180, '佣金记录状态', 'brokerage_record_status', 0, NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (181, '佣金提现状态', 'brokerage_withdraw_status', 0, NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (182, '佣金提现银行', 'brokerage_bank_name', 0, NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (183, '砍价记录的状态', 'promotion_bargain_record_status', 0, '', '1', '2023-10-05 10:41:08', '1', '2023-10-05 10:41:08', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (184, '拼团记录的状态', 'promotion_combination_record_status', 0, '', '1', '2023-10-08 07:24:25', '1', '2023-10-08 07:24:25', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (185, '回款-回款方式', 'crm_receivable_return_type', 0, '回款-回款方式', '1', '2023-10-18 21:54:10', '1', '2023-10-18 21:54:10', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (186, 'CRM 客户行业', 'crm_customer_industry', 0, 'CRM 客户所属行业', '1', '2023-10-28 22:57:07', '1', '2024-02-18 23:30:22', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (187, '客户等级', 'crm_customer_level', 0, 'CRM 客户等级', '1', '2023-10-28 22:59:12', '1', '2023-10-28 15:11:16', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (188, '客户来源', 'crm_customer_source', 0, 'CRM 客户来源', '1', '2023-10-28 23:00:34', '1', '2023-10-28 15:11:16', '0', NULL); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (600, 'Banner 位置', 'promotion_banner_position', 0, '', '1', '2023-10-08 07:24:25', '1', '2023-11-04 13:04:02', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (601, '社交类型', 'system_social_type', 0, '', '1', '2023-11-04 13:03:54', '1', '2023-11-04 13:03:54', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (604, '产品状态', 'crm_product_status', 0, '', '1', '2023-10-30 21:47:59', '1', '2023-10-30 21:48:45', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (605, 'CRM 数据权限的级别', 'crm_permission_level', 0, '', '1', '2023-11-30 09:51:59', '1', '2023-11-30 09:51:59', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (606, 'CRM 审批状态', 'crm_audit_status', 0, '', '1', '2023-11-30 18:56:23', '1', '2023-11-30 18:56:23', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (607, 'CRM 产品单位', 'crm_product_unit', 0, '', '1', '2023-12-05 23:01:51', '1', '2023-12-05 23:01:51', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (608, 'CRM 跟进方式', 'crm_follow_up_type', 0, '', '1', '2024-01-15 20:48:05', '1', '2024-01-15 20:48:05', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (609, '支付转账类型', 'pay_transfer_type', 0, '', '1', '2023-10-28 16:27:18', '1', '2023-10-28 16:27:18', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (610, '转账订单状态', 'pay_transfer_status', 0, '', '1', '2023-10-28 16:18:32', '1', '2023-10-28 16:18:32', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (611, 'ERP 库存明细的业务类型', 'erp_stock_record_biz_type', 0, 'ERP 库存明细的业务类型', '1', '2024-02-05 18:07:02', '1', '2024-02-05 18:07:02', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (612, 'ERP 审批状态', 'erp_audit_status', 0, '', '1', '2024-02-06 00:00:07', '1', '2024-02-06 00:00:07', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (613, 'BPM 监听器类型', 'bpm_process_listener_type', 0, '', '1', '2024-03-23 12:52:24', '1', '2024-03-09 15:54:28', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (615, 'BPM 监听器值类型', 'bpm_process_listener_value_type', 0, '', '1', '2024-03-23 13:00:31', '1', '2024-03-23 13:00:31', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (616, '时间间隔', 'date_interval', 0, '', '1', '2024-03-29 22:50:09', '1', '2024-03-29 22:50:09', '0', '1970-01-01 00:00:00'); +INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) VALUES (619, 'CRM 商机结束状态类型', 'crm_business_end_status_type', 0, '', '1', '2024-04-13 23:23:00', '1', '2024-04-13 23:23:00', '0', '1970-01-01 00:00:00'); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS system_dict_type_seq; +CREATE SEQUENCE system_dict_type_seq + START 620; + +-- ---------------------------- +-- Table structure for system_login_log +-- ---------------------------- +DROP TABLE IF EXISTS system_login_log; +CREATE TABLE system_login_log +( + id int8 NOT NULL, + log_type int8 NOT NULL, + trace_id varchar(64) NULL DEFAULT '', + user_id int8 NOT NULL DEFAULT 0, + user_type int2 NOT NULL DEFAULT 0, + username varchar(50) NULL DEFAULT '', + result int2 NOT NULL, + user_ip varchar(50) NOT NULL, + user_agent varchar(512) NOT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_login_log + ADD CONSTRAINT pk_system_login_log PRIMARY KEY (id); + +COMMENT ON COLUMN system_login_log.id IS '访问ID'; +COMMENT ON COLUMN system_login_log.log_type IS '日志类型'; +COMMENT ON COLUMN system_login_log.trace_id IS '链路追踪编号'; +COMMENT ON COLUMN system_login_log.user_id IS '用户编号'; +COMMENT ON COLUMN system_login_log.user_type IS '用户类型'; +COMMENT ON COLUMN system_login_log.username IS '用户账号'; +COMMENT ON COLUMN system_login_log.result IS '登陆结果'; +COMMENT ON COLUMN system_login_log.user_ip IS '用户 IP'; +COMMENT ON COLUMN system_login_log.user_agent IS '浏览器 UA'; +COMMENT ON COLUMN system_login_log.creator IS '创建者'; +COMMENT ON COLUMN system_login_log.create_time IS '创建时间'; +COMMENT ON COLUMN system_login_log.updater IS '更新者'; +COMMENT ON COLUMN system_login_log.update_time IS '更新时间'; +COMMENT ON COLUMN system_login_log.deleted IS '是否删除'; +COMMENT ON COLUMN system_login_log.tenant_id IS '租户编号'; +COMMENT ON TABLE system_login_log IS '系统访问记录'; + +DROP SEQUENCE IF EXISTS system_login_log_seq; +CREATE SEQUENCE system_login_log_seq + START 1; + +-- ---------------------------- +-- Table structure for system_mail_account +-- ---------------------------- +DROP TABLE IF EXISTS system_mail_account; +CREATE TABLE system_mail_account +( + id int8 NOT NULL, + mail varchar(255) NOT NULL, + username varchar(255) NOT NULL, + password varchar(255) NOT NULL, + host varchar(255) NOT NULL, + port int4 NOT NULL, + ssl_enable bool NOT NULL DEFAULT '0', + starttls_enable bool NOT NULL DEFAULT '0', + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_mail_account + ADD CONSTRAINT pk_system_mail_account PRIMARY KEY (id); + +COMMENT ON COLUMN system_mail_account.id IS '主键'; +COMMENT ON COLUMN system_mail_account.mail IS '邮箱'; +COMMENT ON COLUMN system_mail_account.username IS '用户名'; +COMMENT ON COLUMN system_mail_account.password IS '密码'; +COMMENT ON COLUMN system_mail_account.host IS 'SMTP 服务器域名'; +COMMENT ON COLUMN system_mail_account.port IS 'SMTP 服务器端口'; +COMMENT ON COLUMN system_mail_account.ssl_enable IS '是否开启 SSL'; +COMMENT ON COLUMN system_mail_account.starttls_enable IS '是否开启 STARTTLS'; +COMMENT ON COLUMN system_mail_account.creator IS '创建者'; +COMMENT ON COLUMN system_mail_account.create_time IS '创建时间'; +COMMENT ON COLUMN system_mail_account.updater IS '更新者'; +COMMENT ON COLUMN system_mail_account.update_time IS '更新时间'; +COMMENT ON COLUMN system_mail_account.deleted IS '是否删除'; +COMMENT ON TABLE system_mail_account IS '邮箱账号表'; + +-- ---------------------------- +-- Records of system_mail_account +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO system_mail_account (id, mail, username, password, host, port, ssl_enable, starttls_enable, creator, create_time, updater, update_time, deleted) VALUES (1, '7684413@qq.com', '7684413@qq.com', '1234576', '127.0.0.1', 8080, '0', '0', '1', '2023-01-25 17:39:52', '1', '2024-04-24 09:13:56', '0'); +INSERT INTO system_mail_account (id, mail, username, password, host, port, ssl_enable, starttls_enable, creator, create_time, updater, update_time, deleted) VALUES (2, 'ydym_test@163.com', 'ydym_test@163.com', 'WBZTEINMIFVRYSOE', 'smtp.163.com', 465, '1', '0', '1', '2023-01-26 01:26:03', '1', '2023-04-12 22:39:38', '0'); +INSERT INTO system_mail_account (id, mail, username, password, host, port, ssl_enable, starttls_enable, creator, create_time, updater, update_time, deleted) VALUES (3, '76854114@qq.com', '3335', '11234', 'yunai1.cn', 466, '0', '0', '1', '2023-01-27 15:06:38', '1', '2023-01-27 07:08:36', '1'); +INSERT INTO system_mail_account (id, mail, username, password, host, port, ssl_enable, starttls_enable, creator, create_time, updater, update_time, deleted) VALUES (4, '7685413x@qq.com', '2', '3', '4', 5, '1', '0', '1', '2023-04-12 23:05:06', '1', '2023-04-12 15:05:11', '1'); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS system_mail_account_seq; +CREATE SEQUENCE system_mail_account_seq + START 5; + +-- ---------------------------- +-- Table structure for system_mail_log +-- ---------------------------- +DROP TABLE IF EXISTS system_mail_log; +CREATE TABLE system_mail_log +( + id int8 NOT NULL, + user_id int8 NULL DEFAULT NULL, + user_type int2 NULL DEFAULT NULL, + to_mail varchar(255) NOT NULL, + account_id int8 NOT NULL, + from_mail varchar(255) NOT NULL, + template_id int8 NOT NULL, + template_code varchar(63) NOT NULL, + template_nickname varchar(255) NULL DEFAULT NULL, + template_title varchar(255) NOT NULL, + template_content varchar(10240) NOT NULL, + template_params varchar(255) NOT NULL, + send_status int2 NOT NULL DEFAULT 0, + send_time timestamp NULL DEFAULT NULL, + send_message_id varchar(255) NULL DEFAULT NULL, + send_exception varchar(4096) NULL DEFAULT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_mail_log + ADD CONSTRAINT pk_system_mail_log PRIMARY KEY (id); + +COMMENT ON COLUMN system_mail_log.id IS '编号'; +COMMENT ON COLUMN system_mail_log.user_id IS '用户编号'; +COMMENT ON COLUMN system_mail_log.user_type IS '用户类型'; +COMMENT ON COLUMN system_mail_log.to_mail IS '接收邮箱地址'; +COMMENT ON COLUMN system_mail_log.account_id IS '邮箱账号编号'; +COMMENT ON COLUMN system_mail_log.from_mail IS '发送邮箱地址'; +COMMENT ON COLUMN system_mail_log.template_id IS '模板编号'; +COMMENT ON COLUMN system_mail_log.template_code IS '模板编码'; +COMMENT ON COLUMN system_mail_log.template_nickname IS '模版发送人名称'; +COMMENT ON COLUMN system_mail_log.template_title IS '邮件标题'; +COMMENT ON COLUMN system_mail_log.template_content IS '邮件内容'; +COMMENT ON COLUMN system_mail_log.template_params IS '邮件参数'; +COMMENT ON COLUMN system_mail_log.send_status IS '发送状态'; +COMMENT ON COLUMN system_mail_log.send_time IS '发送时间'; +COMMENT ON COLUMN system_mail_log.send_message_id IS '发送返回的消息 ID'; +COMMENT ON COLUMN system_mail_log.send_exception IS '发送异常'; +COMMENT ON COLUMN system_mail_log.creator IS '创建者'; +COMMENT ON COLUMN system_mail_log.create_time IS '创建时间'; +COMMENT ON COLUMN system_mail_log.updater IS '更新者'; +COMMENT ON COLUMN system_mail_log.update_time IS '更新时间'; +COMMENT ON COLUMN system_mail_log.deleted IS '是否删除'; +COMMENT ON TABLE system_mail_log IS '邮件日志表'; + +DROP SEQUENCE IF EXISTS system_mail_log_seq; +CREATE SEQUENCE system_mail_log_seq + START 1; + +-- ---------------------------- +-- Table structure for system_mail_template +-- ---------------------------- +DROP TABLE IF EXISTS system_mail_template; +CREATE TABLE system_mail_template +( + id int8 NOT NULL, + name varchar(63) NOT NULL, + code varchar(63) NOT NULL, + account_id int8 NOT NULL, + nickname varchar(255) NULL DEFAULT NULL, + title varchar(255) NOT NULL, + content varchar(10240) NOT NULL, + params varchar(255) NOT NULL, + status int2 NOT NULL, + remark varchar(255) NULL DEFAULT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_mail_template + ADD CONSTRAINT pk_system_mail_template PRIMARY KEY (id); + +COMMENT ON COLUMN system_mail_template.id IS '编号'; +COMMENT ON COLUMN system_mail_template.name IS '模板名称'; +COMMENT ON COLUMN system_mail_template.code IS '模板编码'; +COMMENT ON COLUMN system_mail_template.account_id IS '发送的邮箱账号编号'; +COMMENT ON COLUMN system_mail_template.nickname IS '发送人名称'; +COMMENT ON COLUMN system_mail_template.title IS '模板标题'; +COMMENT ON COLUMN system_mail_template.content IS '模板内容'; +COMMENT ON COLUMN system_mail_template.params IS '参数数组'; +COMMENT ON COLUMN system_mail_template.status IS '开启状态'; +COMMENT ON COLUMN system_mail_template.remark IS '备注'; +COMMENT ON COLUMN system_mail_template.creator IS '创建者'; +COMMENT ON COLUMN system_mail_template.create_time IS '创建时间'; +COMMENT ON COLUMN system_mail_template.updater IS '更新者'; +COMMENT ON COLUMN system_mail_template.update_time IS '更新时间'; +COMMENT ON COLUMN system_mail_template.deleted IS '是否删除'; +COMMENT ON TABLE system_mail_template IS '邮件模版表'; + +-- ---------------------------- +-- Records of system_mail_template +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO system_mail_template (id, name, code, account_id, nickname, title, content, params, status, remark, creator, create_time, updater, update_time, deleted) VALUES (13, '后台用户短信登录', 'admin-sms-login', 1, '奥特曼', '你猜我猜', '

您的验证码是{code},名字是{name}

', '["code","name"]', 0, '3', '1', '2021-10-11 08:10:00', '1', '2023-12-02 19:51:14', '0'); +INSERT INTO system_mail_template (id, name, code, account_id, nickname, title, content, params, status, remark, creator, create_time, updater, update_time, deleted) VALUES (14, '测试模版', 'test_01', 2, '芋艿', '一个标题', '

你是 {key01} 吗?


是的话,赶紧 {key02} 一下!

', '["key01","key02"]', 0, NULL, '1', '2023-01-26 01:27:40', '1', '2023-01-27 10:32:16', '0'); +INSERT INTO system_mail_template (id, name, code, account_id, nickname, title, content, params, status, remark, creator, create_time, updater, update_time, deleted) VALUES (15, '3', '2', 2, '7', '4', '

45

', '[]', 1, '80', '1', '2023-01-27 15:50:35', '1', '2023-01-27 16:34:49', '0'); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS system_mail_template_seq; +CREATE SEQUENCE system_mail_template_seq + START 16; + +-- ---------------------------- +-- Table structure for system_menu +-- ---------------------------- +DROP TABLE IF EXISTS system_menu; +CREATE TABLE system_menu +( + id int8 NOT NULL, + name varchar(50) NOT NULL, + permission varchar(100) NULL DEFAULT '', + type int2 NOT NULL, + sort int4 NOT NULL DEFAULT 0, + parent_id int8 NOT NULL DEFAULT 0, + path varchar(200) NULL DEFAULT '', + icon varchar(100) NULL DEFAULT '#', + component varchar(255) NULL DEFAULT NULL, + component_name varchar(255) NULL DEFAULT NULL, + status int2 NOT NULL DEFAULT 0, + visible bool NOT NULL DEFAULT '1', + keep_alive bool NOT NULL DEFAULT '1', + always_show bool NOT NULL DEFAULT '1', + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_menu + ADD CONSTRAINT pk_system_menu PRIMARY KEY (id); + +COMMENT ON COLUMN system_menu.id IS '菜单ID'; +COMMENT ON COLUMN system_menu.name IS '菜单名称'; +COMMENT ON COLUMN system_menu.permission IS '权限标识'; +COMMENT ON COLUMN system_menu.type IS '菜单类型'; +COMMENT ON COLUMN system_menu.sort IS '显示顺序'; +COMMENT ON COLUMN system_menu.parent_id IS '父菜单ID'; +COMMENT ON COLUMN system_menu.path IS '路由地址'; +COMMENT ON COLUMN system_menu.icon IS '菜单图标'; +COMMENT ON COLUMN system_menu.component IS '组件路径'; +COMMENT ON COLUMN system_menu.component_name IS '组件名'; +COMMENT ON COLUMN system_menu.status IS '菜单状态'; +COMMENT ON COLUMN system_menu.visible IS '是否可见'; +COMMENT ON COLUMN system_menu.keep_alive IS '是否缓存'; +COMMENT ON COLUMN system_menu.always_show IS '是否总是显示'; +COMMENT ON COLUMN system_menu.creator IS '创建者'; +COMMENT ON COLUMN system_menu.create_time IS '创建时间'; +COMMENT ON COLUMN system_menu.updater IS '更新者'; +COMMENT ON COLUMN system_menu.update_time IS '更新时间'; +COMMENT ON COLUMN system_menu.deleted IS '是否删除'; +COMMENT ON TABLE system_menu IS '菜单权限表'; + +-- ---------------------------- +-- Records of system_menu +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1, '系统管理', '', 1, 10, 0, '/system', 'ep:tools', NULL, NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:04:23', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2, '基础设施', '', 1, 20, 0, '/infra', 'ep:monitor', NULL, NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2024-03-01 08:28:40', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (5, 'OA 示例', '', 1, 40, 1185, 'oa', 'fa:road', NULL, NULL, 0, '1', '1', '1', 'admin', '2021-09-20 16:26:19', '1', '2024-02-29 12:38:13', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (100, '用户管理', 'system:user:list', 2, 1, 1, 'user', 'ep:avatar', 'system/user/index', 'SystemUser', 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:02:04', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (101, '角色管理', '', 2, 2, 1, 'role', 'ep:user', 'system/role/index', 'SystemRole', 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:03:28', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (102, '菜单管理', '', 2, 3, 1, 'menu', 'ep:menu', 'system/menu/index', 'SystemMenu', 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:03:50', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (103, '部门管理', '', 2, 4, 1, 'dept', 'fa:address-card', 'system/dept/index', 'SystemDept', 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:06:28', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (104, '岗位管理', '', 2, 5, 1, 'post', 'fa:address-book-o', 'system/post/index', 'SystemPost', 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:06:39', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (105, '字典管理', '', 2, 6, 1, 'dict', 'ep:collection', 'system/dict/index', 'SystemDictType', 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:07:12', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (106, '配置管理', '', 2, 8, 2, 'config', 'fa:connectdevelop', 'infra/config/index', 'InfraConfig', 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2024-04-23 00:02:45', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (107, '通知公告', '', 2, 4, 2739, 'notice', 'ep:takeaway-box', 'system/notice/index', 'SystemNotice', 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2024-04-22 23:56:17', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (108, '审计日志', '', 1, 9, 1, 'log', 'ep:document-copy', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:08:30', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (109, '令牌管理', '', 2, 2, 1261, 'token', 'fa:key', 'system/oauth2/token/index', 'SystemTokenClient', 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:13:48', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (110, '定时任务', '', 2, 7, 2, 'job', 'fa-solid:tasks', 'infra/job/index', 'InfraJob', 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 08:57:36', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (111, 'MySQL 监控', '', 2, 1, 2740, 'druid', 'fa-solid:box', 'infra/druid/index', 'InfraDruid', 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2024-04-23 00:05:58', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (112, 'Java 监控', '', 2, 3, 2740, 'admin-server', 'ep:coffee-cup', 'infra/server/index', 'InfraAdminServer', 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2024-04-23 00:06:57', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (113, 'Redis 监控', '', 2, 2, 2740, 'redis', 'fa:reddit-square', 'infra/redis/index', 'InfraRedis', 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2024-04-23 00:06:09', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (114, '表单构建', 'infra:build:list', 2, 2, 2, 'build', 'fa:wpforms', 'infra/build/index', 'InfraBuild', 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 08:51:35', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (115, '代码生成', 'infra:codegen:query', 2, 1, 2, 'codegen', 'ep:document-copy', 'infra/codegen/index', 'InfraCodegen', 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 08:51:06', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (116, 'API 接口', 'infra:swagger:list', 2, 3, 2, 'swagger', 'fa:fighter-jet', 'infra/swagger/index', 'InfraSwagger', 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2024-04-23 00:01:24', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (500, '操作日志', '', 2, 1, 108, 'operate-log', 'ep:position', 'system/operatelog/index', 'SystemOperateLog', 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:09:59', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (501, '登录日志', '', 2, 2, 108, 'login-log', 'ep:promotion', 'system/loginlog/index', 'SystemLoginLog', 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:10:29', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1001, '用户查询', 'system:user:query', 3, 1, 100, '', '#', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1002, '用户新增', 'system:user:create', 3, 2, 100, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1003, '用户修改', 'system:user:update', 3, 3, 100, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1004, '用户删除', 'system:user:delete', 3, 4, 100, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1005, '用户导出', 'system:user:export', 3, 5, 100, '', '#', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1006, '用户导入', 'system:user:import', 3, 6, 100, '', '#', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1007, '重置密码', 'system:user:update-password', 3, 7, 100, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1008, '角色查询', 'system:role:query', 3, 1, 101, '', '#', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1009, '角色新增', 'system:role:create', 3, 2, 101, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1010, '角色修改', 'system:role:update', 3, 3, 101, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1011, '角色删除', 'system:role:delete', 3, 4, 101, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1012, '角色导出', 'system:role:export', 3, 5, 101, '', '#', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1013, '菜单查询', 'system:menu:query', 3, 1, 102, '', '#', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1014, '菜单新增', 'system:menu:create', 3, 2, 102, '', '#', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1015, '菜单修改', 'system:menu:update', 3, 3, 102, '', '#', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1016, '菜单删除', 'system:menu:delete', 3, 4, 102, '', '#', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1017, '部门查询', 'system:dept:query', 3, 1, 103, '', '#', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1018, '部门新增', 'system:dept:create', 3, 2, 103, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1019, '部门修改', 'system:dept:update', 3, 3, 103, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1020, '部门删除', 'system:dept:delete', 3, 4, 103, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1021, '岗位查询', 'system:post:query', 3, 1, 104, '', '#', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1022, '岗位新增', 'system:post:create', 3, 2, 104, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1023, '岗位修改', 'system:post:update', 3, 3, 104, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1024, '岗位删除', 'system:post:delete', 3, 4, 104, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1025, '岗位导出', 'system:post:export', 3, 5, 104, '', '#', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1026, '字典查询', 'system:dict:query', 3, 1, 105, '#', '#', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1027, '字典新增', 'system:dict:create', 3, 2, 105, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1028, '字典修改', 'system:dict:update', 3, 3, 105, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1029, '字典删除', 'system:dict:delete', 3, 4, 105, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1030, '字典导出', 'system:dict:export', 3, 5, 105, '#', '#', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1031, '配置查询', 'infra:config:query', 3, 1, 106, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1032, '配置新增', 'infra:config:create', 3, 2, 106, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1033, '配置修改', 'infra:config:update', 3, 3, 106, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1034, '配置删除', 'infra:config:delete', 3, 4, 106, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1035, '配置导出', 'infra:config:export', 3, 5, 106, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1036, '公告查询', 'system:notice:query', 3, 1, 107, '#', '#', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1037, '公告新增', 'system:notice:create', 3, 2, 107, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1038, '公告修改', 'system:notice:update', 3, 3, 107, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1039, '公告删除', 'system:notice:delete', 3, 4, 107, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1040, '操作查询', 'system:operate-log:query', 3, 1, 500, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1042, '日志导出', 'system:operate-log:export', 3, 2, 500, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1043, '登录查询', 'system:login-log:query', 3, 1, 501, '#', '#', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1045, '日志导出', 'system:login-log:export', 3, 3, 501, '#', '#', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1046, '令牌列表', 'system:oauth2-token:page', 3, 1, 109, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-05-09 23:54:42', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1048, '令牌删除', 'system:oauth2-token:delete', 3, 2, 109, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-05-09 23:54:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1050, '任务新增', 'infra:job:create', 3, 2, 110, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1051, '任务修改', 'infra:job:update', 3, 3, 110, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1052, '任务删除', 'infra:job:delete', 3, 4, 110, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1053, '状态修改', 'infra:job:update', 3, 5, 110, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1054, '任务导出', 'infra:job:export', 3, 7, 110, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1056, '生成修改', 'infra:codegen:update', 3, 2, 115, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1057, '生成删除', 'infra:codegen:delete', 3, 3, 115, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1058, '导入代码', 'infra:codegen:create', 3, 2, 115, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1059, '预览代码', 'infra:codegen:preview', 3, 4, 115, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1060, '生成代码', 'infra:codegen:download', 3, 5, 115, '', '', '', NULL, 0, '1', '1', '1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1063, '设置角色菜单权限', 'system:permission:assign-role-menu', 3, 6, 101, '', '', '', NULL, 0, '1', '1', '1', '', '2021-01-06 17:53:44', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1064, '设置角色数据权限', 'system:permission:assign-role-data-scope', 3, 7, 101, '', '', '', NULL, 0, '1', '1', '1', '', '2021-01-06 17:56:31', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1065, '设置用户角色', 'system:permission:assign-user-role', 3, 8, 101, '', '', '', NULL, 0, '1', '1', '1', '', '2021-01-07 10:23:28', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1066, '获得 Redis 监控信息', 'infra:redis:get-monitor-info', 3, 1, 113, '', '', '', NULL, 0, '1', '1', '1', '', '2021-01-26 01:02:31', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1067, '获得 Redis Key 列表', 'infra:redis:get-key-list', 3, 2, 113, '', '', '', NULL, 0, '1', '1', '1', '', '2021-01-26 01:02:52', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1070, '代码生成案例', '', 1, 1, 2, 'demo', 'ep:aim', 'infra/testDemo/index', NULL, 0, '1', '1', '1', '', '2021-02-06 12:42:49', '1', '2023-11-15 23:45:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1075, '任务触发', 'infra:job:trigger', 3, 8, 110, '', '', '', NULL, 0, '1', '1', '1', '', '2021-02-07 13:03:10', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1077, '链路追踪', '', 2, 4, 2740, 'skywalking', 'fa:eye', 'infra/skywalking/index', 'InfraSkyWalking', 0, '1', '1', '1', '', '2021-02-08 20:41:31', '1', '2024-04-23 00:07:15', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1078, '访问日志', '', 2, 1, 1083, 'api-access-log', 'ep:place', 'infra/apiAccessLog/index', 'InfraApiAccessLog', 0, '1', '1', '1', '', '2021-02-26 01:32:59', '1', '2024-02-29 08:54:57', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1082, '日志导出', 'infra:api-access-log:export', 3, 2, 1078, '', '', '', NULL, 0, '1', '1', '1', '', '2021-02-26 01:32:59', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1083, 'API 日志', '', 2, 4, 2, 'log', 'fa:tasks', NULL, NULL, 0, '1', '1', '1', '', '2021-02-26 02:18:24', '1', '2024-04-22 23:58:36', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1084, '错误日志', 'infra:api-error-log:query', 2, 2, 1083, 'api-error-log', 'ep:warning-filled', 'infra/apiErrorLog/index', 'InfraApiErrorLog', 0, '1', '1', '1', '', '2021-02-26 07:53:20', '1', '2024-02-29 08:55:17', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1085, '日志处理', 'infra:api-error-log:update-status', 3, 2, 1084, '', '', '', NULL, 0, '1', '1', '1', '', '2021-02-26 07:53:20', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1086, '日志导出', 'infra:api-error-log:export', 3, 3, 1084, '', '', '', NULL, 0, '1', '1', '1', '', '2021-02-26 07:53:20', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1087, '任务查询', 'infra:job:query', 3, 1, 110, '', '', '', NULL, 0, '1', '1', '1', '1', '2021-03-10 01:26:19', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1088, '日志查询', 'infra:api-access-log:query', 3, 1, 1078, '', '', '', NULL, 0, '1', '1', '1', '1', '2021-03-10 01:28:04', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1089, '日志查询', 'infra:api-error-log:query', 3, 1, 1084, '', '', '', NULL, 0, '1', '1', '1', '1', '2021-03-10 01:29:09', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1090, '文件列表', '', 2, 5, 1243, 'file', 'ep:upload-filled', 'infra/file/index', 'InfraFile', 0, '1', '1', '1', '', '2021-03-12 20:16:20', '1', '2024-02-29 08:53:02', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1091, '文件查询', 'infra:file:query', 3, 1, 1090, '', '', '', NULL, 0, '1', '1', '1', '', '2021-03-12 20:16:20', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1092, '文件删除', 'infra:file:delete', 3, 4, 1090, '', '', '', NULL, 0, '1', '1', '1', '', '2021-03-12 20:16:20', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1093, '短信管理', '', 1, 1, 2739, 'sms', 'ep:message', NULL, NULL, 0, '1', '1', '1', '1', '2021-04-05 01:10:16', '1', '2024-04-22 23:56:03', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1094, '短信渠道', '', 2, 0, 1093, 'sms-channel', 'fa:stack-exchange', 'system/sms/channel/index', 'SystemSmsChannel', 0, '1', '1', '1', '', '2021-04-01 11:07:15', '1', '2024-02-29 01:15:54', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1095, '短信渠道查询', 'system:sms-channel:query', 3, 1, 1094, '', '', '', NULL, 0, '1', '1', '1', '', '2021-04-01 11:07:15', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1096, '短信渠道创建', 'system:sms-channel:create', 3, 2, 1094, '', '', '', NULL, 0, '1', '1', '1', '', '2021-04-01 11:07:15', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1097, '短信渠道更新', 'system:sms-channel:update', 3, 3, 1094, '', '', '', NULL, 0, '1', '1', '1', '', '2021-04-01 11:07:15', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1098, '短信渠道删除', 'system:sms-channel:delete', 3, 4, 1094, '', '', '', NULL, 0, '1', '1', '1', '', '2021-04-01 11:07:15', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1100, '短信模板', '', 2, 1, 1093, 'sms-template', 'ep:connection', 'system/sms/template/index', 'SystemSmsTemplate', 0, '1', '1', '1', '', '2021-04-01 17:35:17', '1', '2024-02-29 01:16:18', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1101, '短信模板查询', 'system:sms-template:query', 3, 1, 1100, '', '', '', NULL, 0, '1', '1', '1', '', '2021-04-01 17:35:17', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1102, '短信模板创建', 'system:sms-template:create', 3, 2, 1100, '', '', '', NULL, 0, '1', '1', '1', '', '2021-04-01 17:35:17', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1103, '短信模板更新', 'system:sms-template:update', 3, 3, 1100, '', '', '', NULL, 0, '1', '1', '1', '', '2021-04-01 17:35:17', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1104, '短信模板删除', 'system:sms-template:delete', 3, 4, 1100, '', '', '', NULL, 0, '1', '1', '1', '', '2021-04-01 17:35:17', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1105, '短信模板导出', 'system:sms-template:export', 3, 5, 1100, '', '', '', NULL, 0, '1', '1', '1', '', '2021-04-01 17:35:17', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1106, '发送测试短信', 'system:sms-template:send-sms', 3, 6, 1100, '', '', '', NULL, 0, '1', '1', '1', '1', '2021-04-11 00:26:40', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1107, '短信日志', '', 2, 2, 1093, 'sms-log', 'fa:edit', 'system/sms/log/index', 'SystemSmsLog', 0, '1', '1', '1', '', '2021-04-11 08:37:05', '1', '2024-02-29 08:49:02', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1108, '短信日志查询', 'system:sms-log:query', 3, 1, 1107, '', '', '', NULL, 0, '1', '1', '1', '', '2021-04-11 08:37:05', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1109, '短信日志导出', 'system:sms-log:export', 3, 5, 1107, '', '', '', NULL, 0, '1', '1', '1', '', '2021-04-11 08:37:05', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1117, '支付管理', '', 1, 30, 0, '/pay', 'ep:money', NULL, NULL, 0, '1', '1', '1', '1', '2021-12-25 16:43:41', '1', '2024-02-29 08:58:38', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1118, '请假查询', '', 2, 0, 5, 'leave', 'fa:leanpub', 'bpm/oa/leave/index', 'BpmOALeave', 0, '1', '1', '1', '', '2021-09-20 08:51:03', '1', '2024-02-29 12:38:21', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1119, '请假申请查询', 'bpm:oa-leave:query', 3, 1, 1118, '', '', '', NULL, 0, '1', '1', '1', '', '2021-09-20 08:51:03', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1120, '请假申请创建', 'bpm:oa-leave:create', 3, 2, 1118, '', '', '', NULL, 0, '1', '1', '1', '', '2021-09-20 08:51:03', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1126, '应用信息', '', 2, 1, 1117, 'app', 'fa:apple', 'pay/app/index', 'PayApp', 0, '1', '1', '1', '', '2021-11-10 01:13:30', '1', '2024-02-29 08:59:55', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1127, '支付应用信息查询', 'pay:app:query', 3, 1, 1126, '', '', '', NULL, 0, '1', '1', '1', '', '2021-11-10 01:13:31', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1128, '支付应用信息创建', 'pay:app:create', 3, 2, 1126, '', '', '', NULL, 0, '1', '1', '1', '', '2021-11-10 01:13:31', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1129, '支付应用信息更新', 'pay:app:update', 3, 3, 1126, '', '', '', NULL, 0, '1', '1', '1', '', '2021-11-10 01:13:31', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1130, '支付应用信息删除', 'pay:app:delete', 3, 4, 1126, '', '', '', NULL, 0, '1', '1', '1', '', '2021-11-10 01:13:31', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1132, '秘钥解析', 'pay:channel:parsing', 3, 6, 1129, '', '', '', NULL, 0, '1', '1', '1', '1', '2021-11-08 15:15:47', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1133, '支付商户信息查询', 'pay:merchant:query', 3, 1, 1132, '', '', '', NULL, 0, '1', '1', '1', '', '2021-11-10 01:13:41', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1134, '支付商户信息创建', 'pay:merchant:create', 3, 2, 1132, '', '', '', NULL, 0, '1', '1', '1', '', '2021-11-10 01:13:41', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1135, '支付商户信息更新', 'pay:merchant:update', 3, 3, 1132, '', '', '', NULL, 0, '1', '1', '1', '', '2021-11-10 01:13:41', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1136, '支付商户信息删除', 'pay:merchant:delete', 3, 4, 1132, '', '', '', NULL, 0, '1', '1', '1', '', '2021-11-10 01:13:41', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1137, '支付商户信息导出', 'pay:merchant:export', 3, 5, 1132, '', '', '', NULL, 0, '1', '1', '1', '', '2021-11-10 01:13:41', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1138, '租户列表', '', 2, 0, 1224, 'list', 'ep:house', 'system/tenant/index', 'SystemTenant', 0, '1', '1', '1', '', '2021-12-14 12:31:43', '1', '2024-02-29 01:01:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1139, '租户查询', 'system:tenant:query', 3, 1, 1138, '', '', '', NULL, 0, '1', '1', '1', '', '2021-12-14 12:31:44', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1140, '租户创建', 'system:tenant:create', 3, 2, 1138, '', '', '', NULL, 0, '1', '1', '1', '', '2021-12-14 12:31:44', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1141, '租户更新', 'system:tenant:update', 3, 3, 1138, '', '', '', NULL, 0, '1', '1', '1', '', '2021-12-14 12:31:44', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1142, '租户删除', 'system:tenant:delete', 3, 4, 1138, '', '', '', NULL, 0, '1', '1', '1', '', '2021-12-14 12:31:44', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1143, '租户导出', 'system:tenant:export', 3, 5, 1138, '', '', '', NULL, 0, '1', '1', '1', '', '2021-12-14 12:31:44', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1150, '秘钥解析', '', 3, 6, 1129, '', '', '', NULL, 0, '1', '1', '1', '1', '2021-11-08 15:15:47', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1161, '退款订单', '', 2, 3, 1117, 'refund', 'fa:registered', 'pay/refund/index', 'PayRefund', 0, '1', '1', '1', '', '2021-12-25 08:29:07', '1', '2024-02-29 08:59:20', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1162, '退款订单查询', 'pay:refund:query', 3, 1, 1161, '', '', '', NULL, 0, '1', '1', '1', '', '2021-12-25 08:29:07', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1163, '退款订单创建', 'pay:refund:create', 3, 2, 1161, '', '', '', NULL, 0, '1', '1', '1', '', '2021-12-25 08:29:07', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1164, '退款订单更新', 'pay:refund:update', 3, 3, 1161, '', '', '', NULL, 0, '1', '1', '1', '', '2021-12-25 08:29:07', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1165, '退款订单删除', 'pay:refund:delete', 3, 4, 1161, '', '', '', NULL, 0, '1', '1', '1', '', '2021-12-25 08:29:07', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1166, '退款订单导出', 'pay:refund:export', 3, 5, 1161, '', '', '', NULL, 0, '1', '1', '1', '', '2021-12-25 08:29:07', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1173, '支付订单', '', 2, 2, 1117, 'order', 'fa:cc-paypal', 'pay/order/index', 'PayOrder', 0, '1', '1', '1', '', '2021-12-25 08:49:43', '1', '2024-02-29 08:59:43', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1174, '支付订单查询', 'pay:order:query', 3, 1, 1173, '', '', '', NULL, 0, '1', '1', '1', '', '2021-12-25 08:49:43', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1175, '支付订单创建', 'pay:order:create', 3, 2, 1173, '', '', '', NULL, 0, '1', '1', '1', '', '2021-12-25 08:49:43', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1176, '支付订单更新', 'pay:order:update', 3, 3, 1173, '', '', '', NULL, 0, '1', '1', '1', '', '2021-12-25 08:49:43', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1177, '支付订单删除', 'pay:order:delete', 3, 4, 1173, '', '', '', NULL, 0, '1', '1', '1', '', '2021-12-25 08:49:43', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1178, '支付订单导出', 'pay:order:export', 3, 5, 1173, '', '', '', NULL, 0, '1', '1', '1', '', '2021-12-25 08:49:43', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1185, '工作流程', '', 1, 50, 0, '/bpm', 'fa:medium', NULL, NULL, 0, '1', '1', '1', '1', '2021-12-30 20:26:36', '1', '2024-02-29 12:43:43', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1186, '流程管理', '', 1, 10, 1185, 'manager', 'fa:dedent', NULL, NULL, 0, '1', '1', '1', '1', '2021-12-30 20:28:30', '1', '2024-02-29 12:36:02', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1187, '流程表单', '', 2, 2, 1186, 'form', 'fa:hdd-o', 'bpm/form/index', 'BpmForm', 0, '1', '1', '1', '', '2021-12-30 12:38:22', '1', '2024-03-19 12:25:25', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1188, '表单查询', 'bpm:form:query', 3, 1, 1187, '', '', '', NULL, 0, '1', '1', '1', '', '2021-12-30 12:38:22', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1189, '表单创建', 'bpm:form:create', 3, 2, 1187, '', '', '', NULL, 0, '1', '1', '1', '', '2021-12-30 12:38:22', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1190, '表单更新', 'bpm:form:update', 3, 3, 1187, '', '', '', NULL, 0, '1', '1', '1', '', '2021-12-30 12:38:22', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1191, '表单删除', 'bpm:form:delete', 3, 4, 1187, '', '', '', NULL, 0, '1', '1', '1', '', '2021-12-30 12:38:22', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1192, '表单导出', 'bpm:form:export', 3, 5, 1187, '', '', '', NULL, 0, '1', '1', '1', '', '2021-12-30 12:38:22', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1193, '流程模型', '', 2, 1, 1186, 'model', 'fa-solid:project-diagram', 'bpm/model/index', 'BpmModel', 0, '1', '1', '1', '1', '2021-12-31 23:24:58', '1', '2024-03-19 12:25:19', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1194, '模型查询', 'bpm:model:query', 3, 1, 1193, '', '', '', NULL, 0, '1', '1', '1', '1', '2022-01-03 19:01:10', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1195, '模型创建', 'bpm:model:create', 3, 2, 1193, '', '', '', NULL, 0, '1', '1', '1', '1', '2022-01-03 19:01:24', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1196, '模型导入', 'bpm:model:import', 3, 3, 1193, '', '', '', NULL, 0, '1', '1', '1', '1', '2022-01-03 19:01:35', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1197, '模型更新', 'bpm:model:update', 3, 4, 1193, '', '', '', NULL, 0, '1', '1', '1', '1', '2022-01-03 19:02:28', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1198, '模型删除', 'bpm:model:delete', 3, 5, 1193, '', '', '', NULL, 0, '1', '1', '1', '1', '2022-01-03 19:02:43', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1199, '模型发布', 'bpm:model:deploy', 3, 6, 1193, '', '', '', NULL, 0, '1', '1', '1', '1', '2022-01-03 19:03:24', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1200, '审批中心', '', 2, 20, 1185, 'task', 'fa:tasks', NULL, NULL, 0, '1', '1', '1', '1', '2022-01-07 23:51:48', '1', '2024-03-21 00:33:15', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1201, '我的流程', '', 2, 1, 1200, 'my', 'fa-solid:book', 'bpm/processInstance/index', 'BpmProcessInstanceMy', 0, '1', '1', '1', '', '2022-01-07 15:53:44', '1', '2024-03-21 23:52:12', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1202, '流程实例的查询', 'bpm:process-instance:query', 3, 1, 1201, '', '', '', NULL, 0, '1', '1', '1', '', '2022-01-07 15:53:44', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1207, '待办任务', '', 2, 10, 1200, 'todo', 'fa:slack', 'bpm/task/todo/index', 'BpmTodoTask', 0, '1', '1', '1', '1', '2022-01-08 10:33:37', '1', '2024-02-29 12:37:39', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1208, '已办任务', '', 2, 20, 1200, 'done', 'fa:delicious', 'bpm/task/done/index', 'BpmDoneTask', 0, '1', '1', '1', '1', '2022-01-08 10:34:13', '1', '2024-02-29 12:37:54', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1209, '用户分组', '', 2, 4, 1186, 'user-group', 'fa:user-secret', 'bpm/group/index', 'BpmUserGroup', 0, '1', '1', '1', '', '2022-01-14 02:14:20', '1', '2024-03-21 23:55:29', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1210, '用户组查询', 'bpm:user-group:query', 3, 1, 1209, '', '', '', NULL, 0, '1', '1', '1', '', '2022-01-14 02:14:20', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1211, '用户组创建', 'bpm:user-group:create', 3, 2, 1209, '', '', '', NULL, 0, '1', '1', '1', '', '2022-01-14 02:14:20', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1212, '用户组更新', 'bpm:user-group:update', 3, 3, 1209, '', '', '', NULL, 0, '1', '1', '1', '', '2022-01-14 02:14:20', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1213, '用户组删除', 'bpm:user-group:delete', 3, 4, 1209, '', '', '', NULL, 0, '1', '1', '1', '', '2022-01-14 02:14:20', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1215, '流程定义查询', 'bpm:process-definition:query', 3, 10, 1193, '', '', '', NULL, 0, '1', '1', '1', '1', '2022-01-23 00:21:43', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1216, '流程任务分配规则查询', 'bpm:task-assign-rule:query', 3, 20, 1193, '', '', '', NULL, 0, '1', '1', '1', '1', '2022-01-23 00:26:53', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1217, '流程任务分配规则创建', 'bpm:task-assign-rule:create', 3, 21, 1193, '', '', '', NULL, 0, '1', '1', '1', '1', '2022-01-23 00:28:15', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1218, '流程任务分配规则更新', 'bpm:task-assign-rule:update', 3, 22, 1193, '', '', '', NULL, 0, '1', '1', '1', '1', '2022-01-23 00:28:41', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1219, '流程实例的创建', 'bpm:process-instance:create', 3, 2, 1201, '', '', '', NULL, 0, '1', '1', '1', '1', '2022-01-23 00:36:15', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1220, '流程实例的取消', 'bpm:process-instance:cancel', 3, 3, 1201, '', '', '', NULL, 0, '1', '1', '1', '1', '2022-01-23 00:36:33', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1221, '流程任务的查询', 'bpm:task:query', 3, 1, 1207, '', '', '', NULL, 0, '1', '1', '1', '1', '2022-01-23 00:38:52', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1222, '流程任务的更新', 'bpm:task:update', 3, 2, 1207, '', '', '', NULL, 0, '1', '1', '1', '1', '2022-01-23 00:39:24', '1', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1224, '租户管理', '', 2, 0, 1, 'tenant', 'fa-solid:house-user', NULL, NULL, 0, '1', '1', '1', '1', '2022-02-20 01:41:13', '1', '2024-02-29 00:59:29', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1225, '租户套餐', '', 2, 0, 1224, 'package', 'fa:bars', 'system/tenantPackage/index', 'SystemTenantPackage', 0, '1', '1', '1', '', '2022-02-19 17:44:06', '1', '2024-02-29 01:01:43', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1226, '租户套餐查询', 'system:tenant-package:query', 3, 1, 1225, '', '', '', NULL, 0, '1', '1', '1', '', '2022-02-19 17:44:06', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1227, '租户套餐创建', 'system:tenant-package:create', 3, 2, 1225, '', '', '', NULL, 0, '1', '1', '1', '', '2022-02-19 17:44:06', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1228, '租户套餐更新', 'system:tenant-package:update', 3, 3, 1225, '', '', '', NULL, 0, '1', '1', '1', '', '2022-02-19 17:44:06', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1229, '租户套餐删除', 'system:tenant-package:delete', 3, 4, 1225, '', '', '', NULL, 0, '1', '1', '1', '', '2022-02-19 17:44:06', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1237, '文件配置', '', 2, 0, 1243, 'file-config', 'fa-solid:file-signature', 'infra/fileConfig/index', 'InfraFileConfig', 0, '1', '1', '1', '', '2022-03-15 14:35:28', '1', '2024-02-29 08:52:54', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1238, '文件配置查询', 'infra:file-config:query', 3, 1, 1237, '', '', '', NULL, 0, '1', '1', '1', '', '2022-03-15 14:35:28', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1239, '文件配置创建', 'infra:file-config:create', 3, 2, 1237, '', '', '', NULL, 0, '1', '1', '1', '', '2022-03-15 14:35:28', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1240, '文件配置更新', 'infra:file-config:update', 3, 3, 1237, '', '', '', NULL, 0, '1', '1', '1', '', '2022-03-15 14:35:28', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1241, '文件配置删除', 'infra:file-config:delete', 3, 4, 1237, '', '', '', NULL, 0, '1', '1', '1', '', '2022-03-15 14:35:28', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1242, '文件配置导出', 'infra:file-config:export', 3, 5, 1237, '', '', '', NULL, 0, '1', '1', '1', '', '2022-03-15 14:35:28', '', '2022-04-20 17:03:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1243, '文件管理', '', 2, 6, 2, 'file', 'ep:files', NULL, '', 0, '1', '1', '1', '1', '2022-03-16 23:47:40', '1', '2024-04-23 00:02:11', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1254, '作者动态', '', 1, 0, 0, 'https://www.iocoder.cn', 'ep:avatar', NULL, NULL, 0, '1', '1', '1', '1', '2022-04-23 01:03:15', '1', '2023-12-08 23:40:01', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1255, '数据源配置', '', 2, 1, 2, 'data-source-config', 'ep:data-analysis', 'infra/dataSourceConfig/index', 'InfraDataSourceConfig', 0, '1', '1', '1', '', '2022-04-27 14:37:32', '1', '2024-02-29 08:51:25', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1256, '数据源配置查询', 'infra:data-source-config:query', 3, 1, 1255, '', '', '', NULL, 0, '1', '1', '1', '', '2022-04-27 14:37:32', '', '2022-04-27 14:37:32', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1257, '数据源配置创建', 'infra:data-source-config:create', 3, 2, 1255, '', '', '', NULL, 0, '1', '1', '1', '', '2022-04-27 14:37:32', '', '2022-04-27 14:37:32', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1258, '数据源配置更新', 'infra:data-source-config:update', 3, 3, 1255, '', '', '', NULL, 0, '1', '1', '1', '', '2022-04-27 14:37:32', '', '2022-04-27 14:37:32', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1259, '数据源配置删除', 'infra:data-source-config:delete', 3, 4, 1255, '', '', '', NULL, 0, '1', '1', '1', '', '2022-04-27 14:37:32', '', '2022-04-27 14:37:32', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1260, '数据源配置导出', 'infra:data-source-config:export', 3, 5, 1255, '', '', '', NULL, 0, '1', '1', '1', '', '2022-04-27 14:37:32', '', '2022-04-27 14:37:32', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1261, 'OAuth 2.0', '', 2, 10, 1, 'oauth2', 'fa:dashcube', NULL, NULL, 0, '1', '1', '1', '1', '2022-05-09 23:38:17', '1', '2024-02-29 01:12:08', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1263, '应用管理', '', 2, 0, 1261, 'oauth2/application', 'fa:hdd-o', 'system/oauth2/client/index', 'SystemOAuth2Client', 0, '1', '1', '1', '', '2022-05-10 16:26:33', '1', '2024-02-29 01:13:14', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1264, '客户端查询', 'system:oauth2-client:query', 3, 1, 1263, '', '', '', NULL, 0, '1', '1', '1', '', '2022-05-10 16:26:33', '1', '2022-05-11 00:31:06', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1265, '客户端创建', 'system:oauth2-client:create', 3, 2, 1263, '', '', '', NULL, 0, '1', '1', '1', '', '2022-05-10 16:26:33', '1', '2022-05-11 00:31:23', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1266, '客户端更新', 'system:oauth2-client:update', 3, 3, 1263, '', '', '', NULL, 0, '1', '1', '1', '', '2022-05-10 16:26:33', '1', '2022-05-11 00:31:28', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1267, '客户端删除', 'system:oauth2-client:delete', 3, 4, 1263, '', '', '', NULL, 0, '1', '1', '1', '', '2022-05-10 16:26:33', '1', '2022-05-11 00:31:33', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1281, '报表管理', '', 2, 40, 0, '/report', 'ep:pie-chart', NULL, NULL, 0, '1', '1', '1', '1', '2022-07-10 20:22:15', '1', '2024-02-29 12:33:03', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (1282, '报表设计器', '', 2, 1, 1281, 'jimu-report', 'ep:trend-charts', 'report/jmreport/index', 'GoView', 0, '1', '1', '1', '1', '2022-07-10 20:26:36', '1', '2024-02-29 12:33:54', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2000, '商品中心', '', 1, 60, 2362, 'product', 'fa:product-hunt', NULL, NULL, 0, '1', '1', '1', '', '2022-07-29 15:53:53', '1', '2023-09-30 11:52:36', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2002, '商品分类', '', 2, 2, 2000, 'category', 'ep:cellphone', 'mall/product/category/index', 'ProductCategory', 0, '1', '1', '1', '', '2022-07-29 15:53:53', '1', '2023-08-21 10:27:15', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2003, '分类查询', 'product:category:query', 3, 1, 2002, '', '', '', NULL, 0, '1', '1', '1', '', '2022-07-29 15:53:53', '', '2022-07-29 15:53:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2004, '分类创建', 'product:category:create', 3, 2, 2002, '', '', '', NULL, 0, '1', '1', '1', '', '2022-07-29 15:53:53', '', '2022-07-29 15:53:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2005, '分类更新', 'product:category:update', 3, 3, 2002, '', '', '', NULL, 0, '1', '1', '1', '', '2022-07-29 15:53:53', '', '2022-07-29 15:53:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2006, '分类删除', 'product:category:delete', 3, 4, 2002, '', '', '', NULL, 0, '1', '1', '1', '', '2022-07-29 15:53:53', '', '2022-07-29 15:53:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2008, '商品品牌', '', 2, 3, 2000, 'brand', 'ep:chicken', 'mall/product/brand/index', 'ProductBrand', 0, '1', '1', '1', '', '2022-07-30 13:52:44', '1', '2023-08-21 10:27:28', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2009, '品牌查询', 'product:brand:query', 3, 1, 2008, '', '', '', NULL, 0, '1', '1', '1', '', '2022-07-30 13:52:44', '', '2022-07-30 13:52:44', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2010, '品牌创建', 'product:brand:create', 3, 2, 2008, '', '', '', NULL, 0, '1', '1', '1', '', '2022-07-30 13:52:44', '', '2022-07-30 13:52:44', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2011, '品牌更新', 'product:brand:update', 3, 3, 2008, '', '', '', NULL, 0, '1', '1', '1', '', '2022-07-30 13:52:44', '', '2022-07-30 13:52:44', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2012, '品牌删除', 'product:brand:delete', 3, 4, 2008, '', '', '', NULL, 0, '1', '1', '1', '', '2022-07-30 13:52:44', '', '2022-07-30 13:52:44', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2014, '商品列表', '', 2, 1, 2000, 'spu', 'ep:apple', 'mall/product/spu/index', 'ProductSpu', 0, '1', '1', '1', '', '2022-07-30 14:22:58', '1', '2023-08-21 10:27:01', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2015, '商品查询', 'product:spu:query', 3, 1, 2014, '', '', '', NULL, 0, '1', '1', '1', '', '2022-07-30 14:22:58', '', '2022-07-30 14:22:58', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2016, '商品创建', 'product:spu:create', 3, 2, 2014, '', '', '', NULL, 0, '1', '1', '1', '', '2022-07-30 14:22:58', '', '2022-07-30 14:22:58', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2017, '商品更新', 'product:spu:update', 3, 3, 2014, '', '', '', NULL, 0, '1', '1', '1', '', '2022-07-30 14:22:58', '', '2022-07-30 14:22:58', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2018, '商品删除', 'product:spu:delete', 3, 4, 2014, '', '', '', NULL, 0, '1', '1', '1', '', '2022-07-30 14:22:58', '', '2022-07-30 14:22:58', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2019, '商品属性', '', 2, 4, 2000, 'property', 'ep:cold-drink', 'mall/product/property/index', 'ProductProperty', 0, '1', '1', '1', '', '2022-08-01 14:55:35', '1', '2023-08-26 11:01:05', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2020, '规格查询', 'product:property:query', 3, 1, 2019, '', '', '', NULL, 0, '1', '1', '1', '', '2022-08-01 14:55:35', '', '2022-12-12 20:26:24', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2021, '规格创建', 'product:property:create', 3, 2, 2019, '', '', '', NULL, 0, '1', '1', '1', '', '2022-08-01 14:55:35', '', '2022-12-12 20:26:30', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2022, '规格更新', 'product:property:update', 3, 3, 2019, '', '', '', NULL, 0, '1', '1', '1', '', '2022-08-01 14:55:35', '', '2022-12-12 20:26:33', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2023, '规格删除', 'product:property:delete', 3, 4, 2019, '', '', '', NULL, 0, '1', '1', '1', '', '2022-08-01 14:55:35', '', '2022-12-12 20:26:37', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2025, 'Banner', '', 2, 100, 2387, 'banner', 'fa:bandcamp', 'mall/promotion/banner/index', NULL, 0, '1', '1', '1', '', '2022-08-01 14:56:14', '1', '2023-10-24 20:20:06', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2026, 'Banner查询', 'promotion:banner:query', 3, 1, 2025, '', '', '', '', 0, '1', '1', '1', '', '2022-08-01 14:56:14', '1', '2023-10-24 20:20:18', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2027, 'Banner创建', 'promotion:banner:create', 3, 2, 2025, '', '', '', '', 0, '1', '1', '1', '', '2022-08-01 14:56:14', '1', '2023-10-24 20:20:23', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2028, 'Banner更新', 'promotion:banner:update', 3, 3, 2025, '', '', '', '', 0, '1', '1', '1', '', '2022-08-01 14:56:14', '1', '2023-10-24 20:20:28', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2029, 'Banner删除', 'promotion:banner:delete', 3, 4, 2025, '', '', '', '', 0, '1', '1', '1', '', '2022-08-01 14:56:14', '1', '2023-10-24 20:20:36', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2030, '营销中心', '', 1, 70, 2362, 'promotion', 'ep:present', NULL, NULL, 0, '1', '1', '1', '1', '2022-10-31 21:25:09', '1', '2023-09-30 11:54:27', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2032, '优惠劵列表', '', 2, 1, 2365, 'template', 'ep:discount', 'mall/promotion/coupon/template/index', 'PromotionCouponTemplate', 0, '1', '1', '1', '', '2022-10-31 22:27:14', '1', '2023-10-03 12:40:06', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2033, '优惠劵模板查询', 'promotion:coupon-template:query', 3, 1, 2032, '', '', '', NULL, 0, '1', '1', '1', '', '2022-10-31 22:27:14', '', '2022-10-31 22:27:14', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2034, '优惠劵模板创建', 'promotion:coupon-template:create', 3, 2, 2032, '', '', '', NULL, 0, '1', '1', '1', '', '2022-10-31 22:27:14', '', '2022-10-31 22:27:14', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2035, '优惠劵模板更新', 'promotion:coupon-template:update', 3, 3, 2032, '', '', '', NULL, 0, '1', '1', '1', '', '2022-10-31 22:27:14', '', '2022-10-31 22:27:14', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2036, '优惠劵模板删除', 'promotion:coupon-template:delete', 3, 4, 2032, '', '', '', NULL, 0, '1', '1', '1', '', '2022-10-31 22:27:14', '', '2022-10-31 22:27:14', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2038, '领取记录', '', 2, 2, 2365, 'list', 'ep:collection-tag', 'mall/promotion/coupon/index', 'PromotionCoupon', 0, '1', '1', '1', '', '2022-11-03 23:21:31', '1', '2023-10-03 12:55:30', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2039, '优惠劵查询', 'promotion:coupon:query', 3, 1, 2038, '', '', '', NULL, 0, '1', '1', '1', '', '2022-11-03 23:21:31', '', '2022-11-03 23:21:31', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2040, '优惠劵删除', 'promotion:coupon:delete', 3, 4, 2038, '', '', '', NULL, 0, '1', '1', '1', '', '2022-11-03 23:21:31', '', '2022-11-03 23:21:31', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2041, '满减送', '', 2, 10, 2390, 'reward-activity', 'ep:goblet-square-full', 'mall/promotion/rewardActivity/index', 'PromotionRewardActivity', 0, '1', '1', '1', '', '2022-11-04 23:47:49', '1', '2023-10-21 19:24:46', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2042, '满减送活动查询', 'promotion:reward-activity:query', 3, 1, 2041, '', '', '', NULL, 0, '1', '1', '1', '', '2022-11-04 23:47:49', '', '2022-11-04 23:47:49', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2043, '满减送活动创建', 'promotion:reward-activity:create', 3, 2, 2041, '', '', '', NULL, 0, '1', '1', '1', '', '2022-11-04 23:47:49', '', '2022-11-04 23:47:49', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2044, '满减送活动更新', 'promotion:reward-activity:update', 3, 3, 2041, '', '', '', NULL, 0, '1', '1', '1', '', '2022-11-04 23:47:50', '', '2022-11-04 23:47:50', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2045, '满减送活动删除', 'promotion:reward-activity:delete', 3, 4, 2041, '', '', '', NULL, 0, '1', '1', '1', '', '2022-11-04 23:47:50', '', '2022-11-04 23:47:50', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2046, '满减送活动关闭', 'promotion:reward-activity:close', 3, 5, 2041, '', '', '', NULL, 0, '1', '1', '1', '1', '2022-11-05 10:42:53', '1', '2022-11-05 10:42:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2047, '限时折扣', '', 2, 7, 2390, 'discount-activity', 'ep:timer', 'mall/promotion/discountActivity/index', 'PromotionDiscountActivity', 0, '1', '1', '1', '', '2022-11-05 17:12:15', '1', '2023-10-21 19:24:21', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2048, '限时折扣活动查询', 'promotion:discount-activity:query', 3, 1, 2047, '', '', '', NULL, 0, '1', '1', '1', '', '2022-11-05 17:12:15', '', '2022-11-05 17:12:15', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2049, '限时折扣活动创建', 'promotion:discount-activity:create', 3, 2, 2047, '', '', '', NULL, 0, '1', '1', '1', '', '2022-11-05 17:12:15', '', '2022-11-05 17:12:15', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2050, '限时折扣活动更新', 'promotion:discount-activity:update', 3, 3, 2047, '', '', '', NULL, 0, '1', '1', '1', '', '2022-11-05 17:12:16', '', '2022-11-05 17:12:16', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2051, '限时折扣活动删除', 'promotion:discount-activity:delete', 3, 4, 2047, '', '', '', NULL, 0, '1', '1', '1', '', '2022-11-05 17:12:16', '', '2022-11-05 17:12:16', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2052, '限时折扣活动关闭', 'promotion:discount-activity:close', 3, 5, 2047, '', '', '', NULL, 0, '1', '1', '1', '', '2022-11-05 17:12:16', '', '2022-11-05 17:12:16', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2059, '秒杀商品', '', 2, 2, 2209, 'activity', 'ep:basketball', 'mall/promotion/seckill/activity/index', 'PromotionSeckillActivity', 0, '1', '1', '1', '', '2022-11-06 22:24:49', '1', '2023-06-24 18:57:25', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2060, '秒杀活动查询', 'promotion:seckill-activity:query', 3, 1, 2059, '', '', '', NULL, 0, '1', '1', '1', '', '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2061, '秒杀活动创建', 'promotion:seckill-activity:create', 3, 2, 2059, '', '', '', NULL, 0, '1', '1', '1', '', '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2062, '秒杀活动更新', 'promotion:seckill-activity:update', 3, 3, 2059, '', '', '', NULL, 0, '1', '1', '1', '', '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2063, '秒杀活动删除', 'promotion:seckill-activity:delete', 3, 4, 2059, '', '', '', NULL, 0, '1', '1', '1', '', '2022-11-06 22:24:49', '', '2022-11-06 22:24:49', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2066, '秒杀时段', '', 2, 1, 2209, 'config', 'ep:baseball', 'mall/promotion/seckill/config/index', 'PromotionSeckillConfig', 0, '1', '1', '1', '', '2022-11-15 19:46:50', '1', '2023-06-24 18:57:14', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2067, '秒杀时段查询', 'promotion:seckill-config:query', 3, 1, 2066, '', '', '', '', 0, '1', '1', '1', '', '2022-11-15 19:46:51', '1', '2023-06-24 17:50:25', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2068, '秒杀时段创建', 'promotion:seckill-config:create', 3, 2, 2066, '', '', '', '', 0, '1', '1', '1', '', '2022-11-15 19:46:51', '1', '2023-06-24 17:48:39', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2069, '秒杀时段更新', 'promotion:seckill-config:update', 3, 3, 2066, '', '', '', '', 0, '1', '1', '1', '', '2022-11-15 19:46:51', '1', '2023-06-24 17:50:29', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2070, '秒杀时段删除', 'promotion:seckill-config:delete', 3, 4, 2066, '', '', '', '', 0, '1', '1', '1', '', '2022-11-15 19:46:51', '1', '2023-06-24 17:50:32', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2072, '订单中心', '', 1, 65, 2362, 'trade', 'ep:eleme', NULL, NULL, 0, '1', '1', '1', '1', '2022-11-19 18:57:19', '1', '2023-09-30 11:54:07', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2073, '售后退款', '', 2, 2, 2072, 'after-sale', 'ep:refrigerator', 'mall/trade/afterSale/index', 'TradeAfterSale', 0, '1', '1', '1', '', '2022-11-19 20:15:32', '1', '2023-10-01 21:42:21', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2074, '售后查询', 'trade:after-sale:query', 3, 1, 2073, '', '', '', NULL, 0, '1', '1', '1', '', '2022-11-19 20:15:33', '1', '2022-12-10 21:04:29', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2075, '秒杀活动关闭', 'promotion:seckill-activity:close', 3, 5, 2059, '', '', '', '', 0, '1', '1', '1', '1', '2022-11-28 20:20:15', '1', '2023-10-03 18:34:28', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2076, '订单列表', '', 2, 1, 2072, 'order', 'ep:list', 'mall/trade/order/index', 'TradeOrder', 0, '1', '1', '1', '1', '2022-12-10 21:05:44', '1', '2023-10-01 21:42:08', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2083, '地区管理', '', 2, 14, 1, 'area', 'fa:map-marker', 'system/area/index', 'SystemArea', 0, '1', '1', '1', '1', '2022-12-23 17:35:05', '1', '2024-02-29 08:50:28', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2084, '公众号管理', '', 1, 100, 0, '/mp', 'ep:compass', NULL, NULL, 0, '1', '1', '1', '1', '2023-01-01 20:11:04', '1', '2024-02-29 12:39:30', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2085, '账号管理', '', 2, 1, 2084, 'account', 'fa:user', 'mp/account/index', 'MpAccount', 0, '1', '1', '1', '1', '2023-01-01 20:13:31', '1', '2024-02-29 12:42:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2086, '新增账号', 'mp:account:create', 3, 1, 2085, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-01 20:21:40', '1', '2023-01-07 17:32:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2087, '修改账号', 'mp:account:update', 3, 2, 2085, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-07 17:32:46', '1', '2023-01-07 17:32:46', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2088, '查询账号', 'mp:account:query', 3, 0, 2085, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-07 17:33:07', '1', '2023-01-07 17:33:07', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2089, '删除账号', 'mp:account:delete', 3, 3, 2085, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-07 17:33:21', '1', '2023-01-07 17:33:21', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2090, '生成二维码', 'mp:account:qr-code', 3, 4, 2085, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-07 17:33:58', '1', '2023-01-07 17:33:58', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2091, '清空 API 配额', 'mp:account:clear-quota', 3, 5, 2085, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-07 18:20:32', '1', '2023-01-07 18:20:59', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2092, '数据统计', 'mp:statistics:query', 2, 2, 2084, 'statistics', 'ep:trend-charts', 'mp/statistics/index', 'MpStatistics', 0, '1', '1', '1', '1', '2023-01-07 20:17:36', '1', '2024-02-29 12:42:21', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2093, '标签管理', '', 2, 3, 2084, 'tag', 'ep:collection-tag', 'mp/tag/index', 'MpTag', 0, '1', '1', '1', '1', '2023-01-08 11:37:32', '1', '2024-02-29 12:42:29', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2094, '查询标签', 'mp:tag:query', 3, 0, 2093, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-08 11:59:03', '1', '2023-01-08 11:59:03', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2095, '新增标签', 'mp:tag:create', 3, 1, 2093, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-08 11:59:23', '1', '2023-01-08 11:59:23', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2096, '修改标签', 'mp:tag:update', 3, 2, 2093, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-08 11:59:41', '1', '2023-01-08 11:59:41', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2097, '删除标签', 'mp:tag:delete', 3, 3, 2093, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-08 12:00:04', '1', '2023-01-08 12:00:13', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2098, '同步标签', 'mp:tag:sync', 3, 4, 2093, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-08 12:00:29', '1', '2023-01-08 12:00:29', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2099, '粉丝管理', '', 2, 4, 2084, 'user', 'fa:user-secret', 'mp/user/index', 'MpUser', 0, '1', '1', '1', '1', '2023-01-08 16:51:20', '1', '2024-02-29 12:42:39', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2100, '查询粉丝', 'mp:user:query', 3, 0, 2099, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-08 17:16:59', '1', '2023-01-08 17:17:23', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2101, '修改粉丝', 'mp:user:update', 3, 1, 2099, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-08 17:17:11', '1', '2023-01-08 17:17:11', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2102, '同步粉丝', 'mp:user:sync', 3, 2, 2099, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-08 17:17:40', '1', '2023-01-08 17:17:40', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2103, '消息管理', '', 2, 5, 2084, 'message', 'ep:message', 'mp/message/index', 'MpMessage', 0, '1', '1', '1', '1', '2023-01-08 18:44:19', '1', '2024-02-29 12:42:50', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2104, '图文发表记录', '', 2, 10, 2084, 'free-publish', 'ep:edit-pen', 'mp/freePublish/index', 'MpFreePublish', 0, '1', '1', '1', '1', '2023-01-13 00:30:50', '1', '2024-02-29 12:43:31', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2105, '查询发布列表', 'mp:free-publish:query', 3, 1, 2104, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-13 07:19:17', '1', '2023-01-13 07:19:17', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2106, '发布草稿', 'mp:free-publish:submit', 3, 2, 2104, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-13 07:19:46', '1', '2023-01-13 07:19:46', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2107, '删除发布记录', 'mp:free-publish:delete', 3, 3, 2104, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-13 07:20:01', '1', '2023-01-13 07:20:01', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2108, '图文草稿箱', '', 2, 9, 2084, 'draft', 'ep:edit', 'mp/draft/index', 'MpDraft', 0, '1', '1', '1', '1', '2023-01-13 07:40:21', '1', '2024-02-29 12:43:26', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2109, '新建草稿', 'mp:draft:create', 3, 1, 2108, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-13 23:15:30', '1', '2023-01-13 23:15:44', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2110, '修改草稿', 'mp:draft:update', 3, 2, 2108, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-14 10:08:47', '1', '2023-01-14 10:08:47', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2111, '查询草稿', 'mp:draft:query', 3, 0, 2108, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-14 10:09:01', '1', '2023-01-14 10:09:01', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2112, '删除草稿', 'mp:draft:delete', 3, 3, 2108, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-14 10:09:19', '1', '2023-01-14 10:09:19', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2113, '素材管理', '', 2, 8, 2084, 'material', 'ep:basketball', 'mp/material/index', 'MpMaterial', 0, '1', '1', '1', '1', '2023-01-14 14:12:07', '1', '2024-02-29 12:43:18', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2114, '上传临时素材', 'mp:material:upload-temporary', 3, 1, 2113, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-14 15:33:55', '1', '2023-01-14 15:33:55', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2115, '上传永久素材', 'mp:material:upload-permanent', 3, 2, 2113, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-14 15:34:14', '1', '2023-01-14 15:34:14', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2116, '删除素材', 'mp:material:delete', 3, 3, 2113, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-14 15:35:37', '1', '2023-01-14 15:35:37', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2117, '上传图文图片', 'mp:material:upload-news-image', 3, 4, 2113, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-14 15:36:31', '1', '2023-01-14 15:36:31', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2118, '查询素材', 'mp:material:query', 3, 5, 2113, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-14 15:39:22', '1', '2023-01-14 15:39:22', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2119, '菜单管理', '', 2, 6, 2084, 'menu', 'ep:menu', 'mp/menu/index', 'MpMenu', 0, '1', '1', '1', '1', '2023-01-14 17:43:54', '1', '2024-02-29 12:42:56', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2120, '自动回复', '', 2, 7, 2084, 'auto-reply', 'fa-solid:republican', 'mp/autoReply/index', 'MpAutoReply', 0, '1', '1', '1', '1', '2023-01-15 22:13:09', '1', '2024-02-29 12:43:10', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2121, '查询回复', 'mp:auto-reply:query', 3, 0, 2120, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-16 22:28:41', '1', '2023-01-16 22:28:41', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2122, '新增回复', 'mp:auto-reply:create', 3, 1, 2120, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-16 22:28:54', '1', '2023-01-16 22:28:54', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2123, '修改回复', 'mp:auto-reply:update', 3, 2, 2120, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-16 22:29:05', '1', '2023-01-16 22:29:05', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2124, '删除回复', 'mp:auto-reply:delete', 3, 3, 2120, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-16 22:29:34', '1', '2023-01-16 22:29:34', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2125, '查询菜单', 'mp:menu:query', 3, 0, 2119, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-17 23:05:41', '1', '2023-01-17 23:05:41', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2126, '保存菜单', 'mp:menu:save', 3, 1, 2119, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-17 23:06:01', '1', '2023-01-17 23:06:01', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2127, '删除菜单', 'mp:menu:delete', 3, 2, 2119, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-17 23:06:16', '1', '2023-01-17 23:06:16', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2128, '查询消息', 'mp:message:query', 3, 0, 2103, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-17 23:07:14', '1', '2023-01-17 23:07:14', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2129, '发送消息', 'mp:message:send', 3, 1, 2103, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-17 23:07:26', '1', '2023-01-17 23:07:26', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2130, '邮箱管理', '', 2, 2, 2739, 'mail', 'fa-solid:mail-bulk', NULL, NULL, 0, '1', '1', '1', '1', '2023-01-25 17:27:44', '1', '2024-04-22 23:56:08', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2131, '邮箱账号', '', 2, 0, 2130, 'mail-account', 'fa:universal-access', 'system/mail/account/index', 'SystemMailAccount', 0, '1', '1', '1', '', '2023-01-25 09:33:48', '1', '2024-02-29 08:48:16', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2132, '账号查询', 'system:mail-account:query', 3, 1, 2131, '', '', '', NULL, 0, '1', '1', '1', '', '2023-01-25 09:33:48', '', '2023-01-25 09:33:48', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2133, '账号创建', 'system:mail-account:create', 3, 2, 2131, '', '', '', NULL, 0, '1', '1', '1', '', '2023-01-25 09:33:48', '', '2023-01-25 09:33:48', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2134, '账号更新', 'system:mail-account:update', 3, 3, 2131, '', '', '', NULL, 0, '1', '1', '1', '', '2023-01-25 09:33:48', '', '2023-01-25 09:33:48', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2135, '账号删除', 'system:mail-account:delete', 3, 4, 2131, '', '', '', NULL, 0, '1', '1', '1', '', '2023-01-25 09:33:48', '', '2023-01-25 09:33:48', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2136, '邮件模版', '', 2, 0, 2130, 'mail-template', 'fa:tag', 'system/mail/template/index', 'SystemMailTemplate', 0, '1', '1', '1', '', '2023-01-25 12:05:31', '1', '2024-02-29 08:48:41', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2137, '模版查询', 'system:mail-template:query', 3, 1, 2136, '', '', '', NULL, 0, '1', '1', '1', '', '2023-01-25 12:05:31', '', '2023-01-25 12:05:31', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2138, '模版创建', 'system:mail-template:create', 3, 2, 2136, '', '', '', NULL, 0, '1', '1', '1', '', '2023-01-25 12:05:31', '', '2023-01-25 12:05:31', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2139, '模版更新', 'system:mail-template:update', 3, 3, 2136, '', '', '', NULL, 0, '1', '1', '1', '', '2023-01-25 12:05:31', '', '2023-01-25 12:05:31', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2140, '模版删除', 'system:mail-template:delete', 3, 4, 2136, '', '', '', NULL, 0, '1', '1', '1', '', '2023-01-25 12:05:31', '', '2023-01-25 12:05:31', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2141, '邮件记录', '', 2, 0, 2130, 'mail-log', 'fa:edit', 'system/mail/log/index', 'SystemMailLog', 0, '1', '1', '1', '', '2023-01-26 02:16:50', '1', '2024-02-29 08:48:51', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2142, '日志查询', 'system:mail-log:query', 3, 1, 2141, '', '', '', NULL, 0, '1', '1', '1', '', '2023-01-26 02:16:50', '', '2023-01-26 02:16:50', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2143, '发送测试邮件', 'system:mail-template:send-mail', 3, 5, 2136, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-26 23:29:15', '1', '2023-01-26 23:29:15', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2144, '站内信管理', '', 1, 3, 2739, 'notify', 'ep:message-box', NULL, NULL, 0, '1', '1', '1', '1', '2023-01-28 10:25:18', '1', '2024-04-22 23:56:12', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2145, '模板管理', '', 2, 0, 2144, 'notify-template', 'fa:archive', 'system/notify/template/index', 'SystemNotifyTemplate', 0, '1', '1', '1', '', '2023-01-28 02:26:42', '1', '2024-02-29 08:49:14', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2146, '站内信模板查询', 'system:notify-template:query', 3, 1, 2145, '', '', '', NULL, 0, '1', '1', '1', '', '2023-01-28 02:26:42', '', '2023-01-28 02:26:42', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2147, '站内信模板创建', 'system:notify-template:create', 3, 2, 2145, '', '', '', NULL, 0, '1', '1', '1', '', '2023-01-28 02:26:42', '', '2023-01-28 02:26:42', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2148, '站内信模板更新', 'system:notify-template:update', 3, 3, 2145, '', '', '', NULL, 0, '1', '1', '1', '', '2023-01-28 02:26:42', '', '2023-01-28 02:26:42', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2149, '站内信模板删除', 'system:notify-template:delete', 3, 4, 2145, '', '', '', NULL, 0, '1', '1', '1', '', '2023-01-28 02:26:42', '', '2023-01-28 02:26:42', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2150, '发送测试站内信', 'system:notify-template:send-notify', 3, 5, 2145, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-01-28 10:54:43', '1', '2023-01-28 10:54:43', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2151, '消息记录', '', 2, 0, 2144, 'notify-message', 'fa:edit', 'system/notify/message/index', 'SystemNotifyMessage', 0, '1', '1', '1', '', '2023-01-28 04:28:22', '1', '2024-02-29 08:49:22', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2152, '站内信消息查询', 'system:notify-message:query', 3, 1, 2151, '', '', '', NULL, 0, '1', '1', '1', '', '2023-01-28 04:28:22', '', '2023-01-28 04:28:22', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2153, '大屏设计器', '', 2, 2, 1281, 'go-view', 'fa:area-chart', 'report/goview/index', 'JimuReport', 0, '1', '1', '1', '1', '2023-02-07 00:03:19', '1', '2024-02-29 12:34:02', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2154, '创建项目', 'report:go-view-project:create', 3, 1, 2153, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-02-07 19:25:14', '1', '2023-02-07 19:25:14', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2155, '更新项目', 'report:go-view-project:update', 3, 2, 2153, '', '', '', '', 0, '1', '1', '1', '1', '2023-02-07 19:25:34', '1', '2024-04-24 20:01:18', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2156, '查询项目', 'report:go-view-project:query', 3, 0, 2153, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-02-07 19:25:53', '1', '2023-02-07 19:25:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2157, '使用 SQL 查询数据', 'report:go-view-data:get-by-sql', 3, 3, 2153, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-02-07 19:26:15', '1', '2023-02-07 19:26:15', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2158, '使用 HTTP 查询数据', 'report:go-view-data:get-by-http', 3, 4, 2153, '', '', '', NULL, 0, '1', '1', '1', '1', '2023-02-07 19:26:35', '1', '2023-02-07 19:26:35', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2159, 'Boot 开发文档', '', 1, 1, 0, 'https://doc.iocoder.cn/', 'ep:document', NULL, NULL, 0, '1', '1', '1', '1', '2023-02-10 22:46:28', '1', '2023-12-02 21:32:20', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2160, 'Cloud 开发文档', '', 1, 2, 0, 'https://cloud.iocoder.cn', 'ep:document-copy', NULL, NULL, 0, '1', '1', '1', '1', '2023-02-10 22:47:07', '1', '2023-12-02 21:32:29', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2161, '接入示例', '', 1, 99, 1117, 'demo', 'fa-solid:dragon', 'pay/demo/index', NULL, 0, '1', '1', '1', '', '2023-02-11 14:21:42', '1', '2024-01-18 23:50:00', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2162, '商品导出', 'product:spu:export', 3, 5, 2014, '', '', '', NULL, 0, '1', '1', '1', '', '2022-07-30 14:22:58', '', '2022-07-30 14:22:58', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2164, '配送管理', '', 1, 3, 2072, 'delivery', 'ep:shopping-cart', '', '', 0, '1', '1', '1', '1', '2023-05-18 09:18:02', '1', '2023-09-28 10:58:09', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2165, '快递发货', '', 1, 0, 2164, 'express', 'ep:bicycle', '', '', 0, '1', '1', '1', '1', '2023-05-18 09:22:06', '1', '2023-08-30 21:02:49', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2166, '门店自提', '', 1, 1, 2164, 'pick-up-store', 'ep:add-location', '', '', 0, '1', '1', '1', '1', '2023-05-18 09:23:14', '1', '2023-08-30 21:03:21', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2167, '快递公司', '', 2, 0, 2165, 'express', 'ep:compass', 'mall/trade/delivery/express/index', 'Express', 0, '1', '1', '1', '1', '2023-05-18 09:27:21', '1', '2023-08-30 21:02:59', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2168, '快递公司查询', 'trade:delivery:express:query', 3, 1, 2167, '', '', '', NULL, 0, '1', '1', '1', '', '2023-05-18 09:37:53', '', '2023-05-18 09:37:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2169, '快递公司创建', 'trade:delivery:express:create', 3, 2, 2167, '', '', '', NULL, 0, '1', '1', '1', '', '2023-05-18 09:37:53', '', '2023-05-18 09:37:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2170, '快递公司更新', 'trade:delivery:express:update', 3, 3, 2167, '', '', '', NULL, 0, '1', '1', '1', '', '2023-05-18 09:37:53', '', '2023-05-18 09:37:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2171, '快递公司删除', 'trade:delivery:express:delete', 3, 4, 2167, '', '', '', NULL, 0, '1', '1', '1', '', '2023-05-18 09:37:53', '', '2023-05-18 09:37:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2172, '快递公司导出', 'trade:delivery:express:export', 3, 5, 2167, '', '', '', NULL, 0, '1', '1', '1', '', '2023-05-18 09:37:53', '', '2023-05-18 09:37:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2173, '运费模版', 'trade:delivery:express-template:query', 2, 1, 2165, 'express-template', 'ep:coordinate', 'mall/trade/delivery/expressTemplate/index', 'ExpressTemplate', 0, '1', '1', '1', '1', '2023-05-20 06:48:10', '1', '2023-08-30 21:03:13', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2174, '快递运费模板查询', 'trade:delivery:express-template:query', 3, 1, 2173, '', '', '', NULL, 0, '1', '1', '1', '', '2023-05-20 06:49:53', '', '2023-05-20 06:49:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2175, '快递运费模板创建', 'trade:delivery:express-template:create', 3, 2, 2173, '', '', '', NULL, 0, '1', '1', '1', '', '2023-05-20 06:49:53', '', '2023-05-20 06:49:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2176, '快递运费模板更新', 'trade:delivery:express-template:update', 3, 3, 2173, '', '', '', NULL, 0, '1', '1', '1', '', '2023-05-20 06:49:53', '', '2023-05-20 06:49:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2177, '快递运费模板删除', 'trade:delivery:express-template:delete', 3, 4, 2173, '', '', '', NULL, 0, '1', '1', '1', '', '2023-05-20 06:49:53', '', '2023-05-20 06:49:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2178, '快递运费模板导出', 'trade:delivery:express-template:export', 3, 5, 2173, '', '', '', NULL, 0, '1', '1', '1', '', '2023-05-20 06:49:53', '', '2023-05-20 06:49:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2179, '门店管理', '', 2, 1, 2166, 'pick-up-store', 'ep:basketball', 'mall/trade/delivery/pickUpStore/index', 'PickUpStore', 0, '1', '1', '1', '1', '2023-05-25 10:50:00', '1', '2023-08-30 21:03:28', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2180, '自提门店查询', 'trade:delivery:pick-up-store:query', 3, 1, 2179, '', '', '', NULL, 0, '1', '1', '1', '', '2023-05-25 10:53:29', '', '2023-05-25 10:53:29', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2181, '自提门店创建', 'trade:delivery:pick-up-store:create', 3, 2, 2179, '', '', '', NULL, 0, '1', '1', '1', '', '2023-05-25 10:53:29', '', '2023-05-25 10:53:29', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2182, '自提门店更新', 'trade:delivery:pick-up-store:update', 3, 3, 2179, '', '', '', NULL, 0, '1', '1', '1', '', '2023-05-25 10:53:29', '', '2023-05-25 10:53:29', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2183, '自提门店删除', 'trade:delivery:pick-up-store:delete', 3, 4, 2179, '', '', '', NULL, 0, '1', '1', '1', '', '2023-05-25 10:53:29', '', '2023-05-25 10:53:29', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2184, '自提门店导出', 'trade:delivery:pick-up-store:export', 3, 5, 2179, '', '', '', NULL, 0, '1', '1', '1', '', '2023-05-25 10:53:29', '', '2023-05-25 10:53:29', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2209, '秒杀活动', '', 2, 3, 2030, 'seckill', 'ep:place', '', '', 0, '1', '1', '1', '1', '2023-06-24 17:39:13', '1', '2023-06-24 18:55:15', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2262, '会员中心', '', 1, 55, 0, '/member', 'ep:bicycle', NULL, NULL, 0, '1', '1', '1', '1', '2023-06-10 00:42:03', '1', '2023-08-20 09:23:56', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2275, '会员配置', '', 2, 0, 2262, 'config', 'fa:archive', 'member/config/index', 'MemberConfig', 0, '1', '1', '1', '', '2023-06-10 02:07:44', '1', '2023-10-01 23:41:29', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2276, '会员配置查询', 'member:config:query', 3, 1, 2275, '', '', '', '', 0, '1', '1', '1', '', '2023-06-10 02:07:44', '1', '2024-04-24 19:48:58', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2277, '会员配置保存', 'member:config:save', 3, 2, 2275, '', '', '', '', 0, '1', '1', '1', '', '2023-06-10 02:07:44', '1', '2024-04-24 19:49:28', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2281, '签到配置', '', 2, 2, 2300, 'config', 'ep:calendar', 'member/signin/config/index', 'SignInConfig', 0, '1', '1', '1', '', '2023-06-10 03:26:12', '1', '2023-08-20 19:25:51', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2282, '积分签到规则查询', 'point:sign-in-config:query', 3, 1, 2281, '', '', '', NULL, 0, '1', '1', '1', '', '2023-06-10 03:26:12', '', '2023-06-10 03:26:12', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2283, '积分签到规则创建', 'point:sign-in-config:create', 3, 2, 2281, '', '', '', NULL, 0, '1', '1', '1', '', '2023-06-10 03:26:12', '', '2023-06-10 03:26:12', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2284, '积分签到规则更新', 'point:sign-in-config:update', 3, 3, 2281, '', '', '', NULL, 0, '1', '1', '1', '', '2023-06-10 03:26:12', '', '2023-06-10 03:26:12', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2285, '积分签到规则删除', 'point:sign-in-config:delete', 3, 4, 2281, '', '', '', NULL, 0, '1', '1', '1', '', '2023-06-10 03:26:12', '', '2023-06-10 03:26:12', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2287, '会员积分', '', 2, 10, 2262, 'record', 'fa:asterisk', 'member/point/record/index', 'PointRecord', 0, '1', '1', '1', '', '2023-06-10 04:18:50', '1', '2023-10-01 23:42:11', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2288, '用户积分记录查询', 'point:record:query', 3, 1, 2287, '', '', '', NULL, 0, '1', '1', '1', '', '2023-06-10 04:18:50', '', '2023-06-10 04:18:50', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2293, '签到记录', '', 2, 3, 2300, 'record', 'ep:chicken', 'member/signin/record/index', 'SignInRecord', 0, '1', '1', '1', '', '2023-06-10 04:48:22', '1', '2023-08-20 19:26:02', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2294, '用户签到积分查询', 'point:sign-in-record:query', 3, 1, 2293, '', '', '', NULL, 0, '1', '1', '1', '', '2023-06-10 04:48:22', '', '2023-06-10 04:48:22', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2297, '用户签到积分删除', 'point:sign-in-record:delete', 3, 4, 2293, '', '', '', NULL, 0, '1', '1', '1', '', '2023-06-10 04:48:22', '', '2023-06-10 04:48:22', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2300, '会员签到', '', 1, 11, 2262, 'signin', 'ep:alarm-clock', '', '', 0, '1', '1', '1', '1', '2023-06-27 22:49:53', '1', '2023-08-20 09:23:48', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2301, '回调通知', '', 2, 5, 1117, 'notify', 'ep:mute-notification', 'pay/notify/index', 'PayNotify', 0, '1', '1', '1', '', '2023-07-20 04:41:32', '1', '2024-01-18 23:56:48', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2302, '支付通知查询', 'pay:notify:query', 3, 1, 2301, '', '', '', NULL, 0, '1', '1', '1', '', '2023-07-20 04:41:32', '', '2023-07-20 04:41:32', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2303, '拼团活动', '', 2, 3, 2030, 'combination', 'fa:group', '', '', 0, '1', '1', '1', '1', '2023-08-12 17:19:54', '1', '2023-08-12 17:20:05', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2304, '拼团商品', '', 2, 1, 2303, 'acitivity', 'ep:apple', 'mall/promotion/combination/activity/index', 'PromotionCombinationActivity', 0, '1', '1', '1', '1', '2023-08-12 17:22:03', '1', '2023-08-12 17:22:29', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2305, '拼团活动查询', 'promotion:combination-activity:query', 3, 1, 2304, '', '', '', '', 0, '1', '1', '1', '1', '2023-08-12 17:54:32', '1', '2023-11-24 11:57:40', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2306, '拼团活动创建', 'promotion:combination-activity:create', 3, 2, 2304, '', '', '', '', 0, '1', '1', '1', '1', '2023-08-12 17:54:49', '1', '2023-08-12 17:54:49', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2307, '拼团活动更新', 'promotion:combination-activity:update', 3, 3, 2304, '', '', '', '', 0, '1', '1', '1', '1', '2023-08-12 17:55:04', '1', '2023-08-12 17:55:04', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2308, '拼团活动删除', 'promotion:combination-activity:delete', 3, 4, 2304, '', '', '', '', 0, '1', '1', '1', '1', '2023-08-12 17:55:23', '1', '2023-08-12 17:55:23', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2309, '拼团活动关闭', 'promotion:combination-activity:close', 3, 5, 2304, '', '', '', '', 0, '1', '1', '1', '1', '2023-08-12 17:55:37', '1', '2023-10-06 10:51:57', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2310, '砍价活动', '', 2, 4, 2030, 'bargain', 'ep:box', '', '', 0, '1', '1', '1', '1', '2023-08-13 00:27:25', '1', '2023-08-13 00:27:25', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2311, '砍价商品', '', 2, 1, 2310, 'activity', 'ep:burger', 'mall/promotion/bargain/activity/index', 'PromotionBargainActivity', 0, '1', '1', '1', '1', '2023-08-13 00:28:49', '1', '2023-10-05 01:16:23', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2312, '砍价活动查询', 'promotion:bargain-activity:query', 3, 1, 2311, '', '', '', '', 0, '1', '1', '1', '1', '2023-08-13 00:32:30', '1', '2023-08-13 00:32:30', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2313, '砍价活动创建', 'promotion:bargain-activity:create', 3, 2, 2311, '', '', '', '', 0, '1', '1', '1', '1', '2023-08-13 00:32:44', '1', '2023-08-13 00:32:44', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2314, '砍价活动更新', 'promotion:bargain-activity:update', 3, 3, 2311, '', '', '', '', 0, '1', '1', '1', '1', '2023-08-13 00:32:55', '1', '2023-08-13 00:32:55', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2315, '砍价活动删除', 'promotion:bargain-activity:delete', 3, 4, 2311, '', '', '', '', 0, '1', '1', '1', '1', '2023-08-13 00:34:50', '1', '2023-08-13 00:34:50', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2316, '砍价活动关闭', 'promotion:bargain-activity:close', 3, 5, 2311, '', '', '', '', 0, '1', '1', '1', '1', '2023-08-13 00:35:02', '1', '2023-08-13 00:35:02', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2317, '会员管理', '', 2, 0, 2262, 'user', 'ep:avatar', 'member/user/index', 'MemberUser', 0, '1', '1', '1', '', '2023-08-19 04:12:15', '1', '2023-08-24 00:50:55', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2318, '会员用户查询', 'member:user:query', 3, 1, 2317, '', '', '', NULL, 0, '1', '1', '1', '', '2023-08-19 04:12:15', '', '2023-08-19 04:12:15', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2319, '会员用户更新', 'member:user:update', 3, 3, 2317, '', '', '', NULL, 0, '1', '1', '1', '', '2023-08-19 04:12:15', '', '2023-08-19 04:12:15', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2320, '会员标签', '', 2, 1, 2262, 'tag', 'ep:collection-tag', 'member/tag/index', 'MemberTag', 0, '1', '1', '1', '', '2023-08-20 01:03:08', '1', '2023-08-20 09:23:19', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2321, '会员标签查询', 'member:tag:query', 3, 1, 2320, '', '', '', NULL, 0, '1', '1', '1', '', '2023-08-20 01:03:08', '', '2023-08-20 01:03:08', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2322, '会员标签创建', 'member:tag:create', 3, 2, 2320, '', '', '', NULL, 0, '1', '1', '1', '', '2023-08-20 01:03:08', '', '2023-08-20 01:03:08', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2323, '会员标签更新', 'member:tag:update', 3, 3, 2320, '', '', '', NULL, 0, '1', '1', '1', '', '2023-08-20 01:03:08', '', '2023-08-20 01:03:08', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2324, '会员标签删除', 'member:tag:delete', 3, 4, 2320, '', '', '', NULL, 0, '1', '1', '1', '', '2023-08-20 01:03:08', '', '2023-08-20 01:03:08', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2325, '会员等级', '', 2, 2, 2262, 'level', 'fa:level-up', 'member/level/index', 'MemberLevel', 0, '1', '1', '1', '', '2023-08-22 12:41:01', '1', '2023-08-22 21:47:00', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2326, '会员等级查询', 'member:level:query', 3, 1, 2325, '', '', '', NULL, 0, '1', '1', '1', '', '2023-08-22 12:41:02', '', '2023-08-22 12:41:02', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2327, '会员等级创建', 'member:level:create', 3, 2, 2325, '', '', '', NULL, 0, '1', '1', '1', '', '2023-08-22 12:41:02', '', '2023-08-22 12:41:02', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2328, '会员等级更新', 'member:level:update', 3, 3, 2325, '', '', '', NULL, 0, '1', '1', '1', '', '2023-08-22 12:41:02', '', '2023-08-22 12:41:02', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2329, '会员等级删除', 'member:level:delete', 3, 4, 2325, '', '', '', NULL, 0, '1', '1', '1', '', '2023-08-22 12:41:02', '', '2023-08-22 12:41:02', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2330, '会员分组', '', 2, 3, 2262, 'group', 'fa:group', 'member/group/index', 'MemberGroup', 0, '1', '1', '1', '', '2023-08-22 13:50:06', '1', '2023-10-01 23:42:01', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2331, '用户分组查询', 'member:group:query', 3, 1, 2330, '', '', '', NULL, 0, '1', '1', '1', '', '2023-08-22 13:50:06', '', '2023-08-22 13:50:06', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2332, '用户分组创建', 'member:group:create', 3, 2, 2330, '', '', '', NULL, 0, '1', '1', '1', '', '2023-08-22 13:50:06', '', '2023-08-22 13:50:06', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2333, '用户分组更新', 'member:group:update', 3, 3, 2330, '', '', '', NULL, 0, '1', '1', '1', '', '2023-08-22 13:50:06', '', '2023-08-22 13:50:06', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2334, '用户分组删除', 'member:group:delete', 3, 4, 2330, '', '', '', NULL, 0, '1', '1', '1', '', '2023-08-22 13:50:06', '', '2023-08-22 13:50:06', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2335, '用户等级修改', 'member:user:update-level', 3, 5, 2317, '', '', '', NULL, 0, '1', '1', '1', '', '2023-08-23 16:49:05', '', '2023-08-23 16:50:48', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2336, '商品评论', '', 2, 5, 2000, 'comment', 'ep:comment', 'mall/product/comment/index', 'ProductComment', 0, '1', '1', '1', '1', '2023-08-26 11:03:00', '1', '2023-08-26 11:03:38', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2337, '评论查询', 'product:comment:query', 3, 1, 2336, '', '', '', '', 0, '1', '1', '1', '1', '2023-08-26 11:04:01', '1', '2023-08-26 11:04:01', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2338, '添加自评', 'product:comment:create', 3, 2, 2336, '', '', '', '', 0, '1', '1', '1', '1', '2023-08-26 11:04:23', '1', '2023-08-26 11:08:18', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2339, '商家回复', 'product:comment:update', 3, 3, 2336, '', '', '', '', 0, '1', '1', '1', '1', '2023-08-26 11:04:37', '1', '2023-08-26 11:04:37', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2340, '显隐评论', 'product:comment:update', 3, 4, 2336, '', '', '', '', 0, '1', '1', '1', '1', '2023-08-26 11:04:55', '1', '2023-08-26 11:04:55', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2341, '优惠劵发送', 'promotion:coupon:send', 3, 2, 2038, '', '', '', '', 0, '1', '1', '1', '1', '2023-09-02 00:03:14', '1', '2023-09-02 00:03:14', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2342, '交易配置', '', 2, 0, 2072, 'config', 'ep:setting', 'mall/trade/config/index', 'TradeConfig', 0, '1', '1', '1', '', '2023-09-28 02:46:22', '1', '2024-02-26 20:30:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2343, '交易中心配置查询', 'trade:config:query', 3, 1, 2342, '', '', '', NULL, 0, '1', '1', '1', '', '2023-09-28 02:46:22', '', '2023-09-28 02:46:22', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2344, '交易中心配置保存', 'trade:config:save', 3, 2, 2342, '', '', '', NULL, 0, '1', '1', '1', '', '2023-09-28 02:46:22', '', '2023-09-28 02:46:22', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2345, '分销管理', '', 1, 4, 2072, 'brokerage', 'fa-solid:project-diagram', '', '', 0, '1', '1', '1', '', '2023-09-28 02:46:22', '1', '2023-09-28 10:58:44', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2346, '分销用户', '', 2, 0, 2345, 'brokerage-user', 'fa-solid:user-tie', 'mall/trade/brokerage/user/index', 'TradeBrokerageUser', 0, '1', '1', '1', '', '2023-09-28 02:46:22', '1', '2024-02-26 20:33:23', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2347, '分销用户查询', 'trade:brokerage-user:query', 3, 1, 2346, '', '', '', NULL, 0, '1', '1', '1', '', '2023-09-28 02:46:22', '', '2023-09-28 02:46:22', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2348, '分销用户推广人查询', 'trade:brokerage-user:user-query', 3, 2, 2346, '', '', '', NULL, 0, '1', '1', '1', '', '2023-09-28 02:46:22', '', '2023-09-28 02:46:22', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2349, '分销用户推广订单查询', 'trade:brokerage-user:order-query', 3, 3, 2346, '', '', '', NULL, 0, '1', '1', '1', '', '2023-09-28 02:46:22', '', '2023-09-28 02:46:22', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2350, '分销用户修改推广资格', 'trade:brokerage-user:update-brokerage-enable', 3, 4, 2346, '', '', '', NULL, 0, '1', '1', '1', '', '2023-09-28 02:46:22', '', '2023-09-28 02:46:22', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2351, '分销用户修改推广员', 'trade:brokerage-user:update-bind-user', 3, 5, 2346, '', '', '', NULL, 0, '1', '1', '1', '', '2023-09-28 02:46:22', '', '2023-09-28 02:46:22', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2352, '分销用户清除推广员', 'trade:brokerage-user:clear-bind-user', 3, 6, 2346, '', '', '', NULL, 0, '1', '1', '1', '', '2023-09-28 02:46:22', '', '2023-09-28 02:46:22', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2353, '佣金记录', '', 2, 1, 2345, 'brokerage-record', 'fa:money', 'mall/trade/brokerage/record/index', 'TradeBrokerageRecord', 0, '1', '1', '1', '', '2023-09-28 02:46:22', '1', '2024-02-26 20:33:30', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2354, '佣金记录查询', 'trade:brokerage-record:query', 3, 1, 2353, '', '', '', NULL, 0, '1', '1', '1', '', '2023-09-28 02:46:22', '', '2023-09-28 02:46:22', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2355, '佣金提现', '', 2, 2, 2345, 'brokerage-withdraw', 'fa:credit-card', 'mall/trade/brokerage/withdraw/index', 'TradeBrokerageWithdraw', 0, '1', '1', '1', '', '2023-09-28 02:46:22', '1', '2024-02-26 20:33:35', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2356, '佣金提现查询', 'trade:brokerage-withdraw:query', 3, 1, 2355, '', '', '', NULL, 0, '1', '1', '1', '', '2023-09-28 02:46:22', '', '2023-09-28 02:46:22', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2357, '佣金提现审核', 'trade:brokerage-withdraw:audit', 3, 2, 2355, '', '', '', NULL, 0, '1', '1', '1', '', '2023-09-28 02:46:22', '', '2023-09-28 02:46:22', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2358, '统计中心', '', 1, 75, 2362, 'statistics', 'ep:data-line', '', '', 0, '1', '1', '1', '', '2023-09-30 03:22:40', '1', '2023-09-30 11:54:48', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2359, '交易统计', '', 2, 4, 2358, 'trade', 'fa-solid:credit-card', 'mall/statistics/trade/index', 'TradeStatistics', 0, '1', '1', '1', '', '2023-09-30 03:22:40', '1', '2024-02-26 20:42:00', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2360, '交易统计查询', 'statistics:trade:query', 3, 1, 2359, '', '', '', NULL, 0, '1', '1', '1', '', '2023-09-30 03:22:40', '', '2023-09-30 03:22:40', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2361, '交易统计导出', 'statistics:trade:export', 3, 2, 2359, '', '', '', NULL, 0, '1', '1', '1', '', '2023-09-30 03:22:40', '', '2023-09-30 03:22:40', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2362, '商城系统', '', 1, 59, 0, '/mall', 'ep:shop', '', '', 0, '1', '1', '1', '1', '2023-09-30 11:52:02', '1', '2023-09-30 11:52:18', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2363, '用户积分修改', 'member:user:update-point', 3, 6, 2317, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-01 14:39:43', '', '2023-10-01 14:39:43', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2364, '用户余额修改', 'member:user:update-balance', 3, 7, 2317, '', '', '', '', 0, '1', '1', '1', '', '2023-10-01 14:39:43', '1', '2023-10-01 22:42:31', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2365, '优惠劵', '', 1, 2, 2030, 'coupon', 'fa-solid:disease', '', '', 0, '1', '1', '1', '1', '2023-10-03 12:39:15', '1', '2023-10-05 00:16:07', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2366, '砍价记录', '', 2, 2, 2310, 'record', 'ep:list', 'mall/promotion/bargain/record/index', 'PromotionBargainRecord', 0, '1', '1', '1', '', '2023-10-05 02:49:06', '1', '2023-10-05 10:50:38', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2367, '砍价记录查询', 'promotion:bargain-record:query', 3, 1, 2366, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-05 02:49:06', '', '2023-10-05 02:49:06', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2368, '助力记录查询', 'promotion:bargain-help:query', 3, 2, 2366, '', '', '', '', 0, '1', '1', '1', '1', '2023-10-05 12:27:49', '1', '2023-10-05 12:27:49', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2369, '拼团记录', 'promotion:combination-record:query', 2, 2, 2303, 'record', 'ep:avatar', 'mall/promotion/combination/record/index.vue', 'PromotionCombinationRecord', 0, '1', '1', '1', '1', '2023-10-08 07:10:22', '1', '2023-10-08 07:34:11', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2374, '会员统计', '', 2, 2, 2358, 'member', 'ep:avatar', 'mall/statistics/member/index', 'MemberStatistics', 0, '1', '1', '1', '', '2023-10-11 04:39:24', '1', '2024-02-26 20:41:46', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2375, '会员统计查询', 'statistics:member:query', 3, 1, 2374, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-11 04:39:24', '', '2023-10-11 04:39:24', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2376, '订单核销', 'trade:order:pick-up', 3, 10, 2076, '', '', '', '', 0, '1', '1', '1', '1', '2023-10-14 17:11:58', '1', '2023-10-14 17:11:58', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2377, '文章分类', '', 2, 0, 2387, 'article/category', 'fa:certificate', 'mall/promotion/article/category/index', 'ArticleCategory', 0, '1', '1', '1', '', '2023-10-16 01:26:18', '1', '2023-10-16 09:38:26', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2378, '分类查询', 'promotion:article-category:query', 3, 1, 2377, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-16 01:26:18', '', '2023-10-16 01:26:18', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2379, '分类创建', 'promotion:article-category:create', 3, 2, 2377, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-16 01:26:18', '', '2023-10-16 01:26:18', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2380, '分类更新', 'promotion:article-category:update', 3, 3, 2377, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-16 01:26:18', '', '2023-10-16 01:26:18', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2381, '分类删除', 'promotion:article-category:delete', 3, 4, 2377, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-16 01:26:18', '', '2023-10-16 01:26:18', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2382, '文章列表', '', 2, 2, 2387, 'article', 'ep:connection', 'mall/promotion/article/index', 'Article', 0, '1', '1', '1', '', '2023-10-16 01:26:18', '1', '2023-10-16 09:41:19', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2383, '文章管理查询', 'promotion:article:query', 3, 1, 2382, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-16 01:26:18', '', '2023-10-16 01:26:18', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2384, '文章管理创建', 'promotion:article:create', 3, 2, 2382, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-16 01:26:18', '', '2023-10-16 01:26:18', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2385, '文章管理更新', 'promotion:article:update', 3, 3, 2382, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-16 01:26:18', '', '2023-10-16 01:26:18', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2386, '文章管理删除', 'promotion:article:delete', 3, 4, 2382, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-16 01:26:18', '', '2023-10-16 01:26:18', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2387, '内容管理', '', 1, 1, 2030, 'content', 'ep:collection', '', '', 0, '1', '1', '1', '1', '2023-10-16 09:37:31', '1', '2023-10-16 09:37:31', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2388, '商城首页', '', 2, 1, 2362, 'home', 'ep:home-filled', 'mall/home/index', 'MallHome', 0, '1', '1', '1', '', '2023-10-16 12:10:33', '', '2023-10-16 12:10:33', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2389, '核销订单', '', 2, 2, 2166, 'pick-up-order', 'ep:list', 'mall/trade/delivery/pickUpOrder/index', 'PickUpOrder', 0, '1', '1', '1', '', '2023-10-19 16:09:51', '', '2023-10-19 16:09:51', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2390, '优惠活动', '', 1, 99, 2030, 'youhui', 'ep:aim', '', '', 0, '1', '1', '1', '1', '2023-10-21 19:23:49', '1', '2023-10-21 19:23:49', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2391, '客户管理', '', 2, 10, 2397, 'customer', 'fa:address-book-o', 'crm/customer/index', 'CrmCustomer', 0, '1', '1', '1', '', '2023-10-29 09:04:21', '1', '2024-02-17 17:13:32', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2392, '客户查询', 'crm:customer:query', 3, 1, 2391, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 09:04:21', '', '2023-10-29 09:04:21', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2393, '客户创建', 'crm:customer:create', 3, 2, 2391, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 09:04:21', '', '2023-10-29 09:04:21', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2394, '客户更新', 'crm:customer:update', 3, 3, 2391, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 09:04:21', '', '2023-10-29 09:04:21', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2395, '客户删除', 'crm:customer:delete', 3, 4, 2391, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 09:04:21', '', '2023-10-29 09:04:21', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2396, '客户导出', 'crm:customer:export', 3, 5, 2391, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 09:04:21', '', '2023-10-29 09:04:21', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2397, 'CRM 系统', '', 1, 200, 0, '/crm', 'ep:avatar', '', '', 0, '1', '1', '1', '1', '2023-10-29 17:08:30', '1', '2024-02-04 15:37:31', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2398, '合同管理', '', 2, 50, 2397, 'contract', 'ep:notebook', 'crm/contract/index', 'CrmContract', 0, '1', '1', '1', '', '2023-10-29 10:50:41', '1', '2024-02-17 17:15:09', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2399, '合同查询', 'crm:contract:query', 3, 1, 2398, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 10:50:41', '', '2023-10-29 10:50:41', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2400, '合同创建', 'crm:contract:create', 3, 2, 2398, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 10:50:41', '', '2023-10-29 10:50:41', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2401, '合同更新', 'crm:contract:update', 3, 3, 2398, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 10:50:41', '', '2023-10-29 10:50:41', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2402, '合同删除', 'crm:contract:delete', 3, 4, 2398, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 10:50:41', '', '2023-10-29 10:50:41', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2403, '合同导出', 'crm:contract:export', 3, 5, 2398, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 10:50:41', '', '2023-10-29 10:50:41', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2404, '线索管理', '', 2, 8, 2397, 'clue', 'fa:pagelines', 'crm/clue/index', 'CrmClue', 0, '1', '1', '1', '', '2023-10-29 11:06:29', '1', '2024-02-17 17:15:41', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2405, '线索查询', 'crm:clue:query', 3, 1, 2404, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:06:29', '', '2023-10-29 11:06:29', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2406, '线索创建', 'crm:clue:create', 3, 2, 2404, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:06:29', '', '2023-10-29 11:06:29', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2407, '线索更新', 'crm:clue:update', 3, 3, 2404, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:06:29', '', '2023-10-29 11:06:29', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2408, '线索删除', 'crm:clue:delete', 3, 4, 2404, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:06:29', '', '2023-10-29 11:06:29', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2409, '线索导出', 'crm:clue:export', 3, 5, 2404, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:06:29', '', '2023-10-29 11:06:29', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2410, '商机管理', '', 2, 40, 2397, 'business', 'fa:bus', 'crm/business/index', 'CrmBusiness', 0, '1', '1', '1', '', '2023-10-29 11:12:35', '1', '2024-02-17 17:14:55', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2411, '商机查询', 'crm:business:query', 3, 1, 2410, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:12:35', '', '2023-10-29 11:12:35', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2412, '商机创建', 'crm:business:create', 3, 2, 2410, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:12:35', '', '2023-10-29 11:12:35', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2413, '商机更新', 'crm:business:update', 3, 3, 2410, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:12:35', '', '2023-10-29 11:12:35', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2414, '商机删除', 'crm:business:delete', 3, 4, 2410, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:12:35', '', '2023-10-29 11:12:35', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2415, '商机导出', 'crm:business:export', 3, 5, 2410, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:12:35', '', '2023-10-29 11:12:35', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2416, '联系人管理', '', 2, 20, 2397, 'contact', 'fa:address-book-o', 'crm/contact/index', 'CrmContact', 0, '1', '1', '1', '', '2023-10-29 11:14:56', '1', '2024-02-17 17:13:49', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2417, '联系人查询', 'crm:contact:query', 3, 1, 2416, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:14:56', '', '2023-10-29 11:14:56', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2418, '联系人创建', 'crm:contact:create', 3, 2, 2416, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:14:56', '', '2023-10-29 11:14:56', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2419, '联系人更新', 'crm:contact:update', 3, 3, 2416, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:14:56', '', '2023-10-29 11:14:56', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2420, '联系人删除', 'crm:contact:delete', 3, 4, 2416, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:14:56', '', '2023-10-29 11:14:56', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2421, '联系人导出', 'crm:contact:export', 3, 5, 2416, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:14:56', '', '2023-10-29 11:14:56', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2422, '回款管理', '', 2, 60, 2397, 'receivable', 'ep:money', 'crm/receivable/index', 'CrmReceivable', 0, '1', '1', '1', '', '2023-10-29 11:18:09', '1', '2024-02-17 17:16:18', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2423, '回款管理查询', 'crm:receivable:query', 3, 1, 2422, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2424, '回款管理创建', 'crm:receivable:create', 3, 2, 2422, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2425, '回款管理更新', 'crm:receivable:update', 3, 3, 2422, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2426, '回款管理删除', 'crm:receivable:delete', 3, 4, 2422, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2427, '回款管理导出', 'crm:receivable:export', 3, 5, 2422, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2428, '回款计划', '', 2, 61, 2397, 'receivable-plan', 'fa:money', 'crm/receivable/plan/index', 'CrmReceivablePlan', 0, '1', '1', '1', '', '2023-10-29 11:18:09', '1', '2024-02-17 17:16:11', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2429, '回款计划查询', 'crm:receivable-plan:query', 3, 1, 2428, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2430, '回款计划创建', 'crm:receivable-plan:create', 3, 2, 2428, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2431, '回款计划更新', 'crm:receivable-plan:update', 3, 3, 2428, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2432, '回款计划删除', 'crm:receivable-plan:delete', 3, 4, 2428, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2433, '回款计划导出', 'crm:receivable-plan:export', 3, 5, 2428, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2435, '商城装修', '', 2, 20, 2030, 'diy-template', 'fa6-solid:brush', 'mall/promotion/diy/template/index', 'DiyTemplate', 0, '1', '1', '1', '', '2023-10-29 14:19:25', '', '2023-10-29 14:19:25', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2436, '装修模板', '', 2, 1, 2435, 'diy-template', 'fa6-solid:brush', 'mall/promotion/diy/template/index', 'DiyTemplate', 0, '1', '1', '1', '', '2023-10-29 14:19:25', '', '2023-10-29 14:19:25', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2437, '装修模板查询', 'promotion:diy-template:query', 3, 1, 2436, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 14:19:25', '', '2023-10-29 14:19:25', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2438, '装修模板创建', 'promotion:diy-template:create', 3, 2, 2436, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 14:19:25', '', '2023-10-29 14:19:25', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2439, '装修模板更新', 'promotion:diy-template:update', 3, 3, 2436, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 14:19:25', '', '2023-10-29 14:19:25', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2440, '装修模板删除', 'promotion:diy-template:delete', 3, 4, 2436, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 14:19:25', '', '2023-10-29 14:19:25', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2441, '装修模板使用', 'promotion:diy-template:use', 3, 5, 2436, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 14:19:25', '', '2023-10-29 14:19:25', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2442, '装修页面', '', 2, 2, 2435, 'diy-page', 'foundation:page-edit', 'mall/promotion/diy/page/index', 'DiyPage', 0, '1', '1', '1', '', '2023-10-29 14:19:25', '', '2023-10-29 14:19:25', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2443, '装修页面查询', 'promotion:diy-page:query', 3, 1, 2442, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 14:19:25', '', '2023-10-29 14:19:25', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2444, '装修页面创建', 'promotion:diy-page:create', 3, 2, 2442, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 14:19:26', '', '2023-10-29 14:19:26', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2445, '装修页面更新', 'promotion:diy-page:update', 3, 3, 2442, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 14:19:26', '', '2023-10-29 14:19:26', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2446, '装修页面删除', 'promotion:diy-page:delete', 3, 4, 2442, '', '', '', NULL, 0, '1', '1', '1', '', '2023-10-29 14:19:26', '', '2023-10-29 14:19:26', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2447, '三方登录', '', 1, 10, 1, 'social', 'fa:rocket', '', '', 0, '1', '1', '1', '1', '2023-11-04 12:12:01', '1', '2024-02-29 01:14:05', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2448, '三方应用', '', 2, 1, 2447, 'client', 'ep:set-up', 'views/system/social/client/index.vue', 'SocialClient', 0, '1', '1', '1', '1', '2023-11-04 12:17:19', '1', '2023-11-04 12:17:19', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2449, '三方应用查询', 'system:social-client:query', 3, 1, 2448, '', '', '', '', 0, '1', '1', '1', '1', '2023-11-04 12:43:12', '1', '2023-11-04 12:43:33', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2450, '三方应用创建', 'system:social-client:create', 3, 2, 2448, '', '', '', '', 0, '1', '1', '1', '1', '2023-11-04 12:43:58', '1', '2023-11-04 12:43:58', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2451, '三方应用更新', 'system:social-client:update', 3, 3, 2448, '', '', '', '', 0, '1', '1', '1', '1', '2023-11-04 12:44:27', '1', '2023-11-04 12:44:27', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2452, '三方应用删除', 'system:social-client:delete', 3, 4, 2448, '', '', '', '', 0, '1', '1', '1', '1', '2023-11-04 12:44:43', '1', '2023-11-04 12:44:43', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2453, '三方用户', 'system:social-user:query', 2, 2, 2447, 'user', 'ep:avatar', 'system/social/user/index.vue', 'SocialUser', 0, '1', '1', '1', '1', '2023-11-04 14:01:05', '1', '2023-11-04 14:01:05', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2472, '主子表(内嵌)', '', 2, 12, 1070, 'demo03-inner', 'fa:power-off', 'infra/demo/demo03/inner/index', 'Demo03StudentInner', 0, '1', '1', '1', '', '2023-11-13 04:39:51', '1', '2023-11-16 23:53:46', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2478, '单表(增删改查)', '', 2, 1, 1070, 'demo01-contact', 'ep:bicycle', 'infra/demo/demo01/index', 'Demo01Contact', 0, '1', '1', '1', '', '2023-11-15 14:42:30', '1', '2023-11-16 20:34:40', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2479, '示例联系人查询', 'infra:demo01-contact:query', 3, 1, 2478, '', '', '', NULL, 0, '1', '1', '1', '', '2023-11-15 14:42:30', '', '2023-11-15 14:42:30', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2480, '示例联系人创建', 'infra:demo01-contact:create', 3, 2, 2478, '', '', '', NULL, 0, '1', '1', '1', '', '2023-11-15 14:42:30', '', '2023-11-15 14:42:30', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2481, '示例联系人更新', 'infra:demo01-contact:update', 3, 3, 2478, '', '', '', NULL, 0, '1', '1', '1', '', '2023-11-15 14:42:30', '', '2023-11-15 14:42:30', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2482, '示例联系人删除', 'infra:demo01-contact:delete', 3, 4, 2478, '', '', '', NULL, 0, '1', '1', '1', '', '2023-11-15 14:42:30', '', '2023-11-15 14:42:30', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2483, '示例联系人导出', 'infra:demo01-contact:export', 3, 5, 2478, '', '', '', NULL, 0, '1', '1', '1', '', '2023-11-15 14:42:30', '', '2023-11-15 14:42:30', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2484, '树表(增删改查)', '', 2, 2, 1070, 'demo02-category', 'fa:tree', 'infra/demo/demo02/index', 'Demo02Category', 0, '1', '1', '1', '', '2023-11-16 12:18:27', '1', '2023-11-16 20:35:01', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2485, '示例分类查询', 'infra:demo02-category:query', 3, 1, 2484, '', '', '', NULL, 0, '1', '1', '1', '', '2023-11-16 12:18:27', '', '2023-11-16 12:18:27', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2486, '示例分类创建', 'infra:demo02-category:create', 3, 2, 2484, '', '', '', NULL, 0, '1', '1', '1', '', '2023-11-16 12:18:27', '', '2023-11-16 12:18:27', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2487, '示例分类更新', 'infra:demo02-category:update', 3, 3, 2484, '', '', '', NULL, 0, '1', '1', '1', '', '2023-11-16 12:18:27', '', '2023-11-16 12:18:27', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2488, '示例分类删除', 'infra:demo02-category:delete', 3, 4, 2484, '', '', '', NULL, 0, '1', '1', '1', '', '2023-11-16 12:18:27', '', '2023-11-16 12:18:27', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2489, '示例分类导出', 'infra:demo02-category:export', 3, 5, 2484, '', '', '', NULL, 0, '1', '1', '1', '', '2023-11-16 12:18:27', '', '2023-11-16 12:18:27', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2490, '主子表(标准)', '', 2, 10, 1070, 'demo03-normal', 'fa:battery-3', 'infra/demo/demo03/normal/index', 'Demo03StudentNormal', 0, '1', '1', '1', '', '2023-11-16 12:53:37', '1', '2023-11-16 23:10:03', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2491, '学生查询', 'infra:demo03-student:query', 3, 1, 2490, '', '', '', NULL, 0, '1', '1', '1', '', '2023-11-16 12:53:37', '', '2023-11-16 12:53:37', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2492, '学生创建', 'infra:demo03-student:create', 3, 2, 2490, '', '', '', NULL, 0, '1', '1', '1', '', '2023-11-16 12:53:37', '', '2023-11-16 12:53:37', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2493, '学生更新', 'infra:demo03-student:update', 3, 3, 2490, '', '', '', NULL, 0, '1', '1', '1', '', '2023-11-16 12:53:37', '', '2023-11-16 12:53:37', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2494, '学生删除', 'infra:demo03-student:delete', 3, 4, 2490, '', '', '', NULL, 0, '1', '1', '1', '', '2023-11-16 12:53:37', '', '2023-11-16 12:53:37', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2495, '学生导出', 'infra:demo03-student:export', 3, 5, 2490, '', '', '', NULL, 0, '1', '1', '1', '', '2023-11-16 12:53:37', '', '2023-11-16 12:53:37', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2497, '主子表(ERP)', '', 2, 11, 1070, 'demo03-erp', 'ep:calendar', 'infra/demo/demo03/erp/index', 'Demo03StudentERP', 0, '1', '1', '1', '', '2023-11-16 15:50:59', '1', '2023-11-17 13:19:56', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2516, '客户公海配置', '', 2, 0, 2524, 'customer-pool-config', 'ep:data-analysis', 'crm/customer/poolConfig/index', 'CrmCustomerPoolConfig', 0, '1', '1', '1', '', '2023-11-18 13:33:31', '1', '2024-01-03 19:52:06', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2517, '客户公海配置保存', 'crm:customer-pool-config:update', 3, 1, 2516, '', '', '', NULL, 0, '1', '1', '1', '', '2023-11-18 13:33:31', '', '2023-11-18 13:33:31', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2518, '客户限制配置', '', 2, 1, 2524, 'customer-limit-config', 'ep:avatar', 'crm/customer/limitConfig/index', 'CrmCustomerLimitConfig', 0, '1', '1', '1', '', '2023-11-18 13:33:53', '1', '2024-02-24 16:43:33', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2519, '客户限制配置查询', 'crm:customer-limit-config:query', 3, 1, 2518, '', '', '', NULL, 0, '1', '1', '1', '', '2023-11-18 13:33:53', '', '2023-11-18 13:33:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2520, '客户限制配置创建', 'crm:customer-limit-config:create', 3, 2, 2518, '', '', '', NULL, 0, '1', '1', '1', '', '2023-11-18 13:33:53', '', '2023-11-18 13:33:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2521, '客户限制配置更新', 'crm:customer-limit-config:update', 3, 3, 2518, '', '', '', NULL, 0, '1', '1', '1', '', '2023-11-18 13:33:53', '', '2023-11-18 13:33:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2522, '客户限制配置删除', 'crm:customer-limit-config:delete', 3, 4, 2518, '', '', '', NULL, 0, '1', '1', '1', '', '2023-11-18 13:33:53', '', '2023-11-18 13:33:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2523, '客户限制配置导出', 'crm:customer-limit-config:export', 3, 5, 2518, '', '', '', NULL, 0, '1', '1', '1', '', '2023-11-18 13:33:53', '', '2023-11-18 13:33:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2524, '系统配置', '', 1, 999, 2397, 'config', 'ep:connection', '', '', 0, '1', '1', '1', '1', '2023-11-18 21:58:00', '1', '2024-02-17 17:14:34', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2525, 'WebSocket', '', 2, 5, 2, 'websocket', 'ep:connection', 'infra/webSocket/index', 'InfraWebSocket', 0, '1', '1', '1', '1', '2023-11-23 19:41:55', '1', '2024-04-23 00:02:00', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2526, '产品管理', '', 2, 80, 2397, 'product', 'fa:product-hunt', 'crm/product/index', 'CrmProduct', 0, '1', '1', '1', '1', '2023-12-05 22:45:26', '1', '2024-02-20 20:36:20', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2527, '产品查询', 'crm:product:query', 3, 1, 2526, '', '', '', '', 0, '1', '1', '1', '1', '2023-12-05 22:47:16', '1', '2023-12-05 22:47:16', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2528, '产品创建', 'crm:product:create', 3, 2, 2526, '', '', '', '', 0, '1', '1', '1', '1', '2023-12-05 22:47:41', '1', '2023-12-05 22:47:48', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2529, '产品更新', 'crm:product:update', 3, 3, 2526, '', '', '', '', 0, '1', '1', '1', '1', '2023-12-05 22:48:03', '1', '2023-12-05 22:48:03', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2530, '产品删除', 'crm:product:delete', 3, 4, 2526, '', '', '', '', 0, '1', '1', '1', '1', '2023-12-05 22:48:17', '1', '2023-12-05 22:48:17', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2531, '产品导出', 'crm:product:export', 3, 5, 2526, '', '', '', '', 0, '1', '1', '1', '1', '2023-12-05 22:48:29', '1', '2023-12-05 22:48:29', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2532, '产品分类配置', '', 2, 3, 2524, 'product/category', 'fa-solid:window-restore', 'crm/product/category/index', 'CrmProductCategory', 0, '1', '1', '1', '1', '2023-12-06 12:52:36', '1', '2023-12-06 12:52:51', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2533, '产品分类查询', 'crm:product-category:query', 3, 1, 2532, '', '', '', '', 0, '1', '1', '1', '1', '2023-12-06 12:53:23', '1', '2023-12-06 12:53:23', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2534, '产品分类创建', 'crm:product-category:create', 3, 2, 2532, '', '', '', '', 0, '1', '1', '1', '1', '2023-12-06 12:53:41', '1', '2023-12-06 12:53:41', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2535, '产品分类更新', 'crm:product-category:update', 3, 3, 2532, '', '', '', '', 0, '1', '1', '1', '1', '2023-12-06 12:53:59', '1', '2023-12-06 12:53:59', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2536, '产品分类删除', 'crm:product-category:delete', 3, 4, 2532, '', '', '', '', 0, '1', '1', '1', '1', '2023-12-06 12:54:14', '1', '2023-12-06 12:54:14', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2543, '关联商机', 'crm:contact:create-business', 3, 10, 2416, '', '', '', '', 0, '1', '1', '1', '1', '2024-01-02 17:28:25', '1', '2024-01-02 17:28:25', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2544, '取关商机', 'crm:contact:delete-business', 3, 11, 2416, '', '', '', '', 0, '1', '1', '1', '1', '2024-01-02 17:28:43', '1', '2024-01-02 17:28:51', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2545, '商品统计', '', 2, 3, 2358, 'product', 'fa:product-hunt', 'mall/statistics/product/index', 'ProductStatistics', 0, '1', '1', '1', '', '2023-12-15 18:54:28', '1', '2024-02-26 20:41:52', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2546, '客户公海', '', 2, 30, 2397, 'customer/pool', 'fa-solid:swimming-pool', 'crm/customer/pool/index', 'CrmCustomerPool', 0, '1', '1', '1', '1', '2024-01-15 21:29:34', '1', '2024-02-17 17:14:18', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2547, '订单查询', 'trade:order:query', 3, 1, 2076, '', '', '', '', 0, '1', '1', '1', '1', '2024-01-16 08:52:00', '1', '2024-01-16 08:52:00', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2548, '订单更新', 'trade:order:update', 3, 2, 2076, '', '', '', '', 0, '1', '1', '1', '1', '2024-01-16 08:52:21', '1', '2024-01-16 08:52:21', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2549, '支付&退款案例', '', 2, 1, 2161, 'order', 'fa:paypal', 'pay/demo/order/index', '', 0, '1', '1', '1', '1', '2024-01-18 23:45:00', '1', '2024-01-18 23:47:21', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2550, '转账案例', '', 2, 2, 2161, 'transfer', 'fa:transgender-alt', 'pay/demo/transfer/index', '', 0, '1', '1', '1', '1', '2024-01-18 23:51:16', '1', '2024-01-18 23:51:16', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2551, '钱包管理', '', 1, 4, 1117, 'wallet', 'ep:wallet', '', '', 0, '1', '1', '1', '', '2023-12-29 02:32:54', '1', '2024-02-29 08:58:54', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2552, '充值套餐', '', 2, 2, 2551, 'wallet-recharge-package', 'fa:leaf', 'pay/wallet/rechargePackage/index', 'WalletRechargePackage', 0, '1', '1', '1', '', '2023-12-29 02:32:54', '', '2023-12-29 02:32:54', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2553, '钱包充值套餐查询', 'pay:wallet-recharge-package:query', 3, 1, 2552, '', '', '', NULL, 0, '1', '1', '1', '', '2023-12-29 02:32:54', '', '2023-12-29 02:32:54', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2554, '钱包充值套餐创建', 'pay:wallet-recharge-package:create', 3, 2, 2552, '', '', '', NULL, 0, '1', '1', '1', '', '2023-12-29 02:32:54', '', '2023-12-29 02:32:54', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2555, '钱包充值套餐更新', 'pay:wallet-recharge-package:update', 3, 3, 2552, '', '', '', NULL, 0, '1', '1', '1', '', '2023-12-29 02:32:54', '', '2023-12-29 02:32:54', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2556, '钱包充值套餐删除', 'pay:wallet-recharge-package:delete', 3, 4, 2552, '', '', '', NULL, 0, '1', '1', '1', '', '2023-12-29 02:32:54', '', '2023-12-29 02:32:54', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2557, '钱包余额', '', 2, 1, 2551, 'wallet-balance', 'fa:leaf', 'pay/wallet/balance/index', 'WalletBalance', 0, '1', '1', '1', '', '2023-12-29 02:32:54', '', '2023-12-29 02:32:54', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2558, '钱包余额查询', 'pay:wallet:query', 3, 1, 2557, '', '', '', NULL, 0, '1', '1', '1', '', '2023-12-29 02:32:54', '', '2023-12-29 02:32:54', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2559, '转账订单', '', 2, 3, 1117, 'transfer', 'ep:credit-card', 'pay/transfer/index', 'PayTransfer', 0, '1', '1', '1', '', '2023-12-29 02:32:54', '', '2023-12-29 02:32:54', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2560, '数据统计', '', 1, 200, 2397, 'statistics', 'ep:data-line', '', '', 0, '1', '1', '1', '1', '2024-01-26 22:50:35', '1', '2024-02-24 20:10:07', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2561, '排行榜', 'crm:statistics-rank:query', 2, 1, 2560, 'ranking', 'fa:area-chart', 'crm/statistics/rank/index', 'CrmStatisticsRank', 0, '1', '1', '1', '1', '2024-01-26 22:52:09', '1', '2024-04-24 19:39:11', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2562, '客户导入', 'crm:customer:import', 3, 6, 2391, '', '', '', '', 0, '1', '1', '1', '1', '2024-02-01 13:09:00', '1', '2024-02-01 13:09:05', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2563, 'ERP 系统', '', 1, 300, 0, '/erp', 'fa-solid:store', '', '', 0, '1', '1', '1', '1', '2024-02-04 15:37:25', '1', '2024-02-04 15:37:25', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2564, '产品管理', '', 1, 40, 2563, 'product', 'fa:product-hunt', '', '', 0, '1', '1', '1', '1', '2024-02-04 15:38:43', '1', '2024-02-04 15:38:43', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2565, '产品信息', '', 2, 0, 2564, 'product', 'fa-solid:apple-alt', 'erp/product/product/index', 'ErpProduct', 0, '1', '1', '1', '', '2024-02-04 07:52:15', '1', '2024-02-05 14:42:11', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2566, '产品查询', 'erp:product:query', 3, 1, 2565, '', '', '', '', 0, '1', '1', '1', '', '2024-02-04 07:52:15', '1', '2024-02-04 17:21:57', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2567, '产品创建', 'erp:product:create', 3, 2, 2565, '', '', '', '', 0, '1', '1', '1', '', '2024-02-04 07:52:15', '1', '2024-02-04 17:22:12', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2568, '产品更新', 'erp:product:update', 3, 3, 2565, '', '', '', '', 0, '1', '1', '1', '', '2024-02-04 07:52:15', '1', '2024-02-04 17:22:16', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2569, '产品删除', 'erp:product:delete', 3, 4, 2565, '', '', '', '', 0, '1', '1', '1', '', '2024-02-04 07:52:15', '1', '2024-02-04 17:22:22', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2570, '产品导出', 'erp:product:export', 3, 5, 2565, '', '', '', '', 0, '1', '1', '1', '', '2024-02-04 07:52:15', '1', '2024-02-04 17:22:26', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2571, '产品分类', '', 2, 1, 2564, 'product-category', 'fa:certificate', 'erp/product/category/index', 'ErpProductCategory', 0, '1', '1', '1', '', '2024-02-04 09:21:04', '1', '2024-02-04 17:24:58', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2572, '分类查询', 'erp:product-category:query', 3, 1, 2571, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-04 09:21:04', '', '2024-02-04 09:21:04', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2573, '分类创建', 'erp:product-category:create', 3, 2, 2571, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-04 09:21:04', '', '2024-02-04 09:21:04', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2574, '分类更新', 'erp:product-category:update', 3, 3, 2571, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-04 09:21:04', '', '2024-02-04 09:21:04', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2575, '分类删除', 'erp:product-category:delete', 3, 4, 2571, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-04 09:21:04', '', '2024-02-04 09:21:04', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2576, '分类导出', 'erp:product-category:export', 3, 5, 2571, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-04 09:21:04', '', '2024-02-04 09:21:04', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2577, '产品单位', '', 2, 2, 2564, 'unit', 'ep:opportunity', 'erp/product/unit/index', 'ErpProductUnit', 0, '1', '1', '1', '', '2024-02-04 11:54:08', '1', '2024-02-04 19:54:37', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2578, '单位查询', 'erp:product-unit:query', 3, 1, 2577, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-04 11:54:08', '', '2024-02-04 11:54:08', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2579, '单位创建', 'erp:product-unit:create', 3, 2, 2577, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-04 11:54:08', '', '2024-02-04 11:54:08', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2580, '单位更新', 'erp:product-unit:update', 3, 3, 2577, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-04 11:54:08', '', '2024-02-04 11:54:08', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2581, '单位删除', 'erp:product-unit:delete', 3, 4, 2577, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-04 11:54:08', '', '2024-02-04 11:54:08', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2582, '单位导出', 'erp:product-unit:export', 3, 5, 2577, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-04 11:54:08', '', '2024-02-04 11:54:08', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2583, '库存管理', '', 1, 30, 2563, 'stock', 'fa:window-restore', '', '', 0, '1', '1', '1', '1', '2024-02-05 00:29:37', '1', '2024-02-05 00:29:37', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2584, '仓库信息', '', 2, 0, 2583, 'warehouse', 'ep:house', 'erp/stock/warehouse/index', 'ErpWarehouse', 0, '1', '1', '1', '', '2024-02-04 17:12:09', '1', '2024-02-05 01:12:53', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2585, '仓库查询', 'erp:warehouse:query', 3, 1, 2584, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-04 17:12:09', '', '2024-02-04 17:12:09', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2586, '仓库创建', 'erp:warehouse:create', 3, 2, 2584, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-04 17:12:09', '', '2024-02-04 17:12:09', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2587, '仓库更新', 'erp:warehouse:update', 3, 3, 2584, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-04 17:12:09', '', '2024-02-04 17:12:09', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2588, '仓库删除', 'erp:warehouse:delete', 3, 4, 2584, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-04 17:12:09', '', '2024-02-04 17:12:09', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2589, '仓库导出', 'erp:warehouse:export', 3, 5, 2584, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-04 17:12:09', '', '2024-02-04 17:12:09', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2590, '产品库存', '', 2, 1, 2583, 'stock', 'ep:coffee', 'erp/stock/stock/index', 'ErpStock', 0, '1', '1', '1', '', '2024-02-05 06:40:50', '1', '2024-02-05 14:42:44', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2591, '库存查询', 'erp:stock:query', 3, 1, 2590, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 06:40:50', '', '2024-02-05 06:40:50', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2592, '库存导出', 'erp:stock:export', 3, 5, 2590, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 06:40:50', '', '2024-02-05 06:40:50', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2593, '出入库明细', '', 2, 2, 2583, 'record', 'fa-solid:blog', 'erp/stock/record/index', 'ErpStockRecord', 0, '1', '1', '1', '', '2024-02-05 10:27:21', '1', '2024-02-06 17:26:11', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2594, '库存明细查询', 'erp:stock-record:query', 3, 1, 2593, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 10:27:21', '', '2024-02-05 10:27:21', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2595, '库存明细导出', 'erp:stock-record:export', 3, 5, 2593, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 10:27:21', '', '2024-02-05 10:27:21', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2596, '其它入库', '', 2, 3, 2583, 'in', 'ep:zoom-in', 'erp/stock/in/index', 'ErpStockIn', 0, '1', '1', '1', '', '2024-02-05 16:08:56', '1', '2024-02-07 19:06:51', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2597, '其它入库单查询', 'erp:stock-in:query', 3, 1, 2596, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-05 16:08:56', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2598, '其它入库单创建', 'erp:stock-in:create', 3, 2, 2596, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-05 16:08:56', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2599, '其它入库单更新', 'erp:stock-in:update', 3, 3, 2596, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-05 16:08:56', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2600, '其它入库单删除', 'erp:stock-in:delete', 3, 4, 2596, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-05 16:08:56', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2601, '其它入库单导出', 'erp:stock-in:export', 3, 5, 2596, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-05 16:08:56', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2602, '采购管理', '', 1, 10, 2563, 'purchase', 'fa:buysellads', '', '', 0, '1', '1', '1', '1', '2024-02-06 16:01:01', '1', '2024-02-06 16:01:23', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2603, '供应商信息', '', 2, 4, 2602, 'supplier', 'fa:superpowers', 'erp/purchase/supplier/index', 'ErpSupplier', 0, '1', '1', '1', '', '2024-02-06 08:21:55', '1', '2024-02-06 16:22:25', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2604, '供应商查询', 'erp:supplier:query', 3, 1, 2603, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-06 08:21:55', '', '2024-02-06 08:21:55', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2605, '供应商创建', 'erp:supplier:create', 3, 2, 2603, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-06 08:21:55', '', '2024-02-06 08:21:55', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2606, '供应商更新', 'erp:supplier:update', 3, 3, 2603, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-06 08:21:55', '', '2024-02-06 08:21:55', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2607, '供应商删除', 'erp:supplier:delete', 3, 4, 2603, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-06 08:21:55', '', '2024-02-06 08:21:55', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2608, '供应商导出', 'erp:supplier:export', 3, 5, 2603, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-06 08:21:55', '', '2024-02-06 08:21:55', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2609, '其它入库单审批', 'erp:stock-in:update-status', 3, 6, 2596, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-05 16:08:56', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2610, '其它出库', '', 2, 4, 2583, 'out', 'ep:zoom-out', 'erp/stock/out/index', 'ErpStockOut', 0, '1', '1', '1', '', '2024-02-05 16:08:56', '1', '2024-02-07 19:06:55', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2611, '其它出库单查询', 'erp:stock-out:query', 3, 1, 2610, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 06:43:39', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2612, '其它出库单创建', 'erp:stock-out:create', 3, 2, 2610, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 06:43:42', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2613, '其它出库单更新', 'erp:stock-out:update', 3, 3, 2610, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 06:43:44', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2614, '其它出库单删除', 'erp:stock-out:delete', 3, 4, 2610, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 06:43:56', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2615, '其它出库单导出', 'erp:stock-out:export', 3, 5, 2610, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 06:43:57', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2616, '其它出库单审批', 'erp:stock-out:update-status', 3, 6, 2610, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 06:43:58', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2617, '销售管理', '', 1, 20, 2563, 'sale', 'fa:sellsy', '', '', 0, '1', '1', '1', '1', '2024-02-07 15:12:32', '1', '2024-02-07 15:12:32', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2618, '客户信息', '', 2, 4, 2617, 'customer', 'ep:avatar', 'erp/sale/customer/index', 'ErpCustomer', 0, '1', '1', '1', '', '2024-02-07 07:21:45', '1', '2024-02-07 15:22:25', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2619, '客户查询', 'erp:customer:query', 3, 1, 2618, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-07 07:21:45', '', '2024-02-07 07:21:45', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2620, '客户创建', 'erp:customer:create', 3, 2, 2618, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-07 07:21:45', '', '2024-02-07 07:21:45', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2621, '客户更新', 'erp:customer:update', 3, 3, 2618, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-07 07:21:45', '', '2024-02-07 07:21:45', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2622, '客户删除', 'erp:customer:delete', 3, 4, 2618, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-07 07:21:45', '', '2024-02-07 07:21:45', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2623, '客户导出', 'erp:customer:export', 3, 5, 2618, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-07 07:21:45', '', '2024-02-07 07:21:45', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2624, '库存调拨', '', 2, 5, 2583, 'move', 'ep:folder-remove', 'erp/stock/move/index', 'ErpStockMove', 0, '1', '1', '1', '', '2024-02-05 16:08:56', '1', '2024-02-16 18:53:55', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2625, '库存调度单查询', 'erp:stock-move:query', 3, 1, 2624, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:49', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2626, '库存调度单创建', 'erp:stock-move:create', 3, 2, 2624, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:52', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2627, '库存调度单更新', 'erp:stock-move:update', 3, 3, 2624, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:55', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2628, '库存调度单删除', 'erp:stock-move:delete', 3, 4, 2624, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:57', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2629, '库存调度单导出', 'erp:stock-move:export', 3, 5, 2624, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:59', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2630, '库存调度单审批', 'erp:stock-move:update-status', 3, 6, 2624, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:13:03', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2631, '库存盘点', '', 2, 6, 2583, 'check', 'ep:circle-check-filled', 'erp/stock/check/index', 'ErpStockCheck', 0, '1', '1', '1', '', '2024-02-05 16:08:56', '1', '2024-02-08 08:31:09', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2632, '库存盘点单查询', 'erp:stock-check:query', 3, 1, 2631, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:49', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2633, '库存盘点单创建', 'erp:stock-check:create', 3, 2, 2631, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:52', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2634, '库存盘点单更新', 'erp:stock-check:update', 3, 3, 2631, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:55', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2635, '库存盘点单删除', 'erp:stock-check:delete', 3, 4, 2631, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:57', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2636, '库存盘点单导出', 'erp:stock-check:export', 3, 5, 2631, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:59', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2637, '库存盘点单审批', 'erp:stock-check:update-status', 3, 6, 2631, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:13:03', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2638, '销售订单', '', 2, 1, 2617, 'order', 'fa:first-order', 'erp/sale/order/index', 'ErpSaleOrder', 0, '1', '1', '1', '', '2024-02-05 16:08:56', '1', '2024-02-10 21:59:20', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2639, '销售订单查询', 'erp:sale-order:query', 3, 1, 2638, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:49', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2640, '销售订单创建', 'erp:sale-order:create', 3, 2, 2638, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:52', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2641, '销售订单更新', 'erp:sale-order:update', 3, 3, 2638, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:55', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2642, '销售订单删除', 'erp:sale-order:delete', 3, 4, 2638, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:57', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2643, '销售订单导出', 'erp:sale-order:export', 3, 5, 2638, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:59', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2644, '销售订单审批', 'erp:sale-order:update-status', 3, 6, 2638, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:13:03', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2645, '财务管理', '', 1, 50, 2563, 'finance', 'ep:money', '', '', 0, '1', '1', '1', '1', '2024-02-10 08:05:58', '1', '2024-02-10 08:06:07', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2646, '结算账户', '', 2, 10, 2645, 'account', 'fa:universal-access', 'erp/finance/account/index', 'ErpAccount', 0, '1', '1', '1', '', '2024-02-10 00:15:07', '1', '2024-02-14 08:24:31', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2647, '结算账户查询', 'erp:account:query', 3, 1, 2646, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-10 00:15:07', '', '2024-02-10 00:15:07', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2648, '结算账户创建', 'erp:account:create', 3, 2, 2646, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-10 00:15:07', '', '2024-02-10 00:15:07', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2649, '结算账户更新', 'erp:account:update', 3, 3, 2646, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-10 00:15:07', '', '2024-02-10 00:15:07', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2650, '结算账户删除', 'erp:account:delete', 3, 4, 2646, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-10 00:15:07', '', '2024-02-10 00:15:07', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2651, '结算账户导出', 'erp:account:export', 3, 5, 2646, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-10 00:15:07', '', '2024-02-10 00:15:07', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2652, '销售出库', '', 2, 2, 2617, 'out', 'ep:sold-out', 'erp/sale/out/index', 'ErpSaleOut', 0, '1', '1', '1', '', '2024-02-05 16:08:56', '1', '2024-02-10 22:02:07', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2653, '销售出库查询', 'erp:sale-out:query', 3, 1, 2652, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:49', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2654, '销售出库创建', 'erp:sale-out:create', 3, 2, 2652, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:52', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2655, '销售出库更新', 'erp:sale-out:update', 3, 3, 2652, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:55', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2656, '销售出库删除', 'erp:sale-out:delete', 3, 4, 2652, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:57', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2657, '销售出库导出', 'erp:sale-out:export', 3, 5, 2652, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:59', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2658, '销售出库审批', 'erp:sale-out:update-status', 3, 6, 2652, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:13:03', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2659, '销售退货', '', 2, 3, 2617, 'return', 'fa-solid:bone', 'erp/sale/return/index', 'ErpSaleReturn', 0, '1', '1', '1', '', '2024-02-05 16:08:56', '1', '2024-02-12 06:12:58', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2660, '销售退货查询', 'erp:sale-return:query', 3, 1, 2659, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:49', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2661, '销售退货创建', 'erp:sale-return:create', 3, 2, 2659, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:52', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2662, '销售退货更新', 'erp:sale-return:update', 3, 3, 2659, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:55', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2663, '销售退货删除', 'erp:sale-return:delete', 3, 4, 2659, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:57', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2664, '销售退货导出', 'erp:sale-return:export', 3, 5, 2659, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:59', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2665, '销售退货审批', 'erp:sale-return:update-status', 3, 6, 2659, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:13:03', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2666, '采购订单', '', 2, 1, 2602, 'order', 'fa-solid:border-all', 'erp/purchase/order/index', 'ErpPurchaseOrder', 0, '1', '1', '1', '', '2024-02-05 16:08:56', '1', '2024-02-12 08:51:49', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2667, '采购订单查询', 'erp:purchase-order:query', 3, 1, 2666, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:17', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2668, '采购订单创建', 'erp:purchase-order:create', 3, 2, 2666, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:54', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2669, '采购订单更新', 'erp:purchase-order:update', 3, 3, 2666, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:58', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2670, '采购订单删除', 'erp:purchase-order:delete', 3, 4, 2666, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:00', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2671, '采购订单导出', 'erp:purchase-order:export', 3, 5, 2666, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:05', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2672, '采购订单审批', 'erp:purchase-order:update-status', 3, 6, 2666, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:08', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2673, '采购入库', '', 2, 2, 2602, 'in', 'fa-solid:gopuram', 'erp/purchase/in/index', 'ErpPurchaseIn', 0, '1', '1', '1', '', '2024-02-05 16:08:56', '1', '2024-02-12 11:19:27', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2674, '采购入库查询', 'erp:purchase-in:query', 3, 1, 2673, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:17', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2675, '采购入库创建', 'erp:purchase-in:create', 3, 2, 2673, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:54', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2676, '采购入库更新', 'erp:purchase-in:update', 3, 3, 2673, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:58', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2677, '采购入库删除', 'erp:purchase-in:delete', 3, 4, 2673, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:00', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2678, '采购入库导出', 'erp:purchase-in:export', 3, 5, 2673, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:05', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2679, '采购入库审批', 'erp:purchase-in:update-status', 3, 6, 2673, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:08', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2680, '采购退货', '', 2, 3, 2602, 'return', 'ep:minus', 'erp/purchase/return/index', 'ErpPurchaseReturn', 0, '1', '1', '1', '', '2024-02-05 16:08:56', '1', '2024-02-12 20:51:02', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2681, '采购退货查询', 'erp:purchase-return:query', 3, 1, 2680, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:17', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2682, '采购退货创建', 'erp:purchase-return:create', 3, 2, 2680, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:54', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2683, '采购退货更新', 'erp:purchase-return:update', 3, 3, 2680, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:58', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2684, '采购退货删除', 'erp:purchase-return:delete', 3, 4, 2680, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:00', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2685, '采购退货导出', 'erp:purchase-return:export', 3, 5, 2680, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:05', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2686, '采购退货审批', 'erp:purchase-return:update-status', 3, 6, 2680, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:08', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2687, '付款单', '', 2, 1, 2645, 'payment', 'ep:caret-right', 'erp/finance/payment/index', 'ErpFinancePayment', 0, '1', '1', '1', '', '2024-02-05 16:08:56', '1', '2024-02-14 08:24:23', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2688, '付款单查询', 'erp:finance-payment:query', 3, 1, 2687, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:17', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2689, '付款单创建', 'erp:finance-payment:create', 3, 2, 2687, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:54', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2690, '付款单更新', 'erp:finance-payment:update', 3, 3, 2687, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:58', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2691, '付款单删除', 'erp:finance-payment:delete', 3, 4, 2687, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:00', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2692, '付款单导出', 'erp:finance-payment:export', 3, 5, 2687, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:05', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2693, '付款单审批', 'erp:finance-payment:update-status', 3, 6, 2687, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:08', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2694, '收款单', '', 2, 2, 2645, 'receipt', 'ep:expand', 'erp/finance/receipt/index', 'ErpFinanceReceipt', 0, '1', '1', '1', '', '2024-02-05 16:08:56', '1', '2024-02-15 19:35:45', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2695, '收款单查询', 'erp:finance-receipt:query', 3, 1, 2694, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:17', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2696, '收款单创建', 'erp:finance-receipt:create', 3, 2, 2694, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:54', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2697, '收款单更新', 'erp:finance-receipt:update', 3, 3, 2694, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:58', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2698, '收款单删除', 'erp:finance-receipt:delete', 3, 4, 2694, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:00', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2699, '收款单导出', 'erp:finance-receipt:export', 3, 5, 2694, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:05', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2700, '收款单审批', 'erp:finance-receipt:update-status', 3, 6, 2694, '', '', '', NULL, 0, '1', '1', '1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:08', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2701, '待办事项', '', 2, 0, 2397, 'backlog', 'fa-solid:tasks', 'crm/backlog/index', 'CrmBacklog', 0, '1', '1', '1', '1', '2024-02-17 17:17:11', '1', '2024-02-17 17:17:11', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2702, 'ERP 首页', 'erp:statistics:query', 2, 0, 2563, 'home', 'ep:home-filled', 'erp/home/index.vue', 'ErpHome', 0, '1', '1', '1', '1', '2024-02-18 16:49:40', '1', '2024-02-26 21:12:18', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2703, '商机状态配置', '', 2, 4, 2524, 'business-status', 'fa-solid:charging-station', 'crm/business/status/index', 'CrmBusinessStatus', 0, '1', '1', '1', '1', '2024-02-21 20:15:17', '1', '2024-02-21 20:15:17', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2704, '商机状态查询', 'crm:business-status:query', 3, 1, 2703, '', '', '', '', 0, '1', '1', '1', '1', '2024-02-21 20:35:36', '1', '2024-02-21 20:36:06', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2705, '商机状态创建', 'crm:business-status:create', 3, 2, 2703, '', '', '', '', 0, '1', '1', '1', '1', '2024-02-21 20:35:57', '1', '2024-02-21 20:35:57', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2706, '商机状态更新', 'crm:business-status:update', 3, 3, 2703, '', '', '', '', 0, '1', '1', '1', '1', '2024-02-21 20:36:21', '1', '2024-02-21 20:36:21', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2707, '商机状态删除', 'crm:business-status:delete', 3, 4, 2703, '', '', '', '', 0, '1', '1', '1', '1', '2024-02-21 20:36:36', '1', '2024-02-21 20:36:36', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2708, '合同配置', '', 2, 5, 2524, 'contract-config', 'ep:connection', 'crm/contract/config/index', 'CrmContractConfig', 0, '1', '1', '1', '1', '2024-02-24 16:44:40', '1', '2024-02-24 16:44:48', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2709, '客户公海配置查询', 'crm:customer-pool-config:query', 3, 2, 2516, '', '', '', '', 0, '1', '1', '1', '1', '2024-02-24 16:45:19', '1', '2024-02-24 16:45:28', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2710, '合同配置更新', 'crm:contract-config:update', 3, 1, 2708, '', '', '', '', 0, '1', '1', '1', '1', '2024-02-24 16:45:56', '1', '2024-02-24 16:45:56', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2711, '合同配置查询', 'crm:contract-config:query', 3, 2, 2708, '', '', '', '', 0, '1', '1', '1', '1', '2024-02-24 16:46:16', '1', '2024-02-24 16:46:16', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2712, '客户分析', 'crm:statistics-customer:query', 2, 0, 2560, 'customer', 'ep:avatar', 'views/crm/statistics/customer/index.vue', 'CrmStatisticsCustomer', 0, '1', '1', '1', '1', '2024-03-09 16:43:56', '1', '2024-04-24 19:42:52', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2713, '抄送我的', 'bpm:process-instance-cc:query', 2, 30, 1200, 'copy', 'ep:copy-document', 'bpm/task/copy/index', 'BpmProcessInstanceCopy', 0, '1', '1', '1', '1', '2024-03-17 21:50:23', '1', '2024-04-24 19:55:12', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2714, '流程分类', '', 2, 3, 1186, 'category', 'fa:object-ungroup', 'bpm/category/index', 'BpmCategory', 0, '1', '1', '1', '', '2024-03-08 02:00:51', '1', '2024-03-21 23:51:18', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2715, '分类查询', 'bpm:category:query', 3, 1, 2714, '', '', '', '', 0, '1', '1', '1', '', '2024-03-08 02:00:51', '1', '2024-03-19 14:36:25', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2716, '分类创建', 'bpm:category:create', 3, 2, 2714, '', '', '', '', 0, '1', '1', '1', '', '2024-03-08 02:00:51', '1', '2024-03-19 14:36:31', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2717, '分类更新', 'bpm:category:update', 3, 3, 2714, '', '', '', '', 0, '1', '1', '1', '', '2024-03-08 02:00:51', '1', '2024-03-19 14:36:35', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2718, '分类删除', 'bpm:category:delete', 3, 4, 2714, '', '', '', '', 0, '1', '1', '1', '', '2024-03-08 02:00:51', '1', '2024-03-19 14:36:41', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2720, '发起流程', '', 2, 0, 1200, 'create', 'fa-solid:grin-stars', 'bpm/processInstance/create/index', 'BpmProcessInstanceCreate', 0, '1', '0', '1', '1', '2024-03-19 19:46:05', '1', '2024-03-23 19:03:42', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2721, '流程实例', '', 2, 10, 1186, 'process-instance/manager', 'fa:square', 'bpm/processInstance/manager/index', 'BpmProcessInstanceManager', 0, '1', '1', '1', '1', '2024-03-21 23:57:30', '1', '2024-03-21 23:57:30', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2722, '流程实例的查询(管理员)', 'bpm:process-instance:manager-query', 3, 1, 2721, '', '', '', '', 0, '1', '1', '1', '1', '2024-03-22 08:18:27', '1', '2024-03-22 08:19:05', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2723, '流程实例的取消(管理员)', 'bpm:process-instance:cancel-by-admin', 3, 2, 2721, '', '', '', '', 0, '1', '1', '1', '1', '2024-03-22 08:19:25', '1', '2024-03-22 08:19:25', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2724, '流程任务', '', 2, 11, 1186, 'process-tasnk', 'ep:collection-tag', 'bpm/task/manager/index', 'BpmManagerTask', 0, '1', '1', '1', '1', '2024-03-22 08:43:22', '1', '2024-03-22 08:43:27', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2725, '流程任务的查询(管理员)', 'bpm:task:mananger-query', 3, 1, 2724, '', '', '', '', 0, '1', '1', '1', '1', '2024-03-22 08:43:49', '1', '2024-03-22 08:43:49', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2726, '流程监听器', '', 2, 5, 1186, 'process-listener', 'fa:assistive-listening-systems', 'bpm/processListener/index', 'BpmProcessListener', 0, '1', '1', '1', '', '2024-03-09 16:05:34', '1', '2024-03-23 13:13:38', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2727, '流程监听器查询', 'bpm:process-listener:query', 3, 1, 2726, '', '', '', NULL, 0, '1', '1', '1', '', '2024-03-09 16:05:34', '', '2024-03-09 16:05:34', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2728, '流程监听器创建', 'bpm:process-listener:create', 3, 2, 2726, '', '', '', NULL, 0, '1', '1', '1', '', '2024-03-09 16:05:34', '', '2024-03-09 16:05:34', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2729, '流程监听器更新', 'bpm:process-listener:update', 3, 3, 2726, '', '', '', NULL, 0, '1', '1', '1', '', '2024-03-09 16:05:34', '', '2024-03-09 16:05:34', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2730, '流程监听器删除', 'bpm:process-listener:delete', 3, 4, 2726, '', '', '', NULL, 0, '1', '1', '1', '', '2024-03-09 16:05:34', '', '2024-03-09 16:05:34', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2731, '流程表达式', '', 2, 6, 1186, 'process-expression', 'fa:wpexplorer', 'bpm/processExpression/index', 'BpmProcessExpression', 0, '1', '1', '1', '', '2024-03-09 22:35:08', '1', '2024-03-23 19:43:05', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2732, '流程表达式查询', 'bpm:process-expression:query', 3, 1, 2731, '', '', '', NULL, 0, '1', '1', '1', '', '2024-03-09 22:35:08', '', '2024-03-09 22:35:08', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2733, '流程表达式创建', 'bpm:process-expression:create', 3, 2, 2731, '', '', '', NULL, 0, '1', '1', '1', '', '2024-03-09 22:35:08', '', '2024-03-09 22:35:08', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2734, '流程表达式更新', 'bpm:process-expression:update', 3, 3, 2731, '', '', '', NULL, 0, '1', '1', '1', '', '2024-03-09 22:35:08', '', '2024-03-09 22:35:08', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2735, '流程表达式删除', 'bpm:process-expression:delete', 3, 4, 2731, '', '', '', NULL, 0, '1', '1', '1', '', '2024-03-09 22:35:08', '', '2024-03-09 22:35:08', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2736, '员工业绩', 'crm:statistics-performance:query', 2, 3, 2560, 'performance', 'ep:dish-dot', 'crm/statistics/performance/index', 'CrmStatisticsPerformance', 0, '1', '1', '1', '1', '2024-04-05 13:49:20', '1', '2024-04-24 19:42:43', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2737, '客户画像', 'crm:statistics-portrait:query', 2, 4, 2560, 'portrait', 'ep:picture', 'crm/statistics/portrait/index', 'CrmStatisticsPortrait', 0, '1', '1', '1', '1', '2024-04-05 13:57:40', '1', '2024-04-24 19:42:24', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2738, '销售漏斗', 'crm:statistics-funnel:query', 2, 5, 2560, 'funnel', 'ep:grape', 'crm/statistics/funnel/index', 'CrmStatisticsFunnel', 0, '1', '1', '1', '1', '2024-04-13 10:53:26', '1', '2024-04-24 19:39:33', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2739, '消息中心', '', 1, 7, 1, 'messages', 'ep:chat-dot-round', '', '', 0, '1', '1', '1', '1', '2024-04-22 23:54:30', '1', '2024-04-23 09:36:35', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2740, '监控中心', '', 1, 10, 2, 'monitors', 'ep:monitor', '', '', 0, '1', '1', '1', '1', '2024-04-23 00:04:44', '1', '2024-04-23 00:04:44', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2741, '领取公海客户', 'crm:customer:receive', 3, 1, 2546, '', '', '', '', 0, '1', '1', '1', '1', '2024-04-24 19:47:45', '1', '2024-04-24 19:47:45', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2742, '分配公海客户', 'crm:customer:distribute', 3, 2, 2546, '', '', '', '', 0, '1', '1', '1', '1', '2024-04-24 19:48:05', '1', '2024-04-24 19:48:05', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2743, '商品统计查询', 'statistics:product:query', 3, 1, 2545, '', '', '', '', 0, '1', '1', '1', '1', '2024-04-24 19:50:05', '1', '2024-04-24 19:50:05', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2744, '商品统计导出', 'statistics:product:export', 3, 2, 2545, '', '', '', '', 0, '1', '1', '1', '1', '2024-04-24 19:50:26', '1', '2024-04-24 19:50:26', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2745, '支付渠道查询', 'pay:channel:query', 3, 10, 1126, '', '', '', '', 0, '1', '1', '1', '1', '2024-04-24 19:53:01', '1', '2024-04-24 19:53:01', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2746, '支付渠道创建', 'pay:channel:create', 3, 11, 1126, '', '', '', '', 0, '1', '1', '1', '1', '2024-04-24 19:53:18', '1', '2024-04-24 19:53:18', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2747, '支付渠道更新', 'pay:channel:update', 3, 12, 1126, '', '', '', '', 0, '1', '1', '1', '1', '2024-04-24 19:53:32', '1', '2024-04-24 19:53:58', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2748, '支付渠道删除', 'pay:channel:delete', 3, 13, 1126, '', '', '', '', 0, '1', '1', '1', '1', '2024-04-24 19:54:34', '1', '2024-04-24 19:54:34', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2749, '商品收藏查询', 'product:favorite:query', 3, 10, 2014, '', '', '', '', 0, '1', '1', '1', '1', '2024-04-24 19:55:47', '1', '2024-04-24 19:55:47', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2750, '商品浏览查询', 'product:browse-history:query', 3, 20, 2014, '', '', '', '', 0, '1', '1', '1', '1', '2024-04-24 19:57:43', '1', '2024-04-24 19:57:43', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2751, '售后同意', 'trade:after-sale:agree', 3, 2, 2073, '', '', '', '', 0, '1', '1', '1', '1', '2024-04-24 19:58:40', '1', '2024-04-24 19:58:40', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2752, '售后不同意', 'trade:after-sale:disagree', 3, 3, 2073, '', '', '', '', 0, '1', '1', '1', '1', '2024-04-24 19:59:03', '1', '2024-04-24 19:59:03', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2753, '售后确认退货', 'trade:after-sale:receive', 3, 4, 2073, '', '', '', '', 0, '1', '1', '1', '1', '2024-04-24 20:00:07', '1', '2024-04-24 20:00:07', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2754, '售后确认退款', 'trade:after-sale:refund', 3, 5, 2073, '', '', '', '', 0, '1', '1', '1', '1', '2024-04-24 20:00:24', '1', '2024-04-24 20:00:24', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2755, '删除项目', 'report:go-view-project:delete', 3, 2, 2153, '', '', '', '', 0, '1', '1', '1', '1', '2024-04-24 20:01:37', '1', '2024-04-24 20:01:37', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2756, '会员等级记录查询', 'member:level-record:query', 3, 10, 2325, '', '', '', '', 0, '1', '1', '1', '1', '2024-04-24 20:02:32', '1', '2024-04-24 20:02:32', '0'); +INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES (2757, '会员经验记录查询', 'member:experience-record:query', 3, 11, 2325, '', '', '', '', 0, '1', '1', '1', '1', '2024-04-24 20:02:51', '1', '2024-04-24 20:02:51', '0'); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS system_menu_seq; +CREATE SEQUENCE system_menu_seq + START 2758; + +-- ---------------------------- +-- Table structure for system_notice +-- ---------------------------- +DROP TABLE IF EXISTS system_notice; +CREATE TABLE system_notice +( + id int8 NOT NULL, + title varchar(50) NOT NULL, + content text NOT NULL, + type int2 NOT NULL, + status int2 NOT NULL DEFAULT 0, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_notice + ADD CONSTRAINT pk_system_notice PRIMARY KEY (id); + +COMMENT ON COLUMN system_notice.id IS '公告ID'; +COMMENT ON COLUMN system_notice.title IS '公告标题'; +COMMENT ON COLUMN system_notice.content IS '公告内容'; +COMMENT ON COLUMN system_notice.type IS '公告类型(1通知 2公告)'; +COMMENT ON COLUMN system_notice.status IS '公告状态(0正常 1关闭)'; +COMMENT ON COLUMN system_notice.creator IS '创建者'; +COMMENT ON COLUMN system_notice.create_time IS '创建时间'; +COMMENT ON COLUMN system_notice.updater IS '更新者'; +COMMENT ON COLUMN system_notice.update_time IS '更新时间'; +COMMENT ON COLUMN system_notice.deleted IS '是否删除'; +COMMENT ON COLUMN system_notice.tenant_id IS '租户编号'; +COMMENT ON TABLE system_notice IS '通知公告表'; + +-- ---------------------------- +-- Records of system_notice +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO system_notice (id, title, content, type, status, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1, '芋道的公众', '

新版本内容133

', 1, 0, 'admin', '2021-01-05 17:03:48', '1', '2022-05-04 21:00:20', '0', 1); +INSERT INTO system_notice (id, title, content, type, status, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2, '维护通知:2018-07-01 系统凌晨维护', '

11112222

', 2, 1, 'admin', '2021-01-05 17:03:48', '1', '2023-12-02 20:07:26', '0', 1); +INSERT INTO system_notice (id, title, content, type, status, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4, '我是测试标题', '

哈哈哈哈123

', 1, 0, '110', '2022-02-22 01:01:25', '110', '2022-02-22 01:01:46', '0', 121); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS system_notice_seq; +CREATE SEQUENCE system_notice_seq + START 5; + +-- ---------------------------- +-- Table structure for system_notify_message +-- ---------------------------- +DROP TABLE IF EXISTS system_notify_message; +CREATE TABLE system_notify_message +( + id int8 NOT NULL, + user_id int8 NOT NULL, + user_type int2 NOT NULL, + template_id int8 NOT NULL, + template_code varchar(64) NOT NULL, + template_nickname varchar(63) NOT NULL, + template_content varchar(1024) NOT NULL, + template_type int4 NOT NULL, + template_params varchar(255) NOT NULL, + read_status bool NOT NULL, + read_time timestamp NULL DEFAULT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_notify_message + ADD CONSTRAINT pk_system_notify_message PRIMARY KEY (id); + +COMMENT ON COLUMN system_notify_message.id IS '用户ID'; +COMMENT ON COLUMN system_notify_message.user_id IS '用户id'; +COMMENT ON COLUMN system_notify_message.user_type IS '用户类型'; +COMMENT ON COLUMN system_notify_message.template_id IS '模版编号'; +COMMENT ON COLUMN system_notify_message.template_code IS '模板编码'; +COMMENT ON COLUMN system_notify_message.template_nickname IS '模版发送人名称'; +COMMENT ON COLUMN system_notify_message.template_content IS '模版内容'; +COMMENT ON COLUMN system_notify_message.template_type IS '模版类型'; +COMMENT ON COLUMN system_notify_message.template_params IS '模版参数'; +COMMENT ON COLUMN system_notify_message.read_status IS '是否已读'; +COMMENT ON COLUMN system_notify_message.read_time IS '阅读时间'; +COMMENT ON COLUMN system_notify_message.creator IS '创建者'; +COMMENT ON COLUMN system_notify_message.create_time IS '创建时间'; +COMMENT ON COLUMN system_notify_message.updater IS '更新者'; +COMMENT ON COLUMN system_notify_message.update_time IS '更新时间'; +COMMENT ON COLUMN system_notify_message.deleted IS '是否删除'; +COMMENT ON COLUMN system_notify_message.tenant_id IS '租户编号'; +COMMENT ON TABLE system_notify_message IS '站内信消息表'; + +-- ---------------------------- +-- Records of system_notify_message +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO system_notify_message (id, user_id, user_type, template_id, template_code, template_nickname, template_content, template_type, template_params, read_status, read_time, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2, 1, 2, 1, 'test', '123', '我是 1,我开始 2 了', 1, '{"name":"1","what":"2"}', '1', '2023-02-10 00:47:04', '1', '2023-01-28 11:44:08', '1', '2023-02-10 00:47:04', '0', 1); +INSERT INTO system_notify_message (id, user_id, user_type, template_id, template_code, template_nickname, template_content, template_type, template_params, read_status, read_time, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3, 1, 2, 1, 'test', '123', '我是 1,我开始 2 了', 1, '{"name":"1","what":"2"}', '1', '2023-02-10 00:47:04', '1', '2023-01-28 11:45:04', '1', '2023-02-10 00:47:04', '0', 1); +INSERT INTO system_notify_message (id, user_id, user_type, template_id, template_code, template_nickname, template_content, template_type, template_params, read_status, read_time, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4, 103, 2, 2, 'register', '系统消息', '你好,欢迎 哈哈 加入大家庭!', 2, '{"name":"哈哈"}', '0', NULL, '1', '2023-01-28 21:02:20', '1', '2023-01-28 21:02:20', '0', 1); +INSERT INTO system_notify_message (id, user_id, user_type, template_id, template_code, template_nickname, template_content, template_type, template_params, read_status, read_time, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (5, 1, 2, 1, 'test', '123', '我是 芋艿,我开始 写代码 了', 1, '{"name":"芋艿","what":"写代码"}', '1', '2023-02-10 00:47:04', '1', '2023-01-28 22:21:42', '1', '2023-02-10 00:47:04', '0', 1); +INSERT INTO system_notify_message (id, user_id, user_type, template_id, template_code, template_nickname, template_content, template_type, template_params, read_status, read_time, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (6, 1, 2, 1, 'test', '123', '我是 芋艿,我开始 写代码 了', 1, '{"name":"芋艿","what":"写代码"}', '1', '2023-01-29 10:52:06', '1', '2023-01-28 22:22:07', '1', '2023-01-29 10:52:06', '0', 1); +INSERT INTO system_notify_message (id, user_id, user_type, template_id, template_code, template_nickname, template_content, template_type, template_params, read_status, read_time, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (7, 1, 2, 1, 'test', '123', '我是 2,我开始 3 了', 1, '{"name":"2","what":"3"}', '1', '2023-01-29 10:52:06', '1', '2023-01-28 23:45:21', '1', '2023-01-29 10:52:06', '0', 1); +INSERT INTO system_notify_message (id, user_id, user_type, template_id, template_code, template_nickname, template_content, template_type, template_params, read_status, read_time, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (8, 1, 2, 2, 'register', '系统消息', '你好,欢迎 123 加入大家庭!', 2, '{"name":"123"}', '1', '2023-01-29 10:52:06', '1', '2023-01-28 23:50:21', '1', '2023-01-29 10:52:06', '0', 1); +INSERT INTO system_notify_message (id, user_id, user_type, template_id, template_code, template_nickname, template_content, template_type, template_params, read_status, read_time, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (9, 247, 1, 4, 'brokerage_withdraw_audit_approve', 'system', '您在2023-09-28 08:35:46提现¥0.09元的申请已通过审核', 2, '{"reason":null,"createTime":"2023-09-28 08:35:46","price":"0.09"}', '0', NULL, '1', '2023-09-28 16:36:22', '1', '2023-09-28 16:36:22', '0', 1); +INSERT INTO system_notify_message (id, user_id, user_type, template_id, template_code, template_nickname, template_content, template_type, template_params, read_status, read_time, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (10, 247, 1, 4, 'brokerage_withdraw_audit_approve', 'system', '您在2023-09-30 20:59:40提现¥1.00元的申请已通过审核', 2, '{"reason":null,"createTime":"2023-09-30 20:59:40","price":"1.00"}', '0', NULL, '1', '2023-10-03 12:11:34', '1', '2023-10-03 12:11:34', '0', 1); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS system_notify_message_seq; +CREATE SEQUENCE system_notify_message_seq + START 11; + +-- ---------------------------- +-- Table structure for system_notify_template +-- ---------------------------- +DROP TABLE IF EXISTS system_notify_template; +CREATE TABLE system_notify_template +( + id int8 NOT NULL, + name varchar(63) NOT NULL, + code varchar(64) NOT NULL, + nickname varchar(255) NOT NULL, + content varchar(1024) NOT NULL, + type int2 NOT NULL, + params varchar(255) NULL DEFAULT NULL, + status int2 NOT NULL, + remark varchar(255) NULL DEFAULT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_notify_template + ADD CONSTRAINT pk_system_notify_template PRIMARY KEY (id); + +COMMENT ON COLUMN system_notify_template.id IS '主键'; +COMMENT ON COLUMN system_notify_template.name IS '模板名称'; +COMMENT ON COLUMN system_notify_template.code IS '模版编码'; +COMMENT ON COLUMN system_notify_template.nickname IS '发送人名称'; +COMMENT ON COLUMN system_notify_template.content IS '模版内容'; +COMMENT ON COLUMN system_notify_template.type IS '类型'; +COMMENT ON COLUMN system_notify_template.params IS '参数数组'; +COMMENT ON COLUMN system_notify_template.status IS '状态'; +COMMENT ON COLUMN system_notify_template.remark IS '备注'; +COMMENT ON COLUMN system_notify_template.creator IS '创建者'; +COMMENT ON COLUMN system_notify_template.create_time IS '创建时间'; +COMMENT ON COLUMN system_notify_template.updater IS '更新者'; +COMMENT ON COLUMN system_notify_template.update_time IS '更新时间'; +COMMENT ON COLUMN system_notify_template.deleted IS '是否删除'; +COMMENT ON TABLE system_notify_template IS '站内信模板表'; + +DROP SEQUENCE IF EXISTS system_notify_template_seq; +CREATE SEQUENCE system_notify_template_seq + START 1; + +-- ---------------------------- +-- Table structure for system_oauth2_access_token +-- ---------------------------- +DROP TABLE IF EXISTS system_oauth2_access_token; +CREATE TABLE system_oauth2_access_token +( + id int8 NOT NULL, + user_id int8 NOT NULL, + user_type int2 NOT NULL, + user_info varchar(512) NOT NULL, + access_token varchar(255) NOT NULL, + refresh_token varchar(32) NOT NULL, + client_id varchar(255) NOT NULL, + scopes varchar(255) NULL DEFAULT NULL, + expires_time timestamp NOT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_oauth2_access_token + ADD CONSTRAINT pk_system_oauth2_access_token PRIMARY KEY (id); + +CREATE INDEX idx_system_oauth2_access_token_01 ON system_oauth2_access_token (access_token); +CREATE INDEX idx_system_oauth2_access_token_02 ON system_oauth2_access_token (refresh_token); + +COMMENT ON COLUMN system_oauth2_access_token.id IS '编号'; +COMMENT ON COLUMN system_oauth2_access_token.user_id IS '用户编号'; +COMMENT ON COLUMN system_oauth2_access_token.user_type IS '用户类型'; +COMMENT ON COLUMN system_oauth2_access_token.user_info IS '用户信息'; +COMMENT ON COLUMN system_oauth2_access_token.access_token IS '访问令牌'; +COMMENT ON COLUMN system_oauth2_access_token.refresh_token IS '刷新令牌'; +COMMENT ON COLUMN system_oauth2_access_token.client_id IS '客户端编号'; +COMMENT ON COLUMN system_oauth2_access_token.scopes IS '授权范围'; +COMMENT ON COLUMN system_oauth2_access_token.expires_time IS '过期时间'; +COMMENT ON COLUMN system_oauth2_access_token.creator IS '创建者'; +COMMENT ON COLUMN system_oauth2_access_token.create_time IS '创建时间'; +COMMENT ON COLUMN system_oauth2_access_token.updater IS '更新者'; +COMMENT ON COLUMN system_oauth2_access_token.update_time IS '更新时间'; +COMMENT ON COLUMN system_oauth2_access_token.deleted IS '是否删除'; +COMMENT ON COLUMN system_oauth2_access_token.tenant_id IS '租户编号'; +COMMENT ON TABLE system_oauth2_access_token IS 'OAuth2 访问令牌'; + +DROP SEQUENCE IF EXISTS system_oauth2_access_token_seq; +CREATE SEQUENCE system_oauth2_access_token_seq + START 1; + +-- ---------------------------- +-- Table structure for system_oauth2_approve +-- ---------------------------- +DROP TABLE IF EXISTS system_oauth2_approve; +CREATE TABLE system_oauth2_approve +( + id int8 NOT NULL, + user_id int8 NOT NULL, + user_type int2 NOT NULL, + client_id varchar(255) NOT NULL, + scope varchar(255) NULL DEFAULT '', + approved bool NOT NULL DEFAULT '0', + expires_time timestamp NOT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_oauth2_approve + ADD CONSTRAINT pk_system_oauth2_approve PRIMARY KEY (id); + +COMMENT ON COLUMN system_oauth2_approve.id IS '编号'; +COMMENT ON COLUMN system_oauth2_approve.user_id IS '用户编号'; +COMMENT ON COLUMN system_oauth2_approve.user_type IS '用户类型'; +COMMENT ON COLUMN system_oauth2_approve.client_id IS '客户端编号'; +COMMENT ON COLUMN system_oauth2_approve.scope IS '授权范围'; +COMMENT ON COLUMN system_oauth2_approve.approved IS '是否接受'; +COMMENT ON COLUMN system_oauth2_approve.expires_time IS '过期时间'; +COMMENT ON COLUMN system_oauth2_approve.creator IS '创建者'; +COMMENT ON COLUMN system_oauth2_approve.create_time IS '创建时间'; +COMMENT ON COLUMN system_oauth2_approve.updater IS '更新者'; +COMMENT ON COLUMN system_oauth2_approve.update_time IS '更新时间'; +COMMENT ON COLUMN system_oauth2_approve.deleted IS '是否删除'; +COMMENT ON COLUMN system_oauth2_approve.tenant_id IS '租户编号'; +COMMENT ON TABLE system_oauth2_approve IS 'OAuth2 批准表'; + +DROP SEQUENCE IF EXISTS system_oauth2_approve_seq; +CREATE SEQUENCE system_oauth2_approve_seq + START 1; + +-- ---------------------------- +-- Table structure for system_oauth2_client +-- ---------------------------- +DROP TABLE IF EXISTS system_oauth2_client; +CREATE TABLE system_oauth2_client +( + id int8 NOT NULL, + client_id varchar(255) NOT NULL, + secret varchar(255) NOT NULL, + name varchar(255) NOT NULL, + logo varchar(255) NOT NULL, + description varchar(255) NULL DEFAULT NULL, + status int2 NOT NULL, + access_token_validity_seconds int4 NOT NULL, + refresh_token_validity_seconds int4 NOT NULL, + redirect_uris varchar(255) NOT NULL, + authorized_grant_types varchar(255) NOT NULL, + scopes varchar(255) NULL DEFAULT NULL, + auto_approve_scopes varchar(255) NULL DEFAULT NULL, + authorities varchar(255) NULL DEFAULT NULL, + resource_ids varchar(255) NULL DEFAULT NULL, + additional_information varchar(4096) NULL DEFAULT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_oauth2_client + ADD CONSTRAINT pk_system_oauth2_client PRIMARY KEY (id); + +COMMENT ON COLUMN system_oauth2_client.id IS '编号'; +COMMENT ON COLUMN system_oauth2_client.client_id IS '客户端编号'; +COMMENT ON COLUMN system_oauth2_client.secret IS '客户端密钥'; +COMMENT ON COLUMN system_oauth2_client.name IS '应用名'; +COMMENT ON COLUMN system_oauth2_client.logo IS '应用图标'; +COMMENT ON COLUMN system_oauth2_client.description IS '应用描述'; +COMMENT ON COLUMN system_oauth2_client.status IS '状态'; +COMMENT ON COLUMN system_oauth2_client.access_token_validity_seconds IS '访问令牌的有效期'; +COMMENT ON COLUMN system_oauth2_client.refresh_token_validity_seconds IS '刷新令牌的有效期'; +COMMENT ON COLUMN system_oauth2_client.redirect_uris IS '可重定向的 URI 地址'; +COMMENT ON COLUMN system_oauth2_client.authorized_grant_types IS '授权类型'; +COMMENT ON COLUMN system_oauth2_client.scopes IS '授权范围'; +COMMENT ON COLUMN system_oauth2_client.auto_approve_scopes IS '自动通过的授权范围'; +COMMENT ON COLUMN system_oauth2_client.authorities IS '权限'; +COMMENT ON COLUMN system_oauth2_client.resource_ids IS '资源'; +COMMENT ON COLUMN system_oauth2_client.additional_information IS '附加信息'; +COMMENT ON COLUMN system_oauth2_client.creator IS '创建者'; +COMMENT ON COLUMN system_oauth2_client.create_time IS '创建时间'; +COMMENT ON COLUMN system_oauth2_client.updater IS '更新者'; +COMMENT ON COLUMN system_oauth2_client.update_time IS '更新时间'; +COMMENT ON COLUMN system_oauth2_client.deleted IS '是否删除'; +COMMENT ON TABLE system_oauth2_client IS 'OAuth2 客户端表'; + +-- ---------------------------- +-- Records of system_oauth2_client +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO system_oauth2_client (id, client_id, secret, name, logo, description, status, access_token_validity_seconds, refresh_token_validity_seconds, redirect_uris, authorized_grant_types, scopes, auto_approve_scopes, authorities, resource_ids, additional_information, creator, create_time, updater, update_time, deleted) VALUES (1, 'default', 'admin123', '芋道源码', 'http://test.yudao.iocoder.cn/a5e2e244368878a366b516805a4aabf1.png', '我是描述', 0, 1800, 2592000, '["https://www.iocoder.cn","https://doc.iocoder.cn"]', '["password","authorization_code","implicit","refresh_token"]', '["user.read","user.write"]', '[]', '["user.read","user.write"]', '[]', '{}', '1', '2022-05-11 21:47:12', '1', '2024-02-22 16:31:52', '0'); +INSERT INTO system_oauth2_client (id, client_id, secret, name, logo, description, status, access_token_validity_seconds, refresh_token_validity_seconds, redirect_uris, authorized_grant_types, scopes, auto_approve_scopes, authorities, resource_ids, additional_information, creator, create_time, updater, update_time, deleted) VALUES (40, 'test', 'test2', 'biubiu', 'http://test.yudao.iocoder.cn/277a899d573723f1fcdfb57340f00379.png', '啦啦啦啦', 0, 1800, 43200, '["https://www.iocoder.cn"]', '["password","authorization_code","implicit"]', '["user_info","projects"]', '["user_info"]', '[]', '[]', '{}', '1', '2022-05-12 00:28:20', '1', '2023-12-02 21:01:01', '0'); +INSERT INTO system_oauth2_client (id, client_id, secret, name, logo, description, status, access_token_validity_seconds, refresh_token_validity_seconds, redirect_uris, authorized_grant_types, scopes, auto_approve_scopes, authorities, resource_ids, additional_information, creator, create_time, updater, update_time, deleted) VALUES (41, 'yudao-sso-demo-by-code', 'test', '基于授权码模式,如何实现 SSO 单点登录?', 'http://test.yudao.iocoder.cn/fe4ed36596adad5120036ef61a6d0153654544d44af8dd4ad3ffe8f759933d6f.png', NULL, 0, 1800, 43200, '["http://127.0.0.1:18080"]', '["authorization_code","refresh_token"]', '["user.read","user.write"]', '[]', '[]', '[]', NULL, '1', '2022-09-29 13:28:31', '1', '2022-09-29 13:28:31', '0'); +INSERT INTO system_oauth2_client (id, client_id, secret, name, logo, description, status, access_token_validity_seconds, refresh_token_validity_seconds, redirect_uris, authorized_grant_types, scopes, auto_approve_scopes, authorities, resource_ids, additional_information, creator, create_time, updater, update_time, deleted) VALUES (42, 'yudao-sso-demo-by-password', 'test', '基于密码模式,如何实现 SSO 单点登录?', 'http://test.yudao.iocoder.cn/604bdc695e13b3b22745be704d1f2aa8ee05c5f26f9fead6d1ca49005afbc857.jpeg', NULL, 0, 1800, 43200, '["http://127.0.0.1:18080"]', '["password","refresh_token"]', '["user.read","user.write"]', '[]', '[]', '[]', NULL, '1', '2022-10-04 17:40:16', '1', '2022-10-04 20:31:21', '0'); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS system_oauth2_client_seq; +CREATE SEQUENCE system_oauth2_client_seq + START 43; + +-- ---------------------------- +-- Table structure for system_oauth2_code +-- ---------------------------- +DROP TABLE IF EXISTS system_oauth2_code; +CREATE TABLE system_oauth2_code +( + id int8 NOT NULL, + user_id int8 NOT NULL, + user_type int2 NOT NULL, + code varchar(32) NOT NULL, + client_id varchar(255) NOT NULL, + scopes varchar(255) NULL DEFAULT '', + expires_time timestamp NOT NULL, + redirect_uri varchar(255) NULL DEFAULT NULL, + state varchar(255) NULL DEFAULT '', + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_oauth2_code + ADD CONSTRAINT pk_system_oauth2_code PRIMARY KEY (id); + +COMMENT ON COLUMN system_oauth2_code.id IS '编号'; +COMMENT ON COLUMN system_oauth2_code.user_id IS '用户编号'; +COMMENT ON COLUMN system_oauth2_code.user_type IS '用户类型'; +COMMENT ON COLUMN system_oauth2_code.code IS '授权码'; +COMMENT ON COLUMN system_oauth2_code.client_id IS '客户端编号'; +COMMENT ON COLUMN system_oauth2_code.scopes IS '授权范围'; +COMMENT ON COLUMN system_oauth2_code.expires_time IS '过期时间'; +COMMENT ON COLUMN system_oauth2_code.redirect_uri IS '可重定向的 URI 地址'; +COMMENT ON COLUMN system_oauth2_code.state IS '状态'; +COMMENT ON COLUMN system_oauth2_code.creator IS '创建者'; +COMMENT ON COLUMN system_oauth2_code.create_time IS '创建时间'; +COMMENT ON COLUMN system_oauth2_code.updater IS '更新者'; +COMMENT ON COLUMN system_oauth2_code.update_time IS '更新时间'; +COMMENT ON COLUMN system_oauth2_code.deleted IS '是否删除'; +COMMENT ON COLUMN system_oauth2_code.tenant_id IS '租户编号'; +COMMENT ON TABLE system_oauth2_code IS 'OAuth2 授权码表'; + +DROP SEQUENCE IF EXISTS system_oauth2_code_seq; +CREATE SEQUENCE system_oauth2_code_seq + START 1; + +-- ---------------------------- +-- Table structure for system_oauth2_refresh_token +-- ---------------------------- +DROP TABLE IF EXISTS system_oauth2_refresh_token; +CREATE TABLE system_oauth2_refresh_token +( + id int8 NOT NULL, + user_id int8 NOT NULL, + refresh_token varchar(32) NOT NULL, + user_type int2 NOT NULL, + client_id varchar(255) NOT NULL, + scopes varchar(255) NULL DEFAULT NULL, + expires_time timestamp NOT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_oauth2_refresh_token + ADD CONSTRAINT pk_system_oauth2_refresh_token PRIMARY KEY (id); + +COMMENT ON COLUMN system_oauth2_refresh_token.id IS '编号'; +COMMENT ON COLUMN system_oauth2_refresh_token.user_id IS '用户编号'; +COMMENT ON COLUMN system_oauth2_refresh_token.refresh_token IS '刷新令牌'; +COMMENT ON COLUMN system_oauth2_refresh_token.user_type IS '用户类型'; +COMMENT ON COLUMN system_oauth2_refresh_token.client_id IS '客户端编号'; +COMMENT ON COLUMN system_oauth2_refresh_token.scopes IS '授权范围'; +COMMENT ON COLUMN system_oauth2_refresh_token.expires_time IS '过期时间'; +COMMENT ON COLUMN system_oauth2_refresh_token.creator IS '创建者'; +COMMENT ON COLUMN system_oauth2_refresh_token.create_time IS '创建时间'; +COMMENT ON COLUMN system_oauth2_refresh_token.updater IS '更新者'; +COMMENT ON COLUMN system_oauth2_refresh_token.update_time IS '更新时间'; +COMMENT ON COLUMN system_oauth2_refresh_token.deleted IS '是否删除'; +COMMENT ON COLUMN system_oauth2_refresh_token.tenant_id IS '租户编号'; +COMMENT ON TABLE system_oauth2_refresh_token IS 'OAuth2 刷新令牌'; + +DROP SEQUENCE IF EXISTS system_oauth2_refresh_token_seq; +CREATE SEQUENCE system_oauth2_refresh_token_seq + START 1; + +-- ---------------------------- +-- Table structure for system_operate_log +-- ---------------------------- +DROP TABLE IF EXISTS system_operate_log; +CREATE TABLE system_operate_log +( + id int8 NOT NULL, + trace_id varchar(64) NULL DEFAULT '', + user_id int8 NOT NULL, + user_type int2 NOT NULL DEFAULT 0, + type varchar(50) NOT NULL, + sub_type varchar(50) NOT NULL, + biz_id int8 NOT NULL, + action varchar(2000) NULL DEFAULT '', + extra varchar(2000) NULL DEFAULT '', + request_method varchar(16) NULL DEFAULT '', + request_url varchar(255) NULL DEFAULT '', + user_ip varchar(50) NULL DEFAULT NULL, + user_agent varchar(200) NULL DEFAULT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_operate_log + ADD CONSTRAINT pk_system_operate_log PRIMARY KEY (id); + +COMMENT ON COLUMN system_operate_log.id IS '日志主键'; +COMMENT ON COLUMN system_operate_log.trace_id IS '链路追踪编号'; +COMMENT ON COLUMN system_operate_log.user_id IS '用户编号'; +COMMENT ON COLUMN system_operate_log.user_type IS '用户类型'; +COMMENT ON COLUMN system_operate_log.type IS '操作模块类型'; +COMMENT ON COLUMN system_operate_log.sub_type IS '操作名'; +COMMENT ON COLUMN system_operate_log.biz_id IS '操作数据模块编号'; +COMMENT ON COLUMN system_operate_log.action IS '操作内容'; +COMMENT ON COLUMN system_operate_log.extra IS '拓展字段'; +COMMENT ON COLUMN system_operate_log.request_method IS '请求方法名'; +COMMENT ON COLUMN system_operate_log.request_url IS '请求地址'; +COMMENT ON COLUMN system_operate_log.user_ip IS '用户 IP'; +COMMENT ON COLUMN system_operate_log.user_agent IS '浏览器 UA'; +COMMENT ON COLUMN system_operate_log.creator IS '创建者'; +COMMENT ON COLUMN system_operate_log.create_time IS '创建时间'; +COMMENT ON COLUMN system_operate_log.updater IS '更新者'; +COMMENT ON COLUMN system_operate_log.update_time IS '更新时间'; +COMMENT ON COLUMN system_operate_log.deleted IS '是否删除'; +COMMENT ON COLUMN system_operate_log.tenant_id IS '租户编号'; +COMMENT ON TABLE system_operate_log IS '操作日志记录 V2 版本'; + +DROP SEQUENCE IF EXISTS system_operate_log_seq; +CREATE SEQUENCE system_operate_log_seq + START 1; + +-- ---------------------------- +-- Table structure for system_post +-- ---------------------------- +DROP TABLE IF EXISTS system_post; +CREATE TABLE system_post +( + id int8 NOT NULL, + code varchar(64) NOT NULL, + name varchar(50) NOT NULL, + sort int4 NOT NULL, + status int2 NOT NULL, + remark varchar(500) NULL DEFAULT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_post + ADD CONSTRAINT pk_system_post PRIMARY KEY (id); + +COMMENT ON COLUMN system_post.id IS '岗位ID'; +COMMENT ON COLUMN system_post.code IS '岗位编码'; +COMMENT ON COLUMN system_post.name IS '岗位名称'; +COMMENT ON COLUMN system_post.sort IS '显示顺序'; +COMMENT ON COLUMN system_post.status IS '状态(0正常 1停用)'; +COMMENT ON COLUMN system_post.remark IS '备注'; +COMMENT ON COLUMN system_post.creator IS '创建者'; +COMMENT ON COLUMN system_post.create_time IS '创建时间'; +COMMENT ON COLUMN system_post.updater IS '更新者'; +COMMENT ON COLUMN system_post.update_time IS '更新时间'; +COMMENT ON COLUMN system_post.deleted IS '是否删除'; +COMMENT ON COLUMN system_post.tenant_id IS '租户编号'; +COMMENT ON TABLE system_post IS '岗位信息表'; + +-- ---------------------------- +-- Records of system_post +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO system_post (id, code, name, sort, status, remark, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1, 'ceo', '董事长', 1, 0, '', 'admin', '2021-01-06 17:03:48', '1', '2023-02-11 15:19:04', '0', 1); +INSERT INTO system_post (id, code, name, sort, status, remark, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2, 'se', '项目经理', 2, 0, '', 'admin', '2021-01-05 17:03:48', '1', '2023-11-15 09:18:20', '0', 1); +INSERT INTO system_post (id, code, name, sort, status, remark, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4, 'user', '普通员工', 4, 0, '111', 'admin', '2021-01-05 17:03:48', '1', '2023-12-02 10:04:37', '0', 1); +INSERT INTO system_post (id, code, name, sort, status, remark, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (5, 'HR', '人力资源', 5, 0, '', '1', '2024-03-24 20:45:40', '1', '2024-03-24 20:45:40', '0', 1); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS system_post_seq; +CREATE SEQUENCE system_post_seq + START 6; + +-- ---------------------------- +-- Table structure for system_role +-- ---------------------------- +DROP TABLE IF EXISTS system_role; +CREATE TABLE system_role +( + id int8 NOT NULL, + name varchar(30) NOT NULL, + code varchar(100) NOT NULL, + sort int4 NOT NULL, + data_scope int2 NOT NULL DEFAULT 1, + data_scope_dept_ids varchar(500) NULL DEFAULT '', + status int2 NOT NULL, + type int2 NOT NULL, + remark varchar(500) NULL DEFAULT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_role + ADD CONSTRAINT pk_system_role PRIMARY KEY (id); + +COMMENT ON COLUMN system_role.id IS '角色ID'; +COMMENT ON COLUMN system_role.name IS '角色名称'; +COMMENT ON COLUMN system_role.code IS '角色权限字符串'; +COMMENT ON COLUMN system_role.sort IS '显示顺序'; +COMMENT ON COLUMN system_role.data_scope IS '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)'; +COMMENT ON COLUMN system_role.data_scope_dept_ids IS '数据范围(指定部门数组)'; +COMMENT ON COLUMN system_role.status IS '角色状态(0正常 1停用)'; +COMMENT ON COLUMN system_role.type IS '角色类型'; +COMMENT ON COLUMN system_role.remark IS '备注'; +COMMENT ON COLUMN system_role.creator IS '创建者'; +COMMENT ON COLUMN system_role.create_time IS '创建时间'; +COMMENT ON COLUMN system_role.updater IS '更新者'; +COMMENT ON COLUMN system_role.update_time IS '更新时间'; +COMMENT ON COLUMN system_role.deleted IS '是否删除'; +COMMENT ON COLUMN system_role.tenant_id IS '租户编号'; +COMMENT ON TABLE system_role IS '角色信息表'; + +-- ---------------------------- +-- Records of system_role +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO system_role (id, name, code, sort, data_scope, data_scope_dept_ids, status, type, remark, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1, '超级管理员', 'super_admin', 1, 1, '', 0, 1, '超级管理员', 'admin', '2021-01-05 17:03:48', '', '2022-02-22 05:08:21', '0', 1); +INSERT INTO system_role (id, name, code, sort, data_scope, data_scope_dept_ids, status, type, remark, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2, '普通角色', 'common', 2, 2, '', 0, 1, '普通角色', 'admin', '2021-01-05 17:03:48', '', '2022-02-22 05:08:20', '0', 1); +INSERT INTO system_role (id, name, code, sort, data_scope, data_scope_dept_ids, status, type, remark, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3, 'CRM 管理员', 'crm_admin', 2, 1, '', 0, 1, 'CRM 专属角色', '1', '2024-02-24 10:51:13', '1', '2024-02-24 02:51:32', '0', 1); +INSERT INTO system_role (id, name, code, sort, data_scope, data_scope_dept_ids, status, type, remark, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (101, '测试账号', 'test', 0, 1, '[]', 0, 2, '我想测试', '', '2021-01-06 13:49:35', '1', '2024-03-24 22:22:45', '0', 1); +INSERT INTO system_role (id, name, code, sort, data_scope, data_scope_dept_ids, status, type, remark, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (109, '租户管理员', 'tenant_admin', 0, 1, '', 0, 1, '系统自动生成', '1', '2022-02-22 00:56:14', '1', '2022-02-22 00:56:14', '0', 121); +INSERT INTO system_role (id, name, code, sort, data_scope, data_scope_dept_ids, status, type, remark, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (111, '租户管理员', 'tenant_admin', 0, 1, '', 0, 1, '系统自动生成', '1', '2022-03-07 21:37:58', '1', '2022-03-07 21:37:58', '0', 122); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS system_role_seq; +CREATE SEQUENCE system_role_seq + START 112; + +-- ---------------------------- +-- Table structure for system_role_menu +-- ---------------------------- +DROP TABLE IF EXISTS system_role_menu; +CREATE TABLE system_role_menu +( + id int8 NOT NULL, + role_id int8 NOT NULL, + menu_id int8 NOT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_role_menu + ADD CONSTRAINT pk_system_role_menu PRIMARY KEY (id); + +COMMENT ON COLUMN system_role_menu.id IS '自增编号'; +COMMENT ON COLUMN system_role_menu.role_id IS '角色ID'; +COMMENT ON COLUMN system_role_menu.menu_id IS '菜单ID'; +COMMENT ON COLUMN system_role_menu.creator IS '创建者'; +COMMENT ON COLUMN system_role_menu.create_time IS '创建时间'; +COMMENT ON COLUMN system_role_menu.updater IS '更新者'; +COMMENT ON COLUMN system_role_menu.update_time IS '更新时间'; +COMMENT ON COLUMN system_role_menu.deleted IS '是否删除'; +COMMENT ON COLUMN system_role_menu.tenant_id IS '租户编号'; +COMMENT ON TABLE system_role_menu IS '角色和菜单关联表'; + +-- ---------------------------- +-- Records of system_role_menu +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (263, 109, 1, '1', '2022-02-22 00:56:14', '1', '2022-02-22 00:56:14', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (434, 2, 1, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (454, 2, 1093, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (455, 2, 1094, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (460, 2, 1100, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (467, 2, 1107, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (476, 2, 1117, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (477, 2, 100, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (478, 2, 101, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (479, 2, 102, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (480, 2, 1126, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (481, 2, 103, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (483, 2, 104, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (485, 2, 105, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (488, 2, 107, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (490, 2, 108, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (492, 2, 109, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (498, 2, 1138, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (523, 2, 1224, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (524, 2, 1225, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (541, 2, 500, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (543, 2, 501, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (675, 2, 2, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (689, 2, 1077, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (690, 2, 1078, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (692, 2, 1083, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (693, 2, 1084, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (699, 2, 1090, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (703, 2, 106, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (704, 2, 110, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (705, 2, 111, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (706, 2, 112, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (707, 2, 113, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1296, 110, 1, '110', '2022-02-23 00:23:55', '110', '2022-02-23 00:23:55', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1578, 111, 1, '1', '2022-03-07 21:37:58', '1', '2022-03-07 21:37:58', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1604, 101, 1216, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1605, 101, 1217, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1606, 101, 1218, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1607, 101, 1219, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1608, 101, 1220, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1609, 101, 1221, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1610, 101, 5, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1611, 101, 1222, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1612, 101, 1118, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1613, 101, 1119, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1614, 101, 1120, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1615, 101, 1185, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1616, 101, 1186, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1617, 101, 1187, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1618, 101, 1188, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1619, 101, 1189, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1620, 101, 1190, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1621, 101, 1191, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1622, 101, 1192, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1623, 101, 1193, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1624, 101, 1194, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1625, 101, 1195, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1626, 101, 1196, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1627, 101, 1197, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1628, 101, 1198, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1629, 101, 1199, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1630, 101, 1200, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1631, 101, 1201, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1632, 101, 1202, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1633, 101, 1207, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1634, 101, 1208, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1635, 101, 1209, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1636, 101, 1210, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1637, 101, 1211, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1638, 101, 1212, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1639, 101, 1213, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1640, 101, 1215, '1', '2022-03-19 21:45:52', '1', '2022-03-19 21:45:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1641, 101, 2, '1', '2022-04-01 22:21:24', '1', '2022-04-01 22:21:24', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1642, 101, 1031, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1643, 101, 1032, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1644, 101, 1033, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1645, 101, 1034, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1646, 101, 1035, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1647, 101, 1050, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1648, 101, 1051, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1649, 101, 1052, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1650, 101, 1053, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1651, 101, 1054, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1652, 101, 1056, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1653, 101, 1057, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1654, 101, 1058, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1655, 101, 1059, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1656, 101, 1060, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1657, 101, 1066, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1658, 101, 1067, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1659, 101, 1070, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1664, 101, 1075, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1666, 101, 1077, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1667, 101, 1078, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1668, 101, 1082, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1669, 101, 1083, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1670, 101, 1084, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1671, 101, 1085, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1672, 101, 1086, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1673, 101, 1087, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1674, 101, 1088, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1675, 101, 1089, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1679, 101, 1237, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1680, 101, 1238, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1681, 101, 1239, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1682, 101, 1240, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1683, 101, 1241, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1684, 101, 1242, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1685, 101, 1243, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1687, 101, 106, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1688, 101, 110, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1689, 101, 111, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1690, 101, 112, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1691, 101, 113, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1692, 101, 114, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1693, 101, 115, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1694, 101, 116, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1729, 109, 100, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1730, 109, 101, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1731, 109, 1063, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1732, 109, 1064, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1733, 109, 1001, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1734, 109, 1065, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1735, 109, 1002, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1736, 109, 1003, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1737, 109, 1004, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1738, 109, 1005, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1739, 109, 1006, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1740, 109, 1007, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1741, 109, 1008, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1742, 109, 1009, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1743, 109, 1010, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1744, 109, 1011, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1745, 109, 1012, '1', '2022-09-21 22:08:51', '1', '2022-09-21 22:08:51', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1746, 111, 100, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1747, 111, 101, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1748, 111, 1063, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1749, 111, 1064, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1750, 111, 1001, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1751, 111, 1065, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1752, 111, 1002, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1753, 111, 1003, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1754, 111, 1004, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1755, 111, 1005, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1756, 111, 1006, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1757, 111, 1007, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1758, 111, 1008, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1759, 111, 1009, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1760, 111, 1010, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1761, 111, 1011, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1762, 111, 1012, '1', '2022-09-21 22:08:52', '1', '2022-09-21 22:08:52', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1763, 109, 100, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1764, 109, 101, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1765, 109, 1063, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1766, 109, 1064, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1767, 109, 1001, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1768, 109, 1065, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1769, 109, 1002, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1770, 109, 1003, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1771, 109, 1004, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1772, 109, 1005, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1773, 109, 1006, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1774, 109, 1007, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1775, 109, 1008, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1776, 109, 1009, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1777, 109, 1010, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1778, 109, 1011, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1779, 109, 1012, '1', '2022-09-21 22:08:53', '1', '2022-09-21 22:08:53', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1780, 111, 100, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1781, 111, 101, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1782, 111, 1063, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1783, 111, 1064, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1784, 111, 1001, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1785, 111, 1065, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1786, 111, 1002, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1787, 111, 1003, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1788, 111, 1004, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1789, 111, 1005, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1790, 111, 1006, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1791, 111, 1007, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1792, 111, 1008, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1793, 111, 1009, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1794, 111, 1010, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1795, 111, 1011, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1796, 111, 1012, '1', '2022-09-21 22:08:54', '1', '2022-09-21 22:08:54', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1797, 109, 100, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1798, 109, 101, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1799, 109, 1063, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1800, 109, 1064, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1801, 109, 1001, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1802, 109, 1065, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1803, 109, 1002, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1804, 109, 1003, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1805, 109, 1004, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1806, 109, 1005, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1807, 109, 1006, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1808, 109, 1007, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1809, 109, 1008, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1810, 109, 1009, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1811, 109, 1010, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1812, 109, 1011, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1813, 109, 1012, '1', '2022-09-21 22:08:55', '1', '2022-09-21 22:08:55', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1814, 111, 100, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1815, 111, 101, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1816, 111, 1063, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1817, 111, 1064, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1818, 111, 1001, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1819, 111, 1065, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1820, 111, 1002, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1821, 111, 1003, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1822, 111, 1004, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1823, 111, 1005, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1824, 111, 1006, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1825, 111, 1007, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1826, 111, 1008, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1827, 111, 1009, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1828, 111, 1010, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1829, 111, 1011, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1830, 111, 1012, '1', '2022-09-21 22:08:56', '1', '2022-09-21 22:08:56', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1831, 109, 103, '1', '2022-09-21 22:43:23', '1', '2022-09-21 22:43:23', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1832, 109, 1017, '1', '2022-09-21 22:43:23', '1', '2022-09-21 22:43:23', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1833, 109, 1018, '1', '2022-09-21 22:43:23', '1', '2022-09-21 22:43:23', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1834, 109, 1019, '1', '2022-09-21 22:43:23', '1', '2022-09-21 22:43:23', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1835, 109, 1020, '1', '2022-09-21 22:43:23', '1', '2022-09-21 22:43:23', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1836, 111, 103, '1', '2022-09-21 22:43:24', '1', '2022-09-21 22:43:24', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1837, 111, 1017, '1', '2022-09-21 22:43:24', '1', '2022-09-21 22:43:24', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1838, 111, 1018, '1', '2022-09-21 22:43:24', '1', '2022-09-21 22:43:24', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1839, 111, 1019, '1', '2022-09-21 22:43:24', '1', '2022-09-21 22:43:24', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1840, 111, 1020, '1', '2022-09-21 22:43:24', '1', '2022-09-21 22:43:24', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1841, 109, 1036, '1', '2022-09-21 22:48:13', '1', '2022-09-21 22:48:13', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1842, 109, 1037, '1', '2022-09-21 22:48:13', '1', '2022-09-21 22:48:13', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1843, 109, 1038, '1', '2022-09-21 22:48:13', '1', '2022-09-21 22:48:13', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1844, 109, 1039, '1', '2022-09-21 22:48:13', '1', '2022-09-21 22:48:13', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1845, 109, 107, '1', '2022-09-21 22:48:13', '1', '2022-09-21 22:48:13', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1846, 111, 1036, '1', '2022-09-21 22:48:13', '1', '2022-09-21 22:48:13', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1847, 111, 1037, '1', '2022-09-21 22:48:13', '1', '2022-09-21 22:48:13', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1848, 111, 1038, '1', '2022-09-21 22:48:13', '1', '2022-09-21 22:48:13', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1849, 111, 1039, '1', '2022-09-21 22:48:13', '1', '2022-09-21 22:48:13', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1850, 111, 107, '1', '2022-09-21 22:48:13', '1', '2022-09-21 22:48:13', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1991, 2, 1024, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1992, 2, 1025, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1993, 2, 1026, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1994, 2, 1027, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1995, 2, 1028, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1996, 2, 1029, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1997, 2, 1030, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1998, 2, 1031, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1999, 2, 1032, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2000, 2, 1033, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2001, 2, 1034, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2002, 2, 1035, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2003, 2, 1036, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2004, 2, 1037, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2005, 2, 1038, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2006, 2, 1039, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2007, 2, 1040, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2008, 2, 1042, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2009, 2, 1043, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2010, 2, 1045, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2011, 2, 1046, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2012, 2, 1048, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2013, 2, 1050, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2014, 2, 1051, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2015, 2, 1052, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2016, 2, 1053, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2017, 2, 1054, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2018, 2, 1056, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2019, 2, 1057, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2020, 2, 1058, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2021, 2, 2083, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2022, 2, 1059, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2023, 2, 1060, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2024, 2, 1063, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2025, 2, 1064, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2026, 2, 1065, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2027, 2, 1066, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2028, 2, 1067, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2029, 2, 1070, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2034, 2, 1075, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2036, 2, 1082, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2037, 2, 1085, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2038, 2, 1086, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2039, 2, 1087, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2040, 2, 1088, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2041, 2, 1089, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2042, 2, 1091, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2043, 2, 1092, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2044, 2, 1095, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2045, 2, 1096, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2046, 2, 1097, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2047, 2, 1098, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2048, 2, 1101, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2049, 2, 1102, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2050, 2, 1103, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2051, 2, 1104, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2052, 2, 1105, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2053, 2, 1106, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2054, 2, 1108, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2055, 2, 1109, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2061, 2, 1127, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2062, 2, 1128, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2063, 2, 1129, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2064, 2, 1130, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2066, 2, 1132, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2067, 2, 1133, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2068, 2, 1134, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2069, 2, 1135, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2070, 2, 1136, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2071, 2, 1137, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2072, 2, 114, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2073, 2, 1139, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2074, 2, 115, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2075, 2, 1140, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2076, 2, 116, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2077, 2, 1141, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2078, 2, 1142, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2079, 2, 1143, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2080, 2, 1150, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2081, 2, 1161, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2082, 2, 1162, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2083, 2, 1163, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2084, 2, 1164, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2085, 2, 1165, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2086, 2, 1166, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2087, 2, 1173, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2088, 2, 1174, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2089, 2, 1175, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2090, 2, 1176, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2091, 2, 1177, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2092, 2, 1178, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2099, 2, 1226, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2100, 2, 1227, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2101, 2, 1228, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2102, 2, 1229, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2103, 2, 1237, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2104, 2, 1238, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2105, 2, 1239, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2106, 2, 1240, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2107, 2, 1241, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2108, 2, 1242, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2109, 2, 1243, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2116, 2, 1254, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2117, 2, 1255, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2118, 2, 1256, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2119, 2, 1257, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2120, 2, 1258, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2121, 2, 1259, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2122, 2, 1260, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2123, 2, 1261, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2124, 2, 1263, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2125, 2, 1264, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2126, 2, 1265, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2127, 2, 1266, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2128, 2, 1267, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2129, 2, 1001, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2130, 2, 1002, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2131, 2, 1003, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2132, 2, 1004, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2133, 2, 1005, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2134, 2, 1006, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2135, 2, 1007, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2136, 2, 1008, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2137, 2, 1009, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2138, 2, 1010, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2139, 2, 1011, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2140, 2, 1012, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2141, 2, 1013, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2142, 2, 1014, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2143, 2, 1015, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2144, 2, 1016, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2145, 2, 1017, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2146, 2, 1018, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2147, 2, 1019, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2148, 2, 1020, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2149, 2, 1021, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2150, 2, 1022, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2151, 2, 1023, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2152, 2, 1281, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2153, 2, 1282, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2154, 2, 2000, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2155, 2, 2002, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2156, 2, 2003, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2157, 2, 2004, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2158, 2, 2005, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2159, 2, 2006, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2160, 2, 2008, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2161, 2, 2009, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2162, 2, 2010, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2163, 2, 2011, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2164, 2, 2012, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2170, 2, 2019, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2171, 2, 2020, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2172, 2, 2021, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2173, 2, 2022, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2174, 2, 2023, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2175, 2, 2025, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2177, 2, 2027, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2178, 2, 2028, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2179, 2, 2029, '1', '2023-01-25 08:42:58', '1', '2023-01-25 08:42:58', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2180, 2, 2014, '1', '2023-01-25 08:43:12', '1', '2023-01-25 08:43:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2181, 2, 2015, '1', '2023-01-25 08:43:12', '1', '2023-01-25 08:43:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2182, 2, 2016, '1', '2023-01-25 08:43:12', '1', '2023-01-25 08:43:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2183, 2, 2017, '1', '2023-01-25 08:43:12', '1', '2023-01-25 08:43:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2184, 2, 2018, '1', '2023-01-25 08:43:12', '1', '2023-01-25 08:43:12', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2188, 101, 1024, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2189, 101, 1, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2190, 101, 1025, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2191, 101, 1026, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2192, 101, 1027, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2193, 101, 1028, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2194, 101, 1029, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2195, 101, 1030, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2196, 101, 1036, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2197, 101, 1037, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2198, 101, 1038, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2199, 101, 1039, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2200, 101, 1040, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2201, 101, 1042, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2202, 101, 1043, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2203, 101, 1045, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2204, 101, 1046, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2205, 101, 1048, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2206, 101, 2083, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2207, 101, 1063, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2208, 101, 1064, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2209, 101, 1065, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2210, 101, 1093, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2211, 101, 1094, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2212, 101, 1095, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2213, 101, 1096, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2214, 101, 1097, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2215, 101, 1098, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2216, 101, 1100, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2217, 101, 1101, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2218, 101, 1102, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2219, 101, 1103, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2220, 101, 1104, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2221, 101, 1105, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2222, 101, 1106, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2223, 101, 2130, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2224, 101, 1107, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2225, 101, 2131, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2226, 101, 1108, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2227, 101, 2132, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2228, 101, 1109, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2229, 101, 2133, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2230, 101, 2134, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2232, 101, 2135, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2234, 101, 2136, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2236, 101, 2137, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2238, 101, 2138, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2240, 101, 2139, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2242, 101, 2140, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2243, 101, 2141, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2244, 101, 2142, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2245, 101, 2143, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2246, 101, 2144, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2247, 101, 2145, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2248, 101, 2146, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2249, 101, 2147, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2250, 101, 100, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2251, 101, 2148, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2252, 101, 101, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2253, 101, 2149, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2254, 101, 102, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2255, 101, 2150, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2256, 101, 103, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2257, 101, 2151, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2258, 101, 104, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2259, 101, 2152, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2260, 101, 105, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2261, 101, 107, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2262, 101, 108, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2263, 101, 109, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2264, 101, 1138, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2265, 101, 1139, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2266, 101, 1140, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2267, 101, 1141, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2268, 101, 1142, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2269, 101, 1143, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2270, 101, 1224, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2271, 101, 1225, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2272, 101, 1226, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2273, 101, 1227, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2274, 101, 1228, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2275, 101, 1229, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2282, 101, 1261, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2283, 101, 1263, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2284, 101, 1264, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2285, 101, 1265, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2286, 101, 1266, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2287, 101, 1267, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2288, 101, 1001, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2289, 101, 1002, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2290, 101, 1003, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2291, 101, 1004, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2292, 101, 1005, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2293, 101, 1006, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2294, 101, 1007, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2295, 101, 1008, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2296, 101, 1009, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2297, 101, 1010, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2298, 101, 1011, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2299, 101, 1012, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2300, 101, 500, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2301, 101, 1013, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2302, 101, 501, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2303, 101, 1014, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2304, 101, 1015, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2305, 101, 1016, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2306, 101, 1017, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2307, 101, 1018, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2308, 101, 1019, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2309, 101, 1020, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2310, 101, 1021, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2311, 101, 1022, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2312, 101, 1023, '1', '2023-02-09 23:49:46', '1', '2023-02-09 23:49:46', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2929, 109, 1224, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2930, 109, 1225, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2931, 109, 1226, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2932, 109, 1227, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2933, 109, 1228, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2934, 109, 1229, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2935, 109, 1138, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2936, 109, 1139, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2937, 109, 1140, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2938, 109, 1141, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2939, 109, 1142, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2940, 109, 1143, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2941, 111, 1224, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2942, 111, 1225, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2943, 111, 1226, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2944, 111, 1227, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2945, 111, 1228, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2946, 111, 1229, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2947, 111, 1138, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2948, 111, 1139, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2949, 111, 1140, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2950, 111, 1141, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2951, 111, 1142, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2952, 111, 1143, '1', '2023-12-02 23:19:40', '1', '2023-12-02 23:19:40', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2993, 109, 2, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2994, 109, 1031, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2995, 109, 1032, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2996, 109, 1033, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2997, 109, 1034, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2998, 109, 1035, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2999, 109, 1050, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3000, 109, 1051, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3001, 109, 1052, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3002, 109, 1053, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3003, 109, 1054, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3004, 109, 1056, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3005, 109, 1057, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3006, 109, 1058, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3007, 109, 1059, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3008, 109, 1060, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3009, 109, 1066, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3010, 109, 1067, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3011, 109, 1070, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3012, 109, 1075, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3013, 109, 1076, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3014, 109, 1077, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3015, 109, 1078, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3016, 109, 1082, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3017, 109, 1083, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3018, 109, 1084, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3019, 109, 1085, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3020, 109, 1086, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3021, 109, 1087, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3022, 109, 1088, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3023, 109, 1089, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3024, 109, 1090, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3025, 109, 1091, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3026, 109, 1092, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3027, 109, 106, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3028, 109, 110, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3029, 109, 111, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3030, 109, 112, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3031, 109, 113, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3032, 109, 114, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3033, 109, 115, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3034, 109, 116, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3035, 109, 2472, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3036, 109, 2478, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3037, 109, 2479, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3038, 109, 2480, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3039, 109, 2481, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3040, 109, 2482, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3041, 109, 2483, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3042, 109, 2484, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3043, 109, 2485, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3044, 109, 2486, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3045, 109, 2487, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3046, 109, 2488, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3047, 109, 2489, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3048, 109, 2490, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3049, 109, 2491, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3050, 109, 2492, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3051, 109, 2493, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3052, 109, 2494, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3053, 109, 2495, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3054, 109, 2497, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3055, 109, 1237, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3056, 109, 1238, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3057, 109, 1239, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3058, 109, 1240, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3059, 109, 1241, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3060, 109, 1242, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3061, 109, 1243, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3062, 109, 2525, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3063, 109, 1255, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3064, 109, 1256, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3065, 109, 1257, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3066, 109, 1258, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3067, 109, 1259, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3068, 109, 1260, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3069, 111, 2, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3070, 111, 1031, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3071, 111, 1032, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3072, 111, 1033, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3073, 111, 1034, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3074, 111, 1035, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3075, 111, 1050, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3076, 111, 1051, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3077, 111, 1052, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3078, 111, 1053, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3079, 111, 1054, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3080, 111, 1056, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3081, 111, 1057, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3082, 111, 1058, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3083, 111, 1059, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3084, 111, 1060, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3085, 111, 1066, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3086, 111, 1067, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3087, 111, 1070, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3088, 111, 1075, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3089, 111, 1076, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3090, 111, 1077, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3091, 111, 1078, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3092, 111, 1082, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3093, 111, 1083, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3094, 111, 1084, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3095, 111, 1085, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3096, 111, 1086, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3097, 111, 1087, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3098, 111, 1088, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3099, 111, 1089, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3100, 111, 1090, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3101, 111, 1091, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3102, 111, 1092, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3103, 111, 106, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3104, 111, 110, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3105, 111, 111, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3106, 111, 112, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3107, 111, 113, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3108, 111, 114, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3109, 111, 115, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3110, 111, 116, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3111, 111, 2472, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3112, 111, 2478, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3113, 111, 2479, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3114, 111, 2480, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3115, 111, 2481, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3116, 111, 2482, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3117, 111, 2483, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3118, 111, 2484, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3119, 111, 2485, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3120, 111, 2486, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3121, 111, 2487, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3122, 111, 2488, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3123, 111, 2489, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3124, 111, 2490, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3125, 111, 2491, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3126, 111, 2492, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3127, 111, 2493, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3128, 111, 2494, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3129, 111, 2495, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3130, 111, 2497, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3131, 111, 1237, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3132, 111, 1238, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3133, 111, 1239, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3134, 111, 1240, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3135, 111, 1241, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3136, 111, 1242, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3137, 111, 1243, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3138, 111, 2525, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3139, 111, 1255, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3140, 111, 1256, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3141, 111, 1257, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3142, 111, 1258, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3143, 111, 1259, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3144, 111, 1260, '1', '2023-12-02 23:41:02', '1', '2023-12-02 23:41:02', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3221, 109, 102, '1', '2023-12-30 11:42:36', '1', '2023-12-30 11:42:36', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3222, 109, 1013, '1', '2023-12-30 11:42:36', '1', '2023-12-30 11:42:36', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3223, 109, 1014, '1', '2023-12-30 11:42:36', '1', '2023-12-30 11:42:36', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3224, 109, 1015, '1', '2023-12-30 11:42:36', '1', '2023-12-30 11:42:36', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3225, 109, 1016, '1', '2023-12-30 11:42:36', '1', '2023-12-30 11:42:36', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3226, 111, 102, '1', '2023-12-30 11:42:36', '1', '2023-12-30 11:42:36', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3227, 111, 1013, '1', '2023-12-30 11:42:36', '1', '2023-12-30 11:42:36', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3228, 111, 1014, '1', '2023-12-30 11:42:36', '1', '2023-12-30 11:42:36', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3229, 111, 1015, '1', '2023-12-30 11:42:36', '1', '2023-12-30 11:42:36', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3230, 111, 1016, '1', '2023-12-30 11:42:36', '1', '2023-12-30 11:42:36', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4163, 109, 5, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4164, 109, 1118, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4165, 109, 1119, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4166, 109, 1120, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4167, 109, 2713, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4168, 109, 2714, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4169, 109, 2715, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4170, 109, 2716, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4171, 109, 2717, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4172, 109, 2718, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4173, 109, 2720, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4174, 109, 1185, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4175, 109, 2721, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4176, 109, 1186, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4177, 109, 2722, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4178, 109, 1187, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4179, 109, 2723, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4180, 109, 1188, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4181, 109, 2724, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4182, 109, 1189, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4183, 109, 2725, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4184, 109, 1190, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4185, 109, 2726, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4186, 109, 1191, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4187, 109, 2727, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4188, 109, 1192, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4189, 109, 2728, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4190, 109, 1193, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4191, 109, 2729, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4192, 109, 1194, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4193, 109, 2730, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4194, 109, 1195, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4195, 109, 2731, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4196, 109, 1196, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4197, 109, 2732, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4198, 109, 1197, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4199, 109, 2733, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4200, 109, 1198, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4201, 109, 2734, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4202, 109, 1199, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4203, 109, 2735, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4204, 109, 1200, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4205, 109, 1201, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4206, 109, 1202, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4207, 109, 1207, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4208, 109, 1208, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4209, 109, 1209, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4210, 109, 1210, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4211, 109, 1211, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4212, 109, 1212, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4213, 109, 1213, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4214, 109, 1215, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4215, 109, 1216, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4216, 109, 1217, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4217, 109, 1218, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4218, 109, 1219, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4219, 109, 1220, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4220, 109, 1221, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4221, 109, 1222, '1', '2024-03-30 17:53:17', '1', '2024-03-30 17:53:17', '0', 121); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4222, 111, 5, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4223, 111, 1118, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4224, 111, 1119, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4225, 111, 1120, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4226, 111, 2713, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4227, 111, 2714, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4228, 111, 2715, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4229, 111, 2716, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4230, 111, 2717, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4231, 111, 2718, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4232, 111, 2720, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4233, 111, 1185, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4234, 111, 2721, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4235, 111, 1186, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4236, 111, 2722, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4237, 111, 1187, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4238, 111, 2723, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4239, 111, 1188, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4240, 111, 2724, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4241, 111, 1189, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4242, 111, 2725, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4243, 111, 1190, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4244, 111, 2726, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4245, 111, 1191, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4246, 111, 2727, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4247, 111, 1192, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4248, 111, 2728, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4249, 111, 1193, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4250, 111, 2729, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4251, 111, 1194, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4252, 111, 2730, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4253, 111, 1195, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4254, 111, 2731, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4255, 111, 1196, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4256, 111, 2732, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4257, 111, 1197, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4258, 111, 2733, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4259, 111, 1198, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4260, 111, 2734, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4261, 111, 1199, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4262, 111, 2735, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4263, 111, 1200, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4264, 111, 1201, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4265, 111, 1202, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4266, 111, 1207, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4267, 111, 1208, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4268, 111, 1209, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4269, 111, 1210, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4270, 111, 1211, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4271, 111, 1212, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4272, 111, 1213, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4273, 111, 1215, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4274, 111, 1216, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4275, 111, 1217, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4276, 111, 1218, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4277, 111, 1219, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4278, 111, 1220, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4279, 111, 1221, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4280, 111, 1222, '1', '2024-03-30 17:53:18', '1', '2024-03-30 17:53:18', '0', 122); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (5777, 101, 2739, '1', '2024-04-30 09:38:37', '1', '2024-04-30 09:38:37', '0', 1); +INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (5778, 101, 2740, '1', '2024-04-30 09:38:37', '1', '2024-04-30 09:38:37', '0', 1); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS system_role_menu_seq; +CREATE SEQUENCE system_role_menu_seq + START 5779; + +-- ---------------------------- +-- Table structure for system_sms_channel +-- ---------------------------- +DROP TABLE IF EXISTS system_sms_channel; +CREATE TABLE system_sms_channel +( + id int8 NOT NULL, + signature varchar(12) NOT NULL, + code varchar(63) NOT NULL, + status int2 NOT NULL, + remark varchar(255) NULL DEFAULT NULL, + api_key varchar(128) NOT NULL, + api_secret varchar(128) NULL DEFAULT NULL, + callback_url varchar(255) NULL DEFAULT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_sms_channel + ADD CONSTRAINT pk_system_sms_channel PRIMARY KEY (id); + +COMMENT ON COLUMN system_sms_channel.id IS '编号'; +COMMENT ON COLUMN system_sms_channel.signature IS '短信签名'; +COMMENT ON COLUMN system_sms_channel.code IS '渠道编码'; +COMMENT ON COLUMN system_sms_channel.status IS '开启状态'; +COMMENT ON COLUMN system_sms_channel.remark IS '备注'; +COMMENT ON COLUMN system_sms_channel.api_key IS '短信 API 的账号'; +COMMENT ON COLUMN system_sms_channel.api_secret IS '短信 API 的秘钥'; +COMMENT ON COLUMN system_sms_channel.callback_url IS '短信发送回调 URL'; +COMMENT ON COLUMN system_sms_channel.creator IS '创建者'; +COMMENT ON COLUMN system_sms_channel.create_time IS '创建时间'; +COMMENT ON COLUMN system_sms_channel.updater IS '更新者'; +COMMENT ON COLUMN system_sms_channel.update_time IS '更新时间'; +COMMENT ON COLUMN system_sms_channel.deleted IS '是否删除'; +COMMENT ON TABLE system_sms_channel IS '短信渠道'; + +-- ---------------------------- +-- Records of system_sms_channel +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO system_sms_channel (id, signature, code, status, remark, api_key, api_secret, callback_url, creator, create_time, updater, update_time, deleted) VALUES (2, 'Ballcat', 'ALIYUN', 0, '你要改哦,只有我可以用!!!!', 'LTAI5tCnKso2uG3kJ5gRav88', 'fGJ5SNXL7P1NHNRmJ7DJaMJGPyE55C', NULL, '', '2021-03-31 11:53:10', '1', '2023-12-02 22:10:17', '0'); +INSERT INTO system_sms_channel (id, signature, code, status, remark, api_key, api_secret, callback_url, creator, create_time, updater, update_time, deleted) VALUES (4, '测试渠道', 'DEBUG_DING_TALK', 0, '123', '696b5d8ead48071237e4aa5861ff08dbadb2b4ded1c688a7b7c9afc615579859', 'SEC5c4e5ff888bc8a9923ae47f59e7ccd30af1f14d93c55b4e2c9cb094e35aeed67', NULL, '1', '2021-04-13 00:23:14', '1', '2022-03-27 20:29:49', '0'); +INSERT INTO system_sms_channel (id, signature, code, status, remark, api_key, api_secret, callback_url, creator, create_time, updater, update_time, deleted) VALUES (6, '测试演示', 'DEBUG_DING_TALK', 0, '仅测试', '696b5d8ead48071237e4aa5861ff08dbadb2b4ded1c688a7b7c9afc615579859', 'SEC5c4e5ff888bc8a9923ae47f59e7ccd30af1f14d93c55b4e2c9cb094e35aeed67', NULL, '1', '2022-04-10 23:07:59', '1', '2023-12-02 22:10:08', '0'); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS system_sms_channel_seq; +CREATE SEQUENCE system_sms_channel_seq + START 7; + +-- ---------------------------- +-- Table structure for system_sms_code +-- ---------------------------- +DROP TABLE IF EXISTS system_sms_code; +CREATE TABLE system_sms_code +( + id int8 NOT NULL, + mobile varchar(11) NOT NULL, + code varchar(6) NOT NULL, + create_ip varchar(15) NOT NULL, + scene int2 NOT NULL, + today_index int2 NOT NULL, + used int2 NOT NULL, + used_time timestamp NULL DEFAULT NULL, + used_ip varchar(255) NULL DEFAULT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_sms_code + ADD CONSTRAINT pk_system_sms_code PRIMARY KEY (id); + +CREATE INDEX idx_system_sms_code_01 ON system_sms_code (mobile); + +COMMENT ON COLUMN system_sms_code.id IS '编号'; +COMMENT ON COLUMN system_sms_code.mobile IS '手机号'; +COMMENT ON COLUMN system_sms_code.code IS '验证码'; +COMMENT ON COLUMN system_sms_code.create_ip IS '创建 IP'; +COMMENT ON COLUMN system_sms_code.scene IS '发送场景'; +COMMENT ON COLUMN system_sms_code.today_index IS '今日发送的第几条'; +COMMENT ON COLUMN system_sms_code.used IS '是否使用'; +COMMENT ON COLUMN system_sms_code.used_time IS '使用时间'; +COMMENT ON COLUMN system_sms_code.used_ip IS '使用 IP'; +COMMENT ON COLUMN system_sms_code.creator IS '创建者'; +COMMENT ON COLUMN system_sms_code.create_time IS '创建时间'; +COMMENT ON COLUMN system_sms_code.updater IS '更新者'; +COMMENT ON COLUMN system_sms_code.update_time IS '更新时间'; +COMMENT ON COLUMN system_sms_code.deleted IS '是否删除'; +COMMENT ON COLUMN system_sms_code.tenant_id IS '租户编号'; +COMMENT ON TABLE system_sms_code IS '手机验证码'; + +DROP SEQUENCE IF EXISTS system_sms_code_seq; +CREATE SEQUENCE system_sms_code_seq + START 1; + +-- ---------------------------- +-- Table structure for system_sms_log +-- ---------------------------- +DROP TABLE IF EXISTS system_sms_log; +CREATE TABLE system_sms_log +( + id int8 NOT NULL, + channel_id int8 NOT NULL, + channel_code varchar(63) NOT NULL, + template_id int8 NOT NULL, + template_code varchar(63) NOT NULL, + template_type int2 NOT NULL, + template_content varchar(255) NOT NULL, + template_params varchar(255) NOT NULL, + api_template_id varchar(63) NOT NULL, + mobile varchar(11) NOT NULL, + user_id int8 NULL DEFAULT NULL, + user_type int2 NULL DEFAULT NULL, + send_status int2 NOT NULL DEFAULT 0, + send_time timestamp NULL DEFAULT NULL, + api_send_code varchar(63) NULL DEFAULT NULL, + api_send_msg varchar(255) NULL DEFAULT NULL, + api_request_id varchar(255) NULL DEFAULT NULL, + api_serial_no varchar(255) NULL DEFAULT NULL, + receive_status int2 NOT NULL DEFAULT 0, + receive_time timestamp NULL DEFAULT NULL, + api_receive_code varchar(63) NULL DEFAULT NULL, + api_receive_msg varchar(255) NULL DEFAULT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_sms_log + ADD CONSTRAINT pk_system_sms_log PRIMARY KEY (id); + +COMMENT ON COLUMN system_sms_log.id IS '编号'; +COMMENT ON COLUMN system_sms_log.channel_id IS '短信渠道编号'; +COMMENT ON COLUMN system_sms_log.channel_code IS '短信渠道编码'; +COMMENT ON COLUMN system_sms_log.template_id IS '模板编号'; +COMMENT ON COLUMN system_sms_log.template_code IS '模板编码'; +COMMENT ON COLUMN system_sms_log.template_type IS '短信类型'; +COMMENT ON COLUMN system_sms_log.template_content IS '短信内容'; +COMMENT ON COLUMN system_sms_log.template_params IS '短信参数'; +COMMENT ON COLUMN system_sms_log.api_template_id IS '短信 API 的模板编号'; +COMMENT ON COLUMN system_sms_log.mobile IS '手机号'; +COMMENT ON COLUMN system_sms_log.user_id IS '用户编号'; +COMMENT ON COLUMN system_sms_log.user_type IS '用户类型'; +COMMENT ON COLUMN system_sms_log.send_status IS '发送状态'; +COMMENT ON COLUMN system_sms_log.send_time IS '发送时间'; +COMMENT ON COLUMN system_sms_log.api_send_code IS '短信 API 发送结果的编码'; +COMMENT ON COLUMN system_sms_log.api_send_msg IS '短信 API 发送失败的提示'; +COMMENT ON COLUMN system_sms_log.api_request_id IS '短信 API 发送返回的唯一请求 ID'; +COMMENT ON COLUMN system_sms_log.api_serial_no IS '短信 API 发送返回的序号'; +COMMENT ON COLUMN system_sms_log.receive_status IS '接收状态'; +COMMENT ON COLUMN system_sms_log.receive_time IS '接收时间'; +COMMENT ON COLUMN system_sms_log.api_receive_code IS 'API 接收结果的编码'; +COMMENT ON COLUMN system_sms_log.api_receive_msg IS 'API 接收结果的说明'; +COMMENT ON COLUMN system_sms_log.creator IS '创建者'; +COMMENT ON COLUMN system_sms_log.create_time IS '创建时间'; +COMMENT ON COLUMN system_sms_log.updater IS '更新者'; +COMMENT ON COLUMN system_sms_log.update_time IS '更新时间'; +COMMENT ON COLUMN system_sms_log.deleted IS '是否删除'; +COMMENT ON TABLE system_sms_log IS '短信日志'; + +DROP SEQUENCE IF EXISTS system_sms_log_seq; +CREATE SEQUENCE system_sms_log_seq + START 1; + +-- ---------------------------- +-- Table structure for system_sms_template +-- ---------------------------- +DROP TABLE IF EXISTS system_sms_template; +CREATE TABLE system_sms_template +( + id int8 NOT NULL, + type int2 NOT NULL, + status int2 NOT NULL, + code varchar(63) NOT NULL, + name varchar(63) NOT NULL, + content varchar(255) NOT NULL, + params varchar(255) NOT NULL, + remark varchar(255) NULL DEFAULT NULL, + api_template_id varchar(63) NOT NULL, + channel_id int8 NOT NULL, + channel_code varchar(63) NOT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_sms_template + ADD CONSTRAINT pk_system_sms_template PRIMARY KEY (id); + +COMMENT ON COLUMN system_sms_template.id IS '编号'; +COMMENT ON COLUMN system_sms_template.type IS '模板类型'; +COMMENT ON COLUMN system_sms_template.status IS '开启状态'; +COMMENT ON COLUMN system_sms_template.code IS '模板编码'; +COMMENT ON COLUMN system_sms_template.name IS '模板名称'; +COMMENT ON COLUMN system_sms_template.content IS '模板内容'; +COMMENT ON COLUMN system_sms_template.params IS '参数数组'; +COMMENT ON COLUMN system_sms_template.remark IS '备注'; +COMMENT ON COLUMN system_sms_template.api_template_id IS '短信 API 的模板编号'; +COMMENT ON COLUMN system_sms_template.channel_id IS '短信渠道编号'; +COMMENT ON COLUMN system_sms_template.channel_code IS '短信渠道编码'; +COMMENT ON COLUMN system_sms_template.creator IS '创建者'; +COMMENT ON COLUMN system_sms_template.create_time IS '创建时间'; +COMMENT ON COLUMN system_sms_template.updater IS '更新者'; +COMMENT ON COLUMN system_sms_template.update_time IS '更新时间'; +COMMENT ON COLUMN system_sms_template.deleted IS '是否删除'; +COMMENT ON TABLE system_sms_template IS '短信模板'; + +-- ---------------------------- +-- Records of system_sms_template +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO system_sms_template (id, type, status, code, name, content, params, remark, api_template_id, channel_id, channel_code, creator, create_time, updater, update_time, deleted) VALUES (2, 1, 0, 'test_01', '测试验证码短信', '正在进行登录操作{operation},您的验证码是{code}', '["operation","code"]', '测试备注', '4383920', 6, 'DEBUG_DING_TALK', '', '2021-03-31 10:49:38', '1', '2023-12-02 22:32:47', '0'); +INSERT INTO system_sms_template (id, type, status, code, name, content, params, remark, api_template_id, channel_id, channel_code, creator, create_time, updater, update_time, deleted) VALUES (3, 1, 0, 'test_02', '公告通知', '您的验证码{code},该验证码5分钟内有效,请勿泄漏于他人!', '["code"]', NULL, 'SMS_207945135', 2, 'ALIYUN', '', '2021-03-31 11:56:30', '1', '2021-04-10 01:22:02', '0'); +INSERT INTO system_sms_template (id, type, status, code, name, content, params, remark, api_template_id, channel_id, channel_code, creator, create_time, updater, update_time, deleted) VALUES (6, 3, 0, 'test-01', '测试模板', '哈哈哈 {name}', '["name"]', 'f哈哈哈', '4383920', 6, 'DEBUG_DING_TALK', '1', '2021-04-10 01:07:21', '1', '2022-12-10 21:26:09', '0'); +INSERT INTO system_sms_template (id, type, status, code, name, content, params, remark, api_template_id, channel_id, channel_code, creator, create_time, updater, update_time, deleted) VALUES (7, 3, 0, 'test-04', '测试下', '老鸡{name},牛逼{code}', '["name","code"]', '哈哈哈哈', 'suibian', 4, 'DEBUG_DING_TALK', '1', '2021-04-13 00:29:53', '1', '2023-12-02 22:35:34', '0'); +INSERT INTO system_sms_template (id, type, status, code, name, content, params, remark, api_template_id, channel_id, channel_code, creator, create_time, updater, update_time, deleted) VALUES (8, 1, 0, 'user-sms-login', '前台用户短信登录', '您的验证码是{code}', '["code"]', NULL, '4372216', 6, 'DEBUG_DING_TALK', '1', '2021-10-11 08:10:00', '1', '2022-12-10 21:25:59', '0'); +INSERT INTO system_sms_template (id, type, status, code, name, content, params, remark, api_template_id, channel_id, channel_code, creator, create_time, updater, update_time, deleted) VALUES (9, 2, 0, 'bpm_task_assigned', '【工作流】任务被分配', '您收到了一条新的待办任务:{processInstanceName}-{taskName},申请人:{startUserNickname},处理链接:{detailUrl}', '["processInstanceName","taskName","startUserNickname","detailUrl"]', NULL, 'suibian', 4, 'DEBUG_DING_TALK', '1', '2022-01-21 22:31:19', '1', '2022-01-22 00:03:36', '0'); +INSERT INTO system_sms_template (id, type, status, code, name, content, params, remark, api_template_id, channel_id, channel_code, creator, create_time, updater, update_time, deleted) VALUES (10, 2, 0, 'bpm_process_instance_reject', '【工作流】流程被不通过', '您的流程被审批不通过:{processInstanceName},原因:{reason},查看链接:{detailUrl}', '["processInstanceName","reason","detailUrl"]', NULL, 'suibian', 4, 'DEBUG_DING_TALK', '1', '2022-01-22 00:03:31', '1', '2022-05-01 12:33:14', '0'); +INSERT INTO system_sms_template (id, type, status, code, name, content, params, remark, api_template_id, channel_id, channel_code, creator, create_time, updater, update_time, deleted) VALUES (11, 2, 0, 'bpm_process_instance_approve', '【工作流】流程被通过', '您的流程被审批通过:{processInstanceName},查看链接:{detailUrl}', '["processInstanceName","detailUrl"]', NULL, 'suibian', 4, 'DEBUG_DING_TALK', '1', '2022-01-22 00:04:31', '1', '2022-03-27 20:32:21', '0'); +INSERT INTO system_sms_template (id, type, status, code, name, content, params, remark, api_template_id, channel_id, channel_code, creator, create_time, updater, update_time, deleted) VALUES (12, 2, 0, 'demo', '演示模板', '我就是测试一下下', '[]', NULL, 'biubiubiu', 6, 'DEBUG_DING_TALK', '1', '2022-04-10 23:22:49', '1', '2023-03-24 23:45:07', '0'); +INSERT INTO system_sms_template (id, type, status, code, name, content, params, remark, api_template_id, channel_id, channel_code, creator, create_time, updater, update_time, deleted) VALUES (14, 1, 0, 'user-update-mobile', '会员用户 - 修改手机', '您的验证码{code},该验证码 5 分钟内有效,请勿泄漏于他人!', '["code"]', '', 'null', 4, 'DEBUG_DING_TALK', '1', '2023-08-19 18:58:01', '1', '2023-08-19 11:34:04', '0'); +INSERT INTO system_sms_template (id, type, status, code, name, content, params, remark, api_template_id, channel_id, channel_code, creator, create_time, updater, update_time, deleted) VALUES (15, 1, 0, 'user-update-password', '会员用户 - 修改密码', '您的验证码{code},该验证码 5 分钟内有效,请勿泄漏于他人!', '["code"]', '', 'null', 4, 'DEBUG_DING_TALK', '1', '2023-08-19 18:58:01', '1', '2023-08-19 11:34:18', '0'); +INSERT INTO system_sms_template (id, type, status, code, name, content, params, remark, api_template_id, channel_id, channel_code, creator, create_time, updater, update_time, deleted) VALUES (16, 1, 0, 'user-reset-password', '会员用户 - 重置密码', '您的验证码{code},该验证码 5 分钟内有效,请勿泄漏于他人!', '["code"]', '', 'null', 4, 'DEBUG_DING_TALK', '1', '2023-08-19 18:58:01', '1', '2023-12-02 22:35:27', '0'); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS system_sms_template_seq; +CREATE SEQUENCE system_sms_template_seq + START 17; + +-- ---------------------------- +-- Table structure for system_social_client +-- ---------------------------- +DROP TABLE IF EXISTS system_social_client; +CREATE TABLE system_social_client +( + id int8 NOT NULL, + name varchar(255) NOT NULL, + social_type int2 NOT NULL, + user_type int2 NOT NULL, + client_id varchar(255) NOT NULL, + client_secret varchar(255) NOT NULL, + agent_id varchar(255) NULL DEFAULT NULL, + status int2 NOT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_social_client + ADD CONSTRAINT pk_system_social_client PRIMARY KEY (id); + +COMMENT ON COLUMN system_social_client.id IS '编号'; +COMMENT ON COLUMN system_social_client.name IS '应用名'; +COMMENT ON COLUMN system_social_client.social_type IS '社交平台的类型'; +COMMENT ON COLUMN system_social_client.user_type IS '用户类型'; +COMMENT ON COLUMN system_social_client.client_id IS '客户端编号'; +COMMENT ON COLUMN system_social_client.client_secret IS '客户端密钥'; +COMMENT ON COLUMN system_social_client.agent_id IS '代理编号'; +COMMENT ON COLUMN system_social_client.status IS '状态'; +COMMENT ON COLUMN system_social_client.creator IS '创建者'; +COMMENT ON COLUMN system_social_client.create_time IS '创建时间'; +COMMENT ON COLUMN system_social_client.updater IS '更新者'; +COMMENT ON COLUMN system_social_client.update_time IS '更新时间'; +COMMENT ON COLUMN system_social_client.deleted IS '是否删除'; +COMMENT ON COLUMN system_social_client.tenant_id IS '租户编号'; +COMMENT ON TABLE system_social_client IS '社交客户端表'; + +-- ---------------------------- +-- Records of system_social_client +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO system_social_client (id, name, social_type, user_type, client_id, client_secret, agent_id, status, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1, '钉钉', 20, 2, 'dingvrnreaje3yqvzhxg', 'i8E6iZyDvZj51JIb0tYsYfVQYOks9Cq1lgryEjFRqC79P3iJcrxEwT6Qk2QvLrLI', NULL, 0, '', '2023-10-18 11:21:18', '1', '2023-12-20 21:28:26', '1', 1); +INSERT INTO system_social_client (id, name, social_type, user_type, client_id, client_secret, agent_id, status, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2, '钉钉(王土豆)', 20, 2, 'dingtsu9hpepjkbmthhw', 'FP_bnSq_HAHKCSncmJjw5hxhnzs6vaVDSZZn3egj6rdqTQ_hu5tQVJyLMpgCakdP', NULL, 0, '', '2023-10-18 11:21:18', '', '2023-12-20 21:28:26', '1', 121); +INSERT INTO system_social_client (id, name, social_type, user_type, client_id, client_secret, agent_id, status, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3, '微信公众号', 31, 1, 'wx5b23ba7a5589ecbb', '2a7b3b20c537e52e74afd395eb85f61f', NULL, 0, '', '2023-10-18 16:07:46', '1', '2023-12-20 21:28:23', '1', 1); +INSERT INTO system_social_client (id, name, social_type, user_type, client_id, client_secret, agent_id, status, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (43, '微信小程序', 34, 1, 'wx63c280fe3248a3e7', '6f270509224a7ae1296bbf1c8cb97aed', NULL, 0, '', '2023-10-19 13:37:41', '1', '2023-12-20 21:28:25', '1', 1); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS system_social_client_seq; +CREATE SEQUENCE system_social_client_seq + START 44; + +-- ---------------------------- +-- Table structure for system_social_user +-- ---------------------------- +DROP TABLE IF EXISTS system_social_user; +CREATE TABLE system_social_user +( + id int8 NOT NULL, + type int2 NOT NULL, + openid varchar(32) NOT NULL, + token varchar(256) NULL DEFAULT NULL, + raw_token_info varchar(1024) NOT NULL, + nickname varchar(32) NOT NULL, + avatar varchar(255) NULL DEFAULT NULL, + raw_user_info varchar(1024) NOT NULL, + code varchar(256) NOT NULL, + state varchar(256) NULL DEFAULT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_social_user + ADD CONSTRAINT pk_system_social_user PRIMARY KEY (id); + +COMMENT ON COLUMN system_social_user.id IS '主键(自增策略)'; +COMMENT ON COLUMN system_social_user.type IS '社交平台的类型'; +COMMENT ON COLUMN system_social_user.openid IS '社交 openid'; +COMMENT ON COLUMN system_social_user.token IS '社交 token'; +COMMENT ON COLUMN system_social_user.raw_token_info IS '原始 Token 数据,一般是 JSON 格式'; +COMMENT ON COLUMN system_social_user.nickname IS '用户昵称'; +COMMENT ON COLUMN system_social_user.avatar IS '用户头像'; +COMMENT ON COLUMN system_social_user.raw_user_info IS '原始用户数据,一般是 JSON 格式'; +COMMENT ON COLUMN system_social_user.code IS '最后一次的认证 code'; +COMMENT ON COLUMN system_social_user.state IS '最后一次的认证 state'; +COMMENT ON COLUMN system_social_user.creator IS '创建者'; +COMMENT ON COLUMN system_social_user.create_time IS '创建时间'; +COMMENT ON COLUMN system_social_user.updater IS '更新者'; +COMMENT ON COLUMN system_social_user.update_time IS '更新时间'; +COMMENT ON COLUMN system_social_user.deleted IS '是否删除'; +COMMENT ON COLUMN system_social_user.tenant_id IS '租户编号'; +COMMENT ON TABLE system_social_user IS '社交用户表'; + +DROP SEQUENCE IF EXISTS system_social_user_seq; +CREATE SEQUENCE system_social_user_seq + START 1; + +-- ---------------------------- +-- Table structure for system_social_user_bind +-- ---------------------------- +DROP TABLE IF EXISTS system_social_user_bind; +CREATE TABLE system_social_user_bind +( + id int8 NOT NULL, + user_id int8 NOT NULL, + user_type int2 NOT NULL, + social_type int2 NOT NULL, + social_user_id int8 NOT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_social_user_bind + ADD CONSTRAINT pk_system_social_user_bind PRIMARY KEY (id); + +COMMENT ON COLUMN system_social_user_bind.id IS '主键(自增策略)'; +COMMENT ON COLUMN system_social_user_bind.user_id IS '用户编号'; +COMMENT ON COLUMN system_social_user_bind.user_type IS '用户类型'; +COMMENT ON COLUMN system_social_user_bind.social_type IS '社交平台的类型'; +COMMENT ON COLUMN system_social_user_bind.social_user_id IS '社交用户的编号'; +COMMENT ON COLUMN system_social_user_bind.creator IS '创建者'; +COMMENT ON COLUMN system_social_user_bind.create_time IS '创建时间'; +COMMENT ON COLUMN system_social_user_bind.updater IS '更新者'; +COMMENT ON COLUMN system_social_user_bind.update_time IS '更新时间'; +COMMENT ON COLUMN system_social_user_bind.deleted IS '是否删除'; +COMMENT ON COLUMN system_social_user_bind.tenant_id IS '租户编号'; +COMMENT ON TABLE system_social_user_bind IS '社交绑定表'; + +DROP SEQUENCE IF EXISTS system_social_user_bind_seq; +CREATE SEQUENCE system_social_user_bind_seq + START 1; + +-- ---------------------------- +-- Table structure for system_tenant +-- ---------------------------- +DROP TABLE IF EXISTS system_tenant; +CREATE TABLE system_tenant +( + id int8 NOT NULL, + name varchar(30) NOT NULL, + contact_user_id int8 NULL DEFAULT NULL, + contact_name varchar(30) NOT NULL, + contact_mobile varchar(500) NULL DEFAULT NULL, + status int2 NOT NULL DEFAULT 0, + website varchar(256) NULL DEFAULT '', + package_id int8 NOT NULL, + expire_time timestamp NOT NULL, + account_count int4 NOT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_tenant + ADD CONSTRAINT pk_system_tenant PRIMARY KEY (id); + +COMMENT ON COLUMN system_tenant.id IS '租户编号'; +COMMENT ON COLUMN system_tenant.name IS '租户名'; +COMMENT ON COLUMN system_tenant.contact_user_id IS '联系人的用户编号'; +COMMENT ON COLUMN system_tenant.contact_name IS '联系人'; +COMMENT ON COLUMN system_tenant.contact_mobile IS '联系手机'; +COMMENT ON COLUMN system_tenant.status IS '租户状态(0正常 1停用)'; +COMMENT ON COLUMN system_tenant.website IS '绑定域名'; +COMMENT ON COLUMN system_tenant.package_id IS '租户套餐编号'; +COMMENT ON COLUMN system_tenant.expire_time IS '过期时间'; +COMMENT ON COLUMN system_tenant.account_count IS '账号数量'; +COMMENT ON COLUMN system_tenant.creator IS '创建者'; +COMMENT ON COLUMN system_tenant.create_time IS '创建时间'; +COMMENT ON COLUMN system_tenant.updater IS '更新者'; +COMMENT ON COLUMN system_tenant.update_time IS '更新时间'; +COMMENT ON COLUMN system_tenant.deleted IS '是否删除'; +COMMENT ON TABLE system_tenant IS '租户表'; + +-- ---------------------------- +-- Records of system_tenant +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, website, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'www.iocoder.cn', 0, '2099-02-19 17:14:16', 9999, '1', '2021-01-05 17:03:47', '1', '2023-11-06 11:41:41', '0'); +INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, website, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'zsxq.iocoder.cn', 111, '2024-03-11 00:00:00', 20, '1', '2022-02-22 00:56:14', '1', '2023-11-06 11:41:47', '0'); +INSERT INTO system_tenant (id, name, contact_user_id, contact_name, contact_mobile, status, website, package_id, expire_time, account_count, creator, create_time, updater, update_time, deleted) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'test.iocoder.cn', 111, '2022-04-30 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2023-11-06 11:41:53', '0'); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS system_tenant_seq; +CREATE SEQUENCE system_tenant_seq + START 123; + +-- ---------------------------- +-- Table structure for system_tenant_package +-- ---------------------------- +DROP TABLE IF EXISTS system_tenant_package; +CREATE TABLE system_tenant_package +( + id int8 NOT NULL, + name varchar(30) NOT NULL, + status int2 NOT NULL DEFAULT 0, + remark varchar(256) NULL DEFAULT '', + menu_ids varchar(4096) NOT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_tenant_package + ADD CONSTRAINT pk_system_tenant_package PRIMARY KEY (id); + +COMMENT ON COLUMN system_tenant_package.id IS '套餐编号'; +COMMENT ON COLUMN system_tenant_package.name IS '套餐名'; +COMMENT ON COLUMN system_tenant_package.status IS '租户状态(0正常 1停用)'; +COMMENT ON COLUMN system_tenant_package.remark IS '备注'; +COMMENT ON COLUMN system_tenant_package.menu_ids IS '关联的菜单编号'; +COMMENT ON COLUMN system_tenant_package.creator IS '创建者'; +COMMENT ON COLUMN system_tenant_package.create_time IS '创建时间'; +COMMENT ON COLUMN system_tenant_package.updater IS '更新者'; +COMMENT ON COLUMN system_tenant_package.update_time IS '更新时间'; +COMMENT ON COLUMN system_tenant_package.deleted IS '是否删除'; +COMMENT ON TABLE system_tenant_package IS '租户套餐表'; + +-- ---------------------------- +-- Records of system_tenant_package +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO system_tenant_package (id, name, status, remark, menu_ids, creator, create_time, updater, update_time, deleted) VALUES (111, '普通套餐', 0, '小功能', '[1,2,5,1031,1032,1033,1034,1035,1036,1037,1038,1039,1050,1051,1052,1053,1054,1056,1057,1058,1059,1060,1063,1064,1065,1066,1067,1070,1075,1076,1077,1078,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1118,1119,1120,100,101,102,103,106,107,110,111,112,113,1138,114,1139,115,1140,116,1141,1142,1143,2713,2714,2715,2716,2717,2718,2720,1185,2721,1186,2722,1187,2723,1188,2724,1189,2725,1190,2726,1191,2727,2472,1192,2728,1193,2729,1194,2730,1195,2731,1196,2732,1197,2733,2478,1198,2734,2479,1199,2735,2480,1200,2481,1201,2482,1202,2483,2484,2485,2486,2487,1207,2488,1208,2489,1209,2490,1210,2491,1211,2492,1212,2493,1213,2494,2495,1215,1216,2497,1217,1218,1219,1220,1221,1222,1224,1225,1226,1227,1228,1229,1237,1238,1239,1240,1241,1242,1243,2525,1255,1256,1001,1257,1002,1258,1003,1259,1004,1260,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020]', '1', '2022-02-22 00:54:00', '1', '2024-03-30 17:53:17', '0'); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS system_tenant_package_seq; +CREATE SEQUENCE system_tenant_package_seq + START 112; + +-- ---------------------------- +-- Table structure for system_user_post +-- ---------------------------- +DROP TABLE IF EXISTS system_user_post; +CREATE TABLE system_user_post +( + id int8 NOT NULL, + user_id int8 NOT NULL DEFAULT 0, + post_id int8 NOT NULL DEFAULT 0, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_user_post + ADD CONSTRAINT pk_system_user_post PRIMARY KEY (id); + +COMMENT ON COLUMN system_user_post.id IS 'id'; +COMMENT ON COLUMN system_user_post.user_id IS '用户ID'; +COMMENT ON COLUMN system_user_post.post_id IS '岗位ID'; +COMMENT ON COLUMN system_user_post.creator IS '创建者'; +COMMENT ON COLUMN system_user_post.create_time IS '创建时间'; +COMMENT ON COLUMN system_user_post.updater IS '更新者'; +COMMENT ON COLUMN system_user_post.update_time IS '更新时间'; +COMMENT ON COLUMN system_user_post.deleted IS '是否删除'; +COMMENT ON COLUMN system_user_post.tenant_id IS '租户编号'; +COMMENT ON TABLE system_user_post IS '用户岗位表'; + +-- ---------------------------- +-- Records of system_user_post +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO system_user_post (id, user_id, post_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (112, 1, 1, 'admin', '2022-05-02 07:25:24', 'admin', '2022-05-02 07:25:24', '0', 1); +INSERT INTO system_user_post (id, user_id, post_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (113, 100, 1, 'admin', '2022-05-02 07:25:24', 'admin', '2022-05-02 07:25:24', '0', 1); +INSERT INTO system_user_post (id, user_id, post_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (115, 104, 1, '1', '2022-05-16 19:36:28', '1', '2022-05-16 19:36:28', '0', 1); +INSERT INTO system_user_post (id, user_id, post_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (116, 117, 2, '1', '2022-07-09 17:40:26', '1', '2022-07-09 17:40:26', '0', 1); +INSERT INTO system_user_post (id, user_id, post_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (117, 118, 1, '1', '2022-07-09 17:44:44', '1', '2022-07-09 17:44:44', '0', 1); +INSERT INTO system_user_post (id, user_id, post_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (119, 114, 5, '1', '2024-03-24 20:45:51', '1', '2024-03-24 20:45:51', '0', 1); +INSERT INTO system_user_post (id, user_id, post_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (123, 115, 1, '1', '2024-04-04 09:37:14', '1', '2024-04-04 09:37:14', '0', 1); +INSERT INTO system_user_post (id, user_id, post_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (124, 115, 2, '1', '2024-04-04 09:37:14', '1', '2024-04-04 09:37:14', '0', 1); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS system_user_post_seq; +CREATE SEQUENCE system_user_post_seq + START 125; + +-- ---------------------------- +-- Table structure for system_user_role +-- ---------------------------- +DROP TABLE IF EXISTS system_user_role; +CREATE TABLE system_user_role +( + id int8 NOT NULL, + user_id int8 NOT NULL, + role_id int8 NOT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_user_role + ADD CONSTRAINT pk_system_user_role PRIMARY KEY (id); + +COMMENT ON COLUMN system_user_role.id IS '自增编号'; +COMMENT ON COLUMN system_user_role.user_id IS '用户ID'; +COMMENT ON COLUMN system_user_role.role_id IS '角色ID'; +COMMENT ON COLUMN system_user_role.creator IS '创建者'; +COMMENT ON COLUMN system_user_role.create_time IS '创建时间'; +COMMENT ON COLUMN system_user_role.updater IS '更新者'; +COMMENT ON COLUMN system_user_role.update_time IS '更新时间'; +COMMENT ON COLUMN system_user_role.deleted IS '是否删除'; +COMMENT ON COLUMN system_user_role.tenant_id IS '租户编号'; +COMMENT ON TABLE system_user_role IS '用户和角色关联表'; + +-- ---------------------------- +-- Records of system_user_role +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO system_user_role (id, user_id, role_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1, 1, 1, '', '2022-01-11 13:19:45', '', '2022-05-12 12:35:17', '0', 1); +INSERT INTO system_user_role (id, user_id, role_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2, 2, 2, '', '2022-01-11 13:19:45', '', '2022-05-12 12:35:13', '0', 1); +INSERT INTO system_user_role (id, user_id, role_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4, 100, 101, '', '2022-01-11 13:19:45', '', '2022-05-12 12:35:13', '0', 1); +INSERT INTO system_user_role (id, user_id, role_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (5, 100, 1, '', '2022-01-11 13:19:45', '', '2022-05-12 12:35:12', '0', 1); +INSERT INTO system_user_role (id, user_id, role_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (6, 100, 2, '', '2022-01-11 13:19:45', '', '2022-05-12 12:35:11', '0', 1); +INSERT INTO system_user_role (id, user_id, role_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (10, 103, 1, '1', '2022-01-11 13:19:45', '1', '2022-01-11 13:19:45', '0', 1); +INSERT INTO system_user_role (id, user_id, role_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (14, 110, 109, '1', '2022-02-22 00:56:14', '1', '2022-02-22 00:56:14', '0', 121); +INSERT INTO system_user_role (id, user_id, role_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (15, 111, 110, '110', '2022-02-23 13:14:38', '110', '2022-02-23 13:14:38', '0', 121); +INSERT INTO system_user_role (id, user_id, role_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (16, 113, 111, '1', '2022-03-07 21:37:58', '1', '2022-03-07 21:37:58', '0', 122); +INSERT INTO system_user_role (id, user_id, role_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (18, 1, 2, '1', '2022-05-12 20:39:29', '1', '2022-05-12 20:39:29', '0', 1); +INSERT INTO system_user_role (id, user_id, role_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (20, 104, 101, '1', '2022-05-28 15:43:57', '1', '2022-05-28 15:43:57', '0', 1); +INSERT INTO system_user_role (id, user_id, role_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (22, 115, 2, '1', '2022-07-21 22:08:30', '1', '2022-07-21 22:08:30', '0', 1); +INSERT INTO system_user_role (id, user_id, role_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (35, 112, 1, '1', '2024-03-15 20:00:24', '1', '2024-03-15 20:00:24', '0', 1); +INSERT INTO system_user_role (id, user_id, role_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (36, 118, 1, '1', '2024-03-17 09:12:08', '1', '2024-03-17 09:12:08', '0', 1); +INSERT INTO system_user_role (id, user_id, role_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (38, 114, 101, '1', '2024-03-24 22:23:03', '1', '2024-03-24 22:23:03', '0', 1); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS system_user_role_seq; +CREATE SEQUENCE system_user_role_seq + START 39; + +-- ---------------------------- +-- Table structure for system_users +-- ---------------------------- +DROP TABLE IF EXISTS system_users; +CREATE TABLE system_users +( + id int8 NOT NULL, + username varchar(30) NOT NULL, + password varchar(100) NULL DEFAULT '', + nickname varchar(30) NOT NULL, + remark varchar(500) NULL DEFAULT NULL, + dept_id int8 NULL DEFAULT NULL, + post_ids varchar(255) NULL DEFAULT NULL, + email varchar(50) NULL DEFAULT '', + mobile varchar(11) NULL DEFAULT '', + sex int2 NULL DEFAULT 0, + avatar varchar(512) NULL DEFAULT '', + status int2 NOT NULL DEFAULT 0, + login_ip varchar(50) NULL DEFAULT '', + login_date timestamp NULL DEFAULT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE system_users + ADD CONSTRAINT pk_system_users PRIMARY KEY (id); + +COMMENT ON COLUMN system_users.id IS '用户ID'; +COMMENT ON COLUMN system_users.username IS '用户账号'; +COMMENT ON COLUMN system_users.password IS '密码'; +COMMENT ON COLUMN system_users.nickname IS '用户昵称'; +COMMENT ON COLUMN system_users.remark IS '备注'; +COMMENT ON COLUMN system_users.dept_id IS '部门ID'; +COMMENT ON COLUMN system_users.post_ids IS '岗位编号数组'; +COMMENT ON COLUMN system_users.email IS '用户邮箱'; +COMMENT ON COLUMN system_users.mobile IS '手机号码'; +COMMENT ON COLUMN system_users.sex IS '用户性别'; +COMMENT ON COLUMN system_users.avatar IS '头像地址'; +COMMENT ON COLUMN system_users.status IS '帐号状态(0正常 1停用)'; +COMMENT ON COLUMN system_users.login_ip IS '最后登录IP'; +COMMENT ON COLUMN system_users.login_date IS '最后登录时间'; +COMMENT ON COLUMN system_users.creator IS '创建者'; +COMMENT ON COLUMN system_users.create_time IS '创建时间'; +COMMENT ON COLUMN system_users.updater IS '更新者'; +COMMENT ON COLUMN system_users.update_time IS '更新时间'; +COMMENT ON COLUMN system_users.deleted IS '是否删除'; +COMMENT ON COLUMN system_users.tenant_id IS '租户编号'; +COMMENT ON TABLE system_users IS '用户信息表'; + +-- ---------------------------- +-- Records of system_users +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO system_users (id, username, password, nickname, remark, dept_id, post_ids, email, mobile, sex, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '18818260277', 2, 'http://test.yudao.iocoder.cn/96c787a2ce88bf6d0ce3cd8b6cf5314e80e7703cd41bf4af8cd2e2909dbd6b6d.png', 0, '0:0:0:0:0:0:0:1', '2024-04-29 21:50:32', 'admin', '2021-01-05 17:03:47', NULL, '2024-04-29 21:50:32', '0', 1); +INSERT INTO system_users (id, username, password, nickname, remark, dept_id, post_ids, email, mobile, sex, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (100, 'yudao', '$2a$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 1, '127.0.0.1', '2022-07-09 23:03:33', '', '2021-01-07 09:07:17', NULL, '2022-07-09 23:03:33', '0', 1); +INSERT INTO system_users (id, username, password, nickname, remark, dept_id, post_ids, email, mobile, sex, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (103, 'yuanma', '$2a$10$YMpimV4T6BtDhIaA8jSW.u8UTGBeGhc/qwXP4oxoMr4mOw9.qttt6', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '0:0:0:0:0:0:0:1', '2024-03-18 21:09:04', '', '2021-01-13 23:50:35', NULL, '2024-03-18 21:09:04', '0', 1); +INSERT INTO system_users (id, username, password, nickname, remark, dept_id, post_ids, email, mobile, sex, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (104, 'test', '$2a$04$KhExCYl7lx6eWWZYKsibKOZ8IBJRyuNuCcEOLQ11RYhJKgHmlSwK.', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, '', 0, '0:0:0:0:0:0:0:1', '2024-03-26 07:11:35', '', '2021-01-21 02:13:53', NULL, '2024-03-26 07:11:35', '0', 1); +INSERT INTO system_users (id, username, password, nickname, remark, dept_id, post_ids, email, mobile, sex, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (107, 'admin107', '$2a$10$dYOOBKMO93v/.ReCqzyFg.o67Tqk.bbc2bhrpyBGkIw9aypCtr2pm', '芋艿', NULL, NULL, NULL, '', '15601691300', 0, '', 0, '', NULL, '1', '2022-02-20 22:59:33', '1', '2022-02-27 08:26:51', '0', 118); +INSERT INTO system_users (id, username, password, nickname, remark, dept_id, post_ids, email, mobile, sex, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (108, 'admin108', '$2a$10$y6mfvKoNYL1GXWak8nYwVOH.kCWqjactkzdoIDgiKl93WN3Ejg.Lu', '芋艿', NULL, NULL, NULL, '', '15601691300', 0, '', 0, '', NULL, '1', '2022-02-20 23:00:50', '1', '2022-02-27 08:26:53', '0', 119); +INSERT INTO system_users (id, username, password, nickname, remark, dept_id, post_ids, email, mobile, sex, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (109, 'admin109', '$2a$10$JAqvH0tEc0I7dfDVBI7zyuB4E3j.uH6daIjV53.vUS6PknFkDJkuK', '芋艿', NULL, NULL, NULL, '', '15601691300', 0, '', 0, '', NULL, '1', '2022-02-20 23:11:50', '1', '2022-02-27 08:26:56', '0', 120); +INSERT INTO system_users (id, username, password, nickname, remark, dept_id, post_ids, email, mobile, sex, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (110, 'admin110', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '小王', NULL, NULL, NULL, '', '15601691300', 0, '', 0, '127.0.0.1', '2022-09-25 22:47:33', '1', '2022-02-22 00:56:14', NULL, '2022-09-25 22:47:33', '0', 121); +INSERT INTO system_users (id, username, password, nickname, remark, dept_id, post_ids, email, mobile, sex, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (111, 'test', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '测试用户', NULL, NULL, '[]', '', '', 0, '', 0, '0:0:0:0:0:0:0:1', '2023-12-30 11:42:17', '110', '2022-02-23 13:14:33', NULL, '2023-12-30 11:42:17', '0', 121); +INSERT INTO system_users (id, username, password, nickname, remark, dept_id, post_ids, email, mobile, sex, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (112, 'newobject', '$2a$04$dB0z8Q819fJWz0hbaLe6B.VfHCjYgWx6LFfET5lyz3JwcqlyCkQ4C', '新对象', NULL, 100, '[]', '', '15601691235', 1, '', 0, '0:0:0:0:0:0:0:1', '2024-03-16 23:11:38', '1', '2022-02-23 19:08:03', NULL, '2024-03-16 23:11:38', '0', 1); +INSERT INTO system_users (id, username, password, nickname, remark, dept_id, post_ids, email, mobile, sex, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (113, 'aoteman', '$2a$10$0acJOIk2D25/oC87nyclE..0lzeu9DtQ/n3geP4fkun/zIVRhHJIO', '芋道', NULL, NULL, NULL, '', '15601691300', 0, '', 0, '127.0.0.1', '2022-03-19 18:38:51', '1', '2022-03-07 21:37:58', NULL, '2022-03-19 18:38:51', '0', 122); +INSERT INTO system_users (id, username, password, nickname, remark, dept_id, post_ids, email, mobile, sex, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (114, 'hrmgr', '$2a$10$TR4eybBioGRhBmDBWkqWLO6NIh3mzYa8KBKDDB5woiGYFVlRAi.fu', 'hr 小姐姐', NULL, NULL, '[5]', '', '15601691236', 1, '', 0, '0:0:0:0:0:0:0:1', '2024-03-24 22:21:05', '1', '2022-03-19 21:50:58', NULL, '2024-03-24 22:21:05', '0', 1); +INSERT INTO system_users (id, username, password, nickname, remark, dept_id, post_ids, email, mobile, sex, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (115, 'aotemane', '$2a$04$GcyP0Vyzb2F2Yni5PuIK9ueGxM0tkZGMtDwVRwrNbtMvorzbpNsV2', '阿呆', '11222', 102, '[1,2]', '7648@qq.com', '15601691229', 2, '', 0, '', NULL, '1', '2022-04-30 02:55:43', '1', '2024-04-04 09:37:14', '0', 1); +INSERT INTO system_users (id, username, password, nickname, remark, dept_id, post_ids, email, mobile, sex, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (117, 'admin123', '$2a$10$WI8Gg/lpZQIrOEZMHqka7OdFaD4Nx.B/qY8ZGTTUKrOJwaHFqibaC', '测试号', '1111', 100, '[2]', '', '15601691234', 1, '', 0, '', NULL, '1', '2022-07-09 17:40:26', '1', '2022-07-09 17:40:26', '0', 1); +INSERT INTO system_users (id, username, password, nickname, remark, dept_id, post_ids, email, mobile, sex, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (118, 'goudan', '$2a$04$OB1SuphCdiLVRpiYRKeqH.8NYS7UIp5vmIv1W7U4w6toiFeOAATVK', '狗蛋', NULL, 103, '[1]', '', '15601691239', 1, '', 0, '0:0:0:0:0:0:0:1', '2024-03-17 09:10:27', '1', '2022-07-09 17:44:43', '1', '2024-04-04 09:48:05', '0', 1); +INSERT INTO system_users (id, username, password, nickname, remark, dept_id, post_ids, email, mobile, sex, avatar, status, login_ip, login_date, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (131, 'hh', '$2a$04$jyH9h6.gaw8mpOjPfHIpx.8as2Rzfcmdlj5rlJFwgCw4rsv/MTb2K', '呵呵', NULL, 100, '[]', '777@qq.com', '15601882312', 1, '', 0, '', NULL, '1', '2024-04-27 08:45:56', '1', '2024-04-27 08:45:56', '0', 1); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS system_users_seq; +CREATE SEQUENCE system_users_seq + START 132; + +-- ---------------------------- +-- Table structure for yudao_demo01_contact +-- ---------------------------- +DROP TABLE IF EXISTS yudao_demo01_contact; +CREATE TABLE yudao_demo01_contact +( + id int8 NOT NULL, + name varchar(100) NULL DEFAULT '', + sex int2 NOT NULL, + birthday timestamp NOT NULL, + description varchar(255) NOT NULL, + avatar varchar(512) NULL DEFAULT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE yudao_demo01_contact + ADD CONSTRAINT pk_yudao_demo01_contact PRIMARY KEY (id); + +COMMENT ON COLUMN yudao_demo01_contact.id IS '编号'; +COMMENT ON COLUMN yudao_demo01_contact.name IS '名字'; +COMMENT ON COLUMN yudao_demo01_contact.sex IS '性别'; +COMMENT ON COLUMN yudao_demo01_contact.birthday IS '出生年'; +COMMENT ON COLUMN yudao_demo01_contact.description IS '简介'; +COMMENT ON COLUMN yudao_demo01_contact.avatar IS '头像'; +COMMENT ON COLUMN yudao_demo01_contact.creator IS '创建者'; +COMMENT ON COLUMN yudao_demo01_contact.create_time IS '创建时间'; +COMMENT ON COLUMN yudao_demo01_contact.updater IS '更新者'; +COMMENT ON COLUMN yudao_demo01_contact.update_time IS '更新时间'; +COMMENT ON COLUMN yudao_demo01_contact.deleted IS '是否删除'; +COMMENT ON COLUMN yudao_demo01_contact.tenant_id IS '租户编号'; +COMMENT ON TABLE yudao_demo01_contact IS '示例联系人表'; + +-- ---------------------------- +-- Records of yudao_demo01_contact +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO yudao_demo01_contact (id, name, sex, birthday, description, avatar, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1, '土豆', 2, '2023-11-07 00:00:00', '

天蚕土豆!呀

', 'http://127.0.0.1:48080/admin-api/infra/file/4/get/46f8fa1a37db3f3960d8910ff2fe3962ab3b2db87cf2f8ccb4dc8145b8bdf237.jpeg', '1', '2023-11-15 23:34:30', '1', '2023-11-15 23:47:39', '0', 1); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS yudao_demo01_contact_seq; +CREATE SEQUENCE yudao_demo01_contact_seq + START 2; + +-- ---------------------------- +-- Table structure for yudao_demo02_category +-- ---------------------------- +DROP TABLE IF EXISTS yudao_demo02_category; +CREATE TABLE yudao_demo02_category +( + id int8 NOT NULL, + name varchar(100) NULL DEFAULT '', + parent_id int8 NOT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE yudao_demo02_category + ADD CONSTRAINT pk_yudao_demo02_category PRIMARY KEY (id); + +COMMENT ON COLUMN yudao_demo02_category.id IS '编号'; +COMMENT ON COLUMN yudao_demo02_category.name IS '名字'; +COMMENT ON COLUMN yudao_demo02_category.parent_id IS '父级编号'; +COMMENT ON COLUMN yudao_demo02_category.creator IS '创建者'; +COMMENT ON COLUMN yudao_demo02_category.create_time IS '创建时间'; +COMMENT ON COLUMN yudao_demo02_category.updater IS '更新者'; +COMMENT ON COLUMN yudao_demo02_category.update_time IS '更新时间'; +COMMENT ON COLUMN yudao_demo02_category.deleted IS '是否删除'; +COMMENT ON COLUMN yudao_demo02_category.tenant_id IS '租户编号'; +COMMENT ON TABLE yudao_demo02_category IS '示例分类表'; + +-- ---------------------------- +-- Records of yudao_demo02_category +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO yudao_demo02_category (id, name, parent_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (1, '土豆', 0, '1', '2023-11-15 23:34:30', '1', '2023-11-16 20:24:23', '0', 1); +INSERT INTO yudao_demo02_category (id, name, parent_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2, '番茄', 0, '1', '2023-11-16 20:24:00', '1', '2023-11-16 20:24:15', '0', 1); +INSERT INTO yudao_demo02_category (id, name, parent_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3, '怪怪', 0, '1', '2023-11-16 20:24:32', '1', '2023-11-16 20:24:32', '0', 1); +INSERT INTO yudao_demo02_category (id, name, parent_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (4, '小番茄', 2, '1', '2023-11-16 20:24:39', '1', '2023-11-16 20:24:39', '0', 1); +INSERT INTO yudao_demo02_category (id, name, parent_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (5, '大番茄', 2, '1', '2023-11-16 20:24:46', '1', '2023-11-16 20:24:46', '0', 1); +INSERT INTO yudao_demo02_category (id, name, parent_id, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (6, '11', 3, '1', '2023-11-24 19:29:34', '1', '2023-11-24 19:29:34', '0', 1); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS yudao_demo02_category_seq; +CREATE SEQUENCE yudao_demo02_category_seq + START 7; + +-- ---------------------------- +-- Table structure for yudao_demo03_course +-- ---------------------------- +DROP TABLE IF EXISTS yudao_demo03_course; +CREATE TABLE yudao_demo03_course +( + id int8 NOT NULL, + student_id int8 NOT NULL, + name varchar(100) NULL DEFAULT '', + score int2 NOT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE yudao_demo03_course + ADD CONSTRAINT pk_yudao_demo03_course PRIMARY KEY (id); + +COMMENT ON COLUMN yudao_demo03_course.id IS '编号'; +COMMENT ON COLUMN yudao_demo03_course.student_id IS '学生编号'; +COMMENT ON COLUMN yudao_demo03_course.name IS '名字'; +COMMENT ON COLUMN yudao_demo03_course.score IS '分数'; +COMMENT ON COLUMN yudao_demo03_course.creator IS '创建者'; +COMMENT ON COLUMN yudao_demo03_course.create_time IS '创建时间'; +COMMENT ON COLUMN yudao_demo03_course.updater IS '更新者'; +COMMENT ON COLUMN yudao_demo03_course.update_time IS '更新时间'; +COMMENT ON COLUMN yudao_demo03_course.deleted IS '是否删除'; +COMMENT ON COLUMN yudao_demo03_course.tenant_id IS '租户编号'; +COMMENT ON TABLE yudao_demo03_course IS '学生课程表'; + +-- ---------------------------- +-- Records of yudao_demo03_course +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO yudao_demo03_course (id, student_id, name, score, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2, 2, '语文', 66, '1', '2023-11-16 23:21:49', '1', '2023-11-16 23:21:49', '0', 1); +INSERT INTO yudao_demo03_course (id, student_id, name, score, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (3, 2, '数学', 22, '1', '2023-11-16 23:21:49', '1', '2023-11-16 23:21:49', '0', 1); +INSERT INTO yudao_demo03_course (id, student_id, name, score, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (6, 5, '体育', 23, '1', '2023-11-16 23:22:46', '1', '2023-11-16 15:44:40', '1', 1); +INSERT INTO yudao_demo03_course (id, student_id, name, score, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (7, 5, '计算机', 11, '1', '2023-11-16 23:22:46', '1', '2023-11-16 15:44:40', '1', 1); +INSERT INTO yudao_demo03_course (id, student_id, name, score, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (8, 5, '体育', 23, '1', '2023-11-16 23:22:46', '1', '2023-11-16 15:47:09', '1', 1); +INSERT INTO yudao_demo03_course (id, student_id, name, score, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (9, 5, '计算机', 11, '1', '2023-11-16 23:22:46', '1', '2023-11-16 15:47:09', '1', 1); +INSERT INTO yudao_demo03_course (id, student_id, name, score, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (10, 5, '体育', 23, '1', '2023-11-16 23:22:46', '1', '2023-11-16 23:47:10', '0', 1); +INSERT INTO yudao_demo03_course (id, student_id, name, score, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (11, 5, '计算机', 11, '1', '2023-11-16 23:22:46', '1', '2023-11-16 23:47:10', '0', 1); +INSERT INTO yudao_demo03_course (id, student_id, name, score, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (12, 2, '电脑', 33, '1', '2023-11-17 00:20:42', '1', '2023-11-16 16:20:45', '1', 1); +INSERT INTO yudao_demo03_course (id, student_id, name, score, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (13, 9, '滑雪', 12, '1', '2023-11-17 13:13:20', '1', '2023-11-17 13:13:20', '0', 1); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS yudao_demo03_course_seq; +CREATE SEQUENCE yudao_demo03_course_seq + START 14; + +-- ---------------------------- +-- Table structure for yudao_demo03_grade +-- ---------------------------- +DROP TABLE IF EXISTS yudao_demo03_grade; +CREATE TABLE yudao_demo03_grade +( + id int8 NOT NULL, + student_id int8 NOT NULL, + name varchar(100) NULL DEFAULT '', + teacher varchar(255) NOT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE yudao_demo03_grade + ADD CONSTRAINT pk_yudao_demo03_grade PRIMARY KEY (id); + +COMMENT ON COLUMN yudao_demo03_grade.id IS '编号'; +COMMENT ON COLUMN yudao_demo03_grade.student_id IS '学生编号'; +COMMENT ON COLUMN yudao_demo03_grade.name IS '名字'; +COMMENT ON COLUMN yudao_demo03_grade.teacher IS '班主任'; +COMMENT ON COLUMN yudao_demo03_grade.creator IS '创建者'; +COMMENT ON COLUMN yudao_demo03_grade.create_time IS '创建时间'; +COMMENT ON COLUMN yudao_demo03_grade.updater IS '更新者'; +COMMENT ON COLUMN yudao_demo03_grade.update_time IS '更新时间'; +COMMENT ON COLUMN yudao_demo03_grade.deleted IS '是否删除'; +COMMENT ON COLUMN yudao_demo03_grade.tenant_id IS '租户编号'; +COMMENT ON TABLE yudao_demo03_grade IS '学生班级表'; + +-- ---------------------------- +-- Records of yudao_demo03_grade +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO yudao_demo03_grade (id, student_id, name, teacher, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (7, 2, '三年 2 班', '周杰伦', '1', '2023-11-16 23:21:49', '1', '2023-11-16 23:21:49', '0', 1); +INSERT INTO yudao_demo03_grade (id, student_id, name, teacher, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (8, 5, '华为', '遥遥领先', '1', '2023-11-16 23:22:46', '1', '2023-11-16 23:47:10', '0', 1); +INSERT INTO yudao_demo03_grade (id, student_id, name, teacher, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (9, 9, '小图', '小娃111', '1', '2023-11-17 13:10:23', '1', '2023-11-17 13:10:23', '0', 1); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS yudao_demo03_grade_seq; +CREATE SEQUENCE yudao_demo03_grade_seq + START 10; + +-- ---------------------------- +-- Table structure for yudao_demo03_student +-- ---------------------------- +DROP TABLE IF EXISTS yudao_demo03_student; +CREATE TABLE yudao_demo03_student +( + id int8 NOT NULL, + name varchar(100) NULL DEFAULT '', + sex int2 NOT NULL, + birthday timestamp NOT NULL, + description varchar(255) NOT NULL, + creator varchar(64) NULL DEFAULT '', + create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updater varchar(64) NULL DEFAULT '', + update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + deleted int2 NOT NULL DEFAULT 0, + tenant_id int8 NOT NULL DEFAULT 0 +); + +ALTER TABLE yudao_demo03_student + ADD CONSTRAINT pk_yudao_demo03_student PRIMARY KEY (id); + +COMMENT ON COLUMN yudao_demo03_student.id IS '编号'; +COMMENT ON COLUMN yudao_demo03_student.name IS '名字'; +COMMENT ON COLUMN yudao_demo03_student.sex IS '性别'; +COMMENT ON COLUMN yudao_demo03_student.birthday IS '出生日期'; +COMMENT ON COLUMN yudao_demo03_student.description IS '简介'; +COMMENT ON COLUMN yudao_demo03_student.creator IS '创建者'; +COMMENT ON COLUMN yudao_demo03_student.create_time IS '创建时间'; +COMMENT ON COLUMN yudao_demo03_student.updater IS '更新者'; +COMMENT ON COLUMN yudao_demo03_student.update_time IS '更新时间'; +COMMENT ON COLUMN yudao_demo03_student.deleted IS '是否删除'; +COMMENT ON COLUMN yudao_demo03_student.tenant_id IS '租户编号'; +COMMENT ON TABLE yudao_demo03_student IS '学生表'; + +-- ---------------------------- +-- Records of yudao_demo03_student +-- ---------------------------- +-- @formatter:off +BEGIN; +INSERT INTO yudao_demo03_student (id, name, sex, birthday, description, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (2, '小白', 1, '2023-11-16 00:00:00', '

厉害

', '1', '2023-11-16 23:21:49', '1', '2023-11-17 16:49:06', '0', 1); +INSERT INTO yudao_demo03_student (id, name, sex, birthday, description, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (5, '大黑', 2, '2023-11-13 00:00:00', '

你在教我做事?

', '1', '2023-11-16 23:22:46', '1', '2023-11-17 16:49:07', '0', 1); +INSERT INTO yudao_demo03_student (id, name, sex, birthday, description, creator, create_time, updater, update_time, deleted, tenant_id) VALUES (9, '小花', 1, '2023-11-07 00:00:00', '

哈哈哈

', '1', '2023-11-17 00:04:47', '1', '2023-11-17 16:49:08', '0', 1); +COMMIT; +-- @formatter:on + +DROP SEQUENCE IF EXISTS yudao_demo03_student_seq; +CREATE SEQUENCE yudao_demo03_student_seq + START 10; + diff --git a/sql/tools/README.md b/sql/tools/README.md index 852ebaf73..06eed8bc4 100644 --- a/sql/tools/README.md +++ b/sql/tools/README.md @@ -48,7 +48,7 @@ docker compose exec sqlserver bash /tmp/create_schema.sh ```Bash docker load -i dm8_20230808_rev197096_x86_rh6_64_single.tar -```` +``` ③ 在项目 `sql/tools` 目录下运行: @@ -63,6 +63,29 @@ exit 暂不支持 MacBook Apple Silicon,因为 达梦 官方没有提供 Apple Silicon 版本的 Docker 镜像。 +### 1.6 KingbaseES 人大金仓 + +① 下载人大金仓 Docker 镜像: + +> x86_64版本: https://kingbase.oss-cn-beijing.aliyuncs.com/KESV8R3/V009R001C001B0025-安装包-docker/x86_64/kdb_x86_64_V009R001C001B0025.tar +> aarch64版本:https://kingbase.oss-cn-beijing.aliyuncs.com/KESV8R3/V009R001C001B0025-安装包-docker/aarch64/kdb_aarch64_V009R001C001B0025.tar + +② 加载镜像文件,在镜像 tar 文件所在目录运行: + +```Bash +docker load -i x86_64/kdb_x86_64_V009R001C001B0025.tar +``` + +③ 在项目 `sql/tools` 目录下运行: + +```Bash +docker compose up -d kingbase +# 注意:启动完 dm 后,需要手动再执行如下命令,因为 dm 不支持初始化脚本 +docker compose exec kingbase bash -c "exec ksql -Uroot -d test -f /tmp/schema.sql" +``` + +**注意**: MyBatis, MyBatis Plus 目前不兼容人大金仓,推荐直接使用PostgreSQL JDBC 驱动,已经 url 配置方式连接数据库。 + ## 1.X 容器的销毁重建 开发测试过程中,有时候需要创建全新干净的数据库。由于测试数据 Docker 容器采用数据卷 Volume 挂载数据库实例的数据目录,因此销毁数据需要停止容器后,删除数据卷,然后再重新创建容器。 @@ -78,7 +101,7 @@ docker volume rm ruoyi-vue-pro_postgres ### 2.1 实现原理 -通过读取 MySQL 的 `sql/mysql/ruoyi-vue-pro.sql` 数据库文件,转换成 Oracle、PostgreSQL、SQL Server 等数据库的脚本。 +通过读取 MySQL 的 `sql/mysql/ruoyi-vue-pro.sql` 数据库文件,转换成 Oracle、PostgreSQL、SQL Server、达梦、人大金仓 等数据库的脚本。 ### 2.2 使用方法 @@ -89,7 +112,7 @@ pip install simple-ddl-parser # pip3 install simple-ddl-parser ``` -② 执行如下命令打印生成 postgres 的脚本内容,其他可选参数有:`oracle`、`sqlserver`、`dm8`: +② 执行如下命令打印生成 postgres 的脚本内容,其他可选参数有:`oracle`、`sqlserver`、`dm8`、`kingbase`: ```Bash python3 convertor.py postgres @@ -98,4 +121,4 @@ python3 convertor.py postgres 程序将 SQL 脚本打印到终端,可以重定向到临时文件 `tmp.sql`。 -确认无误后,可以利用 IDEA 进行格式化。当然,也可以直接导入到数据库中。 \ No newline at end of file +确认无误后,可以利用 IDEA 进行格式化。当然,也可以直接导入到数据库中。 diff --git a/sql/tools/convertor.py b/sql/tools/convertor.py index 100e65606..4cab22ddf 100644 --- a/sql/tools/convertor.py +++ b/sql/tools/convertor.py @@ -768,13 +768,49 @@ SET IDENTITY_INSERT {table_name.lower()} OFF; return script +class KingbaseConvertor(PostgreSQLConvertor): + def __init__(self, src): + super().__init__(src) + self.db_type = "Kingbase" + + def gen_create(self, ddl: Dict) -> str: + """生成 create""" + + def _generate_column(col): + name = col["name"].lower() + if name == "deleted": + return "deleted int2 NOT NULL DEFAULT 0" + + type = col["type"].lower() + full_type = self.translate_type(type, col["size"]) + nullable = "NULL" if col["nullable"] else "NOT NULL" + default = f"DEFAULT {col['default']}" if col["default"] is not None else "" + return f"{name} {full_type} {nullable} {default}" + + table_name = ddl["table_name"].lower() + columns = [f"{_generate_column(col).strip()}" for col in ddl["columns"]] + filed_def_list = ",\n ".join(columns) + script = f"""-- ---------------------------- +-- Table structure for {table_name} +-- ---------------------------- +DROP TABLE IF EXISTS {table_name}; +CREATE TABLE {table_name} ( + {filed_def_list} +);""" + + # Kingbase INSERT '' 不能通过 NOT NULL 校验 + script = script.replace("NOT NULL DEFAULT ''", "NULL DEFAULT ''") + + return script + + def main(): parser = argparse.ArgumentParser(description="芋道系统数据库转换工具") parser.add_argument( "type", type=str, help="目标数据库类型", - choices=["postgres", "oracle", "sqlserver", "dm8"], + choices=["postgres", "oracle", "sqlserver", "dm8", "kingbase"], ) args = parser.parse_args() @@ -788,6 +824,8 @@ def main(): convertor = SQLServerConvertor(sql_file) elif args.type == "dm8": convertor = DM8Convertor(sql_file) + elif args.type == "kingbase": + convertor = KingbaseConvertor(sql_file) else: raise NotImplementedError(f"不支持目标数据库类型: {args.type}") diff --git a/sql/tools/docker-compose.yaml b/sql/tools/docker-compose.yaml index 6be209e05..d2f27288b 100644 --- a/sql/tools/docker-compose.yaml +++ b/sql/tools/docker-compose.yaml @@ -5,6 +5,7 @@ volumes: postgres: { } sqlserver: { } dm8: { } + kingbase: { } services: mysql: @@ -92,3 +93,19 @@ services: - dm8:/opt/dmdbms/data - ../dm/ruoyi-vue-pro-dm8.sql:/tmp/schema.sql:ro # docker compose exec dm8 bash -c "exec /opt/dmdbms/bin/disql SYSDBA/SYSDBA001 \`/tmp/schema.sql" + + kingbase: + # x86_64: https://kingbase.oss-cn-beijing.aliyuncs.com/KESV8R3/V009R001C001B0025-安装包-docker/x86_64/kdb_x86_64_V009R001C001B0025.tar + # aarch64: https://kingbase.oss-cn-beijing.aliyuncs.com/KESV8R3/V009R001C001B0025-安装包-docker/aarch64/kdb_aarch64_V009R001C001B0025.tar + # docker load -i kdb_x86_64_V009R001C001B0025.tar + image: kingbase_v009r001c001b0025_single_x86:v1 + restart: unless-stopped + environment: + DB_USER: root + DB_PASSWORD: 123456 + ports: + - "54321:54321" + volumes: + - kingbase:/home/kingbase/userdata/ + - ../kingbase/ruoyi-vue-pro.sql:/tmp/schema.sql:ro + # docker compose exec kingbase bash -c "exec ksql -Uroot -d test -f /tmp/schema.sql" \ No newline at end of file diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index f5912f690..eec316ff7 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -52,6 +52,7 @@ spring: # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=ruoyi-vue-pro;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true;useUnicode=true;characterEncoding=utf-8 # SQLServer 连接的示例 # url: jdbc:dm://127.0.0.1:5236?schema=RUOYI_VUE_PRO # DM 连接的示例 + # url: jdbc:postgresql://127.0.0.1:54321/test # KingbaseES 人大金仓 连接的示例, MyBatis不兼容官方驱动 username: root password: 123456 # username: sa # SQL Server 连接的示例 From 0563503102c6f1aa9106b926cc8653aa1e6a8a74 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 1 Jun 2024 11:24:39 +0800 Subject: [PATCH 387/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E4=BD=BF=E7=94=A8=20DALL=20=E7=BB=98=E5=9B=BE?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E4=BD=BF=E7=94=A8=20b64=5Fjson=20=E8=BF=94?= =?UTF-8?q?=E5=9B=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/image/vo/AiImageDallReqVO.java | 9 +- .../ai/dal/dataobject/image/AiImageDO.java | 5 +- .../ai/service/image/AiImageServiceImpl.java | 95 ++++----- .../src/main/resources/ai_image.sql | 61 ------ .../src/main/resources/chat.sql | 187 ------------------ .../yudao-spring-boot-starter-ai/pom.xml | 5 + .../ai/core/enums/AiPlatformEnum.java | 3 +- .../ai/core/enums/OpenAiImageModelEnum.java | 1 + .../ai/core/enums/OpenAiImageStyleEnum.java | 1 + .../ai/core/factory/AiClientFactory.java | 11 ++ .../ai/core/factory/AiClientFactoryImpl.java | 12 ++ .../src/main/resources/application.yaml | 31 +-- 12 files changed, 108 insertions(+), 313 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/resources/ai_image.sql delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/resources/chat.sql diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallReqVO.java index ad4512832..1bfe48943 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallReqVO.java @@ -4,7 +4,6 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; import lombok.Data; -import lombok.experimental.Accessors; /** * dall2/dall2 绘画 @@ -14,9 +13,11 @@ import lombok.experimental.Accessors; * @since 1.0 */ @Data -@Accessors(chain = true) public class AiImageDallReqVO { + @Schema(description = "模型平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private String platform; // 参见 AiPlatformEnum 枚举 + @Schema(description = "提示词") @NotNull(message = "提示词不能为空!") @Size(max = 1200, message = "提示词最大1200") @@ -31,10 +32,10 @@ public class AiImageDallReqVO { @Schema(description = "图片高度。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。") @NotNull(message = "图片高度不能为空!") - private String height; + private Integer height; @Schema(description = "图片宽度。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。") @NotNull(message = "图片宽度不能为空!") - private String width; + private Integer width; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java index 0f6282a27..b21b2f8d8 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java @@ -41,10 +41,10 @@ public class AiImageDO extends BaseDO { private String model; @Schema(description = "图片宽度") - private String width; + private Integer width; @Schema(description = "图片高度") - private String height; + private Integer height; // TODO @fan:这种就注释绘画状态,然后枚举类关联下就好啦 @Schema(description = "绘画状态:提交、排队、绘画中、绘画完成、绘画失败") @@ -56,6 +56,7 @@ public class AiImageDO extends BaseDO { @Schema(description = "图片地址(自己服务器)") private String picUrl; + // TODO @芋艿:可能要删除掉 @Schema(description = "绘画图片地址(绘画好的服务器)") private String originalPicUrl; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index 2b4f7e617..a9a084d65 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -1,14 +1,15 @@ package cn.iocoder.yudao.module.ai.service.image; import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.util.StrUtil; +import cn.hutool.core.codec.Base64; import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.hutool.http.HttpUtil; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageModelEnum; import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageStyleEnum; -import cn.iocoder.yudao.framework.ai.core.exception.AiException; +import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactory; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -30,11 +31,9 @@ import cn.iocoder.yudao.module.infra.api.file.FileApi; import com.google.common.collect.ImmutableMap; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.springframework.ai.image.ImageGeneration; -import org.springframework.ai.image.ImagePrompt; -import org.springframework.ai.image.ImageResponse; -import org.springframework.ai.openai.OpenAiImageClient; +import org.springframework.ai.image.*; import org.springframework.ai.openai.OpenAiImageOptions; +import org.springframework.ai.stabilityai.api.StabilityAiImageOptions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Async; @@ -42,8 +41,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; - - import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.AI_IMAGE_NOT_EXISTS; /** @@ -62,7 +59,7 @@ public class AiImageServiceImpl implements AiImageService { private FileApi fileApi; @Resource - private OpenAiImageClient openAiImageClient; + private AiClientFactory aiClientFactory; @Autowired private MidjourneyProxyClient midjourneyProxyClient; @@ -81,50 +78,60 @@ public class AiImageServiceImpl implements AiImageService { } @Override - public Long dall(Long loginUserId, AiImageDallReqVO req) { - // 保存数据库 - AiImageDO aiImageDO = BeanUtils.toBean(req, AiImageDO.class) - .setUserId(loginUserId) - .setWidth(req.getWidth()) - .setHeight(req.getHeight()) + public Long dall(Long userId, AiImageDallReqVO req) { + req.setPlatform("dall"); // TODO 芋艿:临时写死 + // 1. 保存数据库 + AiImageDO image = BeanUtils.toBean(req, AiImageDO.class) + .setUserId(userId).setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus()) + .setWidth(req.getWidth()).setHeight(req.getHeight()) .setDrawRequest(ImmutableMap.of(AiCommonConstants.DRAW_REQ_KEY_STYLE, req.getStyle())) - .setPublicStatus(AiImagePublicStatusEnum.PRIVATE.getStatus()) - .setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus()); - imageMapper.insert(aiImageDO); - // 异步执行 - getSelf().doDall(aiImageDO, req); - // 转换 AiImageDallDrawingRespVO - return aiImageDO.getId(); + .setPublicStatus(AiImagePublicStatusEnum.PRIVATE.getStatus()); + imageMapper.insert(image); + // 2. 异步绘制,后续前端通过返回的 id 进行伦旭 + getSelf().doDall(image, req); + return image.getId(); } @Async - public void doDall(AiImageDO aiImageDO, AiImageDallReqVO req) { + public void doDall(AiImageDO image, AiImageDallReqVO req) { try { - // 获取 model - OpenAiImageModelEnum openAiImageModelEnum = OpenAiImageModelEnum.valueOfModel(req.getModel()); - OpenAiImageStyleEnum openAiImageStyleEnum = OpenAiImageStyleEnum.valueOfStyle(req.getStyle()); + // 1.1 构建请求 + ImageOptions request = buildImageOptions(req); + // 1.2 执行请求 + ImageClient imageClient = aiClientFactory.getDefaultImageClient(AiPlatformEnum.validatePlatform(req.getPlatform())); + ImageResponse response = imageClient.call(new ImagePrompt(req.getPrompt(), request)); - // 转换openai 参数 - // TODO @fan:需要考虑,不同平台,参数不同; - OpenAiImageOptions openAiImageOptions = new OpenAiImageOptions(); - openAiImageOptions.setModel(openAiImageModelEnum.getModel()); - openAiImageOptions.setStyle(openAiImageStyleEnum.getStyle()); - openAiImageOptions.setSize(String.format(AiCommonConstants.DALL_SIZE_TEMPLATE, req.getWidth(), req.getHeight())); - ImageResponse imageResponse = openAiImageClient.call(new ImagePrompt(req.getPrompt(), openAiImageOptions)); - // 发送 - ImageGeneration imageGeneration = imageResponse.getResult(); - // 图片保存到服务器 - String filePath = fileApi.createFile(HttpUtil.downloadBytes(imageGeneration.getOutput().getUrl())); - // 更新数据库 - imageMapper.updateById(new AiImageDO().setId(aiImageDO.getId()).setStatus(AiImageStatusEnum.COMPLETE.getStatus()) - .setPicUrl(filePath).setOriginalPicUrl(imageGeneration.getOutput().getUrl())); - } catch (AiException aiException) { - // TODO @fan:错误日志,也打印下哈;因为 aiException.getMessage() 比较精简; - imageMapper.updateById(new AiImageDO().setId(aiImageDO.getId()).setStatus(AiImageStatusEnum.FAIL.getStatus()) - .setErrorMessage(aiException.getMessage())); + // 2. 上传到文件服务 + byte[] fileContent = Base64.decode(response.getResult().getOutput().getB64Json()); + String filePath = fileApi.createFile(fileContent); + + // 3. 更新数据库 + imageMapper.updateById(new AiImageDO().setId(image.getId()).setStatus(AiImageStatusEnum.COMPLETE.getStatus()) + .setPicUrl(filePath)); + } catch (Exception ex) { + log.error("[doDall][image({}) 生成异常]", image, ex); + imageMapper.updateById(new AiImageDO().setId(image.getId()) + .setStatus(AiImageStatusEnum.FAIL.getStatus()).setErrorMessage(ex.getMessage())); } } + private static ImageOptions buildImageOptions(AiImageDallReqVO draw) { + if (ObjUtil.equal(draw.getPlatform(), AiPlatformEnum.OPEN_AI_DALL.getPlatform())) { + OpenAiImageOptions request = new OpenAiImageOptions(); + request.setModel(OpenAiImageModelEnum.valueOfModel(draw.getModel()).getModel()); + request.setStyle(OpenAiImageStyleEnum.valueOfStyle(draw.getStyle()).getStyle()); + request.setSize(String.format(AiCommonConstants.DALL_SIZE_TEMPLATE, draw.getWidth(), draw.getHeight())); + request.setResponseFormat("b64_json"); + return request; + } else { + // https://platform.stability.ai/docs/api-reference#tag/Generate/paths/~1v2beta~1stable-image~1generate~1sd3/post + return StabilityAiImageOptions.builder().withModel(draw.getModel()) + .withHeight(draw.getHeight()).withWidth(draw.getWidth()) + .build(); + } +// return null; + } + @Override @Transactional(rollbackFor = Exception.class) public Long midjourneyImagine(Long loginUserId, AiImageMidjourneyImagineReqVO req) { diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/ai_image.sql b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/ai_image.sql deleted file mode 100644 index 4de719235..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/ai_image.sql +++ /dev/null @@ -1,61 +0,0 @@ -/* - Navicat Premium Data Transfer - - Source Server : localhost - Source Server Type : MySQL - Source Server Version : 80034 (8.0.34) - Source Host : localhost:3306 - Source Schema : ruoyi-vue-pro - - Target Server Type : MySQL - Target Server Version : 80034 (8.0.34) - File Encoding : 65001 - - Date: 30/05/2024 17:20:37 -*/ - -SET NAMES utf8mb4; -SET FOREIGN_KEY_CHECKS = 0; - --- ---------------------------- --- Table structure for ai_image --- ---------------------------- -DROP TABLE IF EXISTS `ai_image`; -CREATE TABLE `ai_image` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `user_id` bigint DEFAULT NULL, - `prompt` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '提示词\n', - `platform` varchar(32) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '平台', - `model` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '模型 dall2/dall3、MJ、NIJI', - `width` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '图片宽度', - `height` varchar(32) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '图片高度', - `status` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '绘画状态:提交、排队、绘画中、绘画完成、绘画失败\n', - `public_status` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '是否发布', - `pic_url` varchar(512) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '图片地址', - `original_pic_url` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '绘画图片地址\n', - `error_message` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '错误信息', - `draw_request` json DEFAULT NULL COMMENT '绘画request', - `draw_response` json DEFAULT NULL COMMENT '绘画response', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - `creator` bigint DEFAULT NULL COMMENT '创建用户', - `updater` bigint DEFAULT NULL COMMENT '更新用户', - `deleted` bit(1) DEFAULT b'0' COMMENT '删除', - PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=107 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; - --- ---------------------------- --- Records of ai_image --- ---------------------------- -BEGIN; -INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `platform`, `model`, `width`, `height`, `status`, `public_status`, `pic_url`, `original_pic_url`, `error_message`, `draw_request`, `draw_response`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (91, 1, '北极企鹅', NULL, 'dall-e-2', '1024', '1024', '20', NULL, 'http://test.yudao.iocoder.cn/75b4d733222b60aafdbdcd0475562ff88149eaaff93a25c4e4c66a95bd07f01f.png', 'https://oaidalleapiprodscus.blob.core.windows.net/private/org-FttVrm20iQRlsxxFE7BLEgkT/user-5p7zykU5aS1sYXCjczkTXn8I/img-z4KBxbWtUpLBYmgaYPvWXjBh.png?st=2024-05-29T04%3A50%3A54Z&se=2024-05-29T06%3A50%3A54Z&sp=r&sv=2023-11-03&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2024-05-28T23%3A21%3A22Z&ske=2024-05-29T23%3A21%3A22Z&sks=b&skv=2023-11-03&sig=jSw/hJfuPWJqQgjSoINtVrt4w61FsaQ6ed4pRCM8UUA%3D', NULL, '{\"style\": \"vivid\"}', NULL, '2024-05-29 13:50:43', '2024-05-29 13:51:05', 1, 1, b'0'); -INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `platform`, `model`, `width`, `height`, `status`, `public_status`, `pic_url`, `original_pic_url`, `error_message`, `draw_request`, `draw_response`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (93, 1, '北极企鹅', NULL, 'dall-e-2', '1024', '1024', '20', 'private', 'http://test.yudao.iocoder.cn/ab326bbf3fae9a940770a5c36bbf39467ae539a5b94a030b6c6cc2f179d7dd31.png', 'https://oaidalleapiprodscus.blob.core.windows.net/private/org-FttVrm20iQRlsxxFE7BLEgkT/user-5p7zykU5aS1sYXCjczkTXn8I/img-CsJtCgLT9lTigTuBDJtPyO8X.png?st=2024-05-29T09%3A02%3A12Z&se=2024-05-29T11%3A02%3A12Z&sp=r&sv=2023-11-03&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2024-05-28T23%3A21%3A54Z&ske=2024-05-29T23%3A21%3A54Z&sks=b&skv=2023-11-03&sig=tH6yFzHtcp3Dxwaua2crFYurCdE7B7%2BAXhyPNVVep1c%3D', NULL, '{\"style\": \"vivid\"}', NULL, '2024-05-29 18:02:03', '2024-05-29 18:02:17', 1, 1, b'0'); -INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `platform`, `model`, `width`, `height`, `status`, `public_status`, `pic_url`, `original_pic_url`, `error_message`, `draw_request`, `draw_response`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (94, 1, '北极大熊猫', NULL, 'dall-e-2', '1024', '1024', '20', 'private', 'http://test.yudao.iocoder.cn/ed9d43a6c841c4a967700e211c998778994eeea60cff2dfeb1c3a88b0542ebdd.png', 'https://oaidalleapiprodscus.blob.core.windows.net/private/org-FttVrm20iQRlsxxFE7BLEgkT/user-5p7zykU5aS1sYXCjczkTXn8I/img-GAwShv01C2408VY5lXvLTP4Q.png?st=2024-05-30T01%3A31%3A28Z&se=2024-05-30T03%3A31%3A28Z&sp=r&sv=2023-11-03&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2024-05-29T23%3A39%3A20Z&ske=2024-05-30T23%3A39%3A20Z&sks=b&skv=2023-11-03&sig=n/rqAnD0qJDkhbh/Qm12lz1Se70PQSdXetarmwCKoMY%3D', NULL, '{\"style\": \"vivid\"}', NULL, '2024-05-30 10:31:18', '2024-05-30 10:31:34', 1, 1, b'1'); -INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `platform`, `model`, `width`, `height`, `status`, `public_status`, `pic_url`, `original_pic_url`, `error_message`, `draw_request`, `draw_response`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (102, 1, '女少侠', 'midjourney', NULL, NULL, NULL, '30', 'private', NULL, NULL, '无可用的账号实例', NULL, '{}', '2024-05-30 16:11:13', '2024-05-30 16:11:13', 1, 1, b'1'); -INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `platform`, `model`, `width`, `height`, `status`, `public_status`, `pic_url`, `original_pic_url`, `error_message`, `draw_request`, `draw_response`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (103, 1, '123123', 'midjourney', NULL, NULL, NULL, '30', 'private', NULL, NULL, '无可用的账号实例', NULL, '{}', '2024-05-30 16:27:34', '2024-05-30 16:27:34', 1, 1, b'1'); -INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `platform`, `model`, `width`, `height`, `status`, `public_status`, `pic_url`, `original_pic_url`, `error_message`, `draw_request`, `draw_response`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (104, 1, '123123', 'midjourney', NULL, NULL, NULL, '30', 'private', NULL, NULL, '无可用的账号实例', NULL, '{}', '2024-05-30 16:28:23', '2024-05-30 16:28:24', 1, 1, b'1'); -INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `platform`, `model`, `width`, `height`, `status`, `public_status`, `pic_url`, `original_pic_url`, `error_message`, `draw_request`, `draw_response`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (105, 1, '123123', 'midjourney', NULL, NULL, NULL, '30', 'private', NULL, NULL, '无可用的账号实例', NULL, '{}', '2024-05-30 16:28:25', '2024-05-30 16:28:25', 1, 1, b'1'); -INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `platform`, `model`, `width`, `height`, `status`, `public_status`, `pic_url`, `original_pic_url`, `error_message`, `draw_request`, `draw_response`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (106, 1, '123123', 'midjourney', NULL, NULL, NULL, '30', 'private', NULL, NULL, '无可用的账号实例', NULL, '{}', '2024-05-30 16:28:34', '2024-05-30 16:28:34', 1, 1, b'1'); -COMMIT; - -SET FOREIGN_KEY_CHECKS = 1; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/chat.sql b/yudao-module-ai/yudao-module-ai-biz/src/main/resources/chat.sql deleted file mode 100644 index a845056d7..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/chat.sql +++ /dev/null @@ -1,187 +0,0 @@ -/* - Navicat Premium Data Transfer - - Source Server : localhost - Source Server Type : MySQL - Source Server Version : 80034 (8.0.34) - Source Host : localhost:3306 - Source Schema : ruoyi-vue-pro - - Target Server Type : MySQL - Target Server Version : 80034 (8.0.34) - File Encoding : 65001 - - Date: 08/05/2024 18:10:05 -*/ - -SET NAMES utf8mb4; -SET FOREIGN_KEY_CHECKS = 0; - --- ---------------------------- --- Table structure for ai_chat_conversation --- ---------------------------- -DROP TABLE IF EXISTS `ai_chat_conversation`; -CREATE TABLE `ai_chat_conversation` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `user_id` bigint DEFAULT NULL COMMENT '用户id', - `role_id` bigint DEFAULT NULL COMMENT '聊天角色', - `title` varchar(256) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '标题', - `type` varchar(16) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '对话类型', - `chat_count` int DEFAULT NULL COMMENT '聊天次数', - `model_id` bigint DEFAULT NULL COMMENT '模型id', - `model` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '模型', - `pinned` blob COMMENT '是否置顶', - `temperature` double DEFAULT NULL COMMENT '温度参数', - `max_tokens` int DEFAULT NULL COMMENT '单条回复的最大 Token 数量', - `max_contexts` int DEFAULT NULL COMMENT '上下文的最大 Message 数量', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - `creator` bigint DEFAULT NULL COMMENT '创建用户', - `updater` bigint DEFAULT NULL COMMENT '更新用户', - `deleted` bit(1) DEFAULT b'0' COMMENT '删除', - PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=1781604279872581650 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; - --- ---------------------------- --- Records of ai_chat_conversation --- ---------------------------- -BEGIN; -INSERT INTO `ai_chat_conversation` (`id`, `user_id`, `role_id`, `title`, `type`, `chat_count`, `model_id`, `model`, `pinned`, `temperature`, `max_tokens`, `max_contexts`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (1781604279872581647, 1, NULL, '新增对话', NULL, NULL, 9, 'ERNIE-3.5-8K', 0x30, NULL, NULL, NULL, '2024-05-07 16:20:06', '2024-05-07 16:20:06', 1, 1, b'1'); -INSERT INTO `ai_chat_conversation` (`id`, `user_id`, `role_id`, `title`, `type`, `chat_count`, `model_id`, `model`, `pinned`, `temperature`, `max_tokens`, `max_contexts`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (1781604279872581648, 1, 9, '新增对话', NULL, NULL, 9, 'ERNIE-3.5-8K', 0x30, NULL, NULL, NULL, '2024-05-07 16:20:35', '2024-05-07 16:20:35', 1, 1, b'0'); -INSERT INTO `ai_chat_conversation` (`id`, `user_id`, `role_id`, `title`, `type`, `chat_count`, `model_id`, `model`, `pinned`, `temperature`, `max_tokens`, `max_contexts`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (1781604279872581649, 1, NULL, '新增对话', NULL, NULL, 9, 'ERNIE-3.5-8K', 0x30, NULL, NULL, NULL, '2024-05-07 16:22:37', '2024-05-07 16:22:37', 1, 1, b'0'); -COMMIT; - --- ---------------------------- --- Table structure for ai_chat_message --- ---------------------------- -DROP TABLE IF EXISTS `ai_chat_message`; -CREATE TABLE `ai_chat_message` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `conversation_id` bigint DEFAULT NULL COMMENT '对话id', - `user_id` bigint DEFAULT NULL COMMENT '用户id', - `role_id` bigint DEFAULT NULL COMMENT '角色id', - `type` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '类型system、user、assistant\n', - `model` varchar(32) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '模型', - `model_id` bigint DEFAULT NULL COMMENT '模型id', - `content` varchar(2048) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '内容', - `tokens` int DEFAULT NULL COMMENT '消耗 Token 数量', - `temperature` double DEFAULT NULL COMMENT '用于调整生成回复的随机性和多样性程度', - `max_tokens` int DEFAULT NULL COMMENT '单条回复的最大 Token 数量', - `max_contexts` int DEFAULT NULL COMMENT '上下文的最大 Message 数量', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - `creator` bigint DEFAULT NULL COMMENT '创建用户', - `updater` bigint DEFAULT NULL COMMENT '更新用户', - `deleted` bit(1) DEFAULT b'0' COMMENT '删除', - PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=65 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; - --- ---------------------------- --- Records of ai_chat_message --- ---------------------------- -BEGIN; -INSERT INTO `ai_chat_message` (`id`, `conversation_id`, `user_id`, `role_id`, `type`, `model`, `model_id`, `content`, `tokens`, `temperature`, `max_tokens`, `max_contexts`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (61, 1781604279872581649, 1, NULL, 'user', 'ERNIE-3.5-8K', 9, '苹果是什么颜色?', NULL, NULL, NULL, NULL, '2024-05-07 17:18:29', '2024-05-07 17:18:29', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `conversation_id`, `user_id`, `role_id`, `type`, `model`, `model_id`, `content`, `tokens`, `temperature`, `max_tokens`, `max_contexts`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (62, 1781604279872581649, 1, NULL, 'system', 'ERNIE-3.5-8K', 9, '苹果是一种水果,其颜色可以因品种和成熟度而异。常见的苹果颜色包括:\n\n1. 红色:许多苹果品种,如红富士、红元帅等,在成熟时会呈现出鲜艳的红色。\n2. 绿色:一些苹果品种,如青苹果、青香蕉等,在成熟时保持绿色或带有绿色条纹。\n3. 黄色:金苹果、黄元帅等品种在成熟时呈黄色。\n\n此外,还有一些苹果品种在成熟时会呈现出不同的颜色组合,如红绿相间、红黄相间等。因此,苹果的颜色并不是单一的,而是根据品种和成熟度而有所不同。', 8, NULL, NULL, NULL, '2024-05-07 17:18:38', '2024-05-07 17:18:38', NULL, NULL, b'0'); -INSERT INTO `ai_chat_message` (`id`, `conversation_id`, `user_id`, `role_id`, `type`, `model`, `model_id`, `content`, `tokens`, `temperature`, `max_tokens`, `max_contexts`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (63, 1781604279872581649, 1, NULL, 'user', 'ERNIE-3.5-8K', 9, '中国好看吗?', NULL, NULL, NULL, NULL, '2024-05-07 17:18:53', '2024-05-07 17:18:53', 1, 1, b'0'); -INSERT INTO `ai_chat_message` (`id`, `conversation_id`, `user_id`, `role_id`, `type`, `model`, `model_id`, `content`, `tokens`, `temperature`, `max_tokens`, `max_contexts`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (64, 1781604279872581649, 1, NULL, 'system', 'ERNIE-3.5-8K', 9, '中国是一个拥有悠久历史、灿烂文化、广袤土地和多元民族的国家,自然景观和人文景观都非常丰富。从雄伟的长城、壮丽的黄山到神秘的西藏,从繁华的上海、历史悠久的北京到充满异域风情的云南,中国各地都有独特的魅力。\n\n此外,中国还拥有丰富多彩的非物质文化遗产,如京剧、川剧、皮影戏等传统艺术形式,以及中秋节、春节等传统节日。这些文化遗产反映了中国人民的智慧和创造力,也是中国文化的重要组成部分。\n\n因此,可以说中国非常美丽,值得人们去探索和发现它的魅力。无论是自然景观还是人文景观,中国都有着独特的魅力和吸引力。', 1, NULL, NULL, NULL, '2024-05-07 17:19:03', '2024-05-07 17:19:03', 1, 1, b'0'); -COMMIT; - --- ---------------------------- --- Table structure for ai_chat_model --- ---------------------------- -DROP TABLE IF EXISTS `ai_chat_model`; -CREATE TABLE `ai_chat_model` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `key_id` bigint DEFAULT NULL COMMENT 'API 秘钥编号', - `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '模型名字\n', - `model` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '模型类型(自己定义qianwen、yiyan、xinghuo、openai)\n', - `platform` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '平台', - `sort` int DEFAULT NULL COMMENT '排序', - `status` tinyint DEFAULT NULL COMMENT '禁用 0、正常 1、禁用\n', - `temperature` double DEFAULT NULL COMMENT '温度参数', - `max_tokens` int DEFAULT NULL COMMENT '单条回复的最大 Token 数量', - `max_contexts` int DEFAULT NULL COMMENT '上下文的最大 Message 数量', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - `creator` bigint DEFAULT NULL COMMENT '创建用户', - `updater` bigint DEFAULT NULL COMMENT '更新用户', - `deleted` bit(1) DEFAULT b'0' COMMENT '删除', - PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; - --- ---------------------------- --- Records of ai_chat_model --- ---------------------------- -BEGIN; -INSERT INTO `ai_chat_model` (`id`, `key_id`, `name`, `model`, `platform`, `sort`, `status`, `temperature`, `max_tokens`, `max_contexts`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (9, 1, '小红书Ai写作大模型3.5 8k', 'ERNIE-3.5-8K', 'yiyan', 100, 0, NULL, NULL, NULL, '2024-05-07 15:08:22', '2024-05-07 15:20:32', 1, 1, b'0'); -INSERT INTO `ai_chat_model` (`id`, `key_id`, `name`, `model`, `platform`, `sort`, `status`, `temperature`, `max_tokens`, `max_contexts`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (10, 1, '小红书Ai写作大模型4.0', 'ERNIE 4.0', 'yiyan', 100, 0, NULL, NULL, NULL, '2024-05-07 15:23:33', '2024-05-07 15:23:33', 1, 1, b'0'); -COMMIT; - --- ---------------------------- --- Table structure for ai_chat_role --- ---------------------------- -DROP TABLE IF EXISTS `ai_chat_role`; -CREATE TABLE `ai_chat_role` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `user_id` bigint DEFAULT NULL, - `model_id` bigint DEFAULT NULL COMMENT '模型编号', - `name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '角色名,角色的显示名称\n', - `avatar` varchar(256) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '头像', - `category` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '分类,角色所属的类别,如娱乐、创作等\n', - `sort` int DEFAULT NULL COMMENT '排序', - `description` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '角色描述', - `welcome_message` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '角色欢迎语', - `system_message` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '角色设定(消息)', - `public_status` blob COMMENT '是否公开 true - 公开;false - 私有', - `status` tinyint DEFAULT NULL COMMENT '状态 0、开启 1、关闭', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - `creator` bigint DEFAULT NULL COMMENT '创建用户', - `updater` bigint DEFAULT NULL COMMENT '更新用户', - `deleted` bit(1) DEFAULT b'0' COMMENT '删除', - PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; - --- ---------------------------- --- Records of ai_chat_role --- ---------------------------- -BEGIN; -INSERT INTO `ai_chat_role` (`id`, `user_id`, `model_id`, `name`, `avatar`, `category`, `sort`, `description`, `welcome_message`, `system_message`, `public_status`, `status`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (8, 1, 9, '小红书写作v2', 'http://baidu.com', 'writing', 0, '采用gpt3.5模型,拥有小红书优质作者写作经验。', '欢迎使用小红书写作模型!', '你是一名优秀的小红书人文、风光作者,你热爱旅游,每去往一个城市你都会用美妙的文字抒写着这座城市的大街小巷,描述着这座城市的美好。', 0x31, 0, '2024-05-07 15:30:30', '2024-05-07 15:35:54', 1, 1, b'1'); -INSERT INTO `ai_chat_role` (`id`, `user_id`, `model_id`, `name`, `avatar`, `category`, `sort`, `description`, `welcome_message`, `system_message`, `public_status`, `status`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (9, 1, 9, '小红书写作v1', 'http://baidu.com', 'writing', 0, '采用gpt3.5模型,拥有小红书优质作者写作经验。', '欢迎使用小红书写作模型!', '你是一名优秀的小红书人文、风光作者,你热爱旅游,每去往一个城市你都会用美妙的文字抒写着这座城市的大街小巷,描述着这座城市的美好。', 0x30, 0, '2024-05-07 15:36:40', '2024-05-07 15:36:40', 1, 1, b'0'); -COMMIT; - --- ---------------------------- --- Table structure for ai_image --- ---------------------------- -DROP TABLE IF EXISTS `ai_image`; -CREATE TABLE `ai_image` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `user_id` bigint DEFAULT NULL, - `prompt` varchar(2000) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '提示词\n', - `modal` varchar(32) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '模型\n', - `size` varchar(32) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。\n', - `drawing_status` varchar(32) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '绘画状态:提交、排队、绘画中、绘画完成、绘画失败\n', - `drawing_image_url` varchar(512) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '绘画图片地址\n', - `drawing_error_message` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '错误信息', - `mj_message_id` varchar(32) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '用户操作的消息编号(MJ返回)\n', - `mj_operation_id` varchar(128) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '用户操作的操作编号(MJ返回)\n', - `mj_operation_name` varchar(32) COLLATE utf8mb4_0900_bin DEFAULT NULL COMMENT '用户操作的操作名字(MJ返回)\n', - `mj_operations` json DEFAULT NULL COMMENT 'mj图片生产成功保存的 components json 数组\n', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - `creator` bigint DEFAULT NULL COMMENT '创建用户', - `updater` bigint DEFAULT NULL COMMENT '更新用户', - `deleted` bit(1) DEFAULT b'0' COMMENT '删除', - PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; - --- ---------------------------- --- Records of ai_image --- ---------------------------- -BEGIN; -INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `modal`, `size`, `drawing_status`, `drawing_image_url`, `drawing_error_message`, `mj_message_id`, `mj_operation_id`, `mj_operation_name`, `mj_operations`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (22, 1, 'Cute cartoon style mobile game scene, a colorful camping car with an outdoor table and chairs next to it on the road in a spring forest, the simple structure of the camper van, soft lighting, C4D rendering, 3d model in the style of a cartoon, cute shape, a pastel color scheme, closeup view from the side angle, high resolution, bright colors, a happy atmosphere. --ar 1:2 --v 6.0', 'midjoureny', NULL, 'fail', NULL, 'You have reached the maximum allowed number of concurrent jobs. Don\'t worry, this job will start as soon as another one finishes!', NULL, NULL, NULL, NULL, '2024-05-08 17:26:01', '2024-05-08 17:26:04', 1, NULL, b'0'); -INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `modal`, `size`, `drawing_status`, `drawing_image_url`, `drawing_error_message`, `mj_message_id`, `mj_operation_id`, `mj_operation_name`, `mj_operations`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (23, 1, 'Cute cartoon style mobile game scene, a colorful camping car with an outdoor table and chairs next to it on the road in a spring forest, the simple structure of the camper van, soft lighting, C4D rendering, 3d model in the style of a cartoon, cute shape, a pastel color scheme, closeup view from the side angle, high resolution, bright colors, a happy atmosphere. --ar 1:2 --v 6.0', 'midjoureny', NULL, 'fail', NULL, 'Your job queue is full. Please wait for a job to finish first, then resubmit this one.', '1788144718477979648', NULL, NULL, NULL, '2024-05-08 17:51:38', '2024-05-08 17:51:39', 1, NULL, b'0'); -INSERT INTO `ai_image` (`id`, `user_id`, `prompt`, `modal`, `size`, `drawing_status`, `drawing_image_url`, `drawing_error_message`, `mj_message_id`, `mj_operation_id`, `mj_operation_name`, `mj_operations`, `create_time`, `update_time`, `creator`, `updater`, `deleted`) VALUES (24, 1, 'Cute cartoon style mobile game scene, a colorful camping car with an outdoor table and chairs next to it on the road in a spring forest, the simple structure of the camper van, soft lighting, C4D rendering, 3d model in the style of a cartoon, cute shape, a pastel color scheme, closeup view from the side angle, high resolution, bright colors, a happy atmosphere. --ar 1:2 --v 6.0', 'midjoureny', NULL, 'submit', NULL, NULL, '1788145293357699072', NULL, NULL, NULL, '2024-05-08 17:53:55', '2024-05-08 17:53:55', 1, 1, b'0'); -COMMIT; - -SET FOREIGN_KEY_CHECKS = 1; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml index 85f5fa63d..bb0b18578 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml @@ -22,6 +22,11 @@ spring-ai-openai-spring-boot-starter 1.0.3 + + io.springboot.ai + spring-ai-stability-ai + 1.0.3 + diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java index 63b8834b8..d1fabd5f4 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java @@ -20,7 +20,8 @@ public enum AiPlatformEnum { QIAN_WEN("QianWen", "千问"), // 阿里 GEMIR ("gemir ", "gemir "), // 谷歌 - OPEN_AI_DALL("dall", "dall"), // TODO OpenAI 提供的绘图,接入中 + OPEN_AI_DALL("dall", "dall"), // TODO OpenAI 提供的绘图,接入中;TODO 要不要统一下?! + STABLE_DIFFUSION("StableDiffusion", "StableDiffusion"), // Stability AI MIDJOURNEY("midjourney", "midjourney"), // TODO MJ 提供的绘图,接入中 ; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageModelEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageModelEnum.java index ea2767fcd..203f435cc 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageModelEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageModelEnum.java @@ -13,6 +13,7 @@ import lombok.Getter; */ @AllArgsConstructor @Getter +@Deprecated public enum OpenAiImageModelEnum { DALL_E_2("dall-e-2", "dall-e-2"), diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageStyleEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageStyleEnum.java index 40cbdfc02..447621391 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageStyleEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageStyleEnum.java @@ -13,6 +13,7 @@ import lombok.Getter; */ @AllArgsConstructor @Getter +@Deprecated public enum OpenAiImageStyleEnum { // 图像生成的风格。可为vivid(生动)或 natural(自然)。vivid会使模型偏向生成超现实和戏剧性的图像,而natural则会让模型产出更自然、不那么超现实的图像。该参数仅对dall-e-3模型有效。 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactory.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactory.java index 98707fdc8..cd46dee81 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactory.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactory.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.ai.core.factory; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import org.springframework.ai.chat.StreamingChatClient; import org.springframework.ai.chat.prompt.ChatOptions; +import org.springframework.ai.image.ImageClient; /** * AI 客户端工厂的接口类 @@ -33,6 +34,16 @@ public interface AiClientFactory { */ StreamingChatClient getDefaultStreamingChatClient(AiPlatformEnum platform); + /** + * 基于默认配置,获得 ImageClient 对象 + * + * 默认配置,指的是在 application.yaml 配置文件中的 spring.ai 相关的配置 + * + * @param platform 平台 + * @return ImageClient 对象 + */ + ImageClient getDefaultImageClient(AiPlatformEnum platform); + /** * 创建 Chat 参数 * diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java index 99fef7436..fa70af490 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java @@ -24,11 +24,13 @@ import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration; import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; import org.springframework.ai.chat.StreamingChatClient; import org.springframework.ai.chat.prompt.ChatOptions; +import org.springframework.ai.image.ImageClient; import org.springframework.ai.ollama.OllamaChatClient; import org.springframework.ai.ollama.api.OllamaApi; import org.springframework.ai.ollama.api.OllamaOptions; import org.springframework.ai.openai.OpenAiChatClient; import org.springframework.ai.openai.OpenAiChatOptions; +import org.springframework.ai.openai.OpenAiImageClient; import org.springframework.ai.openai.api.ApiUtils; import org.springframework.ai.openai.api.OpenAiApi; @@ -84,6 +86,16 @@ public class AiClientFactoryImpl implements AiClientFactory { } } + @Override + public ImageClient getDefaultImageClient(AiPlatformEnum platform) { + switch (platform) { + case OPEN_AI_DALL: + return SpringUtil.getBean(OpenAiImageClient.class); + + } + return null; + } + private static String buildClientCacheKey(Class clazz, Object... params) { if (ArrayUtil.isEmpty(params)) { return clazz.getName(); diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index f1b8f56f7..f2f5ba44c 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -144,19 +144,23 @@ spring: --- #################### AI 相关配置 #################### -spring.ai: - ollama: - base-url: http://127.0.0.1:11434 - chat: - model: llama3 - openai: - api-key: sk-yzKea6d8e8212c3bdd99f9f44ced1cae37c097e5aa3BTS7z - base-url: https://api.gptsapi.net - vertex: - ai: - gemini: - project-id: 1 # TODO 芋艿:缺配置 - location: 2 +spring: + ai: + ollama: + base-url: http://127.0.0.1:11434 + chat: + model: llama3 + openai: + api-key: sk-yzKea6d8e8212c3bdd99f9f44ced1cae37c097e5aa3BTS7z + base-url: https://api.gptsapi.net + stabilityai: + api-key: sk-e53UqbboF8QJCscYvzJscJxJXoFcFg4iJjl1oqgE7baJETmx + vertex: + ai: + gemini: + project-id: 1 # TODO 芋艿:缺配置 + location: 2 + yudao.ai: yiyan: @@ -202,7 +206,6 @@ yudao.ai: suno: enable: true token: 16b4356581984d538652354b60d69ff0 - --- #################### 芋道相关配置 #################### yudao: From 6856f5f192d4c726a67ef3b45c9e744a49c735ae Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 1 Jun 2024 14:16:37 +0800 Subject: [PATCH 388/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E8=BF=9B=E4=B8=80=E6=AD=A5=E7=BB=9F=E4=B8=80=20DALL?= =?UTF-8?q?=E3=80=81SD=20=E7=9A=84=E7=BB=98=E5=88=B6=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/AiCommonConstants.java | 21 ----- .../yudao/module/ai/api/package-info.java | 4 + .../ai/enums/AiChatConversationTypeEnum.java | 37 -------- .../ai/enums/AiChatRoleCategoryEnum.java | 37 -------- .../ai/enums/AiImagePublicStatusEnum.java | 36 -------- .../ai/{ => enums}/ErrorCodeConstants.java | 2 +- .../enums/{ => image}/AiImageStatusEnum.java | 4 +- .../ai/enums/{ => model}/AiModelEnum.java | 2 +- .../admin/image/AiImageController.http} | 30 ++++-- .../admin/image/AiImageController.java | 17 ++-- .../admin/image/vo/AiImageDallReqVO.java | 41 --------- .../admin/image/vo/AiImageDrawReqVO.java | 52 +++++++++++ .../vo/AiImageMidjourneyOperateReqVO.java | 31 ------- .../admin/image/vo/AiImageRespVO.java | 59 ++++-------- .../dataobject/chat/AiChatConversationDO.java | 3 +- .../dal/dataobject/chat/AiChatMessageDO.java | 2 +- .../ai/dal/dataobject/image/AiImageDO.java | 92 +++++++++++-------- .../chat/AiChatConversationServiceImpl.java | 4 +- .../chat/AiChatMessageServiceImpl.java | 6 +- .../ai/service/image/AiImageService.java | 10 +- .../ai/service/image/AiImageServiceImpl.java | 73 ++++++--------- .../YuDaoMidjourneyMessageHandler.java | 5 +- .../vo/AiChatModalChatConfigVO.java | 35 ------- .../vo/AiChatModalConfigVO.java | 31 ------- .../vo/AiChatModalDallConfigVO.java | 41 --------- .../vo/AiChatModalMidjourneyConfigVO.java | 16 ---- .../ai/service/model/AiApiKeyServiceImpl.java | 2 +- .../service/model/AiChatModelServiceImpl.java | 2 +- .../service/model/AiChatRoleServiceImpl.java | 2 +- .../ai/config/YudaoAiProperties.java | 24 +---- .../ai/core/enums/AiPlatformEnum.java | 1 - .../ai/core/enums/OpenAiImageModelEnum.java | 37 -------- .../ai/core/enums/OpenAiImageStyleEnum.java | 38 -------- .../ai/core/factory/AiClientFactoryImpl.java | 10 +- 34 files changed, 220 insertions(+), 587 deletions(-) delete mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/AiCommonConstants.java create mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/api/package-info.java delete mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatConversationTypeEnum.java delete mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleCategoryEnum.java delete mode 100644 yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImagePublicStatusEnum.java rename yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/{ => enums}/ErrorCodeConstants.java (98%) rename yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/{ => image}/AiImageStatusEnum.java (90%) rename yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/{ => model}/AiModelEnum.java (98%) rename yudao-module-ai/yudao-module-ai-biz/src/main/{resources/http/image.http => java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.http} (52%) delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallReqVO.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDrawReqVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyOperateReqVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalChatConfigVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalConfigVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalDallConfigVO.java delete mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalMidjourneyConfigVO.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageModelEnum.java delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageStyleEnum.java diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/AiCommonConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/AiCommonConstants.java deleted file mode 100644 index 01b57733e..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/AiCommonConstants.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.ai; - -/** - * ai 常用的常量 - * - * @author fansili - * @time 2024/5/7 09:29 - * @since 1.0 - */ -public class AiCommonConstants { - - /** - * 绘画 request - style - */ - public static final String DRAW_REQ_KEY_STYLE = "style"; - /** - * dall size - 模板(1024x1024) - */ - public static final String DALL_SIZE_TEMPLATE = "%sx%s"; - -} diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/api/package-info.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/api/package-info.java new file mode 100644 index 000000000..4f94f23f8 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/api/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位,没有特别的作用 + */ +package cn.iocoder.yudao.module.ai.api; \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatConversationTypeEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatConversationTypeEnum.java deleted file mode 100644 index a91bed98d..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatConversationTypeEnum.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 对话类型 - * 创建对话、继续对话 - * - * @author fansili - * @time 2024/4/14 18:15 - * @since 1.0 - */ -@AllArgsConstructor -@Getter -public enum AiChatConversationTypeEnum { - - // roleChat、userChat - ROLE_CHAT("roleChat", "角色对话"), - USER_CHAT("userChat", "用户对话"), - - ; - - private String type; - - private String name; - - public static AiChatConversationTypeEnum valueOfType(String type) { - for (AiChatConversationTypeEnum itemEnum : AiChatConversationTypeEnum.values()) { - if (itemEnum.getType().equals(type)) { - return itemEnum; - } - } - throw new IllegalArgumentException("Invalid MessageType value: " + type); - } - -} diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleCategoryEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleCategoryEnum.java deleted file mode 100644 index 3ca923de9..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleCategoryEnum.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 聊天role 分类 - * - * @author fansili - * @time 2024/4/24 16:41 - * @since 1.0 - */ -@AllArgsConstructor -@Getter -public enum AiChatRoleCategoryEnum { - - WRITING("writing", "写作"), - - ENTERTAINMENT("entertainment", "娱乐"), - - ; - - - private String category; - - private String name; - - - public static AiChatRoleCategoryEnum valueOfCategory(String category) { - for (AiChatRoleCategoryEnum itemEnum : AiChatRoleCategoryEnum.values()) { - if (itemEnum.getCategory().equals(category)) { - return itemEnum; - } - } - throw new IllegalArgumentException("Invalid MessageType value: " + category); - } -} diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImagePublicStatusEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImagePublicStatusEnum.java deleted file mode 100644 index 3a7762bb7..000000000 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImagePublicStatusEnum.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * ai绘画 public 状态 - * - * @author fansili - * @time 2024/4/28 17:05 - * @since 1.0 - */ -@AllArgsConstructor -@Getter -public enum AiImagePublicStatusEnum { - - PRIVATE("private", "私有"), - PUBLIC("public", "公开"), - - ; - - // TODO @fan:final 一下 - private final String status; - - private final String name; - - - public static AiImagePublicStatusEnum valueOfStatus(String status) { - for (AiImagePublicStatusEnum itemEnum : AiImagePublicStatusEnum.values()) { - if (itemEnum.getStatus().equals(status)) { - return itemEnum; - } - } - throw new IllegalArgumentException("Invalid MessageType value: " + status); - } -} diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java similarity index 98% rename from yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java rename to yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java index f0833b71f..be850e6e7 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai; +package cn.iocoder.yudao.module.ai.enums; import cn.iocoder.yudao.framework.common.exception.ErrorCode; diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageStatusEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/image/AiImageStatusEnum.java similarity index 90% rename from yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageStatusEnum.java rename to yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/image/AiImageStatusEnum.java index 39df7b1a8..4fd942b39 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiImageStatusEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/image/AiImageStatusEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.enums; +package cn.iocoder.yudao.module.ai.enums.image; import lombok.AllArgsConstructor; import lombok.Getter; @@ -13,7 +13,7 @@ import lombok.Getter; public enum AiImageStatusEnum { IN_PROGRESS("10", "进行中"), - COMPLETE("20", "完成"), + SUCCESS("20", "完成"), FAIL("30", "失败"); /** diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiModelEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/model/AiModelEnum.java similarity index 98% rename from yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiModelEnum.java rename to yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/model/AiModelEnum.java index 3d30d27cb..12844959b 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiModelEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/model/AiModelEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.ai.enums; +package cn.iocoder.yudao.module.ai.enums.model; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.http similarity index 52% rename from yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http rename to yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.http index bf1165773..4af24f792 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/image.http +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.http @@ -1,17 +1,33 @@ -### chat dallDrawing - -POST {{baseUrl}}/admin-api/ai/image/dallDrawing +### 生成图片:OpenAI(DALL) +POST {{baseUrl}}/ai/image/draw Content-Type: application/json Authorization: {{token}} { - "modal": "dall-e-3", - "size": "1024x1024", - "style": "vivid", - "prompt": "中国长城" + "platform": "OpenAI", + "prompt": "可爱的小喵星人", + "model": "dall-e-3", + "height": "1024", + "width": "1024", + "options": { + "style": "vivid" + } } +### 生成图片:StableDiffusion +POST {{baseUrl}}/ai/image/draw +Content-Type: application/json +Authorization: {{token}} + +{ + "platform": "StableDiffusion", + "prompt": "中国长城", + "model": "stable-diffusion-v1-6", + "height": "1024", + "width": "1024", + "style": "vivid" +} ### chat midjourney diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index 15e4304e6..0f2116a0f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -6,7 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.ai.client.vo.MidjourneyNotifyReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDrawReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyImagineReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageRespVO; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; @@ -48,13 +48,10 @@ public class AiImageController { return success(BeanUtils.toBean(image, AiImageRespVO.class)); } - // TODO @fan:建议把 dallDrawing、midjourney 融合成一个 draw 接口,异步绘制;然后返回一个 id 给前端;前端通过 get 接口轮询,直到获取到生成成功 - // TODO @芋艿: 参数差异较大 - // TODO @fan:直接参数平铺?写好注释,要么? - @Operation(summary = "dall2/dall3绘画", description = "openAi dall3是付费的!") - @PostMapping("/dall") - public CommonResult dall(@Validated @RequestBody AiImageDallReqVO req) { - return success(imageService.dall(getLoginUserId(), req)); + @Operation(summary = "生成图片") + @PostMapping("/draw") + public CommonResult drawImage(@Validated @RequestBody AiImageDrawReqVO drawReqVO) { + return success(imageService.drawImage(getLoginUserId(), drawReqVO)); } @Operation(summary = "删除【我的】绘画记录") @@ -73,11 +70,11 @@ public class AiImageController { return success(imageService.midjourneyImagine(getLoginUserId(), req)); } - // TODO @fan:可以考虑,复用 AiImageDallRespVO,统一成 AIImageRespVO + // TODO @芋艿:不拦截 @Operation(summary = "midjourney proxy - 回调通知") @RequestMapping("/midjourney-notify") public CommonResult midjourneyNotify(MidjourneyNotifyReqVO notifyReqVO) { return success(imageService.midjourneyNotify(getLoginUserId(), notifyReqVO)); } -} +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallReqVO.java deleted file mode 100644 index 1bfe48943..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDallReqVO.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.image.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; -import lombok.Data; - -/** - * dall2/dall2 绘画 - * - * @author fansili - * @time 2024/4/25 16:24 - * @since 1.0 - */ -@Data -public class AiImageDallReqVO { - - @Schema(description = "模型平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private String platform; // 参见 AiPlatformEnum 枚举 - - @Schema(description = "提示词") - @NotNull(message = "提示词不能为空!") - @Size(max = 1200, message = "提示词最大1200") - private String prompt; - - @Schema(description = "模型(dall2、dall3)") - @NotNull(message = "模型不能为空") - private String model; - - @Schema(description = "图像生成的风格。可为vivid(生动)或natural(自然)") - private String style; - - @Schema(description = "图片高度。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。") - @NotNull(message = "图片高度不能为空!") - private Integer height; - - @Schema(description = "图片宽度。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。") - @NotNull(message = "图片宽度不能为空!") - private Integer width; - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDrawReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDrawReqVO.java new file mode 100644 index 000000000..1fd1323bf --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDrawReqVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.ai.controller.admin.image.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; +import org.springframework.ai.openai.OpenAiImageOptions; +import org.springframework.ai.stabilityai.api.StabilityAiImageOptions; + +import java.util.Map; + +@Schema(description = "管理后台 - 绘画 Request VO") +@Data +public class AiImageDrawReqVO { + + @Schema(description = "模型平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI") + private String platform; // 参见 AiPlatformEnum 枚举 + + @Schema(description = "提示词", requiredMode = Schema.RequiredMode.REQUIRED, example = "画一个长城") + @NotEmpty(message = "提示词不能为空") + @Size(max = 1200, message = "提示词最大 1200") + private String prompt; + + @Schema(description = "模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "stable-diffusion-v1-6") + @NotEmpty(message = "模型不能为空") + private String model; + + /** + * 1. dall-e-2 模型:256x256、512x512、1024x1024 + * 2. dall-e-3 模型:1024x1024, 1792x1024, 或 1024x1792 + */ + @Schema(description = "图片高度") + @NotNull(message = "图片高度不能为空") + private Integer height; + + @Schema(description = "图片宽度") + @NotNull(message = "图片宽度不能为空") + private Integer width; + + // ========== 各平台绘画的拓展参数 ========== + + /** + * 绘制参数,不同 platform 的不同参数 + * + * 1. {@link OpenAiImageOptions} + * 2. {@link StabilityAiImageOptions} + */ + @Schema(description = "绘制参数") + private Map options; + +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyOperateReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyOperateReqVO.java deleted file mode 100644 index 994c1c5f0..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageMidjourneyOperateReqVO.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.image.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * midjourney req - * - * @author fansili - * @time 2024/4/28 17:42 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiImageMidjourneyOperateReqVO { - - - @NotNull(message = "图片编号不能为空") - @Schema(description = "编号") - private Long id; - - @NotNull(message = "消息编号不能为空") - @Schema(description = "消息编号") - private String messageId; - - @NotNull(message = "操作编号不能为空") - @Schema(description = "操作编号") - private String operateId; -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageRespVO.java index 4d12f7f4b..92578ce0c 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageRespVO.java @@ -5,63 +5,44 @@ import lombok.Data; import java.util.Map; -// TODO @芋艿:完善 swagger 注解 +@Schema(description = "管理后台 - 绘画 Response VO") @Data public class AiImageRespVO { - @Schema(description = "id编号", example = "1") + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long id; - @Schema(description = "用户id", example = "1") + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long userId; - @Schema(description = "提示词", example = "南极的小企鹅") - private String prompt; + @Schema(description = "平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI") + private String platform; // 参见 AiPlatformEnum 枚举 - @Schema(description = "平台", example = "openai") - private String platform; - - @Schema(description = "模型", example = "dall2") + @Schema(description = "模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "stable-diffusion-v1-6") private String model; - @Schema(description = "图片宽度", example = "1024") - private String width; + @Schema(description = "提示词", requiredMode = Schema.RequiredMode.REQUIRED, example = "南极的小企鹅") + private String prompt; - @Schema(description = "图片高度", example = "1024") - private String height; + @Schema(description = "图片宽度", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer width; - @Schema(description = "绘画状态:10 进行中、20 绘画完成、30 绘画失败", example = "10") - private String status; + @Schema(description = "图片高度", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer height; - @Schema(description = "是否发布", example = "public") - private String publicStatus; + @Schema(description = "绘画状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Integer status; - @Schema(description = "图片地址(自己服务器)", example = "http://") + @Schema(description = "是否发布", requiredMode = Schema.RequiredMode.REQUIRED, example = "public") + private Boolean publicStatus; + + @Schema(description = "图片地址", example = "https://www.iocoder.cn/1.png") private String picUrl; - @Schema(description = "绘画图片地址(绘画好的服务器)", example = "http://") - private String originalPicUrl; - @Schema(description = "绘画错误信息", example = "图片错误信息") private String errorMessage; - // ============ 绘画请求参数 - - // todo @fan:下面的 style、mjNonceId 直接就不用注释啦,直接去看 DO 完事哈 - - /** - * - style - */ - @Schema(description = "绘画请求参数") - private Map drawRequest; - - /** - * - mjNonceId - * - mjOperationId - * - mjOperationName - * - mjOperations - */ - @Schema(description = "绘画请求响应参数") - private Map drawResponse; + @Schema(description = "绘制参数") + private Map options; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java index 8e582f621..67cd490e5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java @@ -3,14 +3,13 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.chat; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.enums.AiModelEnum; +import cn.iocoder.yudao.module.ai.enums.model.AiModelEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; -import java.util.Date; /** * AI Chat 对话 DO diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java index 455a428a7..61608b8cc 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java @@ -5,7 +5,7 @@ import org.springframework.ai.chat.messages.MessageType; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.enums.AiModelEnum; +import cn.iocoder.yudao.module.ai.enums.model.AiModelEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java index b21b2f8d8..b4fc6676a 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java @@ -1,13 +1,17 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.image; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; +import cn.iocoder.yudao.module.ai.enums.image.AiImageStatusEnum; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; -import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.springframework.ai.openai.OpenAiImageOptions; +import org.springframework.ai.stabilityai.api.StabilityAiImageOptions; import java.util.Map; @@ -16,70 +20,86 @@ import java.util.Map; * * @author fansili */ -@TableName("ai_image") +@TableName(value = "ai_image", autoResultMap = true) @Data public class AiImageDO extends BaseDO { // TODO @fan:1)使用 java 注释哈,不要注解。2)关联、枚举字段,要关联到对应类,参考 AiChatMessageDO 的注释 + /** + * 编号 + */ @TableId(type = IdType.AUTO) private Long id; - @Schema(description = "用户编号") + /** + * 用户编号 + * + * 关联 {@link AdminUserRespDTO#getId()} + */ private Long userId; - @Schema(description = "midjourney proxy 关联的 job id") - private String jobId; - - @Schema(description = "提示词") + /** + * 提示词 + */ private String prompt; - @Schema(description = "平台") + /** + * 平台 + * + * 枚举 {@link cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum} + */ private String platform; - - @Schema(description = "模型") + /** + * 模型 + * + * 冗余 {@link AiChatModelDO#getModel()} + */ private String model; - @Schema(description = "图片宽度") + /** + * 图片宽度 + */ private Integer width; - - @Schema(description = "图片高度") + /** + * 图片高度 + */ private Integer height; // TODO @fan:这种就注释绘画状态,然后枚举类关联下就好啦 - @Schema(description = "绘画状态:提交、排队、绘画中、绘画完成、绘画失败") + /** + * 生成状态 + * + * 枚举 {@link AiImageStatusEnum} + */ private String status; - @Schema(description = "是否发布") - private String publicStatus; - - @Schema(description = "图片地址(自己服务器)") + /** + * 图片地址 + */ private String picUrl; - - // TODO @芋艿:可能要删除掉 - @Schema(description = "绘画图片地址(绘画好的服务器)") - private String originalPicUrl; - - // ============ 绘画请求参数 ============ + /** + * 是否公开 + */ + private Boolean publicStatus; /** - * - style + * 绘制参数,不同 platform 的不同参数 + * + * 1. {@link OpenAiImageOptions} + * 2. {@link StabilityAiImageOptions} */ - @Schema(description = "绘画请求参数") @TableField(typeHandler = JacksonTypeHandler.class) - private Map drawRequest; + private Map options; + // TODO @芋艿:再瞅瞅 /** - * - mjNonceId - * - mjOperationId - * - mjOperationName - * - mjOperations + * midjourney proxy 关联的 job id + */ + private String jobId; + /** + * 绘画错误信息 */ - @Schema(description = "绘画请求响应参数") - @TableField(typeHandler = JacksonTypeHandler.class) - private Map drawResponse; - - @Schema(description = "绘画错误信息") private String errorMessage; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java index 85349b760..83dcd8dff 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java @@ -25,8 +25,8 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; -import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_CONVERSATION_MODEL_ERROR; -import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_CONVERSATION_NOT_EXISTS; +import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.CHAT_CONVERSATION_MODEL_ERROR; +import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.CHAT_CONVERSATION_NOT_EXISTS; /** * AI 聊天对话 Service 实现类 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java index 93d8167ca..27dd154ae 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java @@ -8,7 +8,7 @@ import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactory; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.ErrorCodeConstants; +import cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; @@ -39,8 +39,8 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; -import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.AI_CHAT_MESSAGE_NOT_EXIST; -import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_CONVERSATION_NOT_EXISTS; +import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.AI_CHAT_MESSAGE_NOT_EXIST; +import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.CHAT_CONVERSATION_NOT_EXISTS; /** * AI 聊天消息 Service 实现类 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java index 2442e79a9..381a6ba17 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.ai.service.image; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.client.vo.MidjourneyNotifyReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDrawReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyImagineReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; @@ -32,12 +32,12 @@ public interface AiImageService { AiImageDO getImage(Long id); /** - * ai绘画 - dall2/dall3 绘画 + * 绘制图片 * - * @param loginUserId - * @param req + * @param userId 用户编号 + * @param drawReqVO 绘制请求 */ - Long dall(Long loginUserId, AiImageDallReqVO req); + Long drawImage(Long userId, AiImageDrawReqVO drawReqVO); /** * midjourney 图片生成 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index a9a084d65..b0c675030 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -1,19 +1,16 @@ package cn.iocoder.yudao.module.ai.service.image; -import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.codec.Base64; +import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.hutool.http.HttpUtil; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; -import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageModelEnum; -import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageStyleEnum; import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactory; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.AiCommonConstants; import cn.iocoder.yudao.module.ai.client.MidjourneyProxyClient; import cn.iocoder.yudao.module.ai.client.enums.MidjourneyModelEnum; import cn.iocoder.yudao.module.ai.client.enums.MidjourneySubmitCodeEnum; @@ -21,17 +18,18 @@ import cn.iocoder.yudao.module.ai.client.enums.MidjourneyTaskStatusEnum; import cn.iocoder.yudao.module.ai.client.vo.MidjourneyImagineReqVO; import cn.iocoder.yudao.module.ai.client.vo.MidjourneyNotifyReqVO; import cn.iocoder.yudao.module.ai.client.vo.MidjourneySubmitRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDrawReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyImagineReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper; -import cn.iocoder.yudao.module.ai.enums.AiImagePublicStatusEnum; -import cn.iocoder.yudao.module.ai.enums.AiImageStatusEnum; +import cn.iocoder.yudao.module.ai.enums.image.AiImageStatusEnum; import cn.iocoder.yudao.module.infra.api.file.FileApi; -import com.google.common.collect.ImmutableMap; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.springframework.ai.image.*; +import org.springframework.ai.image.ImageClient; +import org.springframework.ai.image.ImageOptions; +import org.springframework.ai.image.ImagePrompt; +import org.springframework.ai.image.ImageResponse; import org.springframework.ai.openai.OpenAiImageOptions; import org.springframework.ai.stabilityai.api.StabilityAiImageOptions; import org.springframework.beans.factory.annotation.Autowired; @@ -41,7 +39,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.AI_IMAGE_NOT_EXISTS; +import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.AI_IMAGE_NOT_EXISTS; /** * AI 绘画 Service 实现类 @@ -78,22 +76,18 @@ public class AiImageServiceImpl implements AiImageService { } @Override - public Long dall(Long userId, AiImageDallReqVO req) { - req.setPlatform("dall"); // TODO 芋艿:临时写死 + public Long drawImage(Long userId, AiImageDrawReqVO drawReqVO) { // 1. 保存数据库 - AiImageDO image = BeanUtils.toBean(req, AiImageDO.class) - .setUserId(userId).setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus()) - .setWidth(req.getWidth()).setHeight(req.getHeight()) - .setDrawRequest(ImmutableMap.of(AiCommonConstants.DRAW_REQ_KEY_STYLE, req.getStyle())) - .setPublicStatus(AiImagePublicStatusEnum.PRIVATE.getStatus()); + AiImageDO image = BeanUtils.toBean(drawReqVO, AiImageDO.class).setUserId(userId).setPublicStatus(false) + .setWidth(drawReqVO.getWidth()).setHeight(drawReqVO.getHeight()).setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus()); imageMapper.insert(image); - // 2. 异步绘制,后续前端通过返回的 id 进行伦旭 - getSelf().doDall(image, req); + // 2. 异步绘制,后续前端通过返回的 id 进行轮询结果 + getSelf().doDall(image, drawReqVO); return image.getId(); } @Async - public void doDall(AiImageDO image, AiImageDallReqVO req) { + public void doDall(AiImageDO image, AiImageDrawReqVO req) { try { // 1.1 构建请求 ImageOptions request = buildImageOptions(req); @@ -106,7 +100,7 @@ public class AiImageServiceImpl implements AiImageService { String filePath = fileApi.createFile(fileContent); // 3. 更新数据库 - imageMapper.updateById(new AiImageDO().setId(image.getId()).setStatus(AiImageStatusEnum.COMPLETE.getStatus()) + imageMapper.updateById(new AiImageDO().setId(image.getId()).setStatus(AiImageStatusEnum.SUCCESS.getStatus()) .setPicUrl(filePath)); } catch (Exception ex) { log.error("[doDall][image({}) 生成异常]", image, ex); @@ -115,30 +109,28 @@ public class AiImageServiceImpl implements AiImageService { } } - private static ImageOptions buildImageOptions(AiImageDallReqVO draw) { - if (ObjUtil.equal(draw.getPlatform(), AiPlatformEnum.OPEN_AI_DALL.getPlatform())) { - OpenAiImageOptions request = new OpenAiImageOptions(); - request.setModel(OpenAiImageModelEnum.valueOfModel(draw.getModel()).getModel()); - request.setStyle(OpenAiImageStyleEnum.valueOfStyle(draw.getStyle()).getStyle()); - request.setSize(String.format(AiCommonConstants.DALL_SIZE_TEMPLATE, draw.getWidth(), draw.getHeight())); - request.setResponseFormat("b64_json"); - return request; - } else { - // https://platform.stability.ai/docs/api-reference#tag/Generate/paths/~1v2beta~1stable-image~1generate~1sd3/post - return StabilityAiImageOptions.builder().withModel(draw.getModel()) + private static ImageOptions buildImageOptions(AiImageDrawReqVO draw) { + if (ObjUtil.equal(draw.getPlatform(), AiPlatformEnum.OPENAI.getPlatform())) { + // https://platform.openai.com/docs/api-reference/images/create + return OpenAiImageOptions.builder().withModel(draw.getModel()) .withHeight(draw.getHeight()).withWidth(draw.getWidth()) + .withStyle(MapUtil.getStr(draw.getOptions(), "style")) // 风格 + .withResponseFormat("b64_json") + .build(); + } else if (ObjUtil.equal(draw.getPlatform(), AiPlatformEnum.STABLE_DIFFUSION.getPlatform())) { + // https://platform.stability.ai/docs/api-reference#tag/Text-to-Image/operation/textToImage + return StabilityAiImageOptions.builder().withModel(draw.getModel()) + .withHeight(draw.getHeight()).withWidth(draw.getWidth()) // TODO @芋艿:各种参数 .build(); } -// return null; + throw new IllegalArgumentException("不支持的 AI 平台:" + draw.getPlatform()); } @Override @Transactional(rollbackFor = Exception.class) public Long midjourneyImagine(Long loginUserId, AiImageMidjourneyImagineReqVO req) { - // 1、构建 AiImageDO AiImageDO aiImageDO = new AiImageDO(); - aiImageDO.setId(null); aiImageDO.setUserId(loginUserId); aiImageDO.setPrompt(req.getPrompt()); aiImageDO.setPlatform(AiPlatformEnum.MIDJOURNEY.getPlatform()); @@ -147,12 +139,6 @@ public class AiImageServiceImpl implements AiImageService { aiImageDO.setWidth(null); aiImageDO.setHeight(null); aiImageDO.setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus()); - aiImageDO.setPublicStatus(AiImagePublicStatusEnum.PRIVATE.getStatus()); - aiImageDO.setPicUrl(null); - aiImageDO.setOriginalPicUrl(null); - aiImageDO.setDrawRequest(null); - aiImageDO.setDrawResponse(null); - aiImageDO.setErrorMessage(null); // 2、保存 image imageMapper.insert(aiImageDO); @@ -211,7 +197,7 @@ public class AiImageServiceImpl implements AiImageService { // String imageStatus = null; if (MidjourneyTaskStatusEnum.SUCCESS == notifyReqVO.getStatus()) { - imageStatus = AiImageStatusEnum.COMPLETE.getStatus(); + imageStatus = AiImageStatusEnum.SUCCESS.getStatus(); } else if (MidjourneyTaskStatusEnum.FAILURE == notifyReqVO.getStatus()) { imageStatus = AiImageStatusEnum.FAIL.getStatus(); } @@ -226,8 +212,7 @@ public class AiImageServiceImpl implements AiImageService { .setId(image.getId()) .setStatus(imageStatus) .setPicUrl(filePath) - .setOriginalPicUrl(notifyReqVO.getImageUrl()) - .setDrawResponse(BeanUtil.beanToMap(notifyReqVO)) +// .setOriginalPicUrl(notifyReqVO.getImageUrl()) TODO @fan:就不存原始的图片地址啦 ); return true; } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/YuDaoMidjourneyMessageHandler.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/YuDaoMidjourneyMessageHandler.java index 0568bbec6..493d0cded 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/YuDaoMidjourneyMessageHandler.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/YuDaoMidjourneyMessageHandler.java @@ -5,7 +5,7 @@ import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyOperationsVO; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper; -import cn.iocoder.yudao.module.ai.enums.AiImageStatusEnum; +import cn.iocoder.yudao.module.ai.enums.image.AiImageStatusEnum; import com.alibaba.fastjson.JSON; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -89,7 +89,7 @@ public class YuDaoMidjourneyMessageHandler implements MidjourneyMessageHandler { AiImageStatusEnum drawingStatusEnum = null; String generateStatus = midjourneyMessage.getGenerateStatus(); if (MidjourneyGennerateStatusEnum.COMPLETED.getStatus().equals(generateStatus)) { - drawingStatusEnum = AiImageStatusEnum.COMPLETE; + drawingStatusEnum = AiImageStatusEnum.SUCCESS; } else if (MidjourneyGennerateStatusEnum.IN_PROGRESS.getStatus().equals(generateStatus)) { drawingStatusEnum = AiImageStatusEnum.IN_PROGRESS; } @@ -101,7 +101,6 @@ public class YuDaoMidjourneyMessageHandler implements MidjourneyMessageHandler { // 更新数据库 aiImageMapper.updateByMjNonce(nonceId, new AiImageDO() - .setOriginalPicUrl(imageUrl) .setStatus(drawingStatusEnum == null ? null : drawingStatusEnum.getStatus()) // .setMjNonceId(midjourneyMessage.getId()) // .setMjOperations(JsonUtils.toJsonString(midjourneyOperations)) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalChatConfigVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalChatConfigVO.java deleted file mode 100644 index c3d2b77cc..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalChatConfigVO.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.yudao.module.ai.service.image.midjourneyHandler.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * chat config - * - * @author fansili - * @time 2024/5/6 15:06 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatModalChatConfigVO extends AiChatModalConfigVO { - - @NotNull - @Schema(description = "在生成消息时采用的Top-K采样大小") - private Double topK; - - @NotNull - @Schema(description = "Top-P核采样方法的概率阈值") - private Double topP; - - @NotNull - @Schema(description = "温度参数,用于调整生成回复的随机性和多样性程度") - private Double temperature; - - @NotNull - @Schema(description = "最大 tokens") - private Integer maxTokens; - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalConfigVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalConfigVO.java deleted file mode 100644 index 426641a0d..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalConfigVO.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.module.ai.service.image.midjourneyHandler.vo; - -import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; -import lombok.Data; -import lombok.experimental.Accessors; -import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; -import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanChatModel; - -/** - * modal config - * - * @author fansili - * @time 2024/5/6 15:06 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatModalConfigVO { - - /** - * 模型平台 (冗余,方便类型转换) - * 参考:{@link AiPlatformEnum} - */ - private String platform; - /** - * 模型类型(冗余,方便类型转换) - * {@link YiYanChatModel} - * {@link XingHuoChatModel} - */ - private String type; -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalDallConfigVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalDallConfigVO.java deleted file mode 100644 index f07b44647..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalDallConfigVO.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.module.ai.service.image.midjourneyHandler.vo; - -import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageStyleEnum; -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * dall - * - * @author fansili - * @time 2024/5/6 15:06 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatModalDallConfigVO extends AiChatModalConfigVO { - // 可选字段,默认为1 - // 生成图像的数量,必须在1到10之间。对于dall-e-3模型,目前仅支持n=1。 - private Integer n = 1; - - // 可选字段,默认为standard - // 设置生成图像的质量。hd质量将创建细节更丰富、图像整体一致性更高的图片。该参数仅对dall-e-3模型有效。 - private String quality = "standard"; - - // 可选字段,默认为url - // 返回生成图像的格式。必须是url或b64_json中的一种。URL链接的有效期是从生成图像后开始计算的60分钟内有效。 - private String responseFormat = "url"; - - // 可选字段,默认为1024x1024 - // 生成图像的尺寸大小。对于dall-e-2模型,尺寸可为256x256, 512x512, 或 1024x1024。对于dall-e-3模型,尺寸可为1024x1024, 1792x1024, 或 1024x1792。 - private String size = "1024x1024"; - - // 可选字段,默认为vivid - // 图像生成的风格。可为vivid(生动)或natural(自然)。vivid会使模型偏向生成超现实和戏剧性的图像,而natural则会让模型产出更自然、不那么超现实的图像。该参数仅对dall-e-3模型有效。 - private OpenAiImageStyleEnum style = OpenAiImageStyleEnum.VIVID; - - // 可选字段 - // 代表您的终端用户的唯一标识符,有助于OpenAI监控并检测滥用行为。了解更多信息请参考官方文档。 - private String endUserId = "UID123456"; - -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalMidjourneyConfigVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalMidjourneyConfigVO.java deleted file mode 100644 index 6c91ca652..000000000 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/midjourneyHandler/vo/AiChatModalMidjourneyConfigVO.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.ai.service.image.midjourneyHandler.vo; - -import lombok.Data; -import lombok.experimental.Accessors; - -/** - * Midjourney Config - * - * @author fansili - * @time 2024/5/6 15:07 - * @since 1.0 - */ -@Data -@Accessors(chain = true) -public class AiChatModalMidjourneyConfigVO extends AiChatModalConfigVO { -} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java index e4db8125b..41cce28f8 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java @@ -17,7 +17,7 @@ import org.springframework.validation.annotation.Validated; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.*; +import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.*; /** * AI API 密钥 Service 实现类 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java index 31d048c70..4b11602f5 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatModelServiceImpl.java @@ -16,7 +16,7 @@ import java.util.Collection; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.*; +import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.*; /** * AI 聊天模型 Service 实现类 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java index faee09d06..4f358e473 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleServiceImpl.java @@ -21,7 +21,7 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; -import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.*; +import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.*; /** * AI 聊天角色 Service 实现类 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java index e0cfa05f9..e56a23996 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java @@ -3,10 +3,9 @@ package cn.iocoder.yudao.framework.ai.config; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanChatModel; -import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageModelEnum; -import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageStyleEnum; import lombok.Data; import lombok.experimental.Accessors; +import org.springframework.ai.autoconfigure.openai.OpenAiImageProperties; import org.springframework.boot.context.properties.ConfigurationProperties; /** @@ -92,27 +91,6 @@ public class YudaoAiProperties { private int refreshTokenSecondTime = 86400; } - @Data - @Accessors(chain = true) - public static class OpenAiImageProperties { - - private boolean enable = false; - - /** - * api key - */ - private String apiKey; - /** - * 模型 - */ - private OpenAiImageModelEnum model = OpenAiImageModelEnum.DALL_E_2; - /** - * 风格 - */ - private OpenAiImageStyleEnum style = OpenAiImageStyleEnum.VIVID; - - } - @Data @Accessors(chain = true) public static class MidjourneyProperties { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java index d1fabd5f4..d6513354e 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java @@ -20,7 +20,6 @@ public enum AiPlatformEnum { QIAN_WEN("QianWen", "千问"), // 阿里 GEMIR ("gemir ", "gemir "), // 谷歌 - OPEN_AI_DALL("dall", "dall"), // TODO OpenAI 提供的绘图,接入中;TODO 要不要统一下?! STABLE_DIFFUSION("StableDiffusion", "StableDiffusion"), // Stability AI MIDJOURNEY("midjourney", "midjourney"), // TODO MJ 提供的绘图,接入中 ; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageModelEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageModelEnum.java deleted file mode 100644 index 203f435cc..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageModelEnum.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.framework.ai.core.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -// TODO 芋艿:待梳理 -/** - * open ai - * - * @author fansili - * @time 2024/4/28 14:21 - * @since 1.0 - */ -@AllArgsConstructor -@Getter -@Deprecated -public enum OpenAiImageModelEnum { - - DALL_E_2("dall-e-2", "dall-e-2"), - - DALL_E_3("dall-e-3", "dall-e-3") - - ; - - private String model; - - private String name; - - public static OpenAiImageModelEnum valueOfModel(String model) { - for (OpenAiImageModelEnum itemEnum : OpenAiImageModelEnum.values()) { - if (itemEnum.getModel().equals(model)) { - return itemEnum; - } - } - throw new IllegalArgumentException("Invalid MessageType value: " + model); - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageStyleEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageStyleEnum.java deleted file mode 100644 index 447621391..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/OpenAiImageStyleEnum.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.iocoder.yudao.framework.ai.core.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -// TODO 芋艿:待梳理 -/** - * open ai image style - * - * @author fansili - * @time 2024/4/28 16:15 - * @since 1.0 - */ -@AllArgsConstructor -@Getter -@Deprecated -public enum OpenAiImageStyleEnum { - - // 图像生成的风格。可为vivid(生动)或 natural(自然)。vivid会使模型偏向生成超现实和戏剧性的图像,而natural则会让模型产出更自然、不那么超现实的图像。该参数仅对dall-e-3模型有效。 - - VIVID("vivid", "生动"), - NATURAL("natural", "自然"), - - ; - - private String style; - - private String name; - - public static OpenAiImageStyleEnum valueOfStyle(String style) { - for (OpenAiImageStyleEnum itemEnum : OpenAiImageStyleEnum.values()) { - if (itemEnum.getStyle().equals(style)) { - return itemEnum; - } - } - throw new IllegalArgumentException("Invalid MessageType value: " + style); - } -} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java index fa70af490..5c8248789 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java @@ -33,6 +33,7 @@ import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.OpenAiImageClient; import org.springframework.ai.openai.api.ApiUtils; import org.springframework.ai.openai.api.OpenAiApi; +import org.springframework.ai.stabilityai.StabilityAiImageClient; import java.util.List; @@ -88,12 +89,15 @@ public class AiClientFactoryImpl implements AiClientFactory { @Override public ImageClient getDefaultImageClient(AiPlatformEnum platform) { + //noinspection EnhancedSwitchMigration switch (platform) { - case OPEN_AI_DALL: + case OPENAI: return SpringUtil.getBean(OpenAiImageClient.class); - + case STABLE_DIFFUSION: + return SpringUtil.getBean(StabilityAiImageClient.class); + default: + throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); } - return null; } private static String buildClientCacheKey(Class clazz, Object... params) { From b7180d34818c7a7ff988c6c9fc74a25a1e20ebee Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 1 Jun 2024 15:15:30 +0800 Subject: [PATCH 389/684] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E4=BC=9A=E8=AF=9D=E6=8E=A5=E5=85=A5=20API=20KEY=20?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/dal/mysql/model/AiApiKeyMapper.java | 9 +++ .../chat/AiChatMessageServiceImpl.java | 40 ++++++++++--- .../ai/service/image/AiImageService.java | 1 + .../ai/service/image/AiImageServiceImpl.java | 10 ++-- .../ai/service/model/AiApiKeyService.java | 12 ++++ .../ai/service/model/AiApiKeyServiceImpl.java | 10 ++++ .../ai/core/factory/AiClientFactory.java | 14 ++--- .../ai/core/factory/AiClientFactoryImpl.java | 59 +++++++++---------- .../src/main/resources/application.yaml | 7 +-- 9 files changed, 106 insertions(+), 56 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiApiKeyMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiApiKeyMapper.java index fef4965b8..0a2efe36f 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiApiKeyMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiApiKeyMapper.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.ai.dal.mysql.model; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; import org.apache.ibatis.annotations.Mapper; @@ -23,4 +24,12 @@ public interface AiApiKeyMapper extends BaseMapperX { .orderByDesc(AiApiKeyDO::getId)); } + default AiApiKeyDO selectFirstByPlatformAndStatus(String platform, Integer status) { + return selectOne(new QueryWrapperX() + .eq("platform", platform) + .eq("status", status) + .limitN(1) + .orderByAsc("id")); + } + } \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java index 27dd154ae..566859abf 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java @@ -4,11 +4,13 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; -import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactory; +import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenOptions; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoOptions; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatOptions; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; @@ -18,6 +20,7 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatMessageMapper; +import cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; @@ -28,6 +31,8 @@ import org.springframework.ai.chat.StreamingChatClient; import org.springframework.ai.chat.messages.*; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.ollama.api.OllamaOptions; +import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import reactor.core.publisher.Flux; @@ -54,9 +59,6 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { @Resource private AiChatMessageMapper chatMessageMapper; - @Resource - private AiClientFactory clientFactory; - @Resource private AiChatConversationService chatConversationService; @Resource @@ -168,11 +170,33 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { // 2. 构建 ChatOptions 对象 AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); - ChatOptions chatOptions = clientFactory.buildChatOptions(platform, model.getModel(), + ChatOptions chatOptions = buildChatOptions(platform, model.getModel(), conversation.getTemperature(), conversation.getMaxTokens()); return new Prompt(chatMessages, chatOptions); } + private static ChatOptions buildChatOptions(AiPlatformEnum platform, String model, Double temperature, Integer maxTokens) { + Float temperatureF = temperature != null ? temperature.floatValue() : null; + //noinspection EnhancedSwitchMigration + switch (platform) { + case OPENAI: + return OpenAiChatOptions.builder().withModel(model).withTemperature(temperatureF).withMaxTokens(maxTokens).build(); + case OLLAMA: + return OllamaOptions.create().withModel(model).withTemperature(temperatureF).withNumPredict(maxTokens); + case YI_YAN: + // TODO @fan:增加一个 model + return new YiYanChatOptions().setTemperature(temperatureF).setMaxOutputTokens(maxTokens); + case XING_HUO: + return new XingHuoOptions().setChatModel(XingHuoChatModel.valueOfModel(model)).setTemperature(temperatureF) + .setMaxTokens(maxTokens); + case QIAN_WEN: + // TODO @fan:增加 model、temperature 参数 + return new QianWenOptions().setMaxTokens(maxTokens); + default: + throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); + } + } + /** * 从历史消息中,获得倒序的 n 组消息作为消息上下文 * @@ -183,7 +207,9 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { * @param sendReqVO 发送请求 * @return 消息上下文 */ - private List filterContextMessages(List messages, AiChatConversationDO conversation, AiChatMessageSendReqVO sendReqVO) { + private List filterContextMessages(List messages, + AiChatConversationDO conversation, + AiChatMessageSendReqVO sendReqVO) { if (conversation.getMaxContexts() == null || ObjUtil.notEqual(sendReqVO.getUseContext(), Boolean.TRUE)) { return Collections.emptyList(); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java index 381a6ba17..8a30121be 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java @@ -64,4 +64,5 @@ public interface AiImageService { * @return */ Boolean midjourneyNotify(Long loginUserId, MidjourneyNotifyReqVO notifyReqVO); + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index b0c675030..ea52dd42b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -7,7 +7,6 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.hutool.http.HttpUtil; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; -import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactory; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -23,6 +22,7 @@ import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyIma import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper; import cn.iocoder.yudao.module.ai.enums.image.AiImageStatusEnum; +import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; import cn.iocoder.yudao.module.infra.api.file.FileApi; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -57,7 +57,7 @@ public class AiImageServiceImpl implements AiImageService { private FileApi fileApi; @Resource - private AiClientFactory aiClientFactory; + private AiApiKeyService apiKeyService; @Autowired private MidjourneyProxyClient midjourneyProxyClient; @@ -82,17 +82,17 @@ public class AiImageServiceImpl implements AiImageService { .setWidth(drawReqVO.getWidth()).setHeight(drawReqVO.getHeight()).setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus()); imageMapper.insert(image); // 2. 异步绘制,后续前端通过返回的 id 进行轮询结果 - getSelf().doDall(image, drawReqVO); + getSelf().executeDrawImage(image, drawReqVO); return image.getId(); } @Async - public void doDall(AiImageDO image, AiImageDrawReqVO req) { + public void executeDrawImage(AiImageDO image, AiImageDrawReqVO req) { try { // 1.1 构建请求 ImageOptions request = buildImageOptions(req); // 1.2 执行请求 - ImageClient imageClient = aiClientFactory.getDefaultImageClient(AiPlatformEnum.validatePlatform(req.getPlatform())); + ImageClient imageClient = apiKeyService.getImageClient(AiPlatformEnum.validatePlatform(req.getPlatform())); ImageResponse response = imageClient.call(new ImagePrompt(req.getPrompt(), request)); // 2. 上传到文件服务 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java index 8056eab78..20cda18af 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java @@ -1,11 +1,13 @@ package cn.iocoder.yudao.module.ai.service.model; +import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; import jakarta.validation.Valid; import org.springframework.ai.chat.StreamingChatClient; +import org.springframework.ai.image.ImageClient; import java.util.List; @@ -79,4 +81,14 @@ public interface AiApiKeyService { */ StreamingChatClient getStreamingChatClient(Long id); + /** + * 获得 ImageClient 对象 + * + * TODO 可优化点:目前默认获取 platform 对应的第一个开启的配置用于绘画;后续可以支持配置选择 + * + * @param platform 平台 + * @return ImageClient 对象 + */ + ImageClient getImageClient(AiPlatformEnum platform); + } \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java index 41cce28f8..14ea6d43e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java @@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; import cn.iocoder.yudao.module.ai.dal.mysql.model.AiApiKeyMapper; import jakarta.annotation.Resource; import org.springframework.ai.chat.StreamingChatClient; +import org.springframework.ai.image.ImageClient; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -101,4 +102,13 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { return clientFactory.getOrCreateStreamingChatClient(platform, apiKey.getApiKey(), apiKey.getUrl()); } + @Override + public ImageClient getImageClient(AiPlatformEnum platform) { + AiApiKeyDO apiKey = apiKeyMapper.selectFirstByPlatformAndStatus(platform.getName(), CommonStatusEnum.ENABLE.getStatus()); + if (apiKey == null) { + return null; + } + return clientFactory.getOrCreateImageClient(platform, apiKey.getApiKey(), apiKey.getUrl()); + } + } \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactory.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactory.java index cd46dee81..ab7e7f996 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactory.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactory.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.framework.ai.core.factory; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import org.springframework.ai.chat.StreamingChatClient; -import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.image.ImageClient; /** @@ -45,14 +44,15 @@ public interface AiClientFactory { ImageClient getDefaultImageClient(AiPlatformEnum platform); /** - * 创建 Chat 参数 + * 基于指定配置,获得 ImageClient 对象 + * + * 如果不存在,则进行创建 * * @param platform 平台 - * @param model 模型 - * @param temperature 温度 - * @param maxTokens 生成的最大 Token - * @return Chat 参数 + * @param apiKey API KEY + * @param url API URL + * @return ImageClient 对象 */ - ChatOptions buildChatOptions(AiPlatformEnum platform, String model, Double temperature, Integer maxTokens); + ImageClient getOrCreateImageClient(AiPlatformEnum platform, String apiKey, String url); } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java index 5c8248789..b54b348b1 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java @@ -11,29 +11,25 @@ import cn.iocoder.yudao.framework.ai.config.YudaoAiProperties; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatClient; import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatModal; -import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenOptions; import cn.iocoder.yudao.framework.ai.core.model.tongyi.api.QianWenApi; import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatClient; -import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; -import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoOptions; import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoApi; import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatClient; -import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatOptions; import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanApi; import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration; import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; import org.springframework.ai.chat.StreamingChatClient; -import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.image.ImageClient; import org.springframework.ai.ollama.OllamaChatClient; import org.springframework.ai.ollama.api.OllamaApi; -import org.springframework.ai.ollama.api.OllamaOptions; import org.springframework.ai.openai.OpenAiChatClient; -import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.OpenAiImageClient; import org.springframework.ai.openai.api.ApiUtils; import org.springframework.ai.openai.api.OpenAiApi; +import org.springframework.ai.openai.api.OpenAiImageApi; import org.springframework.ai.stabilityai.StabilityAiImageClient; +import org.springframework.ai.stabilityai.api.StabilityAiApi; +import org.springframework.web.client.RestClient; import java.util.List; @@ -100,6 +96,19 @@ public class AiClientFactoryImpl implements AiClientFactory { } } + @Override + public ImageClient getOrCreateImageClient(AiPlatformEnum platform, String apiKey, String url) { + //noinspection EnhancedSwitchMigration + switch (platform) { + case OPENAI: + return buildOpenAiImageClient(apiKey, url); + case STABLE_DIFFUSION: + return buildStabilityAiImageClient(apiKey, url); + default: + throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); + } + } + private static String buildClientCacheKey(Class clazz, Object... params) { if (ArrayUtil.isEmpty(params)) { return clazz.getName(); @@ -107,29 +116,6 @@ public class AiClientFactoryImpl implements AiClientFactory { return StrUtil.format("{}#{}", clazz.getName(), ArrayUtil.join(params, "_")); } - @Override - public ChatOptions buildChatOptions(AiPlatformEnum platform, String model, Double temperature, Integer maxTokens) { - Float temperatureF = temperature != null ? temperature.floatValue() : null; - //noinspection EnhancedSwitchMigration - switch (platform) { - case OPENAI: - return OpenAiChatOptions.builder().withModel(model).withTemperature(temperatureF).withMaxTokens(maxTokens).build(); - case OLLAMA: - return OllamaOptions.create().withModel(model).withTemperature(temperatureF).withNumPredict(maxTokens); - case YI_YAN: - // TODO @fan:增加一个 model - return new YiYanChatOptions().setTemperature(temperatureF).setMaxOutputTokens(maxTokens); - case XING_HUO: - return new XingHuoOptions().setChatModel(XingHuoChatModel.valueOfModel(model)).setTemperature(temperatureF) - .setMaxTokens(maxTokens); - case QIAN_WEN: - // TODO @fan:增加 model、temperature 参数 - return new QianWenOptions().setMaxTokens(maxTokens); - default: - throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); - } - } - // ========== 各种创建 spring-ai 客户端的方法 ========== /** @@ -182,7 +168,6 @@ public class AiClientFactoryImpl implements AiClientFactory { return new QianWenChatClient(qianWenApi); } - // private static VertexAiGeminiChatClient buildGoogleGemir(String key) { // List keys = StrUtil.split(key, '|'); // Assert.equals(keys.size(), 2, "VertexAiGeminiChatClient 的密钥需要 (projectId|location) 格式"); @@ -190,4 +175,16 @@ public class AiClientFactoryImpl implements AiClientFactory { // return new VertexAiGeminiChatClient(vertexApi); // } + private ImageClient buildOpenAiImageClient(String openAiToken, String url) { + url = StrUtil.blankToDefault(url, ApiUtils.DEFAULT_BASE_URL); + OpenAiImageApi openAiApi = new OpenAiImageApi(url, openAiToken, RestClient.builder()); + return new OpenAiImageClient(openAiApi); + } + + private ImageClient buildStabilityAiImageClient(String apiKey, String url) { + url = StrUtil.blankToDefault(url, StabilityAiApi.DEFAULT_BASE_URL); + StabilityAiApi stabilityAiApi = new StabilityAiApi(apiKey, StabilityAiApi.DEFAULT_IMAGE_MODEL, url); + return new StabilityAiImageClient(stabilityAiApi); + } + } diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index f2f5ba44c..0289298f0 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -161,7 +161,6 @@ spring: project-id: 1 # TODO 芋艿:缺配置 location: 2 - yudao.ai: yiyan: enable: true @@ -193,11 +192,6 @@ yudao.ai: topP: 0.8 topK: 0 api-key: sk-Zsd81gZYg7 - openAiImage: - enable: true - api-key: ${OPEN_AI_KEY} - model: dall_e_2 - style: vivid midjourney: enable: true token: MTE4MjE3MjY2MjkxNTY3ODIzOA.GEV1SG.c49F8lZoGCUHwsj8O0UdodmM6nyQHvuD2fXflw @@ -206,6 +200,7 @@ yudao.ai: suno: enable: true token: 16b4356581984d538652354b60d69ff0 + --- #################### 芋道相关配置 #################### yudao: From 9152fbfdb727566ff9064ed4acbba9244167432d Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 2 Jun 2024 18:44:12 +0800 Subject: [PATCH 390/684] =?UTF-8?q?=E3=80=90=E5=90=8C=E6=AD=A5=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E6=9C=80=E6=96=B0=20AI=20SQL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/mysql/ruoyi-vue-pro.sql | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/sql/mysql/ruoyi-vue-pro.sql b/sql/mysql/ruoyi-vue-pro.sql index 48c8fb9ca..d02bc102f 100644 --- a/sql/mysql/ruoyi-vue-pro.sql +++ b/sql/mysql/ruoyi-vue-pro.sql @@ -11,7 +11,7 @@ Target Server Version : 80200 (8.2.0) File Encoding : 65001 - Date: 25/05/2024 13:29:34 + Date: 02/06/2024 18:43:50 */ SET NAMES utf8mb4; @@ -91,7 +91,7 @@ CREATE TABLE `infra_api_error_log` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 17651 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; +) ENGINE = InnoDB AUTO_INCREMENT = 17689 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; -- ---------------------------- -- Records of infra_api_error_log @@ -250,7 +250,7 @@ CREATE TABLE `infra_file` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1322 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1336 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; -- ---------------------------- -- Records of infra_file @@ -438,7 +438,7 @@ CREATE TABLE `system_dict_data` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1542 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1543 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表'; -- ---------------------------- -- Records of system_dict_data @@ -814,6 +814,7 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1539, 3, '文心一言', 'YiYan', 'ai_platform', 0, '', '', '', '1', '2024-05-18 09:24:20', '1', '2024-05-18 09:29:01', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1540, 4, '讯飞星火', 'XingHuo', 'ai_platform', 0, '', '', '', '1', '2024-05-18 10:08:56', '1', '2024-05-18 10:08:56', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1541, 5, '通义千问', 'QianWen', 'ai_platform', 0, '', '', '', '1', '2024-05-18 10:32:29', '1', '2024-05-25 13:18:31', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1542, 6, 'StableDiffusion', 'StableDiffusion', 'ai_platform', 0, '', '', '', '1', '2024-06-01 15:09:31', '1', '2024-06-01 15:10:25', b'0'); COMMIT; -- ---------------------------- @@ -946,7 +947,7 @@ CREATE TABLE `system_login_log` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 3152 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; +) ENGINE = InnoDB AUTO_INCREMENT = 3154 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; -- ---------------------------- -- Records of system_login_log @@ -1077,7 +1078,7 @@ CREATE TABLE `system_menu` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 2783 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表'; +) ENGINE = InnoDB AUTO_INCREMENT = 2784 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表'; -- ---------------------------- -- Records of system_menu @@ -1896,6 +1897,7 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2780, '会话删除', 'ai:chat-conversation:delete', 3, 2, 2778, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-05-24 15:39:18', '1', '2024-05-25 08:38:40', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2781, '消息查询', 'ai:chat-message:query', 3, 11, 2778, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-05-25 08:38:56', '1', '2024-05-25 08:38:56', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2782, '消息删除', 'ai:chat-message:delete', 3, 12, 2778, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-05-25 08:39:10', '1', '2024-05-25 08:39:10', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2783, 'AI 绘画', '', 2, 2, 2758, 'image', 'ep:picture-rounded', 'ai/image/index.vue', 'AiImage', 0, b'1', b'1', b'1', '1', '2024-05-26 11:45:17', '1', '2024-05-26 11:45:26', b'0'); COMMIT; -- ---------------------------- @@ -2017,7 +2019,7 @@ CREATE TABLE `system_oauth2_access_token` ( PRIMARY KEY (`id`) USING BTREE, INDEX `idx_access_token`(`access_token` ASC) USING BTREE, INDEX `idx_refresh_token`(`refresh_token` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 7123 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; +) ENGINE = InnoDB AUTO_INCREMENT = 7329 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; -- ---------------------------- -- Records of system_oauth2_access_token @@ -2139,7 +2141,7 @@ CREATE TABLE `system_oauth2_refresh_token` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1521 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; +) ENGINE = InnoDB AUTO_INCREMENT = 1523 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; -- ---------------------------- -- Records of system_oauth2_refresh_token @@ -3479,7 +3481,7 @@ CREATE TABLE `system_users` ( -- Records of system_users -- ---------------------------- BEGIN; -INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '18818260277', 2, 'http://test.yudao.iocoder.cn/96c787a2ce88bf6d0ce3cd8b6cf5314e80e7703cd41bf4af8cd2e2909dbd6b6d.png', 0, '0:0:0:0:0:0:0:1', '2024-05-19 11:11:07', 'admin', '2021-01-05 17:03:47', NULL, '2024-05-19 11:11:07', b'0', 1); +INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '18818260277', 2, 'http://test.yudao.iocoder.cn/96c787a2ce88bf6d0ce3cd8b6cf5314e80e7703cd41bf4af8cd2e2909dbd6b6d.png', 0, '0:0:0:0:0:0:0:1', '2024-05-28 20:36:33', 'admin', '2021-01-05 17:03:47', NULL, '2024-05-28 20:36:33', b'0', 1); INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (100, 'yudao', '$2a$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 1, '127.0.0.1', '2022-07-09 23:03:33', '', '2021-01-07 09:07:17', NULL, '2022-07-09 23:03:33', b'0', 1); INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (103, 'yuanma', '$2a$10$YMpimV4T6BtDhIaA8jSW.u8UTGBeGhc/qwXP4oxoMr4mOw9.qttt6', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '0:0:0:0:0:0:0:1', '2024-03-18 21:09:04', '', '2021-01-13 23:50:35', NULL, '2024-03-18 21:09:04', b'0', 1); INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (104, 'test', '$2a$04$KhExCYl7lx6eWWZYKsibKOZ8IBJRyuNuCcEOLQ11RYhJKgHmlSwK.', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, '', 0, '0:0:0:0:0:0:0:1', '2024-03-26 07:11:35', '', '2021-01-21 02:13:53', NULL, '2024-03-26 07:11:35', b'0', 1); From 3ab218efc6c92a3109c9f197cde8e8e0256d738c Mon Sep 17 00:00:00 2001 From: cherishsince Date: Mon, 3 Jun 2024 10:01:04 +0800 Subject: [PATCH 391/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=B2=A1=E7=94=A8=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ai/core/enums/AiPlatformEnum.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java index d6513354e..7ac341e46 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java @@ -33,18 +33,6 @@ public enum AiPlatformEnum { */ private final String name; -// public static List CHAT_PLATFORM_LIST = Lists.newArrayList( -// AiPlatformEnum.YI_YAN, -// AiPlatformEnum.QIAN_WEN, -// AiPlatformEnum.XING_HUO, -// AiPlatformEnum.OPENAI -// ); -// -// public static List IMAGE_PLATFORM_LIST = Lists.newArrayList( -// AiPlatformEnum.OPEN_AI_DALL, -// AiPlatformEnum.MIDJOURNEY -// ); - public static AiPlatformEnum validatePlatform(String platform) { for (AiPlatformEnum platformEnum : AiPlatformEnum.values()) { if (platformEnum.getPlatform().equals(platform)) { From 851c290c0d3240822272757cc0ef940fb2ebfb47 Mon Sep 17 00:00:00 2001 From: xiaoxin <718949661@qq.com> Date: Mon, 3 Jun 2024 18:20:16 +0800 Subject: [PATCH 392/684] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E4=BD=BF=E7=94=A8suno-api=E6=9C=8D=E5=8A=A1=E6=8E=A5?= =?UTF-8?q?=E5=85=A5Suno?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/music/vo/MusicDataVO.java | 4 +- .../controller/admin/music/vo/SunoRespVO.java | 4 +- .../ai/service/music/MusicServiceImpl.java | 6 +- .../ai/config/YudaoAiAutoConfiguration.java | 6 +- .../core/model/suno/api/AceDataSunoApi.java | 115 ++++++++++ .../ai/core/model/suno/api/SunoApi.java | 209 ++++++++++++------ .../yudao/framework/ai/suno/SunoTests.java | 43 +++- 7 files changed, 307 insertions(+), 80 deletions(-) create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/AceDataSunoApi.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/MusicDataVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/MusicDataVO.java index d4c4afa22..f138d605e 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/MusicDataVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/MusicDataVO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.ai.controller.admin.music.vo; -import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; +import cn.iocoder.yudao.framework.ai.core.model.suno.api.AceDataSunoApi; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; @@ -66,7 +66,7 @@ public class MusicDataVO { */ private String style; - public static List convertFrom(List musicDataList) { + public static List convertFrom(List musicDataList) { return musicDataList.stream().map(musicData -> { MusicDataVO musicDataVO = new MusicDataVO(); musicDataVO.setId(musicData.id()); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/SunoRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/SunoRespVO.java index b3d66363f..5eed0b81d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/SunoRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/SunoRespVO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.ai.controller.admin.music.vo; -import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; +import cn.iocoder.yudao.framework.ai.core.model.suno.api.AceDataSunoApi; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; @@ -29,7 +29,7 @@ public class SunoRespVO { //把 SunoResp转为本vo类 - public static SunoRespVO convertFrom(SunoApi.SunoResp sunoResp) { + public static SunoRespVO convertFrom(AceDataSunoApi.SunoResp sunoResp) { SunoRespVO sunoRespVO = new SunoRespVO(); sunoRespVO.setSuccess(sunoResp.success()); sunoRespVO.setTaskId(sunoResp.taskId()); diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/MusicServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/MusicServiceImpl.java index 0673e59ac..f8b2a9d50 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/MusicServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/music/MusicServiceImpl.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.ai.service.music; -import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; +import cn.iocoder.yudao.framework.ai.core.model.suno.api.AceDataSunoApi; import cn.iocoder.yudao.module.ai.controller.admin.music.vo.SunoReqVO; import cn.iocoder.yudao.module.ai.controller.admin.music.vo.SunoRespVO; import lombok.RequiredArgsConstructor; @@ -14,11 +14,11 @@ import org.springframework.stereotype.Service; @RequiredArgsConstructor public class MusicServiceImpl implements MusicService { - private final SunoApi sunoApi; + private final AceDataSunoApi aceDataSunoApi; @Override public SunoRespVO musicGen(SunoReqVO sunoReqVO) { - SunoApi.SunoResp sunoResp = sunoApi.musicGen(new SunoApi.SunoReq( + AceDataSunoApi.SunoResp sunoResp = aceDataSunoApi.musicGen(new AceDataSunoApi.SunoReq( sunoReqVO.getPrompt(), sunoReqVO.getLyric(), sunoReqVO.isCustom(), diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java index 7285448a3..cd7512bf3 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java @@ -4,7 +4,7 @@ import cn.hutool.core.io.IoUtil; import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactory; import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactoryImpl; import cn.iocoder.yudao.framework.ai.core.model.suno.SunoConfig; -import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; +import cn.iocoder.yudao.framework.ai.core.model.suno.api.AceDataSunoApi; import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatClient; import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatModal; import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenOptions; @@ -150,8 +150,8 @@ public class YudaoAiAutoConfiguration { @Bean @ConditionalOnProperty(value = "yudao.ai.suno.enable", havingValue = "true") - public SunoApi sunoApi(YudaoAiProperties yudaoAiProperties) { - return new SunoApi(new SunoConfig(yudaoAiProperties.getSuno().getToken())); + public AceDataSunoApi sunoApi(YudaoAiProperties yudaoAiProperties) { + return new AceDataSunoApi(new SunoConfig(yudaoAiProperties.getSuno().getToken())); } private static @NotNull MidjourneyConfig getMidjourneyConfig(ApplicationContext applicationContext, diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/AceDataSunoApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/AceDataSunoApi.java new file mode 100644 index 000000000..d50379d59 --- /dev/null +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/AceDataSunoApi.java @@ -0,0 +1,115 @@ +package cn.iocoder.yudao.framework.ai.core.model.suno.api; + +import cn.iocoder.yudao.framework.ai.core.model.suno.SunoConfig; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.extern.slf4j.Slf4j; +import org.springframework.ai.openai.api.ApiUtils; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +import java.util.List; + +/** + * Suno API + *
+ * 文档地址:https://platform.acedata.cloud/documents/d016ee3f-421b-4b6e-989a-8beba8701701 + * + * @Author xiaoxin + * @Date 2024/5/27 + */ +@Slf4j +public class AceDataSunoApi { + + public static final String DEFAULT_BASE_URL = "https://api.acedata.cloud/suno"; + private final WebClient webClient; + + public AceDataSunoApi(SunoConfig config) { + this.webClient = WebClient.builder() + .baseUrl(DEFAULT_BASE_URL) + .defaultHeaders(ApiUtils.getJsonContentHeaders(config.getToken())) + .build(); + } + + // TODO @芋艿:方法名,要考虑下; + public SunoResp musicGen(SunoReq sunReq) { + return this.webClient.post() + .uri("/audios") + .body(Mono.just(sunReq), SunoReq.class) + .retrieve() + .onStatus(status -> !status.is2xxSuccessful(), + response -> response.bodyToMono(String.class) + .handle((respBody, sink) -> { + log.error("【Suno】调用失败!resp: 【{}】", respBody); + sink.error(new IllegalStateException("【Suno】调用失败!")); + })) + .bodyToMono(SunoResp.class) + .block(); + } + + /** + * 请求数据对象,用于生成音乐音频。 + * + * @param prompt 用于生成音乐音频的提示 + * @param lyric 用于生成音乐音频的歌词 + * @param custom 指示音乐音频是否为定制,如果为 true,则从歌词生成,否则从提示生成 + * @param title 音乐音频的标题 + * @param style 音乐音频的风格 + * @param callbackUrl 音乐音频生成后回调的 URL + */ + @JsonInclude(value = JsonInclude.Include.NON_NULL) + public record SunoReq( + String prompt, + String lyric, + boolean custom, + String title, + String style, + String callbackUrl + ) { + public SunoReq(String prompt) { + this(prompt, null, false, null, null, null); + } + + } + + /** + * SunoAPI 响应的数据。 + * + * @param success 表示请求是否成功 + * @param taskId 任务 ID + * @param data 音乐数据列表 + */ + public record SunoResp( + boolean success, + @JsonProperty("task_id") String taskId, + List data + ) { + /** + * 单个音乐数据。 + * + * @param id 音乐数据的 ID + * @param title 音乐音频的标题 + * @param imageUrl 音乐音频的图片 URL + * @param lyric 音乐音频的歌词 + * @param audioUrl 音乐音频的 URL + * @param videoUrl 音乐视频的 URL + * @param createdAt 音乐音频的创建时间 + * @param model 使用的模型名称 + * @param prompt 生成音乐音频的提示 + * @param style 音乐音频的风格 + */ + public record MusicData( + String id, + String title, + @JsonProperty("image_url") String imageUrl, + String lyric, + @JsonProperty("audio_url") String audioUrl, + @JsonProperty("video_url") String videoUrl, + @JsonProperty("created_at") String createdAt, + String model, + String prompt, + String style + ) { + } + } +} diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/SunoApi.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/SunoApi.java index 22435affd..25ae04f51 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/SunoApi.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/suno/api/SunoApi.java @@ -1,115 +1,194 @@ package cn.iocoder.yudao.framework.ai.core.model.suno.api; -import cn.iocoder.yudao.framework.ai.core.model.suno.SunoConfig; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.extern.slf4j.Slf4j; -import org.springframework.ai.openai.api.ApiUtils; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.MediaType; +import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; import java.util.List; +import java.util.function.Function; +import java.util.function.Predicate; /** * Suno API *
- * 文档地址:https://platform.acedata.cloud/documents/d016ee3f-421b-4b6e-989a-8beba8701701 + * 文档地址:https://github.com/status2xx/suno-api/blob/main/README_CN.md * * @Author xiaoxin - * @Date 2024/5/27 + * @Date 2024/6/3 */ @Slf4j public class SunoApi { - public static final String DEFAULT_BASE_URL = "https://api.acedata.cloud/suno"; + public static final String DEFAULT_BASE_URL = "https://suno-9323szg26-status2xxs-projects.vercel.app"; private final WebClient webClient; - public SunoApi(SunoConfig config) { + + private final Predicate STATUS_PREDICATE = status -> !status.is2xxSuccessful(); + private final Function> EXCEPTION_FUNCTION = response -> response.bodyToMono(String.class) + .handle((respBody, sink) -> { + log.error("【suno-api】调用失败!resp: 【{}】", respBody); + sink.error(new IllegalStateException("【suno-api】调用失败!")); + }); + + + public SunoApi() { this.webClient = WebClient.builder() .baseUrl(DEFAULT_BASE_URL) - .defaultHeaders(ApiUtils.getJsonContentHeaders(config.getToken())) + .defaultHeaders((headers) -> headers.setContentType(MediaType.APPLICATION_JSON)) .build(); } - // TODO @芋艿:方法名,要考虑下; - public SunoResp musicGen(SunoReq sunReq) { + public List generate(SunoApi.SunoReq sunReq) { return this.webClient.post() - .uri("/audios") - .body(Mono.just(sunReq), SunoReq.class) + .uri("/api/generate") + .body(Mono.just(sunReq), SunoApi.SunoReq.class) .retrieve() - .onStatus(status -> !status.is2xxSuccessful(), - response -> response.bodyToMono(String.class) - .handle((respBody, sink) -> { - log.error("【Suno】调用失败!resp: 【{}】", respBody); - sink.error(new IllegalStateException("【Suno】调用失败!")); - })) - .bodyToMono(SunoResp.class) + .onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION) + .bodyToMono(new ParameterizedTypeReference>() { + }) .block(); } + public List doChatCompletion(String prompt) { + return this.webClient.post() + .uri("/v1/chat/completions") + .body(Mono.just(new SunoReq(prompt)), SunoApi.SunoReq.class) + .retrieve() + .onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION) + .bodyToMono(new ParameterizedTypeReference>() { + }) + .block(); + } + + public LyricsData generateLyrics(String prompt) { + return this.webClient.post() + .uri("/api/generate_lyrics") + .body(Mono.just(new SunoReq(prompt)), SunoApi.SunoReq.class) + .retrieve() + .onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION) + .bodyToMono(LyricsData.class) + .block(); + } + + + public List selectById(String ids) { + return this.webClient.get() + .uri(uriBuilder -> uriBuilder + .path("/api/get") + .queryParam("ids", ids) + .build()) + .retrieve() + .onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION) + .bodyToMono(new ParameterizedTypeReference>() { + }) + .block(); + } + + + public LimitData selectLimit() { + return this.webClient.get() + .uri("/api/get_limit") + .retrieve() + .onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION) + .bodyToMono(LimitData.class) + .block(); + } + + /** - * 请求数据对象,用于生成音乐音频。 + * 根据提示生成音频 * - * @param prompt 用于生成音乐音频的提示 - * @param lyric 用于生成音乐音频的歌词 - * @param custom 指示音乐音频是否为定制,如果为 true,则从歌词生成,否则从提示生成 - * @param title 音乐音频的标题 - * @param style 音乐音频的风格 - * @param callbackUrl 音乐音频生成后回调的 URL + * @param prompt 用于生成音乐音频的提示 + * @param tags 自定义模式才需要 + * @param title 自定义模式才需要 + * @param waitAudio false表示后台模式,仅返回音频任务信息,需要调用get API获取详细的音频信息。 + * true表示同步模式,API最多等待100s,音频生成完毕后直接返回音频链接等信息,建议在GPT等agent中使用。 + * @param makeInstrumental 指示音乐音频是否为定制,如果为 true,则从歌词生成,否则从提示生成 */ @JsonInclude(value = JsonInclude.Include.NON_NULL) public record SunoReq( String prompt, - String lyric, - boolean custom, + String tags, String title, - String style, - String callbackUrl + @JsonProperty("wait_audio") boolean waitAudio, + @JsonProperty("make_instrumental") boolean makeInstrumental ) { public SunoReq(String prompt) { - this(prompt, null, false, null, null, null); + this(prompt, null, null, false, false); } + public SunoReq(String prompt, String tags, String title) { + this(prompt, tags, title, false, false); + } } + /** - * SunoAPI 响应的数据。 + * SunoAPI 响应的音频数据。 * - * @param success 表示请求是否成功 - * @param taskId 任务 ID - * @param data 音乐数据列表 + * @param id 音乐数据的 ID + * @param title 音乐音频的标题 + * @param imageUrl 音乐音频的图片 URL + * @param lyric 音乐音频的歌词 + * @param audioUrl 音乐音频的 URL + * @param videoUrl 音乐视频的 URL + * @param createdAt 音乐音频的创建时间 + * @param modelName + * @param status + * @param gptDescriptionPrompt + * @param prompt 生成音乐音频的提示 + * @param type + * @param tags */ - public record SunoResp( - boolean success, - @JsonProperty("task_id") String taskId, - List data + public record MusicData( + String id, + String title, + @JsonProperty("image_url") String imageUrl, + String lyric, + @JsonProperty("audio_url") String audioUrl, + @JsonProperty("video_url") String videoUrl, + @JsonProperty("created_at") String createdAt, + @JsonProperty("model_name") String modelName, + String status, + @JsonProperty("gpt_description_prompt") String gptDescriptionPrompt, + String prompt, + String type, + String tags ) { - /** - * 单个音乐数据。 - * - * @param id 音乐数据的 ID - * @param title 音乐音频的标题 - * @param imageUrl 音乐音频的图片 URL - * @param lyric 音乐音频的歌词 - * @param audioUrl 音乐音频的 URL - * @param videoUrl 音乐视频的 URL - * @param createdAt 音乐音频的创建时间 - * @param model 使用的模型名称 - * @param prompt 生成音乐音频的提示 - * @param style 音乐音频的风格 - */ - public record MusicData( - String id, - String title, - @JsonProperty("image_url") String imageUrl, - String lyric, - @JsonProperty("audio_url") String audioUrl, - @JsonProperty("video_url") String videoUrl, - @JsonProperty("created_at") String createdAt, - String model, - String prompt, - String style - ) { - } } + + + /** + * SunoAPI 响应的歌词数据。 + * + * @param text 歌词 + * @param title 标题 + * @param status 状态 + */ + public record LyricsData( + String text, + String title, + String status + ) { + } + + + /** + * SunoAPI 响应的限额数据,目前每日免费50 + */ + public record LimitData( + @JsonProperty("credits_left") Long creditsLeft, + String period, + @JsonProperty("monthly_limit") Long monthlyLimit, + @JsonProperty("monthly_usage") Long monthlyUsage + ) { + } + + } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java index 36fc40b17..39ac1ea9b 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/suno/SunoTests.java @@ -5,6 +5,8 @@ import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; import org.junit.Before; import org.junit.Test; +import java.util.List; + /** * @Author xiaoxin * @Date 2024/5/27 @@ -20,12 +22,43 @@ public class SunoTests { } @Test - public void generateMusic() { - SunoApi sunoApi = new SunoApi(sunoConfig); - SunoApi.SunoReq sunoReq = new SunoApi.SunoReq("创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。"); + public void selectById() { + SunoApi sunoApi = new SunoApi(); + System.out.println(sunoApi.selectById("d460ddda-7c87-4f34-b751-419b08a590ca,ff90ea66-49cd-4fd2-b44c-44267dfd5551")); - SunoApi.SunoResp sunoResp = sunoApi.musicGen(sunoReq); - System.out.println(sunoResp); } + @Test + public void generate() { + SunoApi sunoApi = new SunoApi(); + List generate = sunoApi.generate(new SunoApi.SunoReq("创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。")); + System.out.println(generate); + } + + + @Test + public void doChatCompletion() { + SunoApi sunoApi = new SunoApi(); + List generate = sunoApi.doChatCompletion("创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。"); + System.out.println(generate); + } + + + @Test + public void generateLyrics() { + SunoApi sunoApi = new SunoApi(); + SunoApi.LyricsData lyricsData = sunoApi.generateLyrics("A soothing lullaby"); + System.out.println(lyricsData); + } + + + + @Test + public void selectLimit() { + SunoApi sunoApi = new SunoApi(); + SunoApi.LimitData limitData = sunoApi.selectLimit(); + System.out.println(limitData); + } + + } From dbe23cfe8ea14090daabf4edd3fd0d4d8faecf61 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 4 Jun 2024 14:50:27 +0800 Subject: [PATCH 393/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E8=B0=83=E8=AF=95=20mj=20proxy=20=E9=80=9A=E7=9F=A5=E5=9B=9E?= =?UTF-8?q?=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/client/MidjourneyProxyClient.java | 12 +++++++++++- .../module/ai/client/vo/MidjourneyNotifyReqVO.java | 2 +- .../ai/controller/admin/image/AiImageController.java | 7 ++++--- .../module/ai/service/image/AiImageServiceImpl.java | 1 - .../src/main/resources/application-local.yaml | 7 +++++++ 5 files changed, 23 insertions(+), 6 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/MidjourneyProxyClient.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/MidjourneyProxyClient.java index efba5234b..b68310700 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/MidjourneyProxyClient.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/MidjourneyProxyClient.java @@ -1,10 +1,12 @@ package cn.iocoder.yudao.module.ai.client; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.module.ai.client.vo.MidjourneyImagineReqVO; import cn.iocoder.yudao.module.ai.client.vo.MidjourneySubmitRespVO; import jakarta.validation.constraints.NotNull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.*; import org.springframework.stereotype.Component; import org.springframework.validation.annotation.Validated; import org.springframework.web.client.RestTemplate; @@ -35,7 +37,15 @@ public class MidjourneyProxyClient { * @return */ public MidjourneySubmitRespVO imagine(@Validated @NotNull MidjourneyImagineReqVO imagineReqVO) { - return restTemplate.postForObject(url.concat(URI_IMAGINE), imagineReqVO, MidjourneySubmitRespVO.class); + // 创建 HttpHeaders 对象 + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.set("Authorization", "Bearer sk-c3qxUCVKsPfdQiYU8440E3Fc8dE5424d9cB124A4Ee2489E3"); + // 创建 HttpEntity 对象,将 HttpHeaders 和请求体传递给它 + HttpEntity requestEntity = new HttpEntity<>(JsonUtils.toJsonString(imagineReqVO), headers); + // 发送 post 请求 + ResponseEntity response = restTemplate.exchange(url.concat(URI_IMAGINE), HttpMethod.POST, requestEntity, String.class); + return JsonUtils.parseObject(response.getBody(), MidjourneySubmitRespVO.class); } } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyReqVO.java index 3cc92c719..4398a8272 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyReqVO.java @@ -19,7 +19,7 @@ public class MidjourneyNotifyReqVO { @Schema(description = "任务类型") private MidjourneyTaskActionEnum action; @Schema(description = "任务状态") - private MidjourneyTaskStatusEnum status = MidjourneyTaskStatusEnum.NOT_START; + private MidjourneyTaskStatusEnum status; @Schema(description = "提示词") private String prompt; diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index 0f2116a0f..32e2e73fa 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -15,6 +15,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; +import jakarta.annotation.security.PermitAll; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -70,10 +71,10 @@ public class AiImageController { return success(imageService.midjourneyImagine(getLoginUserId(), req)); } - // TODO @芋艿:不拦截 @Operation(summary = "midjourney proxy - 回调通知") - @RequestMapping("/midjourney-notify") - public CommonResult midjourneyNotify(MidjourneyNotifyReqVO notifyReqVO) { + @PostMapping("/midjourney-notify") + @PermitAll + public CommonResult midjourneyNotify( @RequestBody MidjourneyNotifyReqVO notifyReqVO) { return success(imageService.midjourneyNotify(getLoginUserId(), notifyReqVO)); } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index ea52dd42b..208427bc0 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -212,7 +212,6 @@ public class AiImageServiceImpl implements AiImageService { .setId(image.getId()) .setStatus(imageStatus) .setPicUrl(filePath) -// .setOriginalPicUrl(notifyReqVO.getImageUrl()) TODO @fan:就不存原始的图片地址啦 ); return true; } diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 99c888f31..d4b7530d6 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -76,6 +76,13 @@ server: enabled: true charset: UTF-8 force: true +# ai +ai: + midjourney-proxy: + url: https://api.holdai.top/mj + notifyUrl: http://7b1aada4.r26.cpolar.top/admin-api/ai/image/midjourney-notify + + --- #################### 定时任务相关配置 #################### # Quartz 配置项,对应 QuartzProperties 配置类 From 95d26c9b8d63042af84fc84a661f6df48b03cd18 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 4 Jun 2024 17:38:36 +0800 Subject: [PATCH 394/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E8=B0=83=E6=95=B4=20=20Midjourney=20proxy=20=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E7=8A=B6=E6=80=81=20enum?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/ai/client/enums/MidjourneySubmitCodeEnum.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/enums/MidjourneySubmitCodeEnum.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/enums/MidjourneySubmitCodeEnum.java index 3f432ce36..1158d1f7b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/enums/MidjourneySubmitCodeEnum.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/enums/MidjourneySubmitCodeEnum.java @@ -20,7 +20,7 @@ public enum MidjourneySubmitCodeEnum { // 状态码: 1(提交成功), 21(已存在), 22(排队中), other(错误) SUBMIT_SUCCESS("1", "提交成功"), - ALREADY_EXISTS("1", "已存在"), + ALREADY_EXISTS("21", "已存在"), QUEUING("22", "排队中"), ; From cea888b225021e5be845ee8af21cb6d672dc8f5c Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 4 Jun 2024 17:39:02 +0800 Subject: [PATCH 395/684] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91Mid?= =?UTF-8?q?journeyNotifyReqVO=20action=20=E5=92=8C=20status=20=E6=8E=A5?= =?UTF-8?q?=E5=8F=97=20=E6=94=B9=E4=B8=BA=20string?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/client/vo/MidjourneyNotifyReqVO.java | 38 ++++++++++++++++--- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyReqVO.java index 4398a8272..2f8c280f3 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/client/vo/MidjourneyNotifyReqVO.java @@ -1,11 +1,16 @@ package cn.iocoder.yudao.module.ai.client.vo; -import cn.iocoder.yudao.module.ai.client.enums.MidjourneyTaskActionEnum; -import cn.iocoder.yudao.module.ai.client.enums.MidjourneyTaskStatusEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.util.List; + /** + * Midjourney Proxy 通知回调 + * + * - Midjourney Proxy:通知回调 bean 是 com.github.novicezk.midjourney.support.Task + * - 毫秒 api 通知回调文档地址:https://gpt-best.apifox.cn/doc-3530863 + * * @author fansili * @time 2024/5/31 10:37 * @since 1.0 @@ -16,10 +21,10 @@ public class MidjourneyNotifyReqVO { @Schema(description = "job id") private String id; - @Schema(description = "任务类型") - private MidjourneyTaskActionEnum action; - @Schema(description = "任务状态") - private MidjourneyTaskStatusEnum status; + @Schema(description = "任务类型 MidjourneyTaskActionEnum") + private String action; + @Schema(description = "任务状态 MidjourneyTaskStatusEnum") + private String status; @Schema(description = "提示词") private String prompt; @@ -46,4 +51,25 @@ public class MidjourneyNotifyReqVO { @Schema(description = "失败原因") private String failReason; + @Schema(description = "任务完成后的可执行按钮") + private List