From 8954f59cd7b846c2a4c57f1e1d796b305f2da56f Mon Sep 17 00:00:00 2001 From: zengxb <648669796@qq.com> Date: Thu, 26 Feb 2026 14:36:33 +0800 Subject: [PATCH] =?UTF-8?q?context:=E5=B7=A5=E4=BD=9C=E6=B5=81=E5=92=8CAi?= =?UTF-8?q?=20Chat=E5=AF=B9=E8=AF=9D=E6=B6=88=E6=81=AF=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E6=95=B4=E5=90=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/script/sql/ruoyi-ai-v3_mysql8.sql | 14 ++ docs/script/sql/workFlow-v3.0.sql | 10 -- ruoyi-common/ruoyi-common-chat/pom.xml | 6 + .../common/chat}/base/ThreadContext.java | 8 +- .../chat}/domain/bo/chat/ChatMessageBo.java | 13 +- .../chat/domain/bo/chat/ChatModelBo.java | 2 +- .../chat/domain/dto/request/ChatRequest.java | 20 +++ .../chat/domain/dto/request/ReSumeRunner.java | 19 +++ .../domain/dto/request/WorkFlowRunner.java | 15 ++ .../chat}/domain/vo/chat/ChatMessageVo.java | 9 +- .../chat/domain/vo/chat/ChatModelVo.java | 2 +- .../ruoyi/common/chat}/entity/BaseEntity.java | 2 +- .../org/ruoyi/common/chat}/entity/User.java | 4 +- .../{domain => }/entity/chat/ChatContext.java | 2 +- .../common/chat}/entity/chat/ChatMessage.java | 7 +- .../{domain => }/entity/chat/ChatModel.java | 2 +- .../entity/image/ImageContext.java | 2 +- .../ruoyi/common/chat}/enums/BaseEnum.java | 2 +- .../ruoyi/common/chat}/enums/ErrorEnum.java | 2 +- .../ruoyi/common/chat}/enums/RoleType.java | 3 +- .../common/chat}/enums/UserStatusEnum.java | 2 +- .../chat/factory/ChatServiceFactory.java | 2 +- .../chat/factory/ImageServiceFactory.java | 2 +- .../chat}/IChatModelService.java | 2 +- .../chat}/IChatService.java | 4 +- .../AbstractChatMessageService.java | 59 ++++++++ .../chatMessage}/IChatMessageService.java | 6 +- .../image}/IImageGenerationService.java | 4 +- .../workFlow/IWorkFlowStarterService.java | 33 +++++ .../common/sse/core/SseEmitterManager.java | 2 +- ruoyi-modules/ruoyi-aiflow/pom.xml | 6 - .../org/ruoyi/workflow/base/BaseResponse.java | 2 +- .../controller/WorkflowController.java | 4 +- .../controller/WorkflowRuntimeController.java | 2 +- .../dto/workflow/WorkflowResumeReq.java | 2 + .../workflow/dto/workflow/WorkflowRunReq.java | 1 + .../org/ruoyi/workflow/entity/Workflow.java | 1 + .../workflow/entity/WorkflowComponent.java | 1 + .../ruoyi/workflow/entity/WorkflowEdge.java | 1 + .../ruoyi/workflow/entity/WorkflowNode.java | 1 + .../workflow/entity/WorkflowRuntime.java | 1 + .../workflow/entity/WorkflowRuntimeNode.java | 1 + .../ruoyi/workflow/enums/AiModelStatus.java | 1 + .../workflow/enums/WfIODataTypeEnum.java | 1 + .../workflow/helper/SSEEmitterHelper.java | 2 +- .../service/WorkflowComponentService.java | 4 +- .../workflow/service/WorkflowEdgeService.java | 2 +- .../workflow/service/WorkflowNodeService.java | 2 +- .../service/WorkflowRuntimeNodeService.java | 4 +- .../service/WorkflowRuntimeService.java | 6 +- .../workflow/service/WorkflowService.java | 6 +- .../ruoyi/workflow/util/PrivilegeUtil.java | 4 +- .../workflow/util/WorkflowMessageUtil.java | 37 +++++ .../workflow/workflow/WfNodeIODataUtil.java | 2 +- .../org/ruoyi/workflow/workflow/WfState.java | 6 +- .../workflow/workflow/WorkflowEngine.java | 21 ++- .../workflow/WorkflowGraphBuilder.java | 2 +- .../workflow/workflow/WorkflowStarter.java | 27 ++-- .../ruoyi/workflow/workflow/WorkflowUtil.java | 66 +++++---- .../workflow/node/AbstractWfNode.java | 30 +++- .../node/httpRequest/HttpRequestNode.java | 10 ++ .../node/humanFeedBack/HumanFeedbackNode.java | 1 + .../workflow/node/image/ImageNode.java | 5 + .../workflow/node/mailSend/MailSendNode.java | 138 ++++++++++++------ .../workflow/node/start/StartNode.java | 4 +- .../chat/ChatMessageController.java | 6 +- .../controller/chat/ChatModelController.java | 2 +- .../ruoyi/factory/EmbeddingModelFactory.java | 2 +- .../ruoyi/mapper/chat/ChatMessageMapper.java | 4 +- .../ruoyi/mapper/chat/ChatModelMapper.java | 2 +- .../impl/AbstractStreamingChatService.java | 91 ++++++------ .../chat/impl/ChatMessageServiceImpl.java | 8 +- .../chat/impl/ChatModelServiceImpl.java | 4 +- .../service/chat/impl/ChatServiceFacade.java | 7 +- .../impl/memory/ChatMemoryUsageExample.java | 2 +- .../memory/PersistentChatMemoryStore.java | 2 +- .../impl/GraphExtractionServiceImpl.java | 2 +- .../image/AbstractImageGenerationService.java | 4 +- .../impl/KnowledgeAttachServiceImpl.java | 2 +- 79 files changed, 548 insertions(+), 254 deletions(-) delete mode 100644 docs/script/sql/workFlow-v3.0.sql rename {ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow => ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat}/base/ThreadContext.java (94%) rename {ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi => ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat}/domain/bo/chat/ChatMessageBo.java (90%) create mode 100644 ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/dto/request/ReSumeRunner.java create mode 100644 ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/dto/request/WorkFlowRunner.java rename {ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi => ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat}/domain/vo/chat/ChatMessageVo.java (94%) rename {ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow => ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat}/entity/BaseEntity.java (95%) rename {ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow => ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat}/entity/User.java (95%) rename ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/{domain => }/entity/chat/ChatContext.java (96%) rename {ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain => ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat}/entity/chat/ChatMessage.java (87%) rename ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/{domain => }/entity/chat/ChatModel.java (96%) rename ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/{domain => }/entity/image/ImageContext.java (94%) rename {ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow => ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat}/enums/BaseEnum.java (84%) rename {ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow => ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat}/enums/ErrorEnum.java (99%) rename {ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi => ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat}/enums/RoleType.java (84%) rename {ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow => ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat}/enums/UserStatusEnum.java (93%) rename ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/{Service => service/chat}/IChatModelService.java (97%) rename ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/{Service => service/chat}/IChatService.java (79%) create mode 100644 ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/service/chatMessage/AbstractChatMessageService.java rename {ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat => ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/service/chatMessage}/IChatMessageService.java (92%) rename ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/{Service => service/image}/IImageGenerationService.java (74%) create mode 100644 ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/service/workFlow/IWorkFlowStarterService.java create mode 100644 ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/util/WorkflowMessageUtil.java diff --git a/docs/script/sql/ruoyi-ai-v3_mysql8.sql b/docs/script/sql/ruoyi-ai-v3_mysql8.sql index e7aec981..6d85a2ef 100644 --- a/docs/script/sql/ruoyi-ai-v3_mysql8.sql +++ b/docs/script/sql/ruoyi-ai-v3_mysql8.sql @@ -3647,3 +3647,17 @@ INSERT INTO `test_tree` VALUES (12, '000000', 10, 108, 3, '子节点88', 0, 103, INSERT INTO `test_tree` VALUES (13, '000000', 10, 108, 3, '子节点99', 0, 103, '2026-02-03 05:14:54', 1, NULL, NULL, 0); SET FOREIGN_KEY_CHECKS = 1; + +INSERT INTO `t_workflow_component` (`id`, `uuid`, `name`, `title`, `remark`, `display_order`, `is_enable`, `create_time`, `update_time`, `is_deleted`, `tenant_id`) VALUES (17, '5cd68dccbbb411f0bb7840c2ba9a7fbc', 'Start', '开始', '流程由此开始', 0, 1, '2025-11-07 16:32:49', '2025-11-07 16:32:49', 0, '000000'); +INSERT INTO `t_workflow_component` (`id`, `uuid`, `name`, `title`, `remark`, `display_order`, `is_enable`, `create_time`, `update_time`, `is_deleted`, `tenant_id`) VALUES (18, '5cd6ac69bbb411f0bb7840c2ba9a7fbc', 'End', '结束', '流程由此结束', 0, 1, '2025-11-07 16:32:49', '2025-11-07 16:32:49', 0, '000000'); +INSERT INTO `t_workflow_component` (`id`, `uuid`, `name`, `title`, `remark`, `display_order`, `is_enable`, `create_time`, `update_time`, `is_deleted`, `tenant_id`) VALUES (19, '5cd6c8eabbb411f0bb7840c2ba9a7fbc', 'Answer', '生成回答', '调用大语言模型回答问题', 0, 1, '2025-11-07 16:32:49', '2025-11-07 16:32:49', 0, '000000'); +INSERT INTO `t_workflow_component` (`id`, `uuid`, `name`, `title`, `remark`, `display_order`, `is_enable`, `create_time`, `update_time`, `is_deleted`, `tenant_id`) VALUES (20, '0b4369bb60dc46d6bd84ceb4e36184dc', 'KeywordExtractor', '关键词提取', '从文本中提取关键词', 0, 1, '2025-12-26 16:30:05', '2025-12-26 16:30:05', 0, '000000'); +INSERT INTO `t_workflow_component` (`id`, `uuid`, `name`, `title`, `remark`, `display_order`, `is_enable`, `create_time`, `update_time`, `is_deleted`, `tenant_id`) VALUES (21, 'bb00fc2f52c74fec82ee3f99725b56bb', 'Switcher', '条件分支', '根据条件执行不同分支', 0, 1, '2025-12-26 16:30:46', '2025-12-26 16:30:46', 0, '000000'); +INSERT INTO `t_workflow_component` (`id`, `uuid`, `name`, `title`, `remark`, `display_order`, `is_enable`, `create_time`, `update_time`, `is_deleted`, `tenant_id`) VALUES (22, 'f37dbcb8f0d5464d90fbb22774490a56', 'HumanFeedback', '人类', '人机沟通', 0, 1, '2025-12-30 17:37:14', '2025-12-30 17:37:14', 0, '000000'); +INSERT INTO `t_workflow_component` (`id`, `uuid`, `name`, `title`, `remark`, `display_order`, `is_enable`, `create_time`, `update_time`, `is_deleted`, `tenant_id`) VALUES (23, 'af9d6d7b9c9b47f990ad25ec84912b73', 'Tongyiwanx', '阿里图像生成', '使用通义万相生成图像', 0, 1, '2025-12-26 16:32:25', '2025-12-26 16:32:25', 0, '000000'); +INSERT INTO `t_workflow_component` (`id`, `uuid`, `name`, `title`, `remark`, `display_order`, `is_enable`, `create_time`, `update_time`, `is_deleted`, `tenant_id`) VALUES (24, 'a1e2c9d4b8f04e1a9c3d6f8e2a7b1c9d', 'MailSend', '发送邮箱', '发送邮箱', 0, 1, '2025-12-30 17:37:14', '2025-12-30 17:37:14', 0, '000000'); +INSERT INTO `t_workflow_component` (`id`, `uuid`, `name`, `title`, `remark`, `display_order`, `is_enable`, `create_time`, `update_time`, `is_deleted`, `tenant_id`) VALUES (25, 'f1e2d3c4b5a67890f1e2d3c4b5a6f1e2', 'HttpRequest', '请求节点', '请求节点', 0, 1, '2025-12-30 17:37:14', '2025-12-30 17:37:14', 0, '000000'); +INSERT INTO `chat_model` (`id`, `category`, `model_name`, `provider_code`, `model_describe`, `model_price`, `model_type`, `model_show`, `model_free`, `priority`, `api_host`, `api_key`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`, `tenant_id`) VALUES (2022565766560468994, 'Tongyiwanx', 'wan2.5-t2i-preview', 'Tongyiwanx', 'wan2.5-t2i-preview', 1, '1', 'Y', 'Y', 1, 'https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation', 'skxxxx', 103, 1, '2026-02-14 14:57:11', 1, '2026-02-14 14:57:11', '通义万相文生图', 0); +INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query_param`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2021046920636690433, '流程管理', 0, 0, 'flow', '', NULL, 1, 0, 'M', '0', '0', NULL, 'ph:user-fill', 103, 1, '2026-02-10 10:21:50', 1, '2026-02-10 15:59:28', ''); +INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query_param`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2021047050391678978, '工作流编排', 2021046920636690433, 0, 'aiflowengine', 'aiflow/index', NULL, 1, 0, 'C', '0', '0', '', 'ph:user-fill', 103, 1, '2026-02-10 10:22:21', 1, '2026-02-10 16:04:41', ''); + diff --git a/docs/script/sql/workFlow-v3.0.sql b/docs/script/sql/workFlow-v3.0.sql deleted file mode 100644 index f7573338..00000000 --- a/docs/script/sql/workFlow-v3.0.sql +++ /dev/null @@ -1,10 +0,0 @@ -INSERT INTO `ruoyi-ai-v3`.`t_workflow_component` (`id`, `uuid`, `name`, `title`, `remark`, `display_order`, `is_enable`, `create_time`, `update_time`, `is_deleted`, `tenant_id`) VALUES (17, '5cd68dccbbb411f0bb7840c2ba9a7fbc', 'Start', '开始', '流程由此开始', 0, 1, '2025-11-07 16:32:49', '2025-11-07 16:32:49', 0, '000000'); -INSERT INTO `ruoyi-ai-v3`.`t_workflow_component` (`id`, `uuid`, `name`, `title`, `remark`, `display_order`, `is_enable`, `create_time`, `update_time`, `is_deleted`, `tenant_id`) VALUES (18, '5cd6ac69bbb411f0bb7840c2ba9a7fbc', 'End', '结束', '流程由此结束', 0, 1, '2025-11-07 16:32:49', '2025-11-07 16:32:49', 0, '000000'); -INSERT INTO `ruoyi-ai-v3`.`t_workflow_component` (`id`, `uuid`, `name`, `title`, `remark`, `display_order`, `is_enable`, `create_time`, `update_time`, `is_deleted`, `tenant_id`) VALUES (19, '5cd6c8eabbb411f0bb7840c2ba9a7fbc', 'Answer', '生成回答', '调用大语言模型回答问题', 0, 1, '2025-11-07 16:32:49', '2025-11-07 16:32:49', 0, '000000'); -INSERT INTO `ruoyi-ai-v3`.`t_workflow_component` (`id`, `uuid`, `name`, `title`, `remark`, `display_order`, `is_enable`, `create_time`, `update_time`, `is_deleted`, `tenant_id`) VALUES (20, '0b4369bb60dc46d6bd84ceb4e36184dc', 'KeywordExtractor', '关键词提取', '从文本中提取关键词', 0, 1, '2025-12-26 16:30:05', '2025-12-26 16:30:05', 0, '000000'); -INSERT INTO `ruoyi-ai-v3`.`t_workflow_component` (`id`, `uuid`, `name`, `title`, `remark`, `display_order`, `is_enable`, `create_time`, `update_time`, `is_deleted`, `tenant_id`) VALUES (21, 'bb00fc2f52c74fec82ee3f99725b56bb', 'Switcher', '条件分支', '根据条件执行不同分支', 0, 1, '2025-12-26 16:30:46', '2025-12-26 16:30:46', 0, '000000'); -INSERT INTO `ruoyi-ai-v3`.`t_workflow_component` (`id`, `uuid`, `name`, `title`, `remark`, `display_order`, `is_enable`, `create_time`, `update_time`, `is_deleted`, `tenant_id`) VALUES (22, 'f37dbcb8f0d5464d90fbb22774490a56', 'HumanFeedback', '人类', '人机沟通', 0, 1, '2025-12-30 17:37:14', '2025-12-30 17:37:14', 0, '000000'); -INSERT INTO `ruoyi-ai-v3`.`t_workflow_component` (`id`, `uuid`, `name`, `title`, `remark`, `display_order`, `is_enable`, `create_time`, `update_time`, `is_deleted`, `tenant_id`) VALUES (23, 'af9d6d7b9c9b47f990ad25ec84912b73', 'Tongyiwanx', '阿里图像生成', '使用通义万相生成图像', 0, 1, '2025-12-26 16:32:25', '2025-12-26 16:32:25', 0, '000000'); -INSERT INTO `ruoyi-ai-v3`.`t_workflow_component` (`id`, `uuid`, `name`, `title`, `remark`, `display_order`, `is_enable`, `create_time`, `update_time`, `is_deleted`, `tenant_id`) VALUES (24, 'a1e2c9d4b8f04e1a9c3d6f8e2a7b1c9d', 'MailSend', '发送邮箱', '发送邮箱', 0, 1, '2025-12-30 17:37:14', '2025-12-30 17:37:14', 0, '000000'); -INSERT INTO `ruoyi-ai-v3`.`t_workflow_component` (`id`, `uuid`, `name`, `title`, `remark`, `display_order`, `is_enable`, `create_time`, `update_time`, `is_deleted`, `tenant_id`) VALUES (25, 'f1e2d3c4b5a67890f1e2d3c4b5a6f1e2', 'HttpRequest', '请求节点', '请求节点', 0, 1, '2025-12-30 17:37:14', '2025-12-30 17:37:14', 0, '000000'); -INSERT INTO `ruoyi-ai-v3`.`chat_model` (`id`, `category`, `model_name`, `provider_code`, `model_describe`, `model_price`, `model_type`, `model_show`, `model_free`, `priority`, `api_host`, `api_key`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`, `tenant_id`) VALUES (2022565766560468994, 'Tongyiwanx', 'wan2.5-t2i-preview', 'Tongyiwanx', 'wan2.5-t2i-preview', 1, '1', 'Y', 'Y', 1, 'https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation', 'Bearer sk-f4550b0e138c488cbfcafe3d61f800a5', 103, 1, '2026-02-14 14:57:11', 1, '2026-02-14 14:57:11', '通义万相文生图', 0); diff --git a/ruoyi-common/ruoyi-common-chat/pom.xml b/ruoyi-common/ruoyi-common-chat/pom.xml index 0db3c41c..06e38185 100644 --- a/ruoyi-common/ruoyi-common-chat/pom.xml +++ b/ruoyi-common/ruoyi-common-chat/pom.xml @@ -62,6 +62,12 @@ org.ruoyi ruoyi-common-tenant + + + io.swagger.core.v3 + swagger-annotations + ${swagger-annotations.version} + diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/base/ThreadContext.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/base/ThreadContext.java similarity index 94% rename from ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/base/ThreadContext.java rename to ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/base/ThreadContext.java index d74eb104..7605307d 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/base/ThreadContext.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/base/ThreadContext.java @@ -1,14 +1,14 @@ -package org.ruoyi.workflow.base; +package org.ruoyi.common.chat.base; import cn.dev33.satoken.stp.StpUtil; import org.apache.commons.lang3.StringUtils; +import org.ruoyi.common.chat.entity.User; +import org.ruoyi.common.chat.enums.UserStatusEnum; import org.ruoyi.common.core.domain.model.LoginUser; import org.ruoyi.common.core.exception.base.BaseException; import org.ruoyi.common.satoken.utils.LoginHelper; -import org.ruoyi.workflow.entity.User; -import org.ruoyi.workflow.enums.UserStatusEnum; -import static org.ruoyi.workflow.enums.ErrorEnum.A_USER_NOT_FOUND; +import static org.ruoyi.common.chat.enums.ErrorEnum.A_USER_NOT_FOUND; /** * 线程上下文适配器,统一接入 Sa-Token 登录态。 diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/bo/chat/ChatMessageBo.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/bo/chat/ChatMessageBo.java similarity index 90% rename from ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/bo/chat/ChatMessageBo.java rename to ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/bo/chat/ChatMessageBo.java index 9d44fcaa..2cbb051b 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/bo/chat/ChatMessageBo.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/bo/chat/ChatMessageBo.java @@ -1,13 +1,14 @@ -package org.ruoyi.domain.bo.chat; +package org.ruoyi.common.chat.domain.bo.chat; -import org.ruoyi.common.core.validate.AddGroup; -import org.ruoyi.common.core.validate.EditGroup; -import org.ruoyi.domain.entity.chat.ChatMessage; -import org.ruoyi.common.mybatis.core.domain.BaseEntity; import io.github.linpeilie.annotations.AutoMapper; +import jakarta.validation.constraints.NotNull; import lombok.Data; import lombok.EqualsAndHashCode; -import jakarta.validation.constraints.*; +import org.ruoyi.common.chat.entity.chat.ChatMessage; +import org.ruoyi.common.core.validate.AddGroup; +import org.ruoyi.common.core.validate.EditGroup; +import org.ruoyi.common.mybatis.core.domain.BaseEntity; + /** * 聊天消息业务对象 chat_message diff --git a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/bo/chat/ChatModelBo.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/bo/chat/ChatModelBo.java index 8807503c..4d97dd05 100644 --- a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/bo/chat/ChatModelBo.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/bo/chat/ChatModelBo.java @@ -4,7 +4,7 @@ import io.github.linpeilie.annotations.AutoMapper; import jakarta.validation.constraints.NotNull; import lombok.Data; import lombok.EqualsAndHashCode; -import org.ruoyi.common.chat.domain.entity.chat.ChatModel; +import org.ruoyi.common.chat.entity.chat.ChatModel; import org.ruoyi.common.core.validate.EditGroup; import org.ruoyi.common.mybatis.core.domain.BaseEntity; diff --git a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/dto/request/ChatRequest.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/dto/request/ChatRequest.java index 1b36ae42..8d13339e 100644 --- a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/dto/request/ChatRequest.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/dto/request/ChatRequest.java @@ -21,6 +21,21 @@ public class ChatRequest { @NotEmpty(message = "传入的模型不能为空") private String model; + /** + * 工作流请求体 + */ + private WorkFlowRunner workFlowRunner; + + /** + * 人机交互信息体 + */ + private ReSumeRunner reSumeRunner; + + /** + * 是否启用工作流 + */ + private Boolean enableWorkFlow; + /** * 会话id */ @@ -41,6 +56,11 @@ public class ChatRequest { */ private Long uuid; + /** + * 是否为人机交互用户继续输入 + */ + private Boolean isResume; + /** * 是否启用深度思考 */ diff --git a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/dto/request/ReSumeRunner.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/dto/request/ReSumeRunner.java new file mode 100644 index 00000000..65b39fd0 --- /dev/null +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/dto/request/ReSumeRunner.java @@ -0,0 +1,19 @@ +package org.ruoyi.common.chat.domain.dto.request; + +import lombok.Data; + +/** + * 人机交互输入信息 + */ +@Data +public class ReSumeRunner { + /** + * 运行节点UUID + */ + private String runtimeUuid; + + /** + * 人机交互用户输入信息 + */ + private String feedbackContent; +} diff --git a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/dto/request/WorkFlowRunner.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/dto/request/WorkFlowRunner.java new file mode 100644 index 00000000..fff727ec --- /dev/null +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/dto/request/WorkFlowRunner.java @@ -0,0 +1,15 @@ +package org.ruoyi.common.chat.domain.dto.request; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import lombok.Data; + +import java.util.List; + +/** + * 工作流请求体信息 + */ +@Data +public class WorkFlowRunner { + private List inputs; + private String uuid; +} diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/vo/chat/ChatMessageVo.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/vo/chat/ChatMessageVo.java similarity index 94% rename from ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/vo/chat/ChatMessageVo.java rename to ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/vo/chat/ChatMessageVo.java index 7a548865..17f4d707 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/vo/chat/ChatMessageVo.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/vo/chat/ChatMessageVo.java @@ -1,18 +1,17 @@ -package org.ruoyi.domain.vo.chat; +package org.ruoyi.common.chat.domain.vo.chat; -import org.ruoyi.domain.entity.chat.ChatMessage; import cn.idev.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelProperty; -import org.ruoyi.common.excel.annotation.ExcelDictFormat; -import org.ruoyi.common.excel.convert.ExcelDictConvert; import io.github.linpeilie.annotations.AutoMapper; import lombok.Data; +import org.ruoyi.common.chat.entity.chat.ChatMessage; +import org.ruoyi.common.excel.annotation.ExcelDictFormat; +import org.ruoyi.common.excel.convert.ExcelDictConvert; import java.io.Serial; import java.io.Serializable; - /** * 聊天消息视图对象 chat_message * diff --git a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/vo/chat/ChatModelVo.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/vo/chat/ChatModelVo.java index 77ba3328..f79f9f23 100644 --- a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/vo/chat/ChatModelVo.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/vo/chat/ChatModelVo.java @@ -5,7 +5,7 @@ import cn.idev.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelProperty; import io.github.linpeilie.annotations.AutoMapper; import lombok.Data; -import org.ruoyi.common.chat.domain.entity.chat.ChatModel; +import org.ruoyi.common.chat.entity.chat.ChatModel; import java.io.Serial; import java.io.Serializable; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/BaseEntity.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/entity/BaseEntity.java similarity index 95% rename from ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/BaseEntity.java rename to ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/entity/BaseEntity.java index b657eb16..e9630ff2 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/BaseEntity.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/entity/BaseEntity.java @@ -1,4 +1,4 @@ -package org.ruoyi.workflow.entity; +package org.ruoyi.common.chat.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/User.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/entity/User.java similarity index 95% rename from ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/User.java rename to ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/entity/User.java index 20ac4dc0..dadedf9a 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/User.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/entity/User.java @@ -1,11 +1,11 @@ -package org.ruoyi.workflow.entity; +package org.ruoyi.common.chat.entity; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; -import org.ruoyi.workflow.enums.UserStatusEnum; +import org.ruoyi.common.chat.enums.UserStatusEnum; import java.time.LocalDateTime; diff --git a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/entity/chat/ChatContext.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/entity/chat/ChatContext.java similarity index 96% rename from ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/entity/chat/ChatContext.java rename to ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/entity/chat/ChatContext.java index 13a5b4b9..f90abd82 100644 --- a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/entity/chat/ChatContext.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/entity/chat/ChatContext.java @@ -1,4 +1,4 @@ -package org.ruoyi.common.chat.domain.entity.chat; +package org.ruoyi.common.chat.entity.chat; import dev.langchain4j.model.chat.response.StreamingChatResponseHandler; import jakarta.validation.constraints.NotNull; diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/chat/ChatMessage.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/entity/chat/ChatMessage.java similarity index 87% rename from ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/chat/ChatMessage.java rename to ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/entity/chat/ChatMessage.java index 905f74fb..c0055bd4 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/entity/chat/ChatMessage.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/entity/chat/ChatMessage.java @@ -1,9 +1,10 @@ -package org.ruoyi.domain.entity.chat; +package org.ruoyi.common.chat.entity.chat; -import org.ruoyi.common.tenant.core.TenantEntity; -import com.baomidou.mybatisplus.annotation.*; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.EqualsAndHashCode; +import org.ruoyi.common.tenant.core.TenantEntity; import java.io.Serial; diff --git a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/entity/chat/ChatModel.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/entity/chat/ChatModel.java similarity index 96% rename from ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/entity/chat/ChatModel.java rename to ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/entity/chat/ChatModel.java index 9edee32f..4fc63bfd 100644 --- a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/entity/chat/ChatModel.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/entity/chat/ChatModel.java @@ -1,4 +1,4 @@ -package org.ruoyi.common.chat.domain.entity.chat; +package org.ruoyi.common.chat.entity.chat; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; diff --git a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/entity/image/ImageContext.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/entity/image/ImageContext.java similarity index 94% rename from ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/entity/image/ImageContext.java rename to ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/entity/image/ImageContext.java index 4bf42c61..60be2739 100644 --- a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/entity/image/ImageContext.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/entity/image/ImageContext.java @@ -1,4 +1,4 @@ -package org.ruoyi.common.chat.domain.entity.image; +package org.ruoyi.common.chat.entity.image; import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/enums/BaseEnum.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/enums/BaseEnum.java similarity index 84% rename from ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/enums/BaseEnum.java rename to ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/enums/BaseEnum.java index 66a2fb63..902adf45 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/enums/BaseEnum.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/enums/BaseEnum.java @@ -1,4 +1,4 @@ -package org.ruoyi.workflow.enums; +package org.ruoyi.common.chat.enums; import com.baomidou.mybatisplus.annotation.IEnum; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/enums/ErrorEnum.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/enums/ErrorEnum.java similarity index 99% rename from ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/enums/ErrorEnum.java rename to ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/enums/ErrorEnum.java index f9de801e..06095cec 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/enums/ErrorEnum.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/enums/ErrorEnum.java @@ -1,4 +1,4 @@ -package org.ruoyi.workflow.enums; +package org.ruoyi.common.chat.enums; import lombok.Getter; diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/enums/RoleType.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/enums/RoleType.java similarity index 84% rename from ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/enums/RoleType.java rename to ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/enums/RoleType.java index cb550975..daaaaaa2 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/enums/RoleType.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/enums/RoleType.java @@ -1,4 +1,4 @@ -package org.ruoyi.enums; +package org.ruoyi.common.chat.enums; import lombok.AllArgsConstructor; import lombok.Getter; @@ -18,6 +18,7 @@ public enum RoleType { ASSISTANT("assistant"), FUNCTION("function"), TOOL("tool"), + WORKFLOW("workFlow") ; private final String name; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/enums/UserStatusEnum.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/enums/UserStatusEnum.java similarity index 93% rename from ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/enums/UserStatusEnum.java rename to ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/enums/UserStatusEnum.java index 2be9a950..2b2cca43 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/enums/UserStatusEnum.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/enums/UserStatusEnum.java @@ -1,4 +1,4 @@ -package org.ruoyi.workflow.enums; +package org.ruoyi.common.chat.enums; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/factory/ChatServiceFactory.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/factory/ChatServiceFactory.java index ee884357..6e91254a 100644 --- a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/factory/ChatServiceFactory.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/factory/ChatServiceFactory.java @@ -1,6 +1,6 @@ package org.ruoyi.common.chat.factory; -import org.ruoyi.common.chat.Service.IChatService; +import org.ruoyi.common.chat.service.chat.IChatService; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; diff --git a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/factory/ImageServiceFactory.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/factory/ImageServiceFactory.java index e7ba4160..52d3731b 100644 --- a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/factory/ImageServiceFactory.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/factory/ImageServiceFactory.java @@ -1,6 +1,6 @@ package org.ruoyi.common.chat.factory; -import org.ruoyi.common.chat.Service.IImageGenerationService; +import org.ruoyi.common.chat.service.image.IImageGenerationService; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; diff --git a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/Service/IChatModelService.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/service/chat/IChatModelService.java similarity index 97% rename from ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/Service/IChatModelService.java rename to ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/service/chat/IChatModelService.java index edb7ed52..3c362a52 100644 --- a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/Service/IChatModelService.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/service/chat/IChatModelService.java @@ -1,4 +1,4 @@ -package org.ruoyi.common.chat.Service; +package org.ruoyi.common.chat.service.chat; import org.ruoyi.common.chat.domain.bo.chat.ChatModelBo; import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo; diff --git a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/Service/IChatService.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/service/chat/IChatService.java similarity index 79% rename from ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/Service/IChatService.java rename to ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/service/chat/IChatService.java index 01a02567..de9f13ca 100644 --- a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/Service/IChatService.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/service/chat/IChatService.java @@ -1,7 +1,7 @@ -package org.ruoyi.common.chat.Service; +package org.ruoyi.common.chat.service.chat; import jakarta.validation.Valid; -import org.ruoyi.common.chat.domain.entity.chat.ChatContext; +import org.ruoyi.common.chat.entity.chat.ChatContext; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; /** diff --git a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/service/chatMessage/AbstractChatMessageService.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/service/chatMessage/AbstractChatMessageService.java new file mode 100644 index 00000000..687605eb --- /dev/null +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/service/chatMessage/AbstractChatMessageService.java @@ -0,0 +1,59 @@ +package org.ruoyi.common.chat.service.chatMessage; + +import org.ruoyi.common.chat.domain.bo.chat.ChatMessageBo; +import org.ruoyi.common.chat.domain.dto.request.ChatRequest; +import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * 聊天信息抽象基类 - 保存聊天信息 + * + * @author Zengxb + * @date 2026-02-24 + */ +public abstract class AbstractChatMessageService { + + /** + * 创建日志对象 + */ + Logger log = LoggerFactory.getLogger(AbstractChatMessageService.class); + + @Autowired + private IChatMessageService chatMessageService; + + /** + * 保存聊天信息 + */ + public void saveChatMessage(ChatRequest chatRequest, Long userId, String content, String role, ChatModelVo chatModelVo){ + try { + // 验证必要的上下文信息 + if (chatRequest == null || userId == null) { + log.warn("缺少必要的聊天上下文信息,无法保存消息"); + return; + } + + // 创建ChatMessageBo对象 + ChatMessageBo messageBO = new ChatMessageBo(); + messageBO.setUserId(userId); + messageBO.setSessionId(chatRequest.getSessionId()); + messageBO.setContent(content); + messageBO.setRole(role); + messageBO.setModelName(chatRequest.getModel()); + messageBO.setBillingType(chatModelVo.getModelType()); + messageBO.setRemark(null); + + chatMessageService.insertByBo(messageBO); + } catch (Exception e) { + log.error("保存{}聊天消息时出错: {}", getProviderName(), e.getMessage(), e); + } + } + + /** + * 获取服务提供商名称 + */ + protected String getProviderName(){ + return "默认工作流大模型"; + } +} diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/IChatMessageService.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/service/chatMessage/IChatMessageService.java similarity index 92% rename from ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/IChatMessageService.java rename to ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/service/chatMessage/IChatMessageService.java index 3289b5f2..98e31a40 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/IChatMessageService.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/service/chatMessage/IChatMessageService.java @@ -1,10 +1,10 @@ -package org.ruoyi.service.chat; +package org.ruoyi.common.chat.service.chatMessage; +import org.ruoyi.common.chat.domain.bo.chat.ChatMessageBo; import org.ruoyi.common.chat.domain.dto.ChatMessageDTO; +import org.ruoyi.common.chat.domain.vo.chat.ChatMessageVo; import org.ruoyi.common.mybatis.core.page.PageQuery; import org.ruoyi.common.mybatis.core.page.TableDataInfo; -import org.ruoyi.domain.bo.chat.ChatMessageBo; -import org.ruoyi.domain.vo.chat.ChatMessageVo; import java.util.Collection; import java.util.List; diff --git a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/Service/IImageGenerationService.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/service/image/IImageGenerationService.java similarity index 74% rename from ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/Service/IImageGenerationService.java rename to ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/service/image/IImageGenerationService.java index 237afed1..3be0a84f 100644 --- a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/Service/IImageGenerationService.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/service/image/IImageGenerationService.java @@ -1,7 +1,7 @@ -package org.ruoyi.common.chat.Service; +package org.ruoyi.common.chat.service.image; import jakarta.validation.Valid; -import org.ruoyi.common.chat.domain.entity.image.ImageContext; +import org.ruoyi.common.chat.entity.image.ImageContext; /** * 公共文生图接口 diff --git a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/service/workFlow/IWorkFlowStarterService.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/service/workFlow/IWorkFlowStarterService.java new file mode 100644 index 00000000..4001b67f --- /dev/null +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/service/workFlow/IWorkFlowStarterService.java @@ -0,0 +1,33 @@ +package org.ruoyi.common.chat.service.workFlow; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.ruoyi.common.chat.entity.User; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; + +import java.util.List; + +/** + * 工作流启动Service接口 + * + * @author Zengxb + * @date 2026-02-24 + */ +public interface IWorkFlowStarterService { + + /** + * 启动工作流 + * @param user 用户 + * @param workflowUuid 工作流UUID + * @param userInputs 用户输入信息 + * @return 流式输出结果 + */ + SseEmitter streaming(User user, String workflowUuid, List userInputs, Long sessionId); + + /** + * 恢复工作流 + * @param runtimeUuid 运行时UUID + * @param userInput 用户输入 + * @param sseEmitter SSE连接对象 + */ + void resumeFlow(String runtimeUuid, String userInput, SseEmitter sseEmitter); +} diff --git a/ruoyi-common/ruoyi-common-sse/src/main/java/org/ruoyi/common/sse/core/SseEmitterManager.java b/ruoyi-common/ruoyi-common-sse/src/main/java/org/ruoyi/common/sse/core/SseEmitterManager.java index d111c875..4e7a5481 100644 --- a/ruoyi-common/ruoyi-common-sse/src/main/java/org/ruoyi/common/sse/core/SseEmitterManager.java +++ b/ruoyi-common/ruoyi-common-sse/src/main/java/org/ruoyi/common/sse/core/SseEmitterManager.java @@ -65,7 +65,7 @@ public class SseEmitterManager { emitter.onCompletion(() -> { SseEmitter remove = emitters.remove(token); if (remove != null) { - remove.complete(); +// remove.complete(); } }); emitter.onTimeout(() -> { diff --git a/ruoyi-modules/ruoyi-aiflow/pom.xml b/ruoyi-modules/ruoyi-aiflow/pom.xml index 34d46d62..d7a147c8 100644 --- a/ruoyi-modules/ruoyi-aiflow/pom.xml +++ b/ruoyi-modules/ruoyi-aiflow/pom.xml @@ -81,12 +81,6 @@ - - io.swagger.core.v3 - swagger-annotations - ${swagger-annotations.version} - - com.google.api-client google-api-client diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/base/BaseResponse.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/base/BaseResponse.java index d6220abd..c84389bc 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/base/BaseResponse.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/base/BaseResponse.java @@ -1,7 +1,7 @@ package org.ruoyi.workflow.base; import lombok.Data; -import org.ruoyi.workflow.enums.ErrorEnum; +import org.ruoyi.common.chat.enums.ErrorEnum; import java.io.Serializable; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/controller/WorkflowController.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/controller/WorkflowController.java index d92f79d8..61037520 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/controller/WorkflowController.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/controller/WorkflowController.java @@ -5,8 +5,8 @@ import io.swagger.v3.oas.annotations.Operation; import jakarta.annotation.Resource; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotNull; +import org.ruoyi.common.chat.base.ThreadContext; import org.ruoyi.common.core.domain.R; -import org.ruoyi.workflow.base.ThreadContext; import org.ruoyi.workflow.dto.workflow.*; import org.ruoyi.workflow.entity.WorkflowComponent; import org.ruoyi.workflow.service.WorkflowComponentService; @@ -72,7 +72,7 @@ public class WorkflowController { @Operation(summary = "流式响应") @PostMapping(value = "/run", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public SseEmitter sseAsk(@RequestBody WorkflowRunReq runReq) { - return workflowStarter.streaming(ThreadContext.getCurrentUser(), runReq.getUuid(), runReq.getInputs()); + return workflowStarter.streaming(ThreadContext.getCurrentUser(), runReq.getUuid(), runReq.getInputs(),runReq.getSessionId()); } @GetMapping("/mine/search") diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/controller/WorkflowRuntimeController.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/controller/WorkflowRuntimeController.java index 34fc0065..2d384aaa 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/controller/WorkflowRuntimeController.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/controller/WorkflowRuntimeController.java @@ -30,7 +30,7 @@ public class WorkflowRuntimeController { @Operation(summary = "接收用户输入以继续执行剩余流程") @PostMapping(value = "/resume/{runtimeUuid}") public R resume(@PathVariable String runtimeUuid, @RequestBody WorkflowResumeReq resumeReq) { - workflowStarter.resumeFlow(runtimeUuid, resumeReq.getFeedbackContent()); + workflowStarter.resumeFlow(runtimeUuid, resumeReq.getFeedbackContent(), resumeReq.getSseEmitter()); return R.ok(); } diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/dto/workflow/WorkflowResumeReq.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/dto/workflow/WorkflowResumeReq.java index 27680932..c1b64829 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/dto/workflow/WorkflowResumeReq.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/dto/workflow/WorkflowResumeReq.java @@ -1,8 +1,10 @@ package org.ruoyi.workflow.dto.workflow; import lombok.Data; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; @Data public class WorkflowResumeReq { private String feedbackContent; + private SseEmitter sseEmitter; } diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/dto/workflow/WorkflowRunReq.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/dto/workflow/WorkflowRunReq.java index 54a32a03..40ca0fcc 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/dto/workflow/WorkflowRunReq.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/dto/workflow/WorkflowRunReq.java @@ -9,6 +9,7 @@ import java.util.List; public class WorkflowRunReq { private List inputs; private String uuid; + private Long sessionId; } diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/Workflow.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/Workflow.java index 4334b069..4a43e674 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/Workflow.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/Workflow.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; +import org.ruoyi.common.chat.entity.BaseEntity; import java.io.Serial; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/WorkflowComponent.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/WorkflowComponent.java index d75e92c8..c60b06bc 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/WorkflowComponent.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/WorkflowComponent.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; +import org.ruoyi.common.chat.entity.BaseEntity; import java.io.Serial; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/WorkflowEdge.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/WorkflowEdge.java index 0a9bffda..6c44c70d 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/WorkflowEdge.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/WorkflowEdge.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; +import org.ruoyi.common.chat.entity.BaseEntity; import java.io.Serial; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/WorkflowNode.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/WorkflowNode.java index cc15504a..e4261aab 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/WorkflowNode.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/WorkflowNode.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; +import org.ruoyi.common.chat.entity.BaseEntity; import java.io.Serial; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/WorkflowRuntime.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/WorkflowRuntime.java index 557de3f4..dada5dea 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/WorkflowRuntime.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/WorkflowRuntime.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; +import org.ruoyi.common.chat.entity.BaseEntity; import java.io.Serial; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/WorkflowRuntimeNode.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/WorkflowRuntimeNode.java index 271d9eb7..a472b5a1 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/WorkflowRuntimeNode.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/entity/WorkflowRuntimeNode.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; +import org.ruoyi.common.chat.entity.BaseEntity; import java.io.Serial; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/enums/AiModelStatus.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/enums/AiModelStatus.java index 0dec4a94..f49c3f88 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/enums/AiModelStatus.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/enums/AiModelStatus.java @@ -2,6 +2,7 @@ package org.ruoyi.workflow.enums; import lombok.AllArgsConstructor; import lombok.Getter; +import org.ruoyi.common.chat.enums.BaseEnum; @Getter @AllArgsConstructor diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/enums/WfIODataTypeEnum.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/enums/WfIODataTypeEnum.java index 8f8989c6..2ca638dc 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/enums/WfIODataTypeEnum.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/enums/WfIODataTypeEnum.java @@ -2,6 +2,7 @@ package org.ruoyi.workflow.enums; import lombok.AllArgsConstructor; import lombok.Getter; +import org.ruoyi.common.chat.enums.BaseEnum; import java.util.Arrays; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/helper/SSEEmitterHelper.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/helper/SSEEmitterHelper.java index 4d432c07..61b3dda0 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/helper/SSEEmitterHelper.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/helper/SSEEmitterHelper.java @@ -5,9 +5,9 @@ import com.google.common.cache.CacheBuilder; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.ruoyi.common.chat.entity.User; import org.ruoyi.workflow.cosntant.AdiConstant; import org.ruoyi.workflow.cosntant.RedisKeyConstant; -import org.ruoyi.workflow.entity.User; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowComponentService.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowComponentService.java index 04e3b03c..c1790738 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowComponentService.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowComponentService.java @@ -7,11 +7,11 @@ import com.baomidou.mybatisplus.extension.toolkit.ChainWrappers; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.ruoyi.common.chat.enums.ErrorEnum; import org.ruoyi.common.core.exception.base.BaseException; import org.ruoyi.workflow.dto.workflow.WfComponentReq; import org.ruoyi.workflow.dto.workflow.WfComponentSearchReq; import org.ruoyi.workflow.entity.WorkflowComponent; -import org.ruoyi.workflow.enums.ErrorEnum; import org.ruoyi.workflow.mapper.WorkflowComponentMapper; import org.ruoyi.workflow.util.PrivilegeUtil; import org.ruoyi.workflow.util.UuidUtil; @@ -26,7 +26,7 @@ import java.util.List; import static org.ruoyi.workflow.cosntant.RedisKeyConstant.WORKFLOW_COMPONENTS; import static org.ruoyi.workflow.cosntant.RedisKeyConstant.WORKFLOW_COMPONENT_START_KEY; -import static org.ruoyi.workflow.enums.ErrorEnum.C_WF_COMPONENT_DELETED_FAIL_BY_USED; +import static org.ruoyi.common.chat.enums.ErrorEnum.C_WF_COMPONENT_DELETED_FAIL_BY_USED; @Slf4j @Service diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowEdgeService.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowEdgeService.java index 63cc3530..624482b8 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowEdgeService.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowEdgeService.java @@ -5,10 +5,10 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.toolkit.ChainWrappers; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; +import org.ruoyi.common.chat.enums.ErrorEnum; import org.ruoyi.common.core.exception.base.BaseException; import org.ruoyi.workflow.dto.workflow.WfEdgeReq; import org.ruoyi.workflow.entity.WorkflowEdge; -import org.ruoyi.workflow.enums.ErrorEnum; import org.ruoyi.workflow.mapper.WorkflowEdgeMapper; import org.ruoyi.workflow.util.MPPageUtil; import org.ruoyi.workflow.util.UuidUtil; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowNodeService.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowNodeService.java index e99bd8fd..f56ac479 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowNodeService.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowNodeService.java @@ -6,12 +6,12 @@ import com.baomidou.mybatisplus.extension.toolkit.ChainWrappers; import com.fasterxml.jackson.databind.node.ObjectNode; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; +import org.ruoyi.common.chat.enums.ErrorEnum; import org.ruoyi.common.core.exception.base.BaseException; import org.ruoyi.workflow.dto.workflow.WfNodeDto; import org.ruoyi.workflow.entity.Workflow; import org.ruoyi.workflow.entity.WorkflowComponent; import org.ruoyi.workflow.entity.WorkflowNode; -import org.ruoyi.workflow.enums.ErrorEnum; import org.ruoyi.workflow.enums.WfIODataTypeEnum; import org.ruoyi.workflow.mapper.WorkflowNodeMapper; import org.ruoyi.workflow.util.JsonUtil; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowRuntimeNodeService.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowRuntimeNodeService.java index 43c73207..63aa6d4b 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowRuntimeNodeService.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowRuntimeNodeService.java @@ -4,9 +4,9 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.toolkit.ChainWrappers; import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.extern.slf4j.Slf4j; -import org.ruoyi.workflow.base.ThreadContext; +import org.ruoyi.common.chat.base.ThreadContext; +import org.ruoyi.common.chat.entity.User; import org.ruoyi.workflow.dto.workflow.WfRuntimeNodeDto; -import org.ruoyi.workflow.entity.User; import org.ruoyi.workflow.entity.WorkflowRuntimeNode; import org.ruoyi.workflow.mapper.WorkflowRuntimeNodeMapper; import org.ruoyi.workflow.util.JsonUtil; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowRuntimeService.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowRuntimeService.java index 330974a9..ddd3f3fb 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowRuntimeService.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowRuntimeService.java @@ -7,13 +7,13 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.ruoyi.workflow.base.ThreadContext; +import org.ruoyi.common.chat.base.ThreadContext; +import org.ruoyi.common.chat.entity.User; +import org.ruoyi.common.chat.enums.ErrorEnum; import org.ruoyi.workflow.dto.workflow.WfRuntimeNodeDto; import org.ruoyi.workflow.dto.workflow.WfRuntimeResp; -import org.ruoyi.workflow.entity.User; import org.ruoyi.workflow.entity.Workflow; import org.ruoyi.workflow.entity.WorkflowRuntime; -import org.ruoyi.workflow.enums.ErrorEnum; import org.ruoyi.workflow.mapper.WorkflowRunMapper; import org.ruoyi.workflow.util.JsonUtil; import org.ruoyi.workflow.util.MPPageUtil; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowService.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowService.java index 439ffba4..926dc12b 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowService.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/service/WorkflowService.java @@ -6,15 +6,15 @@ import com.baomidou.mybatisplus.extension.toolkit.ChainWrappers; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.ruoyi.common.chat.base.ThreadContext; +import org.ruoyi.common.chat.entity.User; +import org.ruoyi.common.chat.enums.ErrorEnum; import org.ruoyi.common.core.exception.base.BaseException; -import org.ruoyi.workflow.base.ThreadContext; import org.ruoyi.workflow.dto.workflow.WfEdgeReq; import org.ruoyi.workflow.dto.workflow.WfNodeDto; import org.ruoyi.workflow.dto.workflow.WorkflowResp; import org.ruoyi.workflow.dto.workflow.WorkflowUpdateReq; -import org.ruoyi.workflow.entity.User; import org.ruoyi.workflow.entity.Workflow; -import org.ruoyi.workflow.enums.ErrorEnum; import org.ruoyi.workflow.mapper.WorkflowMapper; import org.ruoyi.workflow.util.MPPageUtil; import org.ruoyi.workflow.util.PrivilegeUtil; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/util/PrivilegeUtil.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/util/PrivilegeUtil.java index 7ad0dc7a..7480cbfe 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/util/PrivilegeUtil.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/util/PrivilegeUtil.java @@ -1,9 +1,9 @@ package org.ruoyi.workflow.util; import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper; +import org.ruoyi.common.chat.base.ThreadContext; +import org.ruoyi.common.chat.enums.ErrorEnum; import org.ruoyi.common.core.exception.base.BaseException; -import org.ruoyi.workflow.base.ThreadContext; -import org.ruoyi.workflow.enums.ErrorEnum; import static org.ruoyi.workflow.cosntant.AdiConstant.*; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/util/WorkflowMessageUtil.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/util/WorkflowMessageUtil.java new file mode 100644 index 00000000..4ae71e3b --- /dev/null +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/util/WorkflowMessageUtil.java @@ -0,0 +1,37 @@ +package org.ruoyi.workflow.util; + +import org.ruoyi.common.chat.domain.dto.request.ChatRequest; +import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo; +import org.ruoyi.common.chat.enums.RoleType; +import lombok.extern.slf4j.Slf4j; +import org.ruoyi.common.core.utils.SpringUtils; +import org.ruoyi.workflow.workflow.WfState; +import org.ruoyi.workflow.workflow.WorkflowUtil; + +/** + * 工作流消息工具类 + * + * @author Zengxb + * @date 2026-02-26 + */ +@Slf4j +public class WorkflowMessageUtil { + + /** + * 保存工作流消息公共方法(对话使用) + * @param wfState 工作流实例状态 + * @param message 消息 + */ + public static void saveWorkflowMessage(WfState wfState, String message) { + Long sessionId = wfState.getSessionId(); + Long userId = wfState.getUserId(); + + if (sessionId != null && userId != null) { + ChatRequest chatRequest = new ChatRequest(); + chatRequest.setSessionId(sessionId); + WorkflowUtil workflowUtil = SpringUtils.getBean(WorkflowUtil.class); + workflowUtil.saveChatMessage(chatRequest, userId, message, RoleType.WORKFLOW.getName(), new ChatModelVo()); + } + } + +} diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WfNodeIODataUtil.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WfNodeIODataUtil.java index 61828568..9bedc711 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WfNodeIODataUtil.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WfNodeIODataUtil.java @@ -4,8 +4,8 @@ import cn.hutool.core.collection.CollUtil; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import org.apache.commons.collections4.CollectionUtils; +import org.ruoyi.common.chat.enums.ErrorEnum; import org.ruoyi.common.core.exception.base.BaseException; -import org.ruoyi.workflow.enums.ErrorEnum; import org.ruoyi.workflow.enums.WfIODataTypeEnum; import org.ruoyi.workflow.util.JsonUtil; import org.ruoyi.workflow.workflow.data.NodeIOData; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WfState.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WfState.java index 97962a71..d0595803 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WfState.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WfState.java @@ -4,8 +4,8 @@ import lombok.Getter; import lombok.Setter; import org.bsc.langgraph4j.langchain4j.generators.StreamingChatGenerator; import org.bsc.langgraph4j.state.AgentState; +import org.ruoyi.common.chat.entity.User; import org.ruoyi.workflow.dto.workflow.WfRuntimeNodeDto; -import org.ruoyi.workflow.entity.User; import org.ruoyi.workflow.entity.WorkflowNode; import org.ruoyi.workflow.workflow.data.NodeIOData; import org.ruoyi.workflow.workflow.node.AbstractWfNode; @@ -28,6 +28,7 @@ public class WfState { private Long userId; private String tokenValue; private SseEmitter sseEmitter; + private Long sessionId; //Source node uuid => target node uuid list private Map> edges = new HashMap<>(); @@ -59,13 +60,14 @@ public class WfState { */ private Set interruptNodes = new HashSet<>(); - public WfState(User user, List input, String uuid, Long userId, String tokenValue, SseEmitter sseEmitter) { + public WfState(User user, List input, String uuid, Long userId, String tokenValue, SseEmitter sseEmitter, Long sessionId) { this.input = input; this.user = user; this.uuid = uuid; this.userId = userId; this.tokenValue = tokenValue; this.sseEmitter = sseEmitter; + this.sessionId = sessionId; } /** diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WorkflowEngine.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WorkflowEngine.java index f84b2164..20a3e783 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WorkflowEngine.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WorkflowEngine.java @@ -3,6 +3,8 @@ package org.ruoyi.workflow.workflow; import cn.hutool.core.collection.CollStreamUtil; import cn.hutool.core.collection.CollUtil; import com.fasterxml.jackson.databind.node.ObjectNode; +import lombok.Getter; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; @@ -13,16 +15,18 @@ import org.bsc.langgraph4j.langchain4j.generators.StreamingChatGenerator; import org.bsc.langgraph4j.state.AgentState; import org.bsc.langgraph4j.state.StateSnapshot; import org.bsc.langgraph4j.streaming.StreamingOutput; +import org.ruoyi.common.chat.entity.User; +import org.ruoyi.common.chat.enums.ErrorEnum; import org.ruoyi.common.core.exception.base.BaseException; import org.ruoyi.workflow.base.NodeInputConfigTypeHandler; import org.ruoyi.workflow.dto.workflow.WfRuntimeNodeDto; import org.ruoyi.workflow.dto.workflow.WfRuntimeResp; import org.ruoyi.workflow.entity.*; -import org.ruoyi.workflow.enums.ErrorEnum; import org.ruoyi.workflow.helper.SSEEmitterHelper; import org.ruoyi.workflow.service.WorkflowRuntimeNodeService; import org.ruoyi.workflow.service.WorkflowRuntimeService; import org.ruoyi.workflow.util.JsonUtil; +import org.ruoyi.workflow.util.WorkflowMessageUtil; import org.ruoyi.workflow.workflow.data.NodeIOData; import org.ruoyi.workflow.workflow.def.WfNodeIO; import org.ruoyi.workflow.workflow.def.WfNodeParamRef; @@ -34,7 +38,7 @@ import java.util.function.Function; import static org.bsc.langgraph4j.StateGraph.END; import static org.ruoyi.workflow.cosntant.AdiConstant.WorkflowConstant.*; -import static org.ruoyi.workflow.enums.ErrorEnum.*; +import static org.ruoyi.common.chat.enums.ErrorEnum.*; @Slf4j public class WorkflowEngine { @@ -45,7 +49,9 @@ public class WorkflowEngine { private final SSEEmitterHelper sseEmitterHelper; private final WorkflowRuntimeService workflowRuntimeService; private final WorkflowRuntimeNodeService workflowRuntimeNodeService; + @Getter private CompiledGraph app; + @Setter private SseEmitter sseEmitter; private User user; private WfState wfState; @@ -68,7 +74,7 @@ public class WorkflowEngine { this.workflowRuntimeNodeService = workflowRuntimeNodeService; } - public void run(User user, List userInputs, SseEmitter sseEmitter, Long userId, String tokenValue) { + public void run(User user, List userInputs, SseEmitter sseEmitter, Long userId, String tokenValue, Long sessionId) { this.user = user; this.sseEmitter = sseEmitter; log.info("WorkflowEngine run,userId:{},workflowUuid:{},userInputs:{}", user.getId(), workflow.getUuid(), userInputs); @@ -86,7 +92,7 @@ public class WorkflowEngine { Pair> startAndEnds = findStartAndEndNode(); WorkflowNode startNode = startAndEnds.getLeft(); List wfInputs = getAndCheckUserInput(userInputs, startNode); - this.wfState = new WfState(user, wfInputs, runtimeUuid,userId, tokenValue, sseEmitter); + this.wfState = new WfState(user, wfInputs, runtimeUuid,userId, tokenValue, sseEmitter, sessionId); workflowRuntimeService.updateInput(this.wfRuntimeResp.getId(), wfState); @@ -122,6 +128,8 @@ public class WorkflowEngine { String intTip = WorkflowUtil.getHumanFeedbackTip(nextNode, wfNodes); //将等待输入信息[事件与提示词]发送到到客户端 SSEEmitterHelper.parseAndSendPartialMsg(sseEmitter, "[NODE_WAIT_FEEDBACK_BY_" + nextNode + "]", intTip); + // 保存提示信息到Chat信息记录中(对话使用) + WorkflowMessageUtil.saveWorkflowMessage(wfState, intTip); InterruptedFlow.RUNTIME_TO_GRAPH.put(wfState.getUuid(), this); //更新状�? wfState.setProcessStatus(WORKFLOW_PROCESS_STATUS_WAITING_INPUT); @@ -241,6 +249,7 @@ public class WorkflowEngine { Map strMap = new HashMap<>(); strMap.put("ck", chunk); // SSEEmitterHelper.parseAndSendPartialMsg(sseEmitter, "[NODE_CHUNK_" + node + "]", strMap.toString()); + SSEEmitterHelper.parseAndSendPartialMsg(sseEmitter, "[NODE_CHUNK_" + node + "]", chunk); } else { AbstractWfNode abstractWfNode = wfState.getCompletedNodes().stream() @@ -349,8 +358,4 @@ public class WorkflowEngine { return Pair.of(startNode, endNodes); } - - public CompiledGraph getApp() { - return app; - } } diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WorkflowGraphBuilder.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WorkflowGraphBuilder.java index aa11b4b5..55241376 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WorkflowGraphBuilder.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WorkflowGraphBuilder.java @@ -5,11 +5,11 @@ import org.apache.commons.lang3.StringUtils; import org.bsc.langgraph4j.GraphStateException; import org.bsc.langgraph4j.StateGraph; import org.bsc.langgraph4j.serializer.std.ObjectStreamStateSerializer; +import org.ruoyi.common.chat.enums.ErrorEnum; import org.ruoyi.common.core.exception.base.BaseException; import org.ruoyi.workflow.entity.WorkflowComponent; import org.ruoyi.workflow.entity.WorkflowEdge; import org.ruoyi.workflow.entity.WorkflowNode; -import org.ruoyi.workflow.enums.ErrorEnum; import java.util.*; import java.util.function.Function; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WorkflowStarter.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WorkflowStarter.java index 7865af51..95885ed1 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WorkflowStarter.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WorkflowStarter.java @@ -4,6 +4,8 @@ import cn.dev33.satoken.stp.StpUtil; import com.fasterxml.jackson.databind.node.ObjectNode; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; +import org.ruoyi.common.chat.entity.User; +import org.ruoyi.common.chat.service.workFlow.IWorkFlowStarterService; import org.ruoyi.common.core.exception.base.BaseException; import org.ruoyi.common.satoken.utils.LoginHelper; import org.ruoyi.common.sse.core.SseEmitterManager; @@ -12,17 +14,16 @@ import org.ruoyi.workflow.helper.SSEEmitterHelper; import org.ruoyi.workflow.service.*; import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Async; -import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import java.util.List; -import static org.ruoyi.workflow.cosntant.AdiConstant.SSE_TIMEOUT; -import static org.ruoyi.workflow.enums.ErrorEnum.*; +import static org.ruoyi.common.chat.enums.ErrorEnum.*; @Slf4j -@Component -public class WorkflowStarter { +@Service +public class WorkflowStarter implements IWorkFlowStarterService { @Lazy @Resource @@ -52,8 +53,7 @@ public class WorkflowStarter { @Resource private SseEmitterManager sseEmitterManager; - - public SseEmitter streaming(User user, String workflowUuid, List userInputs) { + public SseEmitter streaming(User user, String workflowUuid, List userInputs, Long sessionId) { // 获取用户ID Long userId = LoginHelper.getUserId(); // 获取登录Token @@ -71,12 +71,12 @@ public class WorkflowStarter { sseEmitterHelper.sendErrorAndComplete(user.getId(), sseEmitter, A_WF_DISABLED.getInfo()); return sseEmitter; } - self.asyncRun(user, workflow, userInputs, sseEmitter, userId, tokenValue); + self.asyncRun(user, workflow, userInputs, sseEmitter, userId, tokenValue, sessionId); return sseEmitter; } @Async - public void asyncRun(User user, Workflow workflow, List userInputs, SseEmitter sseEmitter, Long userId, String tokenValue) { + public void asyncRun(User user, Workflow workflow, List userInputs, SseEmitter sseEmitter, Long userId, String tokenValue, Long sessionId) { log.info("WorkflowEngine run,userId:{},workflowUuid:{},userInputs:{}", user.getId(), workflow.getUuid(), userInputs); List components = workflowComponentService.getAllEnable(); List nodes = workflowNodeService.lambdaQuery() @@ -90,17 +90,20 @@ public class WorkflowStarter { WorkflowEngine workflowEngine = new WorkflowEngine(workflow, sseEmitterHelper, components, nodes, edges, workflowRuntimeService, workflowRuntimeNodeService); - workflowEngine.run(user, userInputs, sseEmitter, userId, tokenValue); + workflowEngine.run(user, userInputs, sseEmitter, userId, tokenValue, sessionId); } @Async - public void resumeFlow(String runtimeUuid, String userInput) { + public void resumeFlow(String runtimeUuid, String userInput, SseEmitter sseEmitter) { WorkflowEngine workflowEngine = InterruptedFlow.RUNTIME_TO_GRAPH.get(runtimeUuid); if (null == workflowEngine) { log.error("工作流恢复执行时失败,runtime:{}", runtimeUuid); throw new BaseException(A_WF_RESUME_FAIL.getInfo()); } + // 如果SSE连接对象不为空传入该对象(Chat调用工作流对话使用) + if (null != sseEmitter){ + workflowEngine.setSseEmitter(sseEmitter); + } workflowEngine.resume(userInput); } - } diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WorkflowUtil.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WorkflowUtil.java index 63a13845..c34962c0 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WorkflowUtil.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/WorkflowUtil.java @@ -11,12 +11,14 @@ import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.bsc.langgraph4j.langchain4j.generators.StreamingChatGenerator; import org.bsc.langgraph4j.state.AgentState; -import org.ruoyi.common.chat.Service.IChatModelService; -import org.ruoyi.common.chat.Service.IChatService; -import org.ruoyi.common.chat.Service.IImageGenerationService; +import org.ruoyi.common.chat.enums.RoleType; +import org.ruoyi.common.chat.service.chat.IChatModelService; +import org.ruoyi.common.chat.service.chat.IChatService; +import org.ruoyi.common.chat.service.chatMessage.AbstractChatMessageService; +import org.ruoyi.common.chat.service.image.IImageGenerationService; import org.ruoyi.common.chat.domain.dto.request.ChatRequest; -import org.ruoyi.common.chat.domain.entity.chat.ChatContext; -import org.ruoyi.common.chat.domain.entity.image.ImageContext; +import org.ruoyi.common.chat.entity.chat.ChatContext; +import org.ruoyi.common.chat.entity.image.ImageContext; import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo; import org.ruoyi.common.chat.factory.ChatServiceFactory; import org.ruoyi.common.chat.factory.ImageServiceFactory; @@ -28,6 +30,7 @@ import org.ruoyi.workflow.workflow.data.NodeIOData; import org.ruoyi.workflow.workflow.data.NodeIODataContent; import org.ruoyi.workflow.workflow.def.WfNodeParamRef; import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import java.util.*; @@ -35,8 +38,8 @@ import java.util.*; import static org.ruoyi.workflow.cosntant.AdiConstant.WorkflowConstant.DEFAULT_OUTPUT_PARAM_NAME; @Slf4j -@Component -public class WorkflowUtil { +@Service +public class WorkflowUtil extends AbstractChatMessageService { @Resource private ChatServiceFactory chatServiceFactory; @@ -123,11 +126,38 @@ public class WorkflowUtil { // 根据 category 获取对应的 ChatService(不使用计费代理,工作流场景单独计费) IChatService chatService = chatServiceFactory.getOriginalService(category); + // 获取用户信息和Token以及SSe连接对象(对话接口需要使用) + Long sessionId = wfState.getSessionId(); + Long userId = wfState.getUserId(); + String tokenValue = wfState.getTokenValue(); + SseEmitter sseEmitter = wfState.getSseEmitter(); + + // 构建 ruoyi-ai 的 ChatRequest + List chatMessages = new ArrayList<>(); + addUserMessage(node, state.getInputs(), chatMessages); + chatMessages.addAll(systemMessage); + + // 定义模型调用对象 + ChatRequest chatRequest = new ChatRequest(); + // 目前工作流深度思考成员变量只能写死 + chatRequest.setSessionId(sessionId); + chatRequest.setEnableThinking(false); + chatRequest.setModel(modelName); + chatRequest.setChatMessages(chatMessages); + + // 构建流式生成器 StreamingChatGenerator streamingGenerator = StreamingChatGenerator.builder() .mapResult(response -> { String responseTxt = response.aiMessage().text(); log.info("llm response:{}", responseTxt); + // 会话ID不为空时插入数据库 + if (sessionId != null){ + // 保存助手回复消息 + saveChatMessage(chatRequest, userId, responseTxt, RoleType.ASSISTANT.getName(), chatModelVo); + log.info("{}消息结束,已保存到数据库", getProviderName()); + } + // 传递所有输入数据 + 添加 LLM 输出 wfState.getNodeStateByNodeUuid(node.getUuid()).ifPresent(item -> { List outputs = new ArrayList<>(item.getInputs()); @@ -142,24 +172,9 @@ public class WorkflowUtil { .startingState(state) .build(); - // 获取用户信息和Token以及SSe连接对象(对话接口需要使用) - Long userId = wfState.getUserId(); - String tokenValue = wfState.getTokenValue(); - SseEmitter sseEmitter = wfState.getSseEmitter(); + // 构建流式回调响应器 StreamingChatResponseHandler handler = streamingGenerator.handler(); - // 构建 ruoyi-ai 的 ChatRequest - List chatMessages = new ArrayList<>(); - addUserMessage(node, state.getInputs(), chatMessages); - chatMessages.addAll(systemMessage); - - // 定义模型调用对象 - ChatRequest chatRequest = new ChatRequest(); - // 目前工作流深度思考成员变量只能写死 - chatRequest.setEnableThinking(false); - chatRequest.setModel(modelName); - chatRequest.setChatMessages(chatMessages); - //构建聊天对话上下文参数 ChatContext chatContext = ChatContext.builder() .chatModelVo(chatModelVo) @@ -231,9 +246,9 @@ public class WorkflowUtil { throw new IllegalArgumentException("模型不存在: " + modelName); } // 根据模型名称找到模型实体 - String modelVoCategory = chatModelVo.getCategory(); + String category = chatModelVo.getProviderCode(); // 根据 category 获取对应的 IImageGenerationService(不使用计费代理,工作流场景单独计费) - IImageGenerationService imageService = imageServiceFactory.getOriginalService(modelVoCategory); + IImageGenerationService imageService = imageServiceFactory.getOriginalService(category); // 构建文生图上下文对象 ImageContext imageContext = ImageContext.builder() .chatModelVo(chatModelVo) @@ -244,5 +259,4 @@ public class WorkflowUtil { // 调用LLM 生成图片 return imageService.generateImage(imageContext); } - } diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/AbstractWfNode.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/AbstractWfNode.java index d3262971..700071f0 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/AbstractWfNode.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/AbstractWfNode.java @@ -6,18 +6,19 @@ import lombok.Data; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.SerializationUtils; -import org.apache.commons.lang3.StringUtils; +import org.ruoyi.common.chat.domain.dto.request.ChatRequest; +import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo; +import org.ruoyi.common.chat.enums.RoleType; import org.ruoyi.common.core.exception.base.BaseException; import org.ruoyi.workflow.base.NodeInputConfigTypeHandler; import org.ruoyi.workflow.entity.WorkflowComponent; import org.ruoyi.workflow.entity.WorkflowNode; import org.ruoyi.workflow.enums.WfIODataTypeEnum; +import org.ruoyi.workflow.helper.SSEEmitterHelper; import org.ruoyi.workflow.util.JsonUtil; import org.ruoyi.workflow.util.SpringUtil; -import org.ruoyi.workflow.workflow.NodeProcessResult; -import org.ruoyi.workflow.workflow.WfNodeInputConfig; -import org.ruoyi.workflow.workflow.WfNodeState; -import org.ruoyi.workflow.workflow.WfState; +import org.ruoyi.workflow.util.WorkflowMessageUtil; +import org.ruoyi.workflow.workflow.*; import org.ruoyi.workflow.workflow.data.NodeIOData; import org.ruoyi.workflow.workflow.def.WfNodeIO; import org.ruoyi.workflow.workflow.def.WfNodeParamRef; @@ -31,8 +32,8 @@ import java.util.function.Consumer; import java.util.stream.Collectors; import static org.ruoyi.workflow.cosntant.AdiConstant.WorkflowConstant.*; -import static org.ruoyi.workflow.enums.ErrorEnum.A_WF_NODE_CONFIG_ERROR; -import static org.ruoyi.workflow.enums.ErrorEnum.A_WF_NODE_CONFIG_NOT_FOUND; +import static org.ruoyi.common.chat.enums.ErrorEnum.A_WF_NODE_CONFIG_ERROR; +import static org.ruoyi.common.chat.enums.ErrorEnum.A_WF_NODE_CONFIG_NOT_FOUND; /** * 节点实例-运行时 @@ -225,4 +226,19 @@ public abstract class AbstractWfNode { return nodeConfig; } + /** + * 会话消息保存方法 + */ + public void saveSessionMessage(WfState wfState, String message) { + WorkflowMessageUtil.saveWorkflowMessage(wfState, message); + } + + /** + * 发送SSe消息 + * @param message 信息 + */ + public void sendSseEvent(String message){ + String nodeUuid = node.getUuid(); + SSEEmitterHelper.parseAndSendPartialMsg(wfState.getSseEmitter(), "[NODE_CHUNK_" + nodeUuid + "]", message); + } } diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/httpRequest/HttpRequestNode.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/httpRequest/HttpRequestNode.java index 16fc5f71..10248aeb 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/httpRequest/HttpRequestNode.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/httpRequest/HttpRequestNode.java @@ -63,6 +63,11 @@ public class HttpRequestNode extends AbstractWfNode { List outputs = new ArrayList<>(); outputs.add(NodeIOData.createByText("output", "HTTP响应", response)); + // 保存成功会话信息 + String message = "HTTP响应:" + response; + saveSessionMessage(wfState, message); + // 发送驱动消息事件 + sendSseEvent(message); return NodeProcessResult.builder().content(outputs).build(); } catch (Exception e) { @@ -73,6 +78,11 @@ public class HttpRequestNode extends AbstractWfNode { errorOutputs.add(NodeIOData.createByText("output", "错误", "")); errorOutputs.add(NodeIOData.createByText("error", "HTTP请求错误", e.getMessage())); + // 保存失败会话信息 + String message = "HTTP响应失败:" + e.getMessage(); + saveSessionMessage(wfState, message); + // 发送驱动消息事件 + sendSseEvent(message); return NodeProcessResult.builder().content(errorOutputs).build(); } } diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/humanFeedBack/HumanFeedbackNode.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/humanFeedBack/HumanFeedbackNode.java index ea5b918d..bf14b716 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/humanFeedBack/HumanFeedbackNode.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/humanFeedBack/HumanFeedbackNode.java @@ -7,6 +7,7 @@ import org.ruoyi.workflow.entity.WorkflowNode; import org.ruoyi.workflow.workflow.NodeProcessResult; import org.ruoyi.workflow.workflow.WfNodeState; import org.ruoyi.workflow.workflow.WfState; +import org.ruoyi.workflow.workflow.WorkflowUtil; import org.ruoyi.workflow.workflow.data.NodeIOData; import org.ruoyi.workflow.workflow.node.AbstractWfNode; diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/image/ImageNode.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/image/ImageNode.java index 095e4acd..4b887ad7 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/image/ImageNode.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/image/ImageNode.java @@ -51,6 +51,11 @@ public class ImageNode extends AbstractWfNode { Integer seed = nodeConfigObj.getSeed(); // 调用LLM生成图片(后续可以将图片保存到OSS中) String imageUrl = workflowUtil.buildTextToImage(modelName, prompt, size, seed); + // 保存成功信息 + String message = "图片生成地址:" + imageUrl; + saveSessionMessage(wfState, message); + // 发送驱动消息事件 + sendSseEvent(message); // 创建节点参数对象 NodeIOData nodeIOData = NodeIOData.createByText("output", "image", imageUrl); // 添加到输出列表以便给后续节点使用 diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/mailSend/MailSendNode.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/mailSend/MailSendNode.java index c006cbe4..0ae6a197 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/mailSend/MailSendNode.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/mailSend/MailSendNode.java @@ -1,5 +1,7 @@ package org.ruoyi.workflow.workflow.node.mailSend; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.JSONValidator; import jakarta.mail.internet.MimeMessage; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -31,6 +33,12 @@ public class MailSendNode extends AbstractWfNode { try { MailSendNodeConfig config = checkAndGetConfig(MailSendNodeConfig.class); List inputs = state.getInputs(); + // 获取输入信息 + String input = getDataFromInput(inputs); + // 判断是否为JSON格式(LLM输出转换 由LLM生成格式) + if (StringUtils.isNotBlank(input) && isJson(input)) { + config = JSONObject.parseObject(input, MailSendNodeConfig.class); + } // 安全获取模板(使用 defaultString 避免 null) String subjectTemplate = StringUtils.defaultString(config.getSubject()); @@ -49,15 +57,7 @@ public class MailSendNode extends AbstractWfNode { content = WorkflowUtil.renderTemplate(contentTemplate, inputs); } else { // 优先使用 output,如果没有则使用 input - content = inputs.stream() - .filter(item -> "output".equals(item.getName())) - .map(NodeIOData::valueToString) - .findFirst() - .orElseGet(() -> inputs.stream() - .filter(item -> "input".equals(item.getName())) - .map(NodeIOData::valueToString) - .findFirst() - .orElse("")); + content = getDataFromInput(inputs); } // 将换行符转换为 HTML 换行 @@ -84,9 +84,9 @@ public class MailSendNode extends AbstractWfNode { // 设置收件人 String[] toArray = Arrays.stream(toMails.split(",")) - .map(String::trim) - .filter(StringUtils::isNotBlank) - .toArray(String[]::new); + .map(String::trim) + .filter(StringUtils::isNotBlank) + .toArray(String[]::new); if (toArray.length == 0) { throw new IllegalArgumentException("收件人邮箱列表为空"); } @@ -95,9 +95,9 @@ public class MailSendNode extends AbstractWfNode { // 设置抄送(如有) if (StringUtils.isNotBlank(ccMails)) { String[] ccArray = Arrays.stream(ccMails.split(",")) - .map(String::trim) - .filter(StringUtils::isNotBlank) - .toArray(String[]::new); + .map(String::trim) + .filter(StringUtils::isNotBlank) + .toArray(String[]::new); if (ccArray.length > 0) { helper.setCc(ccArray); } @@ -111,25 +111,31 @@ public class MailSendNode extends AbstractWfNode { mailSender.send(message); log.info("Email sent successfully to: {}", toMails); + // 保存成功会话信息 + String resultMessage = "发送邮箱成功"; + saveSessionMessage(wfState, resultMessage); + // 发送驱动消息事件 + sendSseEvent(resultMessage); + // 构造输出:统一输出为 output 参数 List outputs = new java.util.ArrayList<>(); // 优先使用 output,如果没有则使用 input(但重命名为 output) inputs.stream() - .filter(item -> "output".equals(item.getName())) - .findFirst() - .ifPresentOrElse( - outputs::add, - () -> inputs.stream() - .filter(item -> "input".equals(item.getName())) - .findFirst() - .ifPresent(inputParam -> { - String title = inputParam.getContent() != null && inputParam.getContent().getTitle() != null - ? inputParam.getContent().getTitle() : ""; - NodeIOData outputParam = NodeIOData.createByText("output", title, inputParam.valueToString()); - outputs.add(outputParam); - }) - ); + .filter(item -> "output".equals(item.getName())) + .findFirst() + .ifPresentOrElse( + outputs::add, + () -> inputs.stream() + .filter(item -> "input".equals(item.getName())) + .findFirst() + .ifPresent(inputParam -> { + String title = inputParam.getContent() != null && inputParam.getContent().getTitle() != null + ? inputParam.getContent().getTitle() : ""; + NodeIOData outputParam = NodeIOData.createByText("output", title, resultMessage); + outputs.add(outputParam); + }) + ); return NodeProcessResult.builder().content(outputs).build(); @@ -138,23 +144,29 @@ public class MailSendNode extends AbstractWfNode { // 异常时也统一输出为 output 参数,添加错误信息 List errorOutputs = new java.util.ArrayList<>(); - state.getInputs().stream() - .filter(item -> "output".equals(item.getName())) - .findFirst() - .ifPresentOrElse( - errorOutputs::add, - () -> state.getInputs().stream() - .filter(item -> "input".equals(item.getName())) - .findFirst() - .ifPresent(inputParam -> { - String title = inputParam.getContent() != null && inputParam.getContent().getTitle() != null - ? inputParam.getContent().getTitle() : ""; - NodeIOData outputParam = NodeIOData.createByText("output", title, inputParam.valueToString()); - errorOutputs.add(outputParam); - }) - ); + // 保存失败会话信息 + String resultMessage = "发送邮箱失败: " + e.getMessage(); + saveSessionMessage(wfState, resultMessage); + // 发送驱动消息事件 + sendSseEvent(resultMessage); - errorOutputs.add(NodeIOData.createByText("error", "mail", e.getMessage())); + state.getInputs().stream() + .filter(item -> "output".equals(item.getName())) + .findFirst() + .ifPresentOrElse( + errorOutputs::add, + () -> state.getInputs().stream() + .filter(item -> "input".equals(item.getName())) + .findFirst() + .ifPresent(inputParam -> { + String title = inputParam.getContent() != null && inputParam.getContent().getTitle() != null + ? inputParam.getContent().getTitle() : ""; + NodeIOData outputParam = NodeIOData.createByText("output", title, resultMessage); + errorOutputs.add(outputParam); + }) + ); + + errorOutputs.add(NodeIOData.createByText("error", "mail", resultMessage)); return NodeProcessResult.builder().content(errorOutputs).build(); } } @@ -174,4 +186,40 @@ public class MailSendNode extends AbstractWfNode { return sender; } + + /** + * 获取信息 + * @param inputs 用户输入 + * @return 返回输入信息 + */ + public String getDataFromInput(List inputs) { + return inputs.stream() + .filter(item -> "output".equals(item.getName())) + .map(NodeIOData::valueToString) + .findFirst() + .orElseGet(() -> inputs.stream() + .filter(item -> "input".equals(item.getName())) + .map(NodeIOData::valueToString) + .findFirst() + .orElse("")); + } + + /** + * 判断字符串是否为合法的 JSON 格式 + * + * @param str 待检测的字符串 + * @return true 表示是合法 JSON (包括 JSONObject, JSONArray, 或基本类型值) + */ + public static boolean isJson(String str) { + if (str == null || str.trim().isEmpty()) { + return false; + } + // 使用 try-with-resources 正确处理 JSONValidator 资源关闭 + try (JSONValidator validator = JSONValidator.from(str.trim())) { + return validator.getType() == JSONValidator.Type.Object; + } catch (Exception e) { + log.warn("JSON格式校验失败: {}", e.getMessage()); + return false; + } + } } diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/start/StartNode.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/start/StartNode.java index 6f5df29e..e9ccc2be 100644 --- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/start/StartNode.java +++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/start/StartNode.java @@ -16,8 +16,8 @@ import org.ruoyi.workflow.workflow.node.AbstractWfNode; import java.util.List; import static org.ruoyi.workflow.cosntant.AdiConstant.WorkflowConstant.DEFAULT_OUTPUT_PARAM_NAME; -import static org.ruoyi.workflow.enums.ErrorEnum.A_WF_NODE_CONFIG_ERROR; -import static org.ruoyi.workflow.enums.ErrorEnum.A_WF_NODE_CONFIG_NOT_FOUND; +import static org.ruoyi.common.chat.enums.ErrorEnum.A_WF_NODE_CONFIG_ERROR; +import static org.ruoyi.common.chat.enums.ErrorEnum.A_WF_NODE_CONFIG_NOT_FOUND; @Slf4j public class StartNode extends AbstractWfNode { diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/controller/chat/ChatMessageController.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/controller/chat/ChatMessageController.java index c24de577..7d85cdb1 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/controller/chat/ChatMessageController.java +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/controller/chat/ChatMessageController.java @@ -6,7 +6,9 @@ import lombok.RequiredArgsConstructor; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.constraints.*; import cn.dev33.satoken.annotation.SaCheckPermission; -import org.ruoyi.service.chat.IChatMessageService; +import org.ruoyi.common.chat.domain.bo.chat.ChatMessageBo; +import org.ruoyi.common.chat.domain.vo.chat.ChatMessageVo; +import org.ruoyi.common.chat.service.chatMessage.IChatMessageService; import org.springframework.web.bind.annotation.*; import org.springframework.validation.annotation.Validated; import org.ruoyi.common.idempotent.annotation.RepeatSubmit; @@ -18,8 +20,6 @@ import org.ruoyi.common.core.validate.AddGroup; import org.ruoyi.common.core.validate.EditGroup; import org.ruoyi.common.log.enums.BusinessType; import org.ruoyi.common.excel.utils.ExcelUtil; -import org.ruoyi.domain.vo.chat.ChatMessageVo; -import org.ruoyi.domain.bo.chat.ChatMessageBo; import org.ruoyi.common.mybatis.core.page.TableDataInfo; /** diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/controller/chat/ChatModelController.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/controller/chat/ChatModelController.java index 06212c1d..15884158 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/controller/chat/ChatModelController.java +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/controller/chat/ChatModelController.java @@ -6,7 +6,7 @@ import lombok.RequiredArgsConstructor; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.constraints.*; import cn.dev33.satoken.annotation.SaCheckPermission; -import org.ruoyi.common.chat.Service.IChatModelService; +import org.ruoyi.common.chat.service.chat.IChatModelService; import org.ruoyi.common.chat.domain.bo.chat.ChatModelBo; import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo; import org.ruoyi.enums.ModelType; diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/factory/EmbeddingModelFactory.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/factory/EmbeddingModelFactory.java index 0aecf556..41ae8160 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/factory/EmbeddingModelFactory.java +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/factory/EmbeddingModelFactory.java @@ -2,7 +2,7 @@ package org.ruoyi.factory; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.ruoyi.common.chat.Service.IChatModelService; +import org.ruoyi.common.chat.service.chat.IChatModelService; import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo; import org.ruoyi.service.embed.BaseEmbedModelService; import org.ruoyi.service.embed.MultiModalEmbedModelService; diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/mapper/chat/ChatMessageMapper.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/mapper/chat/ChatMessageMapper.java index 63793d19..51ad8651 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/mapper/chat/ChatMessageMapper.java +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/mapper/chat/ChatMessageMapper.java @@ -1,7 +1,7 @@ package org.ruoyi.mapper.chat; -import org.ruoyi.domain.entity.chat.ChatMessage; -import org.ruoyi.domain.vo.chat.ChatMessageVo; +import org.ruoyi.common.chat.domain.vo.chat.ChatMessageVo; +import org.ruoyi.common.chat.entity.chat.ChatMessage; import org.ruoyi.common.mybatis.core.mapper.BaseMapperPlus; /** diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/mapper/chat/ChatModelMapper.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/mapper/chat/ChatModelMapper.java index 50c296a4..ee93917a 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/mapper/chat/ChatModelMapper.java +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/mapper/chat/ChatModelMapper.java @@ -1,6 +1,6 @@ package org.ruoyi.mapper.chat; -import org.ruoyi.common.chat.domain.entity.chat.ChatModel; +import org.ruoyi.common.chat.entity.chat.ChatModel; import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo; import org.ruoyi.common.mybatis.core.mapper.BaseMapperPlus; diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/AbstractStreamingChatService.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/AbstractStreamingChatService.java index 75894c9a..7d8b1a30 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/AbstractStreamingChatService.java +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/AbstractStreamingChatService.java @@ -24,17 +24,20 @@ import org.ruoyi.agent.WebSearchAgent; import org.ruoyi.agent.tool.ExecuteSqlQueryTool; import org.ruoyi.agent.tool.QueryAllTablesTool; import org.ruoyi.agent.tool.QueryTableSchemaTool; -import org.ruoyi.common.chat.Service.IChatService; +import org.ruoyi.common.chat.base.ThreadContext; +import org.ruoyi.common.chat.domain.dto.request.ReSumeRunner; +import org.ruoyi.common.chat.domain.dto.request.WorkFlowRunner; +import org.ruoyi.common.chat.enums.RoleType; +import org.ruoyi.common.chat.service.chat.IChatService; import org.ruoyi.common.chat.domain.dto.request.ChatRequest; -import org.ruoyi.common.chat.domain.entity.chat.ChatContext; +import org.ruoyi.common.chat.entity.chat.ChatContext; import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo; +import org.ruoyi.common.chat.service.chatMessage.AbstractChatMessageService; +import org.ruoyi.common.chat.service.workFlow.IWorkFlowStarterService; import org.ruoyi.common.core.utils.ObjectUtils; import org.ruoyi.common.core.utils.SpringUtils; import org.ruoyi.common.core.utils.StringUtils; import org.ruoyi.common.sse.utils.SseMessageUtils; -import org.ruoyi.domain.bo.chat.ChatMessageBo; -import org.ruoyi.enums.RoleType; -import org.ruoyi.service.chat.IChatMessageService; import org.ruoyi.service.chat.impl.memory.PersistentChatMemoryStore; import org.springframework.util.CollectionUtils; import org.springframework.validation.annotation.Validated; @@ -58,7 +61,7 @@ import java.util.concurrent.ConcurrentHashMap; */ @Slf4j @Validated -public abstract class AbstractStreamingChatService implements IChatService { +public abstract class AbstractStreamingChatService extends AbstractChatMessageService implements IChatService { /** * 默认保留的消息窗口大小(用于长期记忆) @@ -76,6 +79,11 @@ public abstract class AbstractStreamingChatService implements IChatService { */ private static final Map memoryCache = new ConcurrentHashMap<>(); + /** + * 获取工作流启用Bean对象 + */ + private static final IWorkFlowStarterService starterService = SpringUtils.getBean(IWorkFlowStarterService.class); + /** * 定义聊天流程骨架 */ @@ -108,9 +116,28 @@ public abstract class AbstractStreamingChatService implements IChatService { // 保存用户消息 saveChatMessage(chatRequest, userId, content, RoleType.USER.getName(), chatModelVo); + + // 判断用户是否重新输入 + boolean isResume = chatRequest.getIsResume() != null && chatRequest.getIsResume(); + if (isResume){ + ReSumeRunner reSumeRunner = chatRequest.getReSumeRunner(); + if (ObjectUtils.isNotEmpty(reSumeRunner)){ + starterService.resumeFlow(reSumeRunner.getRuntimeUuid(), reSumeRunner.getFeedbackContent(), emitter); + return emitter; + } + } + + // 判断用户是否开启工作流 + boolean enableWorkFlow = chatRequest.getEnableWorkFlow() != null && chatRequest.getEnableWorkFlow(); + if (enableWorkFlow) { + WorkFlowRunner runner = chatRequest.getWorkFlowRunner(); + if (ObjectUtils.isNotEmpty(runner)){ + return starterService.streaming(ThreadContext.getCurrentUser(), runner.getUuid(), runner.getInputs(), chatRequest.getSessionId()); + } + } + // 使用长期记忆增强的消息列表 List messagesWithMemory = buildMessagesWithMemory(chatRequest); - if (chatRequest.getEnableThinking()) { String msg = doAgent(content, chatModelVo); SseMessageUtils.sendMessage(userId, msg); @@ -119,13 +146,10 @@ public abstract class AbstractStreamingChatService implements IChatService { saveChatMessage(chatRequest, userId, msg, RoleType.ASSISTANT.getName(), chatModelVo); } else { // 创建包含内存管理的响应处理器 - if (ObjectUtils.isEmpty(handler)) { - handler = createResponseHandler(chatRequest, userId, tokenValue, chatModelVo); - } + handler = ObjectUtils.isEmpty(handler) ? createResponseHandler(chatRequest, userId, tokenValue, chatModelVo) : handler; // 调用具体实现的聊天方法 doChat(chatModelVo, chatRequest, messagesWithMemory, handler); } - } catch (Exception e) { SseMessageUtils.sendMessage(userId, "对话出错:" + e.getMessage()); SseMessageUtils.completeConnection(userId, tokenValue); @@ -144,6 +168,12 @@ public abstract class AbstractStreamingChatService implements IChatService { */ protected List buildMessagesWithMemory(ChatRequest chatRequest) { List messages = new ArrayList<>(); + // 工作流对话消息 + List chatMessages = chatRequest.getChatMessages(); + if (!CollectionUtils.isEmpty(chatMessages)){ + messages.addAll(chatMessages); + } + // 开启长期记忆 if (enablePersistentMemory && chatRequest.getSessionId() != null) { MessageWindowChatMemory memory = createChatMemory(chatRequest.getSessionId()); if (memory != null) { @@ -155,11 +185,6 @@ public abstract class AbstractStreamingChatService implements IChatService { } return messages; } - // 工作流方式 - List chatMessages = chatRequest.getChatMessages(); - if (!CollectionUtils.isEmpty(chatMessages)){ - messages.addAll(chatMessages); - } return messages; } @@ -276,40 +301,6 @@ public abstract class AbstractStreamingChatService implements IChatService { }; } - /** - * 保存聊天消息到数据库 - * - * @param chatRequest 聊天请求 - * @param userId 用户ID - * @param content 消息内容 - * @param role 消息角色 - * @param chatModelVo 模型配置 - */ - private void saveChatMessage(ChatRequest chatRequest, Long userId, String content, String role, ChatModelVo chatModelVo) { - try { - // 验证必要的上下文信息 - if (chatRequest == null || userId == null) { - log.warn("缺少必要的聊天上下文信息,无法保存消息"); - return; - } - - // 创建ChatMessageBo对象 - ChatMessageBo messageBO = new ChatMessageBo(); - messageBO.setUserId(userId); - messageBO.setSessionId(chatRequest.getSessionId()); - messageBO.setContent(content); - messageBO.setRole(role); - messageBO.setModelName(chatRequest.getModel()); - messageBO.setBillingType(chatModelVo.getModelType()); - messageBO.setRemark(null); - - IChatMessageService chatMessageService = SpringUtils.getBean(IChatMessageService.class); - chatMessageService.insertByBo(messageBO); - } catch (Exception e) { - log.error("保存{}聊天消息时出错: {}", getProviderName(), e.getMessage(), e); - } - } - /** * 构建具体厂商的 StreamingChatModel * 子类必须实现此方法,返回对应厂商的模型实例 diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/ChatMessageServiceImpl.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/ChatMessageServiceImpl.java index 0804f010..95f681fd 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/ChatMessageServiceImpl.java +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/ChatMessageServiceImpl.java @@ -1,6 +1,10 @@ package org.ruoyi.service.chat.impl; +import org.ruoyi.common.chat.domain.bo.chat.ChatMessageBo; import org.ruoyi.common.chat.domain.dto.ChatMessageDTO; +import org.ruoyi.common.chat.domain.vo.chat.ChatMessageVo; +import org.ruoyi.common.chat.entity.chat.ChatMessage; +import org.ruoyi.common.chat.service.chatMessage.IChatMessageService; import org.ruoyi.common.core.utils.MapstructUtils; import org.ruoyi.common.core.utils.StringUtils; import org.ruoyi.common.mybatis.core.page.TableDataInfo; @@ -10,11 +14,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.ruoyi.service.chat.IChatMessageService; import org.springframework.stereotype.Service; -import org.ruoyi.domain.bo.chat.ChatMessageBo; -import org.ruoyi.domain.vo.chat.ChatMessageVo; -import org.ruoyi.domain.entity.chat.ChatMessage; import org.ruoyi.mapper.chat.ChatMessageMapper; import java.util.List; diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/ChatModelServiceImpl.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/ChatModelServiceImpl.java index 32c8f85a..127d66a5 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/ChatModelServiceImpl.java +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/ChatModelServiceImpl.java @@ -1,8 +1,8 @@ package org.ruoyi.service.chat.impl; -import org.ruoyi.common.chat.Service.IChatModelService; +import org.ruoyi.common.chat.service.chat.IChatModelService; import org.ruoyi.common.chat.domain.bo.chat.ChatModelBo; -import org.ruoyi.common.chat.domain.entity.chat.ChatModel; +import org.ruoyi.common.chat.entity.chat.ChatModel; import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo; import org.ruoyi.common.core.utils.MapstructUtils; import org.ruoyi.common.core.utils.StringUtils; diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/ChatServiceFacade.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/ChatServiceFacade.java index 5151c35f..c97dcf95 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/ChatServiceFacade.java +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/ChatServiceFacade.java @@ -4,11 +4,11 @@ import cn.dev33.satoken.stp.StpUtil; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.ruoyi.common.chat.Service.IChatModelService; -import org.ruoyi.common.chat.Service.IChatService; +import org.ruoyi.common.chat.service.chat.IChatModelService; +import org.ruoyi.common.chat.service.chat.IChatService; import org.ruoyi.common.chat.domain.dto.ChatMessageDTO; import org.ruoyi.common.chat.domain.dto.request.ChatRequest; -import org.ruoyi.common.chat.domain.entity.chat.ChatContext; +import org.ruoyi.common.chat.entity.chat.ChatContext; import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo; import org.ruoyi.common.chat.factory.ChatServiceFactory; import org.ruoyi.common.satoken.utils.LoginHelper; @@ -52,7 +52,6 @@ public class ChatServiceFacade { * @return SseEmitter */ public SseEmitter sseChat(ChatRequest chatRequest, HttpServletRequest request) { - // 1. 根据模型名称查询完整配置 ChatModelVo chatModelVo = chatModelService.selectModelByName(chatRequest.getModel()); if (chatModelVo == null) { diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/memory/ChatMemoryUsageExample.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/memory/ChatMemoryUsageExample.java index 2b9a7da4..ca719572 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/memory/ChatMemoryUsageExample.java +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/memory/ChatMemoryUsageExample.java @@ -108,7 +108,7 @@ public class ChatMemoryUsageExample { log.info("=== 示例4:清理过期消息 ==="); /* // 假设已有IChatMessageService实例 - IChatMessageService chatMessageService = getBean(IChatMessageService.class); + AbstractChatMessageService chatMessageService = getBean(AbstractChatMessageService.class); // 场景:用户要求"忘记我们之前的对话" Long sessionId = 789L; diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/memory/PersistentChatMemoryStore.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/memory/PersistentChatMemoryStore.java index 63d9e151..a10ccfb6 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/memory/PersistentChatMemoryStore.java +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/chat/impl/memory/PersistentChatMemoryStore.java @@ -4,8 +4,8 @@ import dev.langchain4j.data.message.ChatMessage; import dev.langchain4j.store.memory.chat.ChatMemoryStore; import lombok.extern.slf4j.Slf4j; import org.ruoyi.common.chat.domain.dto.ChatMessageDTO; +import org.ruoyi.common.chat.service.chatMessage.IChatMessageService; import org.ruoyi.common.core.utils.SpringUtils; -import org.ruoyi.service.chat.IChatMessageService; import java.util.ArrayList; import java.util.List; diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/graph/impl/GraphExtractionServiceImpl.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/graph/impl/GraphExtractionServiceImpl.java index 890bdc12..bdceb35f 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/graph/impl/GraphExtractionServiceImpl.java +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/graph/impl/GraphExtractionServiceImpl.java @@ -3,7 +3,7 @@ package org.ruoyi.service.graph.impl; import cn.hutool.core.util.StrUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.ruoyi.common.chat.Service.IChatModelService; +import org.ruoyi.common.chat.service.chat.IChatModelService; import org.ruoyi.common.chat.domain.bo.chat.ChatModelBo; import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo; import org.ruoyi.config.GraphExtractPrompt; diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/image/AbstractImageGenerationService.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/image/AbstractImageGenerationService.java index 3312239e..4a9065a7 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/image/AbstractImageGenerationService.java +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/image/AbstractImageGenerationService.java @@ -1,9 +1,9 @@ package org.ruoyi.service.image; import lombok.extern.slf4j.Slf4j; -import org.ruoyi.common.chat.Service.IImageGenerationService; +import org.ruoyi.common.chat.service.image.IImageGenerationService; import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo; -import org.ruoyi.common.chat.domain.entity.image.ImageContext; +import org.ruoyi.common.chat.entity.image.ImageContext; import org.springframework.validation.annotation.Validated; @Slf4j diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/knowledge/impl/KnowledgeAttachServiceImpl.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/knowledge/impl/KnowledgeAttachServiceImpl.java index b7106120..ce02785e 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/knowledge/impl/KnowledgeAttachServiceImpl.java +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/knowledge/impl/KnowledgeAttachServiceImpl.java @@ -2,7 +2,7 @@ package org.ruoyi.service.knowledge.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.RandomUtil; -import org.ruoyi.common.chat.Service.IChatModelService; +import org.ruoyi.common.chat.service.chat.IChatModelService; import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo; import org.ruoyi.common.core.domain.dto.OssDTO; import org.ruoyi.common.core.service.OssService;